diff --git a/404.html b/404.html index 9c123dda..253d89b7 100644 --- a/404.html +++ b/404.html @@ -1 +1 @@ -Σ( ° △ °|||)︴404! | Balloon Party = 風船のパーティー = fuusen no party
Σ( ° △ °|||)︴404!
\ No newline at end of file +Σ( ° △ °|||)︴404! | Balloon Party = 風船のパーティー = fuusen no party
Σ( ° △ °|||)︴404!
\ No newline at end of file diff --git a/THANK-YOU/index.html b/THANK-YOU/index.html index 65cd9279..5977c224 100644 --- a/THANK-YOU/index.html +++ b/THANK-YOU/index.html @@ -1 +1 @@ -THANK YOU | Balloon Party = 風船のパーティー = fuusen no party

想在这里特别地感谢你!想在这里特别地感谢你!


每一句“生日快乐”每一句“生日快乐”


就算只是一句“生日快乐”就算只是一句“生日快乐”


都让我非常幸福!都让我非常幸福!


特别感谢:特别感谢:

Thank you for your birthday cake!Thank you for your CPU!Thank you for your ナナチ!\text{Thank you for your birthday cake!}\\ \ \\ \text{Thank you for your CPU!}\\ \ \\ \text{Thank you for your ナナチ!}


THANKYOUTHANK\ YOU

ありがとう!ありがとう!


Edited on Views times
\ No newline at end of file +THANK YOU | Balloon Party = 風船のパーティー = fuusen no party

想在这里特别地感谢你!想在这里特别地感谢你!


每一句“生日快乐”每一句“生日快乐”


就算只是一句“生日快乐”就算只是一句“生日快乐”


都让我非常幸福!都让我非常幸福!


特别感谢:特别感谢:

Thank you for your birthday cake!Thank you for your CPU!Thank you for your ナナチ!\text{Thank you for your birthday cake!}\\ \ \\ \text{Thank you for your CPU!}\\ \ \\ \text{Thank you for your ナナチ!}


THANKYOUTHANK\ YOU

ありがとう!ありがとう!


Edited on Views times
\ No newline at end of file diff --git a/about/index.html b/about/index.html index 3d666aee..46f3aa0f 100644 --- a/about/index.html +++ b/about/index.html @@ -1 +1 @@ -About | Balloon Party = 風船のパーティー = fuusen no party

这里是我的博客,整理收纳了一些笔记、思维导图、资料

您可以叫我 fuuzen 或者「風船」,这是我随便起的一个用的比较久的网名,没有什么特别含义。fuusen 即「ふうせん」,但这个 ID 已经在 github 被注册了,所以只好叫做 fuuzen 了

这个博客网站的名字是 Balloon Party 或者「風船のパーティー」,也是我随便起的一个名字,没有什么特别含义

如果这里所整理收纳的资料对您的学习有帮助的话,欢迎您向您的朋友们推荐本博客!也欢迎您向我指出资料中的任何错误或提出宝贵的意见!

picture

Edited on Views times
\ No newline at end of file +About | Balloon Party = 風船のパーティー = fuusen no party

这里是我的博客,整理收纳了一些笔记、思维导图、资料

您可以叫我 fuuzen 或者「風船」,这是我随便起的一个用的比较久的网名,没有什么特别含义。fuusen 即「ふうせん」,但这个 ID 已经在 github 被注册了,所以只好叫做 fuuzen 了

这个博客网站的名字是 Balloon Party 或者「風船のパーティー」,也是我随便起的一个名字,没有什么特别含义

如果这里所整理收纳的资料对您的学习有帮助的话,欢迎您向您的朋友们推荐本博客!也欢迎您向我指出资料中的任何错误或提出宝贵的意见!

picture

Edited on Views times
\ No newline at end of file diff --git a/acgn/anime-log/index.html b/acgn/anime-log/index.html index 18350aa3..81d9b665 100644 --- a/acgn/anime-log/index.html +++ b/acgn/anime-log/index.html @@ -1 +1 @@ -看番记录表 - ACGN | Balloon Party = 風船のパーティー = fuusen no party

* 星号是没完全看完
持续更新中......

# 2023

# 寒假:

  • EVA 旧版
  • 凉宫春日
  • Angel Beats!
  • Little Busters
  • Air
  • 86 - 不存在的战区
  • ISLAND
  • 斩赤红之瞳
  • 可塑性记忆
  • 虚构推理
  • 冰海战记
  • 魔圆
  • 魔纪
  • 想要成为影之实力者

# 一些短的:

  • 快要坏掉的八音盒
  • 星之梦 + 星之人

# 大一下:

  • Canon *
  • 时光沙漏
  • 安达与岛村
  • 终将成为你
  • 天国大魔境

# 暑假:

  • 处刑少女的生存手册
  • Happy Sugar Life

# 大二上:

  • mygo *
  • 黑之契约者 *
  • Fate Zero

# 2024

# 寒假

  • 死亡笔记

# 暑假

  • 终末列车去往何方
  • 神不在的星期天
  • Another
  • 尸体派对
  • 死后文
  • 无职转生
  • 为美好的世界献上祝福 + 爆炎
  • 魔法少女网站
  • 魔法少女育成计划
Edited on Views times
\ No newline at end of file +看番记录表 - ACGN | Balloon Party = 風船のパーティー = fuusen no party

* 星号是没完全看完
持续更新中......

# 2023

# 寒假:

  • EVA 旧版
  • 凉宫春日
  • Angel Beats!
  • Little Busters
  • Air
  • 86 - 不存在的战区
  • ISLAND
  • 斩赤红之瞳
  • 可塑性记忆
  • 虚构推理
  • 冰海战记
  • 魔圆
  • 魔纪
  • 想要成为影之实力者

# 一些短的:

  • 快要坏掉的八音盒
  • 星之梦 + 星之人

# 大一下:

  • Canon *
  • 时光沙漏
  • 安达与岛村
  • 终将成为你
  • 天国大魔境

# 暑假:

  • 处刑少女的生存手册
  • Happy Sugar Life

# 大二上:

  • mygo *
  • 黑之契约者 *
  • Fate Zero

# 2024

# 寒假

  • 死亡笔记

# 暑假

  • 终末列车去往何方
  • 神不在的星期天
  • Another
  • 尸体派对
  • 死后文
  • 无职转生
  • 为美好的世界献上祝福 + 爆炎
  • 魔法少女网站
  • 魔法少女育成计划
Edited on Views times
\ No newline at end of file diff --git a/acgn/epiao/index.html b/acgn/epiao/index.html index 972cfbdf..cada61fe 100644 --- a/acgn/epiao/index.html +++ b/acgn/epiao/index.html @@ -1 +1 @@ -《饿殍:明末千里行》通关记录 - ACGN | Balloon Party = 風船のパーティー = fuusen no party

今天因为校青马班的活动又跑到南校开会、参观团一大。中涂我也不能用电脑,于是无聊之际,手机打开了一直感兴趣的《饿殍:明末千里行》的游戏录播,看了前面就上头了。于是一直到凌晨 3 点,打完了 2 个 TE ,非常有感触,于是一边听着 ED 写下本篇文章作记录。(即使第二天有早八我也不管了!)

这是我玩的第二篇国产的国产文字冒险游戏。(上一部是《OPUS: 龙脉长歌》,这两部观感都非常好)《饿殍》难怪这么火,是有些原因的:

  • 首先作为一个全年龄向的游戏,受众确实更加广泛
  • 人物立绘、CG 也是蛮出色的
  • 而且描写的饥荒惨状,敢于如此露骨地描写、刻画,也是非常值得称赞的。有些东西,一定要最露骨的刻画,才能真正描绘出来,传达出来
  • 当然也有一些比较出圈的 “名场面”,懂得都懂了
  • 音乐方面并不十分特别,但也不错

我尤其比较喜欢的,还得是双线叙事处理穗的回忆了。穗的回忆可以说是最压抑的部分,在回忆的开头,展现了一点穗原本家庭的美好画面,但后面便开始逐渐步入绝望,令人揪心。尤其是《绝望》这一篇,最为压抑,也最为强而有力,直击玩家的心扉!

这部作品的描绘,很有 “中国” 的历史特色,最后也展现了 “反叛” 这样的末代王朝常见的主旋律。与日系作品相比,少了一分细腻,但却传达了与 “物哀” 一样的悲剧的美。

要说从这作品思考到了什么,倒也没有什么。对我来说,我想也是对于大部分和我一样的观众来说,这样的作品给我们的,更多的是摆脱平常朝九晚五、三点一线生活的一点调味。相比平静的青春校园主题作品,这样的乱世、在乱世中旅行、在乱世中寻仇的题材,更给人刺激感、新鲜感。

1

穗这个角色,塑造的相当好。她给人一种 “小大人” 的感觉,但是这些成熟、懂事、机灵等等不符合其年龄的特点,都反衬着她的艰辛遭遇,都令人心酸。在穗的回忆中,她反而是没有那么 “懂事” 的,还会因为父母煮了小猫而赌气。这样的前后对照,也是对她悲惨遭遇的深层次的刻画,饥荒的灾难不仅摧残她的身体,更塑造了她的性格,催生了她的成长。

而一路上,玩家要想达到好结局,必须要做的只有一件事:尽量在穗面前表现得善良一些,增加所谓的 “好感度”。这也是和传统的文字冒险游戏选项分支不太一样,从这里实际上也看出了游戏的一大主题:原谅。玩家的最终目标,或者说主人公良的终极目标,就是获取穗的原谅。不得不说这还是蛮反差的,因为穗的回忆中,淋漓尽致地描写了良杀害了穗爹爹后,穗家庭的更加惨不忍睹的悲剧,而玩家在见识到这一切之后,还要去替这个 “罪魁祸首” 寻求原谅。

确实,这也是很多人会排斥、难以接受的地方。把穗一家害得如此惨的弑父仇敌,凭什么要原谅?

当然,游戏制作者还是 “上价值”,提醒了玩家们,罪魁祸首不是良,不是男主,而是荒淫无道的王爷、朝廷官府,这也是为什么这个游戏这么有 “中国” 的历史特色,原来一切都是人压迫人导致的悲剧。

2

整个作品描绘的是一个悲剧、一幅惨状、一对命运不幸的主人公。

穗的人生,自从家里只剩她自己之后,就总是在围绕着 “为了复仇而活着” 了。

良的人生,自从父亲去世只剩他一个人之后,直到遇到穗之前,总是围绕着 “为自己而活着”。

两个角色也就是这样,有一种恰到好处的 “距离感”,看似合作伙伴,实则杀父仇人,在相互帮助、依赖的过程中,产生了一点点的、非常少的 “为对方而活着” 的感觉。而尤其是到了 TE “同生” ,“为对方而活着” 的感觉就更强烈了。

贯穿整个故事的,一直都是两人这样的 “距离感”。在 TE 之前的 3 个结局,突出表现了距离感与陌生感:

  • 无言,穗实施了计划让良在茫然、错愕中被捕、处以极刑,可以说是最不好的结局之一
  • 快逃,和无言的区别在于穗给了良准备的机会,给了良体面赴死的机会
  • 不见,最让人放不下的结局
    • 穗的想法来看,可以有两种解读:
      • 可以认为穗似乎原谅良了,不再杀良,宁可自己一人消失
      • 可以认为穗依然复仇了,只是她的复仇,不再是设计良被捕,而是用自己的消失、荷包的提醒,告诉良真相之后一言不发地独自消失
    • 穗的去向来看,也有两种解读:
      • 很大可能,穗投湖自尽了,在失去 “复仇” 这一人生意义后,只好自杀
      • 很小的概率,穗或许伪造了投湖的迹象,依然活着,并且选择不再出现在良眼前

那张惊艳无比的烟花的 CG ,竟是良和穗的最后一面。而后,穗谎称解手,便一去不返,突然没了音讯。两人再次拉开了距离,突然一股陌生感、寂寞感向玩家袭来。

至此,穗这个角色的塑造堪称饱满,她不再是弱小无力的” 小羊 “,而是和良站在平等的位置上的,甚至站在审判良的位置上的,一个饱满的角色。并且,一直保持了一份 “距离感”,即穗与良的 “距离感”,也是玩家与” 穗 “这个角色的” 距离感 “,是不再相见的 “距离感”、是弑父血仇的 “距离感”、是生与死的” 距离感 “。

直到最后的结局 “同生” 也是,一直保留了这份若即若离的距离感,两人还是以仇人相称。这份 “距离感”,比皆大欢喜、甜甜蜜蜜发糖可要好太多了,这也是我非常喜欢的结局。

片段一 (同生)
良 [喂,我算了一下,如今你大概二十有三了吧。]
满穗 [嗯。]
良 [现在嫁人了没?]
满穗 [没嫁呢。]
良 [哦。]
满穗 [良呢?打仗的候娶妻了吗?]
良 [没娶,兵荒乱的,娶什么妻。]
满穗 [也是。]
片段二 (同生)
满穗 [其实,这么多年来,我跟别人提起我的名字,一直都是 “穗”。]
满穗 [唯独良爷,我说了全名,是叫满穗。]
良 [......]
良 [哦?为何只有我有这个区别?]
满穗 [呵...... 当初我就是觉得,要仇人知道我的全名,我才没有白复仇。]
满穗 [如今怎么想的,我也不知道了......]
良 [......]
满穗 [......]
良 [......]
满穗 [话说回来,良爷觉得怎么样?]
良 [什么怎么样?]
满穗 [你喜欢 “满穗”,还是 “穗”?]
良 [......]
满穗 [......]
良 [......]
良 [“满穗” 吧]
满穗 [......]
良 [我喜欢 “满穗”......]
满穗 [哦......]
良 [满穗、满穗、满穗......]
我念了一遍又一遍她的名字。
满穗 [......]
她没有说话,只是装著听不见我在念她的名字
她特不时地整笑著,不知在高兴些什么
她望著窗外,饮著茶,似乎在想著一些什么......
—— 咕
我也饮下了一杯茶,望著她所眺望的方向,嘴角不自地勾起了一丝笑意。
片段三 (共死)
满穗 [以前... 我装成哑巴... 现在... 你真成哑巴了... 真好笑...]
她轻声笑着
满穗 [良,抱紧我吧......]
Edited on Views times
\ No newline at end of file +《饿殍:明末千里行》通关记录 - ACGN | Balloon Party = 風船のパーティー = fuusen no party

今天因为校青马班的活动又跑到南校开会、参观团一大。中涂我也不能用电脑,于是无聊之际,手机打开了一直感兴趣的《饿殍:明末千里行》的游戏录播,看了前面就上头了。于是一直到凌晨 3 点,打完了 2 个 TE ,非常有感触,于是一边听着 ED 写下本篇文章作记录。(即使第二天有早八我也不管了!)

这是我玩的第二篇国产的国产文字冒险游戏。(上一部是《OPUS: 龙脉长歌》,这两部观感都非常好)《饿殍》难怪这么火,是有些原因的:

  • 首先作为一个全年龄向的游戏,受众确实更加广泛
  • 人物立绘、CG 也是蛮出色的
  • 而且描写的饥荒惨状,敢于如此露骨地描写、刻画,也是非常值得称赞的。有些东西,一定要最露骨的刻画,才能真正描绘出来,传达出来
  • 当然也有一些比较出圈的 “名场面”,懂得都懂了
  • 音乐方面并不十分特别,但也不错

我尤其比较喜欢的,还得是双线叙事处理穗的回忆了。穗的回忆可以说是最压抑的部分,在回忆的开头,展现了一点穗原本家庭的美好画面,但后面便开始逐渐步入绝望,令人揪心。尤其是《绝望》这一篇,最为压抑,也最为强而有力,直击玩家的心扉!

这部作品的描绘,很有 “中国” 的历史特色,最后也展现了 “反叛” 这样的末代王朝常见的主旋律。与日系作品相比,少了一分细腻,但却传达了与 “物哀” 一样的悲剧的美。

要说从这作品思考到了什么,倒也没有什么。对我来说,我想也是对于大部分和我一样的观众来说,这样的作品给我们的,更多的是摆脱平常朝九晚五、三点一线生活的一点调味。相比平静的青春校园主题作品,这样的乱世、在乱世中旅行、在乱世中寻仇的题材,更给人刺激感、新鲜感。

1

穗这个角色,塑造的相当好。她给人一种 “小大人” 的感觉,但是这些成熟、懂事、机灵等等不符合其年龄的特点,都反衬着她的艰辛遭遇,都令人心酸。在穗的回忆中,她反而是没有那么 “懂事” 的,还会因为父母煮了小猫而赌气。这样的前后对照,也是对她悲惨遭遇的深层次的刻画,饥荒的灾难不仅摧残她的身体,更塑造了她的性格,催生了她的成长。

而一路上,玩家要想达到好结局,必须要做的只有一件事:尽量在穗面前表现得善良一些,增加所谓的 “好感度”。这也是和传统的文字冒险游戏选项分支不太一样,从这里实际上也看出了游戏的一大主题:原谅。玩家的最终目标,或者说主人公良的终极目标,就是获取穗的原谅。不得不说这还是蛮反差的,因为穗的回忆中,淋漓尽致地描写了良杀害了穗爹爹后,穗家庭的更加惨不忍睹的悲剧,而玩家在见识到这一切之后,还要去替这个 “罪魁祸首” 寻求原谅。

确实,这也是很多人会排斥、难以接受的地方。把穗一家害得如此惨的弑父仇敌,凭什么要原谅?

当然,游戏制作者还是 “上价值”,提醒了玩家们,罪魁祸首不是良,不是男主,而是荒淫无道的王爷、朝廷官府,这也是为什么这个游戏这么有 “中国” 的历史特色,原来一切都是人压迫人导致的悲剧。

2

整个作品描绘的是一个悲剧、一幅惨状、一对命运不幸的主人公。

穗的人生,自从家里只剩她自己之后,就总是在围绕着 “为了复仇而活着” 了。

良的人生,自从父亲去世只剩他一个人之后,直到遇到穗之前,总是围绕着 “为自己而活着”。

两个角色也就是这样,有一种恰到好处的 “距离感”,看似合作伙伴,实则杀父仇人,在相互帮助、依赖的过程中,产生了一点点的、非常少的 “为对方而活着” 的感觉。而尤其是到了 TE “同生” ,“为对方而活着” 的感觉就更强烈了。

贯穿整个故事的,一直都是两人这样的 “距离感”。在 TE 之前的 3 个结局,突出表现了距离感与陌生感:

  • 无言,穗实施了计划让良在茫然、错愕中被捕、处以极刑,可以说是最不好的结局之一
  • 快逃,和无言的区别在于穗给了良准备的机会,给了良体面赴死的机会
  • 不见,最让人放不下的结局
    • 穗的想法来看,可以有两种解读:
      • 可以认为穗似乎原谅良了,不再杀良,宁可自己一人消失
      • 可以认为穗依然复仇了,只是她的复仇,不再是设计良被捕,而是用自己的消失、荷包的提醒,告诉良真相之后一言不发地独自消失
    • 穗的去向来看,也有两种解读:
      • 很大可能,穗投湖自尽了,在失去 “复仇” 这一人生意义后,只好自杀
      • 很小的概率,穗或许伪造了投湖的迹象,依然活着,并且选择不再出现在良眼前

那张惊艳无比的烟花的 CG ,竟是良和穗的最后一面。而后,穗谎称解手,便一去不返,突然没了音讯。两人再次拉开了距离,突然一股陌生感、寂寞感向玩家袭来。

至此,穗这个角色的塑造堪称饱满,她不再是弱小无力的” 小羊 “,而是和良站在平等的位置上的,甚至站在审判良的位置上的,一个饱满的角色。并且,一直保持了一份 “距离感”,即穗与良的 “距离感”,也是玩家与” 穗 “这个角色的” 距离感 “,是不再相见的 “距离感”、是弑父血仇的 “距离感”、是生与死的” 距离感 “。

直到最后的结局 “同生” 也是,一直保留了这份若即若离的距离感,两人还是以仇人相称。这份 “距离感”,比皆大欢喜、甜甜蜜蜜发糖可要好太多了,这也是我非常喜欢的结局。

片段一 (同生)
良 [喂,我算了一下,如今你大概二十有三了吧。]
满穗 [嗯。]
良 [现在嫁人了没?]
满穗 [没嫁呢。]
良 [哦。]
满穗 [良呢?打仗的候娶妻了吗?]
良 [没娶,兵荒乱的,娶什么妻。]
满穗 [也是。]
片段二 (同生)
满穗 [其实,这么多年来,我跟别人提起我的名字,一直都是 “穗”。]
满穗 [唯独良爷,我说了全名,是叫满穗。]
良 [......]
良 [哦?为何只有我有这个区别?]
满穗 [呵...... 当初我就是觉得,要仇人知道我的全名,我才没有白复仇。]
满穗 [如今怎么想的,我也不知道了......]
良 [......]
满穗 [......]
良 [......]
满穗 [话说回来,良爷觉得怎么样?]
良 [什么怎么样?]
满穗 [你喜欢 “满穗”,还是 “穗”?]
良 [......]
满穗 [......]
良 [......]
良 [“满穗” 吧]
满穗 [......]
良 [我喜欢 “满穗”......]
满穗 [哦......]
良 [满穗、满穗、满穗......]
我念了一遍又一遍她的名字。
满穗 [......]
她没有说话,只是装著听不见我在念她的名字
她特不时地整笑著,不知在高兴些什么
她望著窗外,饮著茶,似乎在想著一些什么......
—— 咕
我也饮下了一杯茶,望著她所眺望的方向,嘴角不自地勾起了一丝笑意。
片段三 (共死)
满穗 [以前... 我装成哑巴... 现在... 你真成哑巴了... 真好笑...]
她轻声笑着
满穗 [良,抱紧我吧......]
Edited on Views times
\ No newline at end of file diff --git a/archives/2023/10/index.html b/archives/2023/10/index.html index 6ae403ad..8de76e37 100644 --- a/archives/2023/10/index.html +++ b/archives/2023/10/index.html @@ -1 +1 @@ -2023 Y / 10 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2023 Y / 10 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2023/11/index.html b/archives/2023/11/index.html index e7a94706..489167af 100644 --- a/archives/2023/11/index.html +++ b/archives/2023/11/index.html @@ -1 +1 @@ -2023 Y / 11 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2023 Y / 11 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2023/12/index.html b/archives/2023/12/index.html index ff08c6a9..b0e91b07 100644 --- a/archives/2023/12/index.html +++ b/archives/2023/12/index.html @@ -1 +1 @@ -2023 Y / 12 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2023 Y / 12 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2023/12/page/2/index.html b/archives/2023/12/page/2/index.html index 34c016f1..590f04d3 100644 --- a/archives/2023/12/page/2/index.html +++ b/archives/2023/12/page/2/index.html @@ -1 +1 @@ -2023 Y / 12 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2023 Y / 12 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2023/index.html b/archives/2023/index.html index fbff991d..5e67ff6f 100644 --- a/archives/2023/index.html +++ b/archives/2023/index.html @@ -1 +1 @@ -2023 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2023 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2023/page/2/index.html b/archives/2023/page/2/index.html index f7939e87..d47c01d1 100644 --- a/archives/2023/page/2/index.html +++ b/archives/2023/page/2/index.html @@ -1 +1 @@ -2023 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2023 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2023/page/3/index.html b/archives/2023/page/3/index.html index a89ada3e..c6193b95 100644 --- a/archives/2023/page/3/index.html +++ b/archives/2023/page/3/index.html @@ -1 +1 @@ -2023 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2023 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/01/index.html b/archives/2024/01/index.html index d81283eb..36b161e4 100644 --- a/archives/2024/01/index.html +++ b/archives/2024/01/index.html @@ -1 +1 @@ -2024 Y / 01 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y / 01 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/01/page/2/index.html b/archives/2024/01/page/2/index.html index f89a4e8a..bb7144b8 100644 --- a/archives/2024/01/page/2/index.html +++ b/archives/2024/01/page/2/index.html @@ -1 +1 @@ -2024 Y / 01 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y / 01 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/01/page/3/index.html b/archives/2024/01/page/3/index.html index 6d191fed..35be922e 100644 --- a/archives/2024/01/page/3/index.html +++ b/archives/2024/01/page/3/index.html @@ -1 +1 @@ -2024 Y / 01 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y / 01 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/02/index.html b/archives/2024/02/index.html index 125fcbb1..b21b1634 100644 --- a/archives/2024/02/index.html +++ b/archives/2024/02/index.html @@ -1 +1 @@ -2024 Y / 02 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y / 02 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/02/page/2/index.html b/archives/2024/02/page/2/index.html index 9a710fb0..11d2f01b 100644 --- a/archives/2024/02/page/2/index.html +++ b/archives/2024/02/page/2/index.html @@ -1 +1 @@ -2024 Y / 02 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y / 02 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/03/index.html b/archives/2024/03/index.html index 3bdf5faa..ca54885e 100644 --- a/archives/2024/03/index.html +++ b/archives/2024/03/index.html @@ -1 +1 @@ -2024 Y / 03 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y / 03 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/03/page/2/index.html b/archives/2024/03/page/2/index.html index 281b39b3..b6a43bbf 100644 --- a/archives/2024/03/page/2/index.html +++ b/archives/2024/03/page/2/index.html @@ -1 +1 @@ -2024 Y / 03 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y / 03 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/03/page/3/index.html b/archives/2024/03/page/3/index.html index 9dfb129a..123d3b3b 100644 --- a/archives/2024/03/page/3/index.html +++ b/archives/2024/03/page/3/index.html @@ -1 +1 @@ -2024 Y / 03 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y / 03 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/04/index.html b/archives/2024/04/index.html index dda174e3..1208ae40 100644 --- a/archives/2024/04/index.html +++ b/archives/2024/04/index.html @@ -1 +1 @@ -2024 Y / 04 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y / 04 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/04/page/2/index.html b/archives/2024/04/page/2/index.html index ac5c3a67..94a9ba87 100644 --- a/archives/2024/04/page/2/index.html +++ b/archives/2024/04/page/2/index.html @@ -1 +1 @@ -2024 Y / 04 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y / 04 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/05/index.html b/archives/2024/05/index.html index 5c711b66..ee8dd5b1 100644 --- a/archives/2024/05/index.html +++ b/archives/2024/05/index.html @@ -1 +1 @@ -2024 Y / 05 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y / 05 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/05/page/2/index.html b/archives/2024/05/page/2/index.html index d898c8ac..5ab83406 100644 --- a/archives/2024/05/page/2/index.html +++ b/archives/2024/05/page/2/index.html @@ -1 +1 @@ -2024 Y / 05 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y / 05 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/06/index.html b/archives/2024/06/index.html index 7f8919c4..f1197336 100644 --- a/archives/2024/06/index.html +++ b/archives/2024/06/index.html @@ -1 +1 @@ -2024 Y / 06 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y / 06 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/07/index.html b/archives/2024/07/index.html index 377cbba3..eb00673a 100644 --- a/archives/2024/07/index.html +++ b/archives/2024/07/index.html @@ -1 +1 @@ -2024 Y / 07 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y / 07 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/08/index.html b/archives/2024/08/index.html index 3ed6fd54..ec039b61 100644 --- a/archives/2024/08/index.html +++ b/archives/2024/08/index.html @@ -1 +1 @@ -2024 Y / 08 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y / 08 M - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/index.html b/archives/2024/index.html index d74fc924..561d5857 100644 --- a/archives/2024/index.html +++ b/archives/2024/index.html @@ -1 +1 @@ -2024 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/page/10/index.html b/archives/2024/page/10/index.html index c22d2249..fbc788a2 100644 --- a/archives/2024/page/10/index.html +++ b/archives/2024/page/10/index.html @@ -1 +1 @@ -2024 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/page/11/index.html b/archives/2024/page/11/index.html index d56f5241..a9e35690 100644 --- a/archives/2024/page/11/index.html +++ b/archives/2024/page/11/index.html @@ -1 +1 @@ -2024 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/page/2/index.html b/archives/2024/page/2/index.html index 69d57d98..a9ec4b05 100644 --- a/archives/2024/page/2/index.html +++ b/archives/2024/page/2/index.html @@ -1 +1 @@ -2024 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/page/3/index.html b/archives/2024/page/3/index.html index fb98ad8e..62ee0c63 100644 --- a/archives/2024/page/3/index.html +++ b/archives/2024/page/3/index.html @@ -1 +1 @@ -2024 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/page/4/index.html b/archives/2024/page/4/index.html index f353d8a9..363aacde 100644 --- a/archives/2024/page/4/index.html +++ b/archives/2024/page/4/index.html @@ -1 +1 @@ -2024 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/page/5/index.html b/archives/2024/page/5/index.html index 0e31c511..859ed23a 100644 --- a/archives/2024/page/5/index.html +++ b/archives/2024/page/5/index.html @@ -1 +1 @@ -2024 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/page/6/index.html b/archives/2024/page/6/index.html index e01823e0..17af4f90 100644 --- a/archives/2024/page/6/index.html +++ b/archives/2024/page/6/index.html @@ -1 +1 @@ -2024 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/page/7/index.html b/archives/2024/page/7/index.html index 0c25ddd9..2b7a58b1 100644 --- a/archives/2024/page/7/index.html +++ b/archives/2024/page/7/index.html @@ -1 +1 @@ -2024 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/page/8/index.html b/archives/2024/page/8/index.html index 1e29c725..e8c23cbc 100644 --- a/archives/2024/page/8/index.html +++ b/archives/2024/page/8/index.html @@ -1 +1 @@ -2024 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/2024/page/9/index.html b/archives/2024/page/9/index.html index 614ece59..69e93d7d 100644 --- a/archives/2024/page/9/index.html +++ b/archives/2024/page/9/index.html @@ -1 +1 @@ -2024 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +2024 Y - Archive | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/archives/index.html b/archives/index.html index d30853ab..96d7dd17 100644 --- a/archives/index.html +++ b/archives/index.html @@ -1 +1 @@ -Archive | Balloon Party = 風船のパーティー = fuusen no party

Home / 128 posts in total. Good Keep on posting.

2024 Y/08 M ( 1 )

2024 Y/07 M ( 1 )

2024 Y/06 M ( 6 )

2024 Y/05 M ( 18 )

2024 Y/04 M ( 17 )

2024 Y/03 M ( 28 )

2024 Y/02 M ( 14 )

2024 Y/01 M ( 21 )

2023 Y/12 M ( 16 )

2023 Y/11 M ( 3 )

2023 Y/10 M ( 3 )

\ No newline at end of file +Archive | Balloon Party = 風船のパーティー = fuusen no party

Home / 128 posts in total. Good Keep on posting.

2024 Y/08 M ( 1 )

2024 Y/07 M ( 1 )

2024 Y/06 M ( 6 )

2024 Y/05 M ( 18 )

2024 Y/04 M ( 17 )

2024 Y/03 M ( 28 )

2024 Y/02 M ( 14 )

2024 Y/01 M ( 21 )

2023 Y/12 M ( 16 )

2023 Y/11 M ( 3 )

2023 Y/10 M ( 3 )

\ No newline at end of file diff --git a/assets/yatcpu/lab1/SingleCycle.html b/assets/yatcpu/lab1/SingleCycle.html index 282725b8..ab959c2f 100644 --- a/assets/yatcpu/lab1/SingleCycle.html +++ b/assets/yatcpu/lab1/SingleCycle.html @@ -1 +1 @@ -| Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +| Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/atom.xml b/atom.xml index 1a4a24ee..42187c4e 100644 --- a/atom.xml +++ b/atom.xml @@ -778,8 +778,8 @@ _1</annotation></semantics></math></span><span class= - + 2024-06-08T16:00:00.000Z @@ -1352,6 +1352,47 @@ d(v) 2024-06-02T16:00:00.000Z + + https://fuuzen.github.io/ie/de/shift-register/ + 移位寄存器 + + <h1 id="串行输入串行输出"><a class="anchor" href="#串行输入串行输出">#</a> 串行输入 / 串行输出</h1> +<p><img data-src="/assets/ie/de/shift-register/%E4%B8%B2%E8%A1%8C%E8%BE%93%E5%85%A5-%E4%B8%B2%E8%A1%8C%E8%BE%93%E5%87%BA.png" alt="串行输入:串行输出" /></p> +<h1 id="串行输入并行输出"><a class="anchor" href="#串行输入并行输出">#</a> 串行输入 / 并行输出</h1> +<p><img data-src="/assets/ie/de/shift-register/%E4%B8%B2%E8%A1%8C%E8%BE%93%E5%85%A5-%E5%B9%B6%E8%A1%8C%E8%BE%93%E5%87%BA.png" alt="串行输入:并行输出" /></p> +<h1 id="并行输入串行输出"><a class="anchor" href="#并行输入串行输出">#</a> 并行输入 / 串行输出</h1> +<p><img data-src="/assets/ie/de/shift-register/%E5%B9%B6%E8%A1%8C%E8%BE%93%E5%85%A5-%E4%B8%B2%E8%A1%8C%E8%BE%93%E5%87%BA.png" alt="并行输入:串行输出" /></p> +<h1 id="并行输入并行输出"><a class="anchor" href="#并行输入并行输出">#</a> 并行输入 / 并行输出</h1> +<p>最简单</p> +<h1 id="双向移位寄存器"><a class="anchor" href="#双向移位寄存器">#</a> 双向移位寄存器</h1> +<p><img data-src="/assets/ie/de/shift-register/4%E4%BD%8D%E5%8F%8C%E5%90%91%E4%BD%8D%E7%A7%BB.png" alt="4位双向位移" /></p> +<h2 id="74hc194"><a class="anchor" href="#74hc194">#</a> 74HC194</h2> +<p>通用 4 位双向移位寄存器</p> +<p><img data-src="/assets/ie/de/shift-register/74HC194.png" alt="74HC194" /></p> +<p><img data-src="/assets/ie/de/shift-register/74HC94%E6%B3%A2%E5%BD%A2%E5%9B%BE.png" alt="74HC94波形图" /></p> +<h1 id="移位寄存器计数器"><a class="anchor" href="#移位寄存器计数器">#</a> 移位寄存器计数器</h1> +<h2 id="约翰逊计数器"><a class="anchor" href="#约翰逊计数器">#</a> 约翰逊计数器</h2> +<p><img data-src="/assets/ie/de/shift-register/%E7%BA%A6%E7%BF%B0%E9%80%8A%E8%AE%A1%E6%95%B0%E5%99%A8.png" alt="约翰逊计数器" /></p> +<p><img data-src="/assets/ie/de/shift-register/%E7%BA%A6%E7%BF%B0%E9%80%8A%E8%AE%A1%E6%95%B0%E5%99%A8%E6%B3%A2%E5%BD%A2%E5%9B%BE.png" alt="约翰逊计数器波形图" /></p> +<p>一般来说,约翰逊计 数器将会产生模 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>2</mn><mi>n</mi></mrow><annotation encoding="application/x-tex">2n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">2</span><span class="mord mathnormal">n</span></span></span></span> ,其中 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span></span></span></span> 是计数器中级的个数</p> +<h2 id="环形计数器"><a class="anchor" href="#环形计数器">#</a> 环形计数器</h2> +<p><img data-src="/assets/ie/de/shift-register/%E7%8E%AF%E5%BD%A2%E8%AE%A1%E6%95%B0%E5%99%A8.png" alt="环形计数器" /></p> +<p><img data-src="/assets/ie/de/shift-register/%E7%8E%AF%E5%BD%A2%E8%AE%A1%E6%95%B0%E5%99%A8%E6%B3%A2%E5%BD%A2%E5%9B%BE.png" alt="环形计数器波形图" /></p> +<h1 id="移位寄存器应用"><a class="anchor" href="#移位寄存器应用">#</a> 移位寄存器应用</h1> +<h2 id="精确延时控制"><a class="anchor" href="#精确延时控制">#</a> 精确延时控制</h2> +<p>串行输入 / 串行输出移位寄存器可以用来提供从输入到输出的时间延迟,此时间延迟是寄存器中数 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span></span></span></span> 和时钟频率的函数</p> +<p>从一个数字系统到另一个数字系统的<mark>串行数据传送</mark>,常常用来减少传输线中的导线数</p> +<p><img data-src="/assets/ie/de/shift-register/8%E4%BD%8D%E4%B8%B2%E5%B9%B6%E8%BD%AC%E6%8D%A2%E5%99%A8.png" alt="8位串并转换器" /></p> +<p>当没有数据被传送时,串行数据线上就会有连续的 1 存在 ,0 位就是数据起始位,告诉串并转换器即将有 8 位数据序列到来:</p> +<p><img data-src="/assets/ie/de/shift-register/8%E4%BD%8D%E4%B8%B2%E5%B9%B6%E8%BD%AC%E6%8D%A2%E5%99%A8%E6%95%B0%E6%8D%AE%E4%B8%B2%E6%A0%BC%E5%BC%8F.png" alt="8位串并转换器数据串格式" /></p> +<p>详细波形图解释工作流程如下:</p> +<p><img data-src="/assets/ie/de/shift-register/8%E4%BD%8D%E4%B8%B2%E5%B9%B6%E8%BD%AC%E6%8D%A2%E5%99%A8%E6%B3%A2%E5%BD%A2%E5%9B%BE.png" alt="8位串并转换器波形图" /></p> +<script type="text&#x2F;javascript" src="https://unpkg.com/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.css"> + + + + 2024-05-30T16:00:00.000Z + https://fuuzen.github.io/ie/de/sequential-circuit/ 时序逻辑电路 @@ -1427,47 +1468,6 @@ t_L=0.7R_2C_1 <li>74HC161 十六进制计数器</li> <li>74HC190 十进制计数器</li> </ul> -<script type="text&#x2F;javascript" src="https://unpkg.com/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.css"> - - - - 2024-05-30T16:00:00.000Z - - - https://fuuzen.github.io/ie/de/shift-register/ - 移位寄存器 - - <h1 id="串行输入串行输出"><a class="anchor" href="#串行输入串行输出">#</a> 串行输入 / 串行输出</h1> -<p><img data-src="/assets/ie/de/shift-register/%E4%B8%B2%E8%A1%8C%E8%BE%93%E5%85%A5-%E4%B8%B2%E8%A1%8C%E8%BE%93%E5%87%BA.png" alt="串行输入:串行输出" /></p> -<h1 id="串行输入并行输出"><a class="anchor" href="#串行输入并行输出">#</a> 串行输入 / 并行输出</h1> -<p><img data-src="/assets/ie/de/shift-register/%E4%B8%B2%E8%A1%8C%E8%BE%93%E5%85%A5-%E5%B9%B6%E8%A1%8C%E8%BE%93%E5%87%BA.png" alt="串行输入:并行输出" /></p> -<h1 id="并行输入串行输出"><a class="anchor" href="#并行输入串行输出">#</a> 并行输入 / 串行输出</h1> -<p><img data-src="/assets/ie/de/shift-register/%E5%B9%B6%E8%A1%8C%E8%BE%93%E5%85%A5-%E4%B8%B2%E8%A1%8C%E8%BE%93%E5%87%BA.png" alt="并行输入:串行输出" /></p> -<h1 id="并行输入并行输出"><a class="anchor" href="#并行输入并行输出">#</a> 并行输入 / 并行输出</h1> -<p>最简单</p> -<h1 id="双向移位寄存器"><a class="anchor" href="#双向移位寄存器">#</a> 双向移位寄存器</h1> -<p><img data-src="/assets/ie/de/shift-register/4%E4%BD%8D%E5%8F%8C%E5%90%91%E4%BD%8D%E7%A7%BB.png" alt="4位双向位移" /></p> -<h2 id="74hc194"><a class="anchor" href="#74hc194">#</a> 74HC194</h2> -<p>通用 4 位双向移位寄存器</p> -<p><img data-src="/assets/ie/de/shift-register/74HC194.png" alt="74HC194" /></p> -<p><img data-src="/assets/ie/de/shift-register/74HC94%E6%B3%A2%E5%BD%A2%E5%9B%BE.png" alt="74HC94波形图" /></p> -<h1 id="移位寄存器计数器"><a class="anchor" href="#移位寄存器计数器">#</a> 移位寄存器计数器</h1> -<h2 id="约翰逊计数器"><a class="anchor" href="#约翰逊计数器">#</a> 约翰逊计数器</h2> -<p><img data-src="/assets/ie/de/shift-register/%E7%BA%A6%E7%BF%B0%E9%80%8A%E8%AE%A1%E6%95%B0%E5%99%A8.png" alt="约翰逊计数器" /></p> -<p><img data-src="/assets/ie/de/shift-register/%E7%BA%A6%E7%BF%B0%E9%80%8A%E8%AE%A1%E6%95%B0%E5%99%A8%E6%B3%A2%E5%BD%A2%E5%9B%BE.png" alt="约翰逊计数器波形图" /></p> -<p>一般来说,约翰逊计 数器将会产生模 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>2</mn><mi>n</mi></mrow><annotation encoding="application/x-tex">2n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">2</span><span class="mord mathnormal">n</span></span></span></span> ,其中 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span></span></span></span> 是计数器中级的个数</p> -<h2 id="环形计数器"><a class="anchor" href="#环形计数器">#</a> 环形计数器</h2> -<p><img data-src="/assets/ie/de/shift-register/%E7%8E%AF%E5%BD%A2%E8%AE%A1%E6%95%B0%E5%99%A8.png" alt="环形计数器" /></p> -<p><img data-src="/assets/ie/de/shift-register/%E7%8E%AF%E5%BD%A2%E8%AE%A1%E6%95%B0%E5%99%A8%E6%B3%A2%E5%BD%A2%E5%9B%BE.png" alt="环形计数器波形图" /></p> -<h1 id="移位寄存器应用"><a class="anchor" href="#移位寄存器应用">#</a> 移位寄存器应用</h1> -<h2 id="精确延时控制"><a class="anchor" href="#精确延时控制">#</a> 精确延时控制</h2> -<p>串行输入 / 串行输出移位寄存器可以用来提供从输入到输出的时间延迟,此时间延迟是寄存器中数 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span></span></span></span> 和时钟频率的函数</p> -<p>从一个数字系统到另一个数字系统的<mark>串行数据传送</mark>,常常用来减少传输线中的导线数</p> -<p><img data-src="/assets/ie/de/shift-register/8%E4%BD%8D%E4%B8%B2%E5%B9%B6%E8%BD%AC%E6%8D%A2%E5%99%A8.png" alt="8位串并转换器" /></p> -<p>当没有数据被传送时,串行数据线上就会有连续的 1 存在 ,0 位就是数据起始位,告诉串并转换器即将有 8 位数据序列到来:</p> -<p><img data-src="/assets/ie/de/shift-register/8%E4%BD%8D%E4%B8%B2%E5%B9%B6%E8%BD%AC%E6%8D%A2%E5%99%A8%E6%95%B0%E6%8D%AE%E4%B8%B2%E6%A0%BC%E5%BC%8F.png" alt="8位串并转换器数据串格式" /></p> -<p>详细波形图解释工作流程如下:</p> -<p><img data-src="/assets/ie/de/shift-register/8%E4%BD%8D%E4%B8%B2%E5%B9%B6%E8%BD%AC%E6%8D%A2%E5%99%A8%E6%B3%A2%E5%BD%A2%E5%9B%BE.png" alt="8位串并转换器波形图" /></p> <script type="text&#x2F;javascript" src="https://unpkg.com/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.css"> @@ -2392,8 +2392,8 @@ A\gamma(z)&amp;=By[-1]+Cy[-2]+D\chi(z)\\ - + 2024-05-23T16:00:00.000Z @@ -3161,384 +3161,185 @@ l(v),&amp;\text{others}\\ 2024-05-19T16:00:00.000Z - https://fuuzen.github.io/math/discrete-math/algebra/ring/ - - - <h1 id="环的相关定义"><a class="anchor" href="#环的相关定义">#</a> 环的相关定义</h1> -<p>设 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 是非空集合,如果在 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 上定义了两个二元运算 “<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>+</mo></mrow><annotation encoding="application/x-tex">+</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="mord">+</span></span></span></span>”(称为加法)和 “ <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⋅</mo></mrow><annotation encoding="application/x-tex">\cdot</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.44445em;vertical-align:0em;"></span><span class="mord">⋅</span></span></span></span> ”(称为乘法),且满足:</p> -<ul> -<li>(1) <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 关于加法 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>+</mo></mrow><annotation encoding="application/x-tex">+</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="mord">+</span></span></span></span> 构成交换群(即加群)</li> -<li>(2) <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 关于乘法 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⋅</mo></mrow><annotation encoding="application/x-tex">\cdot</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.44445em;vertical-align:0em;"></span><span class="mord">⋅</span></span></span></span> 构成<mark>半群</mark>,即乘法满足结合律:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>a</mi><mo separator="true">,</mo><mi>b</mi><mo separator="true">,</mo><mi>c</mi><mo>∈</mo><mi>R</mi><mo separator="true">,</mo><mtext>  </mtext><mi>a</mi><mo>⋅</mo><mo stretchy="false">(</mo><mi>b</mi><mo>⋅</mo><mi>c</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi>a</mi><mo>⋅</mo><mi>b</mi><mo stretchy="false">)</mo><mo>⋅</mo><mi>c</mi></mrow><annotation encoding="application/x-tex">\forall a,b,c\in R,\ \ a\cdot(b\cdot c)=(a\cdot b)\cdot c</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="mord">∀</span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">b</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.8777699999999999em;vertical-align:-0.19444em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mpunct">,</span><span class="mspace"> </span><span class="mspace"> </span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">c</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">b</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">c</span></span></span></span>;</li> -<li>(3) <mark>乘法 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⋅</mo></mrow><annotation encoding="application/x-tex">\cdot</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.44445em;vertical-align:0em;"></span><span class="mord">⋅</span></span></span></span> 对加法有左右分配律</mark>:</li> -</ul> -<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>a</mi><mo separator="true">,</mo><mi>b</mi><mo separator="true">,</mo><mi>c</mi><mo>∈</mo><mi>R</mi><mspace linebreak="newline"></mspace><mi>a</mi><mo>⋅</mo><mo stretchy="false">(</mo><mi>b</mi><mo>+</mo><mi>c</mi><mo stretchy="false">)</mo><mo>=</mo><mi>a</mi><mo>⋅</mo><mi>b</mi><mo>+</mo><mi>a</mi><mo>⋅</mo><mi>c</mi><mspace linebreak="newline"></mspace><mo stretchy="false">(</mo><mi>b</mi><mo>+</mo><mi>c</mi><mo stretchy="false">)</mo><mo>⋅</mo><mi>a</mi><mo>=</mo><mi>b</mi><mo>⋅</mo><mi>a</mi><mo>+</mo><mi>c</mi><mo>⋅</mo><mi>a</mi></mrow><annotation encoding="application/x-tex">\forall a,b,c\in R\\ -a\cdot(b+c)=a\cdot b+a\cdot c\\ -(b+c)\cdot a=b\cdot a+c\cdot a -</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="mord">∀</span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">b</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:0.44445em;vertical-align:0em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">c</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.44445em;vertical-align:0em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.77777em;vertical-align:-0.08333em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.44445em;vertical-align:0em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">c</span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">c</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.44445em;vertical-align:0em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">a</span></span></span></span></span></p> -<p>则称代数 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>R</mi><mo separator="true">,</mo><mo>+</mo><mo separator="true">,</mo><mtext> </mtext><mo>⋅</mo><mtext> </mtext><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(R,+,\ \cdot\ )</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">+</span><span class="mpunct">,</span><span class="mspace"> </span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">⋅</span><span class="mspace"> </span><span class="mclose">)</span></span></span></span> 是环(ring)。在通过上下文能明确运算时,通常直接称 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 为环。</p> -<div class="note primary"> -<p>有教材要求环乘法必须有单位元,也有教材要求环乘法必须满足交换律等</p> -</div> -<p>对环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>R</mi><mo separator="true">,</mo><mo>+</mo><mo separator="true">,</mo><mtext> </mtext><mo>⋅</mo><mtext> </mtext><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(R,+,\ \cdot\ )</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">+</span><span class="mpunct">,</span><span class="mspace"> </span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">⋅</span><span class="mspace"> </span><span class="mclose">)</span></span></span></span> ,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>R</mi><mtext> </mtext><mo separator="true">,</mo><mo>+</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(R\ ,+)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace"> </span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">+</span><span class="mclose">)</span></span></span></span> 是交换群,称为环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的加法群,其单位元通常用 0 表示,称为环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的零元,元素 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">a</span></span></span></span> 的加法逆元记为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>−</mo><mi>a</mi></mrow><annotation encoding="application/x-tex">-a</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="mord">−</span><span class="mord mathnormal">a</span></span></span></span> ,称为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">a</span></span></span></span> 的负元。</p> -<p>通过负元引入环的减法,即 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo>−</mo><mi>b</mi></mrow><annotation encoding="application/x-tex">a-b</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal">b</span></span></span></span> 定义为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo>+</mo><mo stretchy="false">(</mo><mo>−</mo><mi>b</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">a+(-b)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">−</span><span class="mord mathnormal">b</span><span class="mclose">)</span></span></span></span>。</p> -<ul> -<li>环乘法是否满足交换律 -<ul> -<li>若环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的乘法也满足交换律,则称为交换环 (commutative ring)</li> -</ul> -</li> -<li>是否有单位元 -<ul> -<li>若环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的乘法有单位元,则称为有单位元环,环乘法的单位元通常记为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">e</span></span></span></span> 或 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn></mrow><annotation encoding="application/x-tex">1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">1</span></span></span></span> ,并称为环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的单位元</li> -</ul> -</li> -<li>环乘法当环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 有单位元 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">e</span></span></span></span> 时,考虑环的元素是否有逆元 + https://fuuzen.github.io/math/discrete-math/graph/euler_hamilton/ + 欧拉图与哈密顿图 + + <h1 id="欧拉图"><a class="anchor" href="#欧拉图">#</a> 欧拉图</h1> +<h2 id="定义"><a class="anchor" href="#定义">#</a> 定义</h2> +<p>欧拉图存在<mark>欧拉闭迹</mark>,半欧拉图只存在<mark>欧拉迹</mark></p> +<p>若能遍历完所有的边但是没法回到起始点,称为非欧拉图但是有欧拉迹</p> +<h3 id="欧拉图-2"><a class="anchor" href="#欧拉图-2">#</a> 欧拉图</h3> +<p>假定 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 是一个连通图,且是欧拉图,则下列命题等价:</p> <ul> -<li>若对 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo>∈</mo><mi>R</mi></mrow><annotation encoding="application/x-tex">a\in R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> ,存在 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>b</mi><mo>∈</mo><mi>R</mi></mrow><annotation encoding="application/x-tex">b\in R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.73354em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> ,使得 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mi>b</mi><mo>=</mo><mi>b</mi><mi>a</mi><mo>=</mo><mi>e</mi></mrow><annotation encoding="application/x-tex">ab=ba=e</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal">a</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal">b</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">e</span></span></span></span> ,则称 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">a</span></span></span></span> 是可逆元,或称为环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的<mark>单位</mark> (unit),并称 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>b</mi></mrow><annotation encoding="application/x-tex">b</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal">b</span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">a</span></span></span></span> 的逆元。当然这时 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>b</mi></mrow><annotation encoding="application/x-tex">b</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal">b</span></span></span></span> 也是可逆元,且 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">a</span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>b</mi></mrow><annotation encoding="application/x-tex">b</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal">b</span></span></span></span> 的逆元</li> -<li>所有可逆元关于环乘法构成群,称为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的<mark>单位群</mark> (group of units),记为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>U</mi><mo stretchy="false">(</mo><mi>R</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">U(R)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">U</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mclose">)</span></span></span></span>。</li> +<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 是欧拉图</li> +<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 的每个点的度数是偶数</li> +<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 的边集能划分为边不重的圈的并</li> +<li>(<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 存在欧拉闭迹)</li> </ul> -</li> -<li>环乘法是否有零因子 +<h3 id="半欧拉图"><a class="anchor" href="#半欧拉图">#</a> 半欧拉图</h3> +<p>假定 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 是一个连通图,且是半欧拉图,则下列命题等价:</p> <ul> -<li>对环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的两个非零元素 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo separator="true">,</mo><mi>b</mi></mrow><annotation encoding="application/x-tex">a,b</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">b</span></span></span></span> ,若 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo>⋅</mo><mi>b</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">a\cdot b=0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.44445em;vertical-align:0em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">0</span></span></span></span> ,则称 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">a</span></span></span></span> 是<mark>左零因子</mark> (left zero-divisor),b 是<mark>右零因子</mark> (right zero-divisor)。左零因子和右零因子统称为<mark>零因子</mark></li> -<li>若环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的所有非零元素都不是左零因子或右零因子,则称 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 为无零因子环。</li> -</ul> -</li> +<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 是半欧拉图</li> +<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 有且仅有 2 个点的度数是奇数</li> +<li>(<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 存在欧拉迹)</li> </ul> -<p>当集合 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 只有一个元素 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn></mrow><annotation encoding="application/x-tex">0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">0</span></span></span></span> ,定义 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的加法运算和乘法运算:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn><mo>+</mo><mn>0</mn><mo>=</mo><mn>0</mn><mo separator="true">,</mo><mtext> </mtext><mn>0</mn><mo>⋅</mo><mn>0</mn><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">0+0=0,\ 0\cdot 0=0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.72777em;vertical-align:-0.08333em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.8388800000000001em;vertical-align:-0.19444em;"></span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace"> </span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">0</span></span></span></span>,则 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mo stretchy="false">{</mo><mn>0</mn><mo stretchy="false">}</mo><mo separator="true">,</mo><mo>+</mo><mo separator="true">,</mo><mtext> </mtext><mo>⋅</mo><mtext> </mtext><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(\{0\},+,\ \cdot\ )</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mopen">{</span><span class="mord">0</span><span class="mclose">}</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">+</span><span class="mpunct">,</span><span class="mspace"> </span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">⋅</span><span class="mspace"> </span><span class="mclose">)</span></span></span></span> 构成环,这个环称为<mark>零环</mark>。在这个环中,<mark>零元也是单位元</mark>,而<mark>零元也是可逆元</mark>。</p> -<p>零环过于简单,通常在对环进行讨论时都将零环排除在外。因此在提到环时,总是默认环至少有两个元素,这时零元不可能是单位元,也不可能是可逆元。</p> -<h2 id="整环"><a class="anchor" href="#整环">#</a> 整环</h2> +<h3 id="小结论"><a class="anchor" href="#小结论">#</a> 小结论💡</h3> <ul> -<li>有单位元</li> -<li>无零因子</li> -<li>(乘法) 可交换</li> -</ul> -<p>的环称为<mark>整环</mark> (integral <mark>domain</mark>)</p> -<hr /> -<p>证明一个环是整环:</p> -\forall a,b\in R,\ \ ab=0\Rightarrow a=0\or b=0 - -<h2 id="除环"><a class="anchor" href="#除环">#</a> 除环</h2> -<ul> -<li>有单位元</li> -<li>至少有两个元素</li> -<li>每个非零元都可逆 (乘法)</li> -<li>(无零因子,可逆元都不是零因子)</li> -</ul> -<p>的环称为<mark>除环</mark> (division ring)</p> -<h2 id="域"><a class="anchor" href="#域">#</a> 域</h2> -<p>交换除环称为<mark>域</mark> (field) (比较常用),也即需满足:</p> -<ul> -<li>有单位元</li> -<li>至少有两个元素</li> -<li>每个非零元都可逆 (乘法)</li> -<li>(乘法) 可交换</li> -<li>(无零因子,可逆元都不是零因子)</li> +<li>当 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span></span></span></span> 满足什么条件时,完全图 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>K</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">K_n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">K</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.07153em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 是欧拉图? <strong><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span></span></span></span> 为奇数</strong></li> +<li>当 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span></span></span></span> 满足什么条件时,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span></span></span></span> 方体 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>Q</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">Q_n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8777699999999999em;vertical-align:-0.19444em;"></span><span class="mord"><span class="mord mathnormal">Q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 是欧拉图? <strong><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span></span></span></span> 为偶数</strong></li> +<li>若完全二部图 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>K</mi><mrow><mi>a</mi><mo separator="true">,</mo><mi>b</mi></mrow></msub></mrow><annotation encoding="application/x-tex">K_{a,b}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.969438em;vertical-align:-0.286108em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">K</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361079999999999em;"><span style="top:-2.5500000000000003em;margin-left:-0.07153em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">b</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span></span></span></span> 为欧拉图,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">a</span></span></span></span> 和 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>b</mi></mrow><annotation encoding="application/x-tex">b</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal">b</span></span></span></span> 需满足什么条件? <strong><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo separator="true">,</mo><mi>b</mi></mrow><annotation encoding="application/x-tex">a,b</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">b</span></span></span></span> 均为偶数</strong></li> +<li>假设图 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 恰好有两个连通分支,并且每个连通分支都是欧拉图,若要将 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 变为欧拉图,最少需要添加几条边? <strong>最少需要添加 2 条边</strong></li> +<li>欧拉图、半欧拉图是否存在割边? <strong>欧拉图不存在割边,半欧拉图存在割边</strong></li> </ul> +<h2 id="fleury算法"><a class="anchor" href="#fleury算法">#</a> Fleury 算法</h2> <blockquote> -<p>可逆元都不是零因子(为什么?),因此域都是整环!</p> +<p>弗勒里算法解决了在欧拉图中求出一条具体欧拉环游的方法,核心思想是尽可能避割边行走</p> </blockquote> -<p>非交换除环也称<mark>体</mark> (skew field) (比较少用)</p> -<h1 id="常用环"><a class="anchor" href="#常用环">#</a> 常用环</h1> -<h2 id="整数环及其子环"><a class="anchor" href="#整数环及其子环">#</a> 整数环及其子环</h2> -<ul> -<li> -<p>整数集 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">Z</mi></mrow><annotation encoding="application/x-tex">\mathbb Z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68889em;vertical-align:0em;"></span><span class="mord mathbb">Z</span></span></span></span> 关于普通加法 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>+</mo></mrow><annotation encoding="application/x-tex">+</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="mord">+</span></span></span></span> 和普通乘法 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⋅</mo></mrow><annotation encoding="application/x-tex">\cdot</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.44445em;vertical-align:0em;"></span><span class="mord">⋅</span></span></span></span> 构成环,称为整数环</p> -<ul> -<li> -<p>整数环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">Z</mi></mrow><annotation encoding="application/x-tex">\mathbb Z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68889em;vertical-align:0em;"></span><span class="mord mathbb">Z</span></span></span></span> 是<mark>交换环</mark>,(乘法) 零元是 0,单位元是 1</p> -</li> -<li> -<p>只有 1 和 -1 是可逆元,因此整数环的单位群是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mo stretchy="false">{</mo><mn>1</mn><mo separator="true">,</mo><mo>−</mo><mn>1</mn><mo stretchy="false">}</mo><mo separator="true">,</mo><mtext> </mtext><mo>⋅</mo><mtext> </mtext><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(\{1, -1\},\ \cdot\ )</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mopen">{</span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">−</span><span class="mord">1</span><span class="mclose">}</span><span class="mpunct">,</span><span class="mspace"> </span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">⋅</span><span class="mspace"> </span><span class="mclose">)</span></span></span></span>;</p> -</li> -<li> -<p>整数环的每个非零整数都不是零因子,因此<mark>整数环是整环</mark></p> -</li> -</ul> -</li> -<li> -<p>固定整数 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi></mrow><annotation encoding="application/x-tex">d</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal">d</span></span></span></span> ,集合 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi mathvariant="double-struck">Z</mi><mo>=</mo><mo stretchy="false">{</mo><mi>k</mi><mi>d</mi><mi mathvariant="normal">∣</mi><mi>k</mi><mo>∈</mo><mi mathvariant="double-struck">Z</mi><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">d\mathbb Z=\{kd|k\in \mathbb Z\}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal">d</span><span class="mord mathbb">Z</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mord mathnormal">d</span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathbb">Z</span><span class="mclose">}</span></span></span></span> 关于普通加法 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>+</mo></mrow><annotation encoding="application/x-tex">+</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="mord">+</span></span></span></span> 和普通乘法 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⋅</mo></mrow><annotation encoding="application/x-tex">\cdot</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.44445em;vertical-align:0em;"></span><span class="mord">⋅</span></span></span></span> 也构成交换环</p> -<ul> -<li> -<p>当 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mo mathvariant="normal">≠</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">d≠1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">d</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel"><span class="mrel"><span class="mord vbox"><span class="thinbox"><span class="rlap"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="inner"><span class="mrel"></span></span><span class="fix"></span></span></span></span></span><span class="mrel">=</span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">1</span></span></span></span> 时,环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi mathvariant="double-struck">Z</mi></mrow><annotation encoding="application/x-tex">d\mathbb Z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal">d</span><span class="mord mathbb">Z</span></span></span></span> 没有单位元。显然环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi mathvariant="double-struck">Z</mi></mrow><annotation encoding="application/x-tex">d\mathbb Z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal">d</span><span class="mord mathbb">Z</span></span></span></span> 也是无零因子环</p> -</li> -<li> -<p>具体来说,所有偶数构成的集合 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>2</mn><mi mathvariant="double-struck">Z</mi></mrow><annotation encoding="application/x-tex">2\mathbb Z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68889em;vertical-align:0em;"></span><span class="mord">2</span><span class="mord mathbb">Z</span></span></span></span> 关于普通加法和普通乘法构成无单位元、无零因子的交换环。</p> -</li> -</ul> -</li> -</ul> -<h2 id="模m剩余类环及其子环"><a class="anchor" href="#模m剩余类环及其子环">#</a> 模 m 剩余类环及其子环</h2> -<p>固定整数 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi><mo>≥</mo><mn>2</mn></mrow><annotation encoding="application/x-tex">m≥2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719400000000001em;vertical-align:-0.13597em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">2</span></span></span></span> ,模 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">m</span></span></span></span> 剩余类 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="double-struck">Z</mi><mi>m</mi></msub><mo>=</mo><mo stretchy="false">{</mo><mover accent="true"><mn>0</mn><mo stretchy="true">‾</mo></mover><mo separator="true">,</mo><mover accent="true"><mn>1</mn><mo stretchy="true">‾</mo></mover><mo separator="true">,</mo><mo>⋯</mo><mtext> </mtext><mo separator="true">,</mo><mover accent="true"><mrow><mi>m</mi><mo>−</mo><mn>1</mn></mrow><mo stretchy="true">‾</mo></mover><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">\mathbb Z_m=\{\overline{0},\overline{1},\cdots,\overline{m-1}\}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83889em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathbb">Z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.09444em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8444400000000001em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.76444em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8444400000000001em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-3.76444em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord overline"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8444400000000001em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mord">1</span></span></span><span style="top:-3.76444em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.08333em;"><span></span></span></span></span></span><span class="mclose">}</span></span></span></span> 关于模 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">m</span></span></span></span> 加 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mo>⊕</mo><mi>m</mi></msub></mrow><annotation encoding="application/x-tex">⊕_m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.73333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mbin">⊕</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 和模 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">m</span></span></span></span> 乘 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mo>⊗</mo><mi>m</mi></msub></mrow><annotation encoding="application/x-tex">⊗_m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.73333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mbin">⊗</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 构成环,称为模 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">m</span></span></span></span> 剩余类环 (residue class ring)</p> +<h3 id="算法流程"><a class="anchor" href="#算法流程">#</a> 算法流程</h3> <ul> -<li> -<p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mn>0</mn><mo stretchy="true">‾</mo></mover></mrow><annotation encoding="application/x-tex">\overline 0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8444400000000001em;vertical-align:0em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8444400000000001em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord">0</span></span><span style="top:-3.76444em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span></span></span></span> 表示整除 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">m</span></span></span></span> 余 0 的所有整数构成的集合,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="double-struck">Z</mi><mi>m</mi></msub></mrow><annotation encoding="application/x-tex">\mathbb Z_m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83889em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathbb">Z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 的元素是集合</p> -</li> -<li> -<p>模 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">m</span></span></span></span> 剩余类环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">Z</mi></mrow><annotation encoding="application/x-tex">\mathbb Z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68889em;vertical-align:0em;"></span><span class="mord mathbb">Z</span></span></span></span> 是有单位元交换环,零元是 0,有单位元 1</p> -</li> -<li> -<p>对于 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo>∈</mo><msub><mi mathvariant="double-struck">Z</mi><mi>m</mi></msub></mrow><annotation encoding="application/x-tex">a\in \mathbb Z_m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.83889em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathbb">Z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> ,如果 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">a</span></span></span></span> 与 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">m</span></span></span></span> 互质,则 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">a</span></span></span></span> 关于模 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">m</span></span></span></span> 乘有逆元,因此单位群是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>U</mi><mo stretchy="false">(</mo><mi>m</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">U(m)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">U</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span> 群</p> -</li> -<li> -<p>当 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">m</span></span></span></span> 是质数 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi></mrow><annotation encoding="application/x-tex">p</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">p</span></span></span></span> 时,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="double-struck">Z</mi><mi>p</mi></msub><mo>=</mo><mo stretchy="false">{</mo><mn>0</mn><mo stretchy="false">}</mo><mo>∪</mo><mi>U</mi><mo stretchy="false">(</mo><mi>p</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathbb Z_p=\{0\}\cup U(p)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.974998em;vertical-align:-0.286108em;"></span><span class="mord"><span class="mord mathbb">Z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.15139200000000003em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">p</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord">0</span><span class="mclose">}</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">U</span><span class="mopen">(</span><span class="mord mathnormal">p</span><span class="mclose">)</span></span></span></span> ,关于 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mo>⊕</mo><mi>p</mi></msub></mrow><annotation encoding="application/x-tex">⊕_p</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8694379999999999em;vertical-align:-0.286108em;"></span><span class="mord"><span class="mbin">⊕</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.15139200000000003em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">p</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span></span></span></span> 和 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mo>⊗</mo><mi>p</mi></msub></mrow><annotation encoding="application/x-tex">⊗_p</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8694379999999999em;vertical-align:-0.286108em;"></span><span class="mord"><span class="mbin">⊗</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.15139200000000003em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">p</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span></span></span></span> 构成有单位元、每个非零元都可逆的交换环,也即这时 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="double-struck">Z</mi><mi>p</mi></msub></mrow><annotation encoding="application/x-tex">\mathbb Z_p</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.974998em;vertical-align:-0.286108em;"></span><span class="mord"><span class="mord mathbb">Z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.15139200000000003em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">p</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span></span></span></span> 是域</p> -</li> -<li> -<p>当 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">m</span></span></span></span> 不是质数时,若 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi><mo>=</mo><mi>k</mi><mi>d</mi><mo stretchy="false">(</mo><mn>2</mn><mo>≤</mo><mi>k</mi><mo>≤</mo><mi>m</mi><mo separator="true">,</mo><mn>2</mn><mo>≤</mo><mi>k</mi><mo>≤</mo><mi>m</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">m=kd(2≤k≤m,2≤k≤m)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mord mathnormal">d</span><span class="mopen">(</span><span class="mord">2</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.83041em;vertical-align:-0.13597em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.8388800000000001em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">m</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.83041em;vertical-align:-0.13597em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span> ,则 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi></mrow><annotation encoding="application/x-tex">k</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span> 和 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi></mrow><annotation encoding="application/x-tex">d</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal">d</span></span></span></span> 都是模 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">m</span></span></span></span> 剩余类环的零因子,这时就不是无零因子环,当然也不是整环</p> -</li> -</ul> -<h2 id="有理数域"><a class="anchor" href="#有理数域">#</a> 有理数域</h2> -<p>有理数集 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>Q</mi></mrow><annotation encoding="application/x-tex">Q</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8777699999999999em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">Q</span></span></span></span> 关于普通加法 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>+</mo></mrow><annotation encoding="application/x-tex">+</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="mord">+</span></span></span></span> 和普通乘法 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⋅</mo></mrow><annotation encoding="application/x-tex">\cdot</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.44445em;vertical-align:0em;"></span><span class="mord">⋅</span></span></span></span> 构成环</p> +<li>(1)任意选取一个顶点 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>v</mi><mn>0</mn></msub></mrow><annotation encoding="application/x-tex">v_0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.58056em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> ,置 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>w</mi><mn>0</mn></msub><mo>=</mo><msub><mi>v</mi><mn>0</mn></msub></mrow><annotation encoding="application/x-tex">w_0=v_0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.58056em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.02691em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.58056em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>;</li> +<li>(2)假设迹 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>w</mi><mi>i</mi></msub><mo>=</mo><msub><mi>v</mi><mn>0</mn></msub><msub><mi>e</mi><mn>1</mn></msub><msub><mi>v</mi><mn>1</mn></msub><mo>⋯</mo><msub><mi>e</mi><mi>i</mi></msub><msub><mi>v</mi><mi>i</mi></msub></mrow><annotation encoding="application/x-tex">w_i=v_0e_1v_1\cdots e_iv_i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.58056em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.31166399999999994em;"><span style="top:-2.5500000000000003em;margin-left:-0.02691em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.58056em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.31166399999999994em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.31166399999999994em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 已经确定,按如下方法从 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>E</mi><mo>−</mo><mo stretchy="false">{</mo><msub><mi>e</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>e</mi><mn>2</mn></msub><mo separator="true">,</mo><mo>⋯</mo><mtext> </mtext><mo separator="true">,</mo><msub><mi>e</mi><mi>i</mi></msub><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">E-\{e_1,e_2,\cdots,e_{i}\}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.76666em;vertical-align:-0.08333em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.31166399999999994em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">}</span></span></span></span> 选一个 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mrow><mi>i</mi><mo>+</mo><mn>1</mn></mrow></msub></mrow><annotation encoding="application/x-tex">e_{i+1}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.638891em;vertical-align:-0.208331em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.311664em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.208331em;"><span></span></span></span></span></span></span></span></span></span>: <ul> -<li> -<p>有单位元 1,是交换环,而且每个非零有理数 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>r</mi></mrow><annotation encoding="application/x-tex">r</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span></span></span></span> 都有逆 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mi mathvariant="normal">/</mi><mi>r</mi></mrow><annotation encoding="application/x-tex">1/r</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span></span></span></span>;</p> -</li> -<li> -<p>单位群是所有非零有理数集 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi mathvariant="double-struck">Q</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">\mathbb Q^*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.85556em;vertical-align:-0.16667em;"></span><span class="mord"><span class="mord mathbb">Q</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.688696em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span> 关于普通乘法构成的群 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><msup><mi mathvariant="double-struck">Q</mi><mo>∗</mo></msup><mo separator="true">,</mo><mtext> </mtext><mo>⋅</mo><mtext> </mtext><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(\mathbb Q^*,\ \cdot\ )</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathbb">Q</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.688696em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace"> </span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">⋅</span><span class="mspace"> </span><span class="mclose">)</span></span></span></span></p> -</li> -<li> -<p>因此通常直接称有理数集 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">Q</mi></mrow><annotation encoding="application/x-tex">\mathbb Q</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.85556em;vertical-align:-0.16667em;"></span><span class="mord mathbb">Q</span></span></span></span> 为有理数域</p> -</li> +<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mrow><mi>i</mi><mo>+</mo><mn>1</mn></mrow></msub></mrow><annotation encoding="application/x-tex">e_{i+1}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.638891em;vertical-align:-0.208331em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.311664em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.208331em;"><span></span></span></span></span></span></span></span></span></span> 与 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>v</mi><mi>i</mi></msub></mrow><annotation encoding="application/x-tex">v_i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.58056em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.31166399999999994em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 相关联;</li> +<li>除非没有其他边可选,否则 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mrow><mi>i</mi><mo>+</mo><mn>1</mn></mrow></msub></mrow><annotation encoding="application/x-tex">e_{i+1}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.638891em;vertical-align:-0.208331em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.311664em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.208331em;"><span></span></span></span></span></span></span></span></span></span> 不能是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>G</mi><mi>i</mi></msub><mo>=</mo><mi>G</mi><mo>−</mo><mo stretchy="false">{</mo><msub><mi>e</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>e</mi><mn>2</mn></msub><mo separator="true">,</mo><mo>⋯</mo><mtext> </mtext><mo separator="true">,</mo><msub><mi>e</mi><mi>i</mi></msub><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">G_i=G-\{e_1,e_2,\cdots,e_{i}\}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.31166399999999994em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.76666em;vertical-align:-0.08333em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.31166399999999994em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">}</span></span></span></span> 的<mark>割边</mark>;</li> </ul> -<p>实数集 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">R</mi></mrow><annotation encoding="application/x-tex">\mathbb R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68889em;vertical-align:0em;"></span><span class="mord mathbb">R</span></span></span></span> 和复数集 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">C</mi></mrow><annotation encoding="application/x-tex">\mathbb C</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68889em;vertical-align:0em;"></span><span class="mord mathbb">C</span></span></span></span> 关于普通加法 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>+</mo></mrow><annotation encoding="application/x-tex">+</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="mord">+</span></span></span></span> 和普通乘法 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⋅</mo></mrow><annotation encoding="application/x-tex">\cdot</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.44445em;vertical-align:0em;"></span><span class="mord">⋅</span></span></span></span> 也都构成域,分别称为实数域 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">R</mi></mrow><annotation encoding="application/x-tex">\mathbb R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68889em;vertical-align:0em;"></span><span class="mord mathbb">R</span></span></span></span> 和复数域 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">C</mi></mrow><annotation encoding="application/x-tex">\mathbb C</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68889em;vertical-align:0em;"></span><span class="mord mathbb">C</span></span></span></span>:</p> -<ul> -<li> -<p>单位群分别是所有非零实数集 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi mathvariant="double-struck">R</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">\mathbb R^*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68889em;vertical-align:0em;"></span><span class="mord"><span class="mord mathbb">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.688696em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span> 和非零复数集 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi mathvariant="double-struck">C</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">\mathbb C^*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68889em;vertical-align:0em;"></span><span class="mord"><span class="mord mathbb">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.688696em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span> 关于普通乘法构成的群</p> -</li> -<li> -<p>复数域 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">C</mi></mrow><annotation encoding="application/x-tex">\mathbb C</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68889em;vertical-align:0em;"></span><span class="mord mathbb">C</span></span></span></span> 的零元是实数 0,单位元是实数 1,而复数乘法的逆为:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>a</mi><mo>+</mo><mi>b</mi><mi>i</mi><msup><mo stretchy="false">)</mo><mrow><mo>−</mo><mn>1</mn></mrow></msup><mo>=</mo><mfrac><mrow><mi>a</mi><mo>−</mo><mi>b</mi><mi>i</mi></mrow><mrow><msup><mi>a</mi><mn>2</mn></msup><mo>+</mo><msup><mi>b</mi><mn>2</mn></msup></mrow></mfrac></mrow><annotation encoding="application/x-tex">(a+bi)^{-1}=\frac{a-bi}{a^2+b^2}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1.064108em;vertical-align:-0.25em;"></span><span class="mord mathnormal">b</span><span class="mord mathnormal">i</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141079999999999em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.283439em;vertical-align:-0.403331em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8801079999999999em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7463142857142857em;"><span style="top:-2.786em;margin-right:0.07142857142857144em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mbin mtight">+</span><span class="mord mtight"><span class="mord mathnormal mtight">b</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7463142857142857em;"><span style="top:-2.786em;margin-right:0.07142857142857144em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mbin mtight">−</span><span class="mord mathnormal mtight">b</span><span class="mord mathnormal mtight">i</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.403331em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span>。</p> </li> +<li>(3)若(2)无法进行则算法停止</li> </ul> -<h2 id="高斯整环"><a class="anchor" href="#高斯整环">#</a> 高斯整环</h2> -<p><img data-src="/assets/math/discrete-math/algebra/ring/%E9%AB%98%E6%96%AF%E6%95%B4%E7%8E%AF.png" alt="高斯整环" /></p> -<h3 id="类高斯整环"><a class="anchor" href="#类高斯整环">#</a> 类高斯整环</h3> +<p>利用 Fluery 算法可以求一个半欧拉图的欧拉迹,半欧拉图有且仅有 2 个奇度顶点 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>u</mi><mo separator="true">,</mo><mi>v</mi></mrow><annotation encoding="application/x-tex">u,v</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">u</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span></span></span></span> ,在这 2 个点之间增加一条边 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">m</span></span></span></span> ,就可以得到一个欧拉图,然后从其中一个奇度顶点,例如 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>u</mi></mrow><annotation encoding="application/x-tex">u</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">u</span></span></span></span> ,开始求欧拉环游。得到的欧拉环游去掉 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">m</span></span></span></span> 就是从 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>u</mi></mrow><annotation encoding="application/x-tex">u</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">u</span></span></span></span> 到 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi></mrow><annotation encoding="application/x-tex">v</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span></span></span></span> 的欧拉迹。</p> +<h2 id="欧拉图中扩展欧拉环游充要条件"><a class="anchor" href="#欧拉图中扩展欧拉环游充要条件">#</a> 欧拉图中扩展欧拉环游充要条件</h2> +<p>设 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 是非平凡的欧拉图,且 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi><mo>∈</mo><mi>V</mi><mo stretchy="false">(</mo><mi>G</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">v\in V(G)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="mopen">(</span><span class="mord mathnormal">G</span><span class="mclose">)</span></span></span></span> ,则 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 的每条具有起点 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi></mrow><annotation encoding="application/x-tex">v</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span></span></span></span> 的迹都能扩展成 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 的欧拉环游当且仅当 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi><mo>−</mo><mi>v</mi></mrow><annotation encoding="application/x-tex">G-v</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.76666em;vertical-align:-0.08333em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span></span></span></span> 是森林。</p> +<h2 id="中国邮递员问题"><a class="anchor" href="#中国邮递员问题">#</a> 中国邮递员问题</h2> <blockquote> -<p>看起来和高斯整环很像,我乱起的名字,不是很重要</p> +<p>1962,中国数学家管梅谷提出并解决了 “中国邮路问题”</p> </blockquote> -<p><img data-src="/assets/math/discrete-math/algebra/ring/%E7%B1%BB%E9%AB%98%E6%96%AF%E6%95%B4%E7%8E%AF1.png" alt="类高斯整环1" /></p> -<p><img data-src="/assets/math/discrete-math/algebra/ring/%E7%B1%BB%E9%AB%98%E6%96%AF%E6%95%B4%E7%8E%AF2.png" alt="类高斯整环2" /></p> -<h2 id="全矩阵环"><a class="anchor" href="#全矩阵环">#</a> 全矩阵环</h2> -<p><img data-src="/assets/math/discrete-math/algebra/ring/%E5%85%A8%E7%9F%A9%E9%98%B5%E7%8E%AF.png" alt="全矩阵环" /></p> -<h2 id="多项式环"><a class="anchor" href="#多项式环">#</a> 多项式环</h2> -<p><img data-src="/assets/math/discrete-math/algebra/ring/%E5%A4%9A%E9%A1%B9%E5%BC%8F%E7%8E%AF1.png" alt="多项式环1" /><img data-src="/assets/math/discrete-math/algebra/ring/%E5%A4%9A%E9%A1%B9%E5%BC%8F%E7%8E%AF2.png" alt="多项式环2" /></p> +<p>即最优环游问题:在一个连通具有非负权的赋权图 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 中找到一条包含每条边(允许重复)且边权之和最小的闭途径,称之为<mark>最优 (欧拉) 环游</mark></p> +<ul> +<li>若图 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 是一个欧拉图,则找出 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 的欧拉环游即可</li> +<li>对一般图,其解法为:添加重复边以使 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 成为欧拉图 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>G</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">G^*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.688696em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.688696em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span> ,并使添加的重复边的边权之和为最小,再求 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>G</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">G^*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.688696em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.688696em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span> 的欧拉回路</li> +</ul> <blockquote> -<p>例子</p> +<p>管梅谷的结论:</p> </blockquote> -<p><img data-src="/assets/math/discrete-math/algebra/ring/%E5%A4%9A%E9%A1%B9%E5%BC%8F%E7%8E%AF%E4%B8%BE%E4%BE%8B.png" alt="多项式环举例" /></p> -<h1 id="理想"><a class="anchor" href="#理想">#</a> 理想</h1> -<h2 id="定义"><a class="anchor" href="#定义">#</a> 定义</h2> -<p>设 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 是环,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi></mrow><annotation encoding="application/x-tex">I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的非空子集。若 I 满足:</p> -<ol> -<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><msub><mi>r</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>r</mi><mn>2</mn></msub><mo>∈</mo><mi>I</mi></mrow><annotation encoding="application/x-tex">\forall r_1,r_2\in I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="mord">∀</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.02778em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.02778em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span>,有 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>r</mi><mn>1</mn></msub><mo>−</mo><msub><mi>r</mi><mn>2</mn></msub><mo>∈</mo><mi>I</mi></mrow><annotation encoding="application/x-tex">r_1-r_2\in I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.73333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.02778em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.6891em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.02778em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span>;</li> -<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>r</mi><mo>∈</mo><mi>I</mi><mo separator="true">,</mo><mtext> </mtext><mi mathvariant="normal">∀</mi><mi>s</mi><mo>∈</mo><mi>R</mi><mo separator="true">,</mo><mtext>  </mtext><mi>r</mi><mi>s</mi><mo separator="true">,</mo><mi>s</mi><mi>r</mi><mo>∈</mo><mi>I</mi></mrow><annotation encoding="application/x-tex">\forall r\in I,\ \forall s\in R,\ \ rs,sr\in I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.73354em;vertical-align:-0.0391em;"></span><span class="mord">∀</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mpunct">,</span><span class="mspace"> </span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">∀</span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.8777699999999999em;vertical-align:-0.19444em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mpunct">,</span><span class="mspace"> </span><span class="mspace"> </span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal">s</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">s</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span>;</li> -</ol> -<p>则称 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi></mrow><annotation encoding="application/x-tex">I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span> 为环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的<mark>理想</mark> (ideal),记为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi><mtext>⊲</mtext><mi>R</mi></mrow><annotation encoding="application/x-tex">I⊲R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord">⊲</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span>,若 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi></mrow><annotation encoding="application/x-tex">I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的真子集,则称 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi></mrow><annotation encoding="application/x-tex">I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的<mark>真理想</mark> (proper ideal)。</p> -<p>理想是子环:显然如果 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi></mrow><annotation encoding="application/x-tex">I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的理想,则 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi></mrow><annotation encoding="application/x-tex">I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span> 必定是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的子环;</p> +<p>假定 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>G</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">G^*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.688696em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.688696em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span> 是在图 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 中添加一些重复边得到的欧拉图,则 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>G</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">G^*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.688696em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.688696em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span> 具有<mark>最小权</mark>值的<mark>充要条件</mark>是:</p> +<ul> +<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 的每一条边最多被添加一次</li> +<li>对于 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>G</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">G^*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.688696em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.688696em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span> 的每个圈来说,该圈新添加的边的总权值不超过该圈总权值的一半</li> +</ul> +<hr /> +<p><strong>证明:必要性</strong></p> +<p>若 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 中某条边在 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>G</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">G^*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.688696em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.688696em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span> 中被添加的次数超过 1,则去掉其中两条重复的边,我们将得到一个总权值更小,且以 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 为生成子图的欧拉图</p> +<p>上述与 “ <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>G</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">G^*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.688696em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.688696em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span> 总权值最小” 相矛盾,因此每条边最多被添加一次</p> +<p>假定在 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>G</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">G^*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.688696em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.688696em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span> 中存在某个圈使得该圈新添加的边的总权值大于该圈权值的一半,不妨设为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></p> +<p>那么在 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>G</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">G^*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.688696em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.688696em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span> 中,将 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span> 上新添加的边全部去掉,然后将原圈未添加新边的边都添加一条重复边</p> +<p>这样的操作使得该圈所有点的度数不变或改变 2,相应的图仍然是欧拉图,但是权值更小,这与 “ <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>G</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">G^*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.688696em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.688696em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span> 总权值最小” 相矛盾</p> <div class="note primary"> -<p>⚠️ 当然子环不一定是理想 ⚠️</p> +<p>这个必要性的证明给出了最优欧拉环游的构造方法</p> </div> -<p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的单个零元构成的集合 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">{</mo><mn>0</mn><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">\{0\}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord">0</span><span class="mclose">}</span></span></span></span>(称为<mark>零理想</mark>)和 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 本身都是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的理想,这两个理想称为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的<mark>平凡理想</mark>。因此 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的非平凡理想就是非零真理想</p> -<h2 id="常用理想"><a class="anchor" href="#常用理想">#</a> 常用理想</h2> -<p>整数环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>Z</mi></mrow><annotation encoding="application/x-tex">Z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span></span></span></span> 的所有理想是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>Z</mi><mo>=</mo><mo stretchy="false">{</mo><mi>d</mi><mi>z</mi><mi mathvariant="normal">∣</mi><mi>z</mi><mo>∈</mo><mi>Z</mi><mo stretchy="false">}</mo><mo separator="true">,</mo><mtext> </mtext><mi>d</mi><mo>=</mo><mn>0</mn><mo separator="true">,</mo><mn>1</mn><mo separator="true">,</mo><mo>⋯</mo></mrow><annotation encoding="application/x-tex">dZ=\{dz|z\in Z\},\ d=0,1,\cdots</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal">d</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span><span class="mclose">}</span><span class="mpunct">,</span><span class="mspace"> </span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">d</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.8388800000000001em;vertical-align:-0.19444em;"></span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner">⋯</span></span></span></span>;</p> -<p>模 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">m</span></span></span></span> 剩余类环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>Z</mi><mi>m</mi></msub></mrow><annotation encoding="application/x-tex">Z_m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.07153em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 的所有理想是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><msub><mi>Z</mi><mi>m</mi></msub><mo>=</mo><mo stretchy="false">{</mo><mi>d</mi><mi>z</mi><mi mathvariant="normal">∣</mi><mi>z</mi><mo>∈</mo><msub><mi>Z</mi><mi>m</mi></msub><mo stretchy="false">}</mo><mo separator="true">,</mo><mtext> </mtext><mi>d</mi><mo>=</mo><mn>0</mn><mo separator="true">,</mo><mn>1</mn><mo separator="true">,</mo><mo>⋯</mo><mtext> </mtext><mo separator="true">,</mo><mi>m</mi><mo>−</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">dZ_m=\{dz|z\in Z_m\},\ d=0, 1, \cdots, m-1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.84444em;vertical-align:-0.15em;"></span><span class="mord mathnormal">d</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.07153em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal">d</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.07153em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">}</span><span class="mpunct">,</span><span class="mspace"> </span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">d</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.8388800000000001em;vertical-align:-0.19444em;"></span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">1</span></span></span></span>;</p> +<h2 id="半欧拉图最优欧拉环游"><a class="anchor" href="#半欧拉图最优欧拉环游">#</a> 半欧拉图最优欧拉环游</h2> +<p>一个非负权的边赋权图 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 中只有两个奇度顶点 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>u</mi></mrow><annotation encoding="application/x-tex">u</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">u</span></span></span></span> 与 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi></mrow><annotation encoding="application/x-tex">v</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span></span></span></span> , 设计一个求其最优欧拉环游的算法如下:</p> +<ul> +<li>(1) 在 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>u</mi></mrow><annotation encoding="application/x-tex">u</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">u</span></span></span></span> 与 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi></mrow><annotation encoding="application/x-tex">v</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span></span></span></span> 间求出一条最短路 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi></mrow><annotation encoding="application/x-tex">P</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span></span>; (最短路算法)</li> +<li>(2) 在最短路 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi></mrow><annotation encoding="application/x-tex">P</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span></span> 上,给每条边添加一条重复边得 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 的欧拉图 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>G</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">G^*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.688696em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.688696em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span>;</li> +<li>(3) 在 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 的欧拉图 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>G</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">G^*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.688696em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.688696em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span> 中用 Fleury 算法求出一条欧拉环游;</li> +</ul> <hr /> -<p><mark>证明</mark></p> -<p>理想是子环,而 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>Z</mi></mrow><annotation encoding="application/x-tex">Z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span></span></span></span> 的每个子环都具有形式 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>Z</mi></mrow><annotation encoding="application/x-tex">dZ</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span></span></span></span> ,而且对任意子环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>Z</mi></mrow><annotation encoding="application/x-tex">dZ</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span></span></span></span> ,对任意 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>z</mi><mo>∈</mo><mi>d</mi><mi>Z</mi></mrow><annotation encoding="application/x-tex">dz\in dZ</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.73354em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span></span></span></span> ,以及 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>s</mi><mo>∈</mo><mi>Z</mi></mrow><annotation encoding="application/x-tex">s\in Z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span></span></span></span> ,显然有 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>z</mi><mi>s</mi><mo separator="true">,</mo><mi>s</mi><mi>d</mi><mi>z</mi><mo>∈</mo><mi>d</mi><mi>Z</mi></mrow><annotation encoding="application/x-tex">dzs, sdz\in dZ</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mord mathnormal">s</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">s</span><span class="mord mathnormal">d</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span></span></span></span> ,因此每个子环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>Z</mi></mrow><annotation encoding="application/x-tex">dZ</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span></span></span></span> 都是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>Z</mi></mrow><annotation encoding="application/x-tex">Z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span></span></span></span> 的理想</p> -<p>类似可得到模 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">m</span></span></span></span> 剩余类环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>Z</mi><mi>m</mi></msub></mrow><annotation encoding="application/x-tex">Z_m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.07153em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 的所有理想是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><msub><mi>Z</mi><mi>m</mi></msub><mo separator="true">,</mo><mi>d</mi><mo>=</mo><mn>0</mn><mo separator="true">,</mo><mn>1</mn><mo separator="true">,</mo><mo>⋯</mo><mtext> </mtext><mo separator="true">,</mo><mi>m</mi><mo>−</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">dZ_m, d=0, 1, \cdots, m-1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">d</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.07153em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">d</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.8388800000000001em;vertical-align:-0.19444em;"></span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">1</span></span></span></span>。</p> -<h2 id="运算"><a class="anchor" href="#运算">#</a> 运算</h2> -<h3 id="和"><a class="anchor" href="#和">#</a> 和</h3> -<p>设 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 是环,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi><mo separator="true">,</mo><mi>J</mi></mrow><annotation encoding="application/x-tex">I,J</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8777699999999999em;vertical-align:-0.19444em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal" style="margin-right:0.09618em;">J</span></span></span></span> 都是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的理想,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi><mo>+</mo><mi>J</mi></mrow><annotation encoding="application/x-tex">I+J</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.76666em;vertical-align:-0.08333em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.09618em;">J</span></span></span></span> 称为理想 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi></mrow><annotation encoding="application/x-tex">I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span> 和 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>J</mi></mrow><annotation encoding="application/x-tex">J</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.09618em;">J</span></span></span></span> 的<mark>和</mark>:</p> -<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>I</mi><mo>+</mo><mi>J</mi><mo>=</mo><mo stretchy="false">{</mo><mi>a</mi><mo>+</mo><mi>b</mi><mo>∈</mo><mi>R</mi><mi mathvariant="normal">∣</mi><mi>a</mi><mo>∈</mo><mi>I</mi><mo separator="true">,</mo><mi>b</mi><mo>∈</mo><mi>J</mi><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">I+J=\{a+b\in R|a\in I, b\in J\} -</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.76666em;vertical-align:-0.08333em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.09618em;">J</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.73354em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mord">∣</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.09618em;">J</span><span class="mclose">}</span></span></span></span></span></p> -<h3 id="交"><a class="anchor" href="#交">#</a> 交</h3> -<p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi><mo>∩</mo><mi>J</mi></mrow><annotation encoding="application/x-tex">I\cap J</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">∩</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.09618em;">J</span></span></span></span> 称为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi></mrow><annotation encoding="application/x-tex">I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span> 和 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>J</mi></mrow><annotation encoding="application/x-tex">J</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.09618em;">J</span></span></span></span> 的<mark>交</mark>:</p> -<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>I</mi><mo>∩</mo><mi>J</mi><mo>=</mo><mo stretchy="false">{</mo><mi>x</mi><mo>∈</mo><mi>R</mi><mi mathvariant="normal">∣</mi><mi>x</mi><mo>∈</mo><mi>I</mi><mo separator="true">,</mo><mi>x</mi><mo>∈</mo><mi>J</mi><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">I\cap J=\{x\in R|x\in I,x\in J\} -</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">∩</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.09618em;">J</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mord">∣</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.8777699999999999em;vertical-align:-0.19444em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.09618em;">J</span><span class="mclose">}</span></span></span></span></span></p> -<h3 id="积"><a class="anchor" href="#积">#</a> 积</h3> -<p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi><mi>J</mi></mrow><annotation encoding="application/x-tex">IJ</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord mathnormal" style="margin-right:0.09618em;">J</span></span></span></span> 称为理想 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi></mrow><annotation encoding="application/x-tex">I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span> 和 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>J</mi></mrow><annotation encoding="application/x-tex">J</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.09618em;">J</span></span></span></span> 的<mark>积</mark>:</p> -<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>I</mi><mi>J</mi><mo>=</mo><mo stretchy="false">{</mo><msub><mi>a</mi><mn>1</mn></msub><msub><mi>b</mi><mn>1</mn></msub><mo>+</mo><msub><mi>a</mi><mn>2</mn></msub><msub><mi>b</mi><mn>2</mn></msub><mo>+</mo><mo>⋯</mo><mo>+</mo><msub><mi>a</mi><mi>n</mi></msub><msub><mi>b</mi><mi>n</mi></msub><mi mathvariant="normal">∣</mi><mi>n</mi><mo>∈</mo><msup><mi mathvariant="double-struck">N</mi><mo>∗</mo></msup><mo separator="true">,</mo><msub><mi>a</mi><mi>k</mi></msub><mo>∈</mo><mi>I</mi><mo separator="true">,</mo><msub><mi>b</mi><mi>k</mi></msub><mo>∈</mo><mi>J</mi><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">IJ=\{a_1b_1+a_2b_2+\cdots+a_nb_n|n\in\mathbb N^*,a_k\in I,b_k\in J\} -</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord mathnormal" style="margin-right:0.09618em;">J</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.84444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">∣</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.933136em;vertical-align:-0.19444em;"></span><span class="mord"><span class="mord mathbb">N</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.738696em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.09618em;">J</span><span class="mclose">}</span></span></span></span></span></p> -<h3 id="和交积保持理想"><a class="anchor" href="#和交积保持理想">#</a> 和交积保持理想</h3> -<p>若 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi></mrow><annotation encoding="application/x-tex">I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span> 和 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>J</mi></mrow><annotation encoding="application/x-tex">J</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.09618em;">J</span></span></span></span> 都是环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的理想,则 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi><mo>+</mo><mi>J</mi></mrow><annotation encoding="application/x-tex">I+J</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.76666em;vertical-align:-0.08333em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.09618em;">J</span></span></span></span> , <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi><mo>∩</mo><mi>J</mi></mrow><annotation encoding="application/x-tex">I\cap J</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">∩</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.09618em;">J</span></span></span></span> ,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi><mi>J</mi></mrow><annotation encoding="application/x-tex">IJ</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord mathnormal" style="margin-right:0.09618em;">J</span></span></span></span> 也是环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的理想</p> -<p>环的任意有限多个理想的和仍是理想,而任意有限或无限多个理想的交仍是理想</p> -<h2 id="主理想"><a class="anchor" href="#主理想">#</a> 主理想</h2> -<h3 id="定义-2"><a class="anchor" href="#定义-2">#</a> 定义</h3> -<p>设 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 是环,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">a</span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的元素,记所有包含 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">a</span></span></span></span> 的理想构成的集合为:</p> -<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo>∑</mo><mo>=</mo><mo stretchy="false">{</mo><mi>I</mi><mo>⊲</mo><mi>R</mi><mi mathvariant="normal">∣</mi><mi>a</mi><mo>∈</mo><mi>I</mi><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">\sum=\{I\lhd R|a\in I\} -</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.6000100000000002em;vertical-align:-0.55001em;"></span><span class="mop op-symbol large-op" style="position:relative;top:-0.000004999999999977245em;">∑</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin amsrm">⊲</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mord">∣</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mclose">}</span></span></span></span></span></p> -<p>至少有 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi><mo>∈</mo><mo>∑</mo></mrow><annotation encoding="application/x-tex">R\in\sum</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.72243em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.00001em;vertical-align:-0.25001em;"></span><span class="mop op-symbol small-op" style="position:relative;top:-0.0000050000000000050004em;">∑</span></span></span></span> ,所以 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>∑</mo></mrow><annotation encoding="application/x-tex">\sum</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.00001em;vertical-align:-0.25001em;"></span><span class="mop op-symbol small-op" style="position:relative;top:-0.0000050000000000050004em;">∑</span></span></span></span> 非空。令:</p> -<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo stretchy="false">⟨</mo><mi>a</mi><mo stretchy="false">⟩</mo><mo>=</mo><munder><mo>⋂</mo><mrow><mi>I</mi><mo>∈</mo><mo>∑</mo></mrow></munder><mi>I</mi></mrow><annotation encoding="application/x-tex">\langle a\rangle=\bigcap_{I\in\sum}I -</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord mathnormal">a</span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:2.5660170000000004em;vertical-align:-1.516012em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.0500050000000003em;"><span style="top:-1.808995em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.07847em;">I</span><span class="mrel mtight">∈</span><span class="mop op-symbol small-op mtight" style="position:relative;top:-0.0000050000000000050004em;">∑</span></span></span></span><span style="top:-3.050005em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">⋂</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.516012em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span></span></p> -<p>则 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">⟨</mo><mi>a</mi><mo stretchy="false">⟩</mo></mrow><annotation encoding="application/x-tex">\langle a\rangle</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord mathnormal">a</span><span class="mclose">⟩</span></span></span></span> 是理想,而且是包含 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">a</span></span></span></span> 的最小理想。这个理想称由 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">a</span></span></span></span> 生成的<mark>主理想</mark>(principal ideal),<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">a</span></span></span></span> 为其<mark>生成元</mark>。</p> -<h3 id="定理结论"><a class="anchor" href="#定理结论">#</a> 定理结论</h3> -<p>环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的由 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">a</span></span></span></span> 生成的主理想满足:</p> -<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo stretchy="false">⟨</mo><mi>a</mi><mo stretchy="false">⟩</mo><mo>=</mo><mo fence="false">{</mo><mo fence="false">(</mo><munderover><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>n</mi></munderover><msub><mi>x</mi><mi>i</mi></msub><mi>a</mi><msub><mi>y</mi><mi>i</mi></msub><mo fence="false">)</mo><mo>+</mo><mi>x</mi><mi>a</mi><mo>+</mo><mi>a</mi><mi>y</mi><mo>+</mo><mi>m</mi><mi>a</mi><mo fence="false">∣</mo><msub><mi>x</mi><mi>i</mi></msub><mo separator="true">,</mo><msub><mi>y</mi><mi>i</mi></msub><mo separator="true">,</mo><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo>∈</mo><mi>R</mi><mo separator="true">,</mo><mi>n</mi><mo>∈</mo><msup><mi mathvariant="double-struck">Z</mi><mo>+</mo></msup><mo separator="true">,</mo><mi>m</mi><mo>∈</mo><mi mathvariant="double-struck">Z</mi><mo fence="false">}</mo></mrow><annotation encoding="application/x-tex">\langle a\rangle=\big\{ -\big(\sum_{i=1}^{n}x_iay_i\big) -+xa+ay+ma\big|x_i,y_i,x,y\in R,n\in\mathbb Z^+,m\in\mathbb Z -\big\} -</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord mathnormal">a</span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:2.929066em;vertical-align:-1.277669em;"></span><span class="mord"><span class="delimsizing size1">{</span></span><span class="mord"><span class="delimsizing size1">(</span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6513970000000002em;"><span style="top:-1.872331em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.050005em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3000050000000005em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.277669em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.31166399999999994em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal">a</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.31166399999999994em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="delimsizing size1">)</span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="mord mathnormal">x</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.7777700000000001em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1.21799em;vertical-align:-0.35000999999999993em;"></span><span class="mord mathnormal">m</span><span class="mord mathnormal">a</span><span class="mord"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8679800000000001em;"><span style="top:-2.2559899999999997em;"><span class="pstrut" style="height:2.606em;"></span><span class="delimsizinginner delim-size1"><span>∣</span></span></span><span style="top:-2.26698em;"><span class="pstrut" style="height:2.606em;"></span><span class="delimsizinginner delim-size1"><span>∣</span></span></span><span style="top:-2.86798em;"><span class="pstrut" style="height:2.606em;"></span><span class="delimsizinginner delim-size1"><span>∣</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.35000999999999993em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.31166399999999994em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.31166399999999994em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.8777699999999999em;vertical-align:-0.19444em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.015771em;vertical-align:-0.19444em;"></span><span class="mord"><span class="mord mathbb">Z</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.821331em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">+</span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.20001em;vertical-align:-0.35001em;"></span><span class="mord mathbb">Z</span><span class="mord"><span class="delimsizing size1">}</span></span></span></span></span></span></p> -<p>若 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> <mark>有单位元</mark>,则:</p> -\langle a\rangle=\big\{ -\big(\sum_{i=1}^{n}x_iay_i\big) -\big|x_i,y_i\in R -\big\}\ - -<p>若 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 是<mark>交换环</mark>,则:</p> -<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo stretchy="false">⟨</mo><mi>a</mi><mo stretchy="false">⟩</mo><mo>=</mo><mo fence="false">{</mo><mi>x</mi><mi>a</mi><mo>+</mo><mi>m</mi><mi>a</mi><mo fence="false">∣</mo><mi>x</mi><mo>∈</mo><mi>R</mi><mo separator="true">,</mo><mi>m</mi><mo>∈</mo><mi mathvariant="double-struck">Z</mi><mo fence="false">}</mo></mrow><annotation encoding="application/x-tex">\langle a\rangle=\big\{ -xa+ma\big|x\in R,m\in\mathbb Z -\big\} -</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord mathnormal">a</span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.20001em;vertical-align:-0.35001em;"></span><span class="mord"><span class="delimsizing size1">{</span></span><span class="mord mathnormal">x</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1.21799em;vertical-align:-0.35000999999999993em;"></span><span class="mord mathnormal">m</span><span class="mord mathnormal">a</span><span class="mord"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8679800000000001em;"><span style="top:-2.2559899999999997em;"><span class="pstrut" style="height:2.606em;"></span><span class="delimsizinginner delim-size1"><span>∣</span></span></span><span style="top:-2.26698em;"><span class="pstrut" style="height:2.606em;"></span><span class="delimsizinginner delim-size1"><span>∣</span></span></span><span style="top:-2.86798em;"><span class="pstrut" style="height:2.606em;"></span><span class="delimsizinginner delim-size1"><span>∣</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.35000999999999993em;"><span></span></span></span></span></span></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.8777699999999999em;vertical-align:-0.19444em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.20001em;vertical-align:-0.35001em;"></span><span class="mord mathbb">Z</span><span class="mord"><span class="delimsizing size1">}</span></span></span></span></span></span></p> -<p>⭐️若 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 是<mark>有单位元的交换环</mark>,则:</p> -<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo stretchy="false">⟨</mo><mi>a</mi><mo stretchy="false">⟩</mo><mo>=</mo><mi>a</mi><mi>R</mi><mo>=</mo><mo fence="false">{</mo><mi>a</mi><mi>r</mi><mo fence="false">∣</mo><mi>r</mi><mo>∈</mo><mi>R</mi><mo fence="false">}</mo></mrow><annotation encoding="application/x-tex">\langle a\rangle=aR=\big\{ -ar\big|r\in R -\big\} -</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord mathnormal">a</span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.2179900000000001em;vertical-align:-0.35001em;"></span><span class="mord"><span class="delimsizing size1">{</span></span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8679800000000001em;"><span style="top:-2.2559899999999997em;"><span class="pstrut" style="height:2.606em;"></span><span class="delimsizinginner delim-size1"><span>∣</span></span></span><span style="top:-2.26698em;"><span class="pstrut" style="height:2.606em;"></span><span class="delimsizinginner delim-size1"><span>∣</span></span></span><span style="top:-2.86798em;"><span class="pstrut" style="height:2.606em;"></span><span class="delimsizinginner delim-size1"><span>∣</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.35000999999999993em;"><span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.20001em;vertical-align:-0.35001em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mord"><span class="delimsizing size1">}</span></span></span></span></span></span></p> -<h3 id="常用理想的主理想"><a class="anchor" href="#常用理想的主理想">#</a> 常用理想的主理想</h3> -<ul> -<li>整数环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">Z</mi></mrow><annotation encoding="application/x-tex">\mathbb Z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68889em;vertical-align:0em;"></span><span class="mord mathbb">Z</span></span></span></span> 的每个理想 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi mathvariant="double-struck">Z</mi></mrow><annotation encoding="application/x-tex">d\mathbb Z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal">d</span><span class="mord mathbb">Z</span></span></span></span> 都是主理想,即是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">⟨</mo><mi>d</mi><mo stretchy="false">⟩</mo></mrow><annotation encoding="application/x-tex">\langle d\rangle</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord mathnormal">d</span><span class="mclose">⟩</span></span></span></span> ;</li> -<li>模 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">m</span></span></span></span> 剩余类环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="double-struck">Z</mi><mi>m</mi></msub></mrow><annotation encoding="application/x-tex">\mathbb Z_m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83889em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathbb">Z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 的每个理想 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><msub><mi mathvariant="double-struck">Z</mi><mi>m</mi></msub></mrow><annotation encoding="application/x-tex">d\mathbb Z_m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.84444em;vertical-align:-0.15em;"></span><span class="mord mathnormal">d</span><span class="mord"><span class="mord mathbb">Z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 也都是主理想,即也是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">⟨</mo><mi>d</mi><mo stretchy="false">⟩</mo></mrow><annotation encoding="application/x-tex">\langle d\rangle</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord mathnormal">d</span><span class="mclose">⟩</span></span></span></span> ;</li> -</ul> -<p>设 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 是环,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>a</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>a</mi><mn>2</mn></msub><mo separator="true">,</mo><mo>⋯</mo><mtext> </mtext><mo separator="true">,</mo><msub><mi>a</mi><mi>n</mi></msub><mo>∈</mo><mi>R</mi></mrow><annotation encoding="application/x-tex">a_1,a_2,\cdots,a_n\in R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7335400000000001em;vertical-align:-0.19444em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span>,则:</p> -<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo stretchy="false">⟨</mo><msub><mi>a</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>a</mi><mn>2</mn></msub><mo separator="true">,</mo><mo>⋯</mo><mtext> </mtext><mo separator="true">,</mo><msub><mi>a</mi><mi>n</mi></msub><mo stretchy="false">⟩</mo><mo>=</mo><mo stretchy="false">⟨</mo><msub><mi>a</mi><mn>1</mn></msub><mo stretchy="false">⟩</mo><mo>+</mo><mo stretchy="false">⟨</mo><msub><mi>a</mi><mn>2</mn></msub><mo stretchy="false">⟩</mo><mo>+</mo><mo>⋯</mo><mo>+</mo><mo stretchy="false">⟨</mo><msub><mi>a</mi><mi>n</mi></msub><mo stretchy="false">⟩</mo></mrow><annotation encoding="application/x-tex">\langle a_1,a_2,\cdots,a_n\rangle=\langle a_1\rangle+\langle a_2\rangle+\cdots+\langle a_n\rangle -</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩</span></span></span></span></span></p> -<p>也是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的理想,并且是包含 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>a</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>a</mi><mn>2</mn></msub><mo separator="true">,</mo><mo>⋯</mo><mtext> </mtext><mo separator="true">,</mo><msub><mi>a</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">a_1,a_2,\cdots,a_n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 的最小理想!称为由 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>a</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>a</mi><mn>2</mn></msub><mo separator="true">,</mo><mo>⋯</mo><mtext> </mtext><mo separator="true">,</mo><msub><mi>a</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">a_1,a_2,\cdots,a_n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 生成的理想。</p> -<p>整数环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">Z</mi></mrow><annotation encoding="application/x-tex">\mathbb Z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68889em;vertical-align:0em;"></span><span class="mord mathbb">Z</span></span></span></span> 由 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>a</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>a</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">a_1,a_2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 生成的理想是<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">⟨</mo><mi>gcd</mi><mo>⁡</mo><mo stretchy="false">(</mo><msub><mi>a</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>a</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo stretchy="false">⟩</mo></mrow><annotation encoding="application/x-tex">\langle\gcd(a_1,a_2)\rangle</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mop"><span style="margin-right:0.01389em;">g</span>cd</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mclose">⟩</span></span></span></span>;</p> -<h1 id="商环"><a class="anchor" href="#商环">#</a> 商环</h1> +<p><strong>证明</strong></p> +<p>设 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>u</mi></mrow><annotation encoding="application/x-tex">u</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">u</span></span></span></span> 与 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi></mrow><annotation encoding="application/x-tex">v</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 的两个奇度顶点,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>G</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">G^*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.688696em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.688696em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 的任意一个欧拉图。</p> +<p>考虑 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>G</mi><mo>∗</mo></msup><mo stretchy="false">[</mo><msup><mi>E</mi><mo>∗</mo></msup><mo>−</mo><mi>E</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">G^*[E^*-E]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.688696em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.688696em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mclose">]</span></span></span></span>, 显然它只有两个奇数顶点 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>u</mi></mrow><annotation encoding="application/x-tex">u</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">u</span></span></span></span> 与 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi></mrow><annotation encoding="application/x-tex">v</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span></span></span></span>, 当然它们必须在 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>G</mi><mo>∗</mo></msup><mo stretchy="false">[</mo><msup><mi>E</mi><mo>∗</mo></msup><mo>−</mo><mi>E</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">G^*[E^*-E]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.688696em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.688696em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mclose">]</span></span></span></span> 的同一个分支中,因此,存在 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>u</mi><mo separator="true">,</mo><mi>v</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(u,v)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">u</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">)</span></span></span></span> 路 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>P</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">P^*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.688696em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.688696em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span>:</p> +<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><munder><mo>∑</mo><mrow><mi>e</mi><mo>∈</mo><msup><mi>E</mi><mo>∗</mo></msup><mo>−</mo><mi>E</mi></mrow></munder><mi>w</mi><mo stretchy="false">(</mo><mi>e</mi><mo stretchy="false">)</mo><mo>≥</mo><mi>w</mi><mo stretchy="false">(</mo><msup><mi>P</mi><mo>∗</mo></msup><mo stretchy="false">)</mo><mo>≥</mo><mi>w</mi><mo stretchy="false">(</mo><mi>P</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\sum_{e\in E^*-E}w(e)\geq w(P^*)\geq w(P) +</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:2.402672em;vertical-align:-1.352667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.050005em;"><span style="top:-1.8556639999999998em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">e</span><span class="mrel mtight">∈</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6183428571428571em;"><span style="top:-2.786em;margin-right:0.07142857142857144em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mathnormal mtight" style="margin-right:0.05764em;">E</span></span></span></span><span style="top:-3.0500049999999996em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.352667em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mopen">(</span><span class="mord mathnormal">e</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.738696em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mclose">)</span></span></span></span></span></p> +<h1 id="哈密顿图"><a class="anchor" href="#哈密顿图">#</a> 哈密顿图</h1> +<h2 id="定义-2"><a class="anchor" href="#定义-2">#</a> 定义</h2> +<h3 id="哈姆顿图"><a class="anchor" href="#哈姆顿图">#</a> 哈姆顿图</h3> +<p>如果经过图 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 的每个顶点恰好一次后能够回到出发点,称这样的图为<mark>哈密尔顿图</mark>,简称 <mark><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span> 图</mark>。所经过的闭途径是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 的一个生成圈,称为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 的<mark>哈密尔顿圈</mark>,简称 <mark><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span> 圈</mark></p> +<h3 id="半哈密顿图"><a class="anchor" href="#半哈密顿图">#</a> 半哈密顿图</h3> <blockquote> -<p>环关于理想的商环</p> +<p>不需回到出发点</p> </blockquote> -<h2 id="定义-3"><a class="anchor" href="#定义-3">#</a> 定义</h2> -<p>设 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 是环,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi></mrow><annotation encoding="application/x-tex">I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>R</mi><mo separator="true">,</mo><mo>+</mo><mo separator="true">,</mo><mtext> </mtext><mo>⋅</mo><mtext> </mtext><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(R,+,\ \cdot\ )</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">+</span><span class="mpunct">,</span><span class="mspace"> </span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">⋅</span><span class="mspace"> </span><span class="mclose">)</span></span></span></span> 的一个理想,则 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>I</mi><mo separator="true">,</mo><mo>+</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(I,+)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">+</span><span class="mclose">)</span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>R</mi><mo separator="true">,</mo><mo>+</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(R,+)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">+</span><span class="mclose">)</span></span></span></span> 的正规子群,它所有(关于加群)的陪集构成集合 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi><mi mathvariant="normal">/</mi><mi>I</mi><mtext>=</mtext><mo stretchy="false">{</mo><mi>x</mi><mo>+</mo><mi>I</mi><mi mathvariant="normal">∣</mi><mi>x</mi><mo>∈</mo><mi>R</mi><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">R/I=\{x+I|x\in R\}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord cjk_fallback">=</span><span class="mopen">{</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord">∣</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mclose">}</span></span></span></span> 、记<mark>陪集 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>+</mo><mi>I</mi></mrow><annotation encoding="application/x-tex">x+I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span> 为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi>x</mi><mo stretchy="true">‾</mo></mover></mrow><annotation encoding="application/x-tex">\overline x</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.63056em;vertical-align:0em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.63056em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal">x</span></span><span style="top:-3.55056em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span></span></span></span></mark> 。</p> -<h3 id="运算的定义"><a class="anchor" href="#运算的定义">#</a> 运算的定义</h3> -<h4 id="加法"><a class="anchor" href="#加法">#</a> 加法</h4> -<p>在集合 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi><mi mathvariant="normal">/</mi><mi>I</mi></mrow><annotation encoding="application/x-tex">R/I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span> 上可定义加法 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>+</mo></mrow><annotation encoding="application/x-tex">+</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="mord">+</span></span></span></span>:</p> -<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi mathvariant="normal">∀</mi><mover accent="true"><mi>x</mi><mo stretchy="true">‾</mo></mover><mo separator="true">,</mo><mover accent="true"><mi>y</mi><mo stretchy="true">‾</mo></mover><mo>∈</mo><mi>R</mi><mi mathvariant="normal">/</mi><mi>I</mi><mo separator="true">,</mo><mspace linebreak="newline"></mspace><mover accent="true"><mi>x</mi><mo stretchy="true">‾</mo></mover><mo>+</mo><mover accent="true"><mi>y</mi><mo stretchy="true">‾</mo></mover><mo>=</mo><mover accent="true"><mrow><mi>x</mi><mo>+</mo><mi>y</mi></mrow><mo stretchy="true">‾</mo></mover><mo>⟺</mo><mo stretchy="false">(</mo><mi>x</mi><mo>+</mo><mi>I</mi><mo stretchy="false">)</mo><mo>+</mo><mo stretchy="false">(</mo><mi>y</mi><mo>+</mo><mi>I</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi>x</mi><mo>+</mo><mi>y</mi><mo stretchy="false">)</mo><mo>+</mo><mi>I</mi></mrow><annotation encoding="application/x-tex">\forall \overline x,\overline y\in R/I,\\ -\overline{x}+\overline{y}=\overline{x+y}\Longleftrightarrow (x+I)+(y+I)=(x+y)+I -</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="mord">∀</span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.63056em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal">x</span></span><span style="top:-3.55056em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord overline"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.63056em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span><span style="top:-3.55056em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.19444em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mpunct">,</span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:0.71389em;vertical-align:-0.08333em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.63056em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">x</span></span></span><span style="top:-3.55056em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.825em;vertical-align:-0.19444em;"></span><span class="mord overline"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.63056em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span><span style="top:-3.55056em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.19444em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.9777700000000003em;vertical-align:-0.19444em;"></span><span class="mord overline"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7833300000000002em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span><span style="top:-3.7033300000000002em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.19444em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">⟺</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span></span></p> -<p>这里 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi>x</mi><mo stretchy="true">‾</mo></mover><mo>+</mo><mover accent="true"><mi>y</mi><mo stretchy="true">‾</mo></mover></mrow><annotation encoding="application/x-tex">\overline{x}+\overline{y}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.71389em;vertical-align:-0.08333em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.63056em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">x</span></span></span><span style="top:-3.55056em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.825em;vertical-align:-0.19444em;"></span><span class="mord overline"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.63056em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span><span style="top:-3.55056em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.19444em;"><span></span></span></span></span></span></span></span></span> 中的 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>+</mo></mrow><annotation encoding="application/x-tex">+</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="mord">+</span></span></span></span> 是要定义的加法,即后面所说商环中的加法,而 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mrow><mi>x</mi><mo>+</mo><mi>y</mi></mrow><mo stretchy="true">‾</mo></mover></mrow><annotation encoding="application/x-tex">\overline{x+y}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9777700000000003em;vertical-align:-0.19444em;"></span><span class="mord overline"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7833300000000002em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span><span style="top:-3.7033300000000002em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.19444em;"><span></span></span></span></span></span></span></span></span> 中的 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>+</mo></mrow><annotation encoding="application/x-tex">+</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="mord">+</span></span></span></span> 是环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 中的加法。</p> -<p>根据正规子群的性质,该定义是合适的。</p> -<h4 id="乘法"><a class="anchor" href="#乘法">#</a> 乘法</h4> -<p>在集合 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi><mi mathvariant="normal">/</mi><mi>I</mi></mrow><annotation encoding="application/x-tex">R/I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span> 上可定义乘法 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>×</mo></mrow><annotation encoding="application/x-tex">\times</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="mord">×</span></span></span></span>:</p> -<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi mathvariant="normal">∀</mi><mover accent="true"><mi>x</mi><mo stretchy="true">‾</mo></mover><mo separator="true">,</mo><mover accent="true"><mi>y</mi><mo stretchy="true">‾</mo></mover><mo>∈</mo><mi>R</mi><mi mathvariant="normal">/</mi><mi>I</mi><mo separator="true">,</mo><mspace linebreak="newline"></mspace><mover accent="true"><mi>x</mi><mo stretchy="true">‾</mo></mover><mo>⋅</mo><mover accent="true"><mi>y</mi><mo stretchy="true">‾</mo></mover><mo>=</mo><mover accent="true"><mrow><mi>x</mi><mo>⋅</mo><mi>y</mi></mrow><mo stretchy="true">‾</mo></mover><mo>⟺</mo><mo stretchy="false">(</mo><mi>x</mi><mo>+</mo><mi>I</mi><mo stretchy="false">)</mo><mo>⋅</mo><mo stretchy="false">(</mo><mi>y</mi><mo>+</mo><mi>I</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi>x</mi><mo>⋅</mo><mi>y</mi><mo stretchy="false">)</mo><mo>+</mo><mi>I</mi></mrow><annotation encoding="application/x-tex">\forall \overline x,\overline y\in R/I,\\ -\overline{x}\cdot\overline{y}=\overline{x\cdot y}\Longleftrightarrow (x+I)\cdot(y+I)=(x\cdot y)+I -</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="mord">∀</span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.63056em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal">x</span></span><span style="top:-3.55056em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord overline"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.63056em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span><span style="top:-3.55056em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.19444em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mpunct">,</span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:0.63056em;vertical-align:0em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.63056em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">x</span></span></span><span style="top:-3.55056em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.825em;vertical-align:-0.19444em;"></span><span class="mord overline"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.63056em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span><span style="top:-3.55056em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.19444em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.8388899999999999em;vertical-align:-0.19444em;"></span><span class="mord overline"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.64445em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span><span style="top:-3.56445em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.19444em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">⟺</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span></span></p> -<p>这里 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi>x</mi><mo stretchy="true">‾</mo></mover><mo>⋅</mo><mover accent="true"><mi>y</mi><mo stretchy="true">‾</mo></mover></mrow><annotation encoding="application/x-tex">\overline{x}\cdot\overline{y}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.63056em;vertical-align:0em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.63056em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">x</span></span></span><span style="top:-3.55056em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.825em;vertical-align:-0.19444em;"></span><span class="mord overline"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.63056em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span><span style="top:-3.55056em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.19444em;"><span></span></span></span></span></span></span></span></span> 中的 $\cdot $ 是要定义的乘法,即后面所说商环中的乘法,而 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mrow><mi>x</mi><mo>⋅</mo><mi>y</mi></mrow><mo stretchy="true">‾</mo></mover></mrow><annotation encoding="application/x-tex">\overline{x\cdot y}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8388899999999999em;vertical-align:-0.19444em;"></span><span class="mord overline"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.64445em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span><span style="top:-3.56445em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.19444em;"><span></span></span></span></span></span></span></span></span> 中的 $\cdot $ 是环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 中的乘法。</p> -<hr /> -<p>由于这定义在等价类(陪集)上,因此需要证明该定义是合适的,即与选择的代表无关,即:</p> -<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mover accent="true"><msub><mi>x</mi><mn>1</mn></msub><mo stretchy="true">‾</mo></mover><mo>=</mo><mover accent="true"><msub><mi>x</mi><mn>2</mn></msub><mo stretchy="true">‾</mo></mover><mtext> </mtext><mo>∧</mo><mover accent="true"><msub><mi>y</mi><mn>1</mn></msub><mo stretchy="true">‾</mo></mover><mo>=</mo><mover accent="true"><msub><mi>y</mi><mn>2</mn></msub><mo stretchy="true">‾</mo></mover><mspace linebreak="newline"></mspace><mo>⇓</mo><mspace linebreak="newline"></mspace><mover accent="true"><mrow><msub><mi>x</mi><mn>1</mn></msub><mo>⋅</mo><msub><mi>y</mi><mn>1</mn></msub></mrow><mo stretchy="true">‾</mo></mover><mo>=</mo><mover accent="true"><mrow><msub><mi>x</mi><mn>2</mn></msub><mo>⋅</mo><msub><mi>y</mi><mn>2</mn></msub></mrow><mo stretchy="true">‾</mo></mover></mrow><annotation encoding="application/x-tex">\overline{x_1}=\overline{x_2}\ \land\overline{y_1}=\overline{y_2}\\ -\Downarrow\\ -\overline{x_1\cdot y_1}=\overline{x_2\cdot y_2} -</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.78056em;vertical-align:-0.15em;"></span><span class="mord overline"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.63056em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.55056em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.78056em;vertical-align:-0.15em;"></span><span class="mord overline"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.63056em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.55056em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span><span class="mspace"> </span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.825em;vertical-align:-0.19444em;"></span><span class="mord overline"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.63056em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.55056em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.19444em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.825em;vertical-align:-0.19444em;"></span><span class="mord overline"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.63056em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.55056em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.19444em;"><span></span></span></span></span></span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="mrel">⇓</span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:0.8388899999999999em;vertical-align:-0.19444em;"></span><span class="mord overline"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.64445em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.56445em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.19444em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.8388899999999999em;vertical-align:-0.19444em;"></span><span class="mord overline"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.64445em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.56445em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.19444em;"><span></span></span></span></span></span></span></span></span></span></p> -<p><img data-src="/assets/math/discrete-math/algebra/ring/%E5%95%86%E7%8E%AF%E4%B9%98%E6%B3%95%E5%90%88%E9%80%82%E5%AE%9A%E4%B9%89%E8%AF%81%E6%98%8E.png" alt="商环乘法合适定义证明" /></p> -<h3 id="构成环"><a class="anchor" href="#构成环">#</a> 构成环</h3> -<p><img data-src="/assets/math/discrete-math/algebra/ring/%E5%95%86%E7%8E%AF%E6%9E%84%E6%88%90%E7%8E%AF%E8%AF%81%E6%98%8E1.png" alt="商环构成环证明1" /></p> -<p><img data-src="/assets/math/discrete-math/algebra/ring/%E5%95%86%E7%8E%AF%E6%9E%84%E6%88%90%E7%8E%AF%E8%AF%81%E6%98%8E2.png" alt="商环构成环证明2" /></p> -<h3 id="商环定义"><a class="anchor" href="#商环定义">#</a> 商环定义</h3> -<p>设 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 是环,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi></mrow><annotation encoding="application/x-tex">I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span> 是理想,则<mark>环的加群</mark>关于<mark>理想的商群</mark> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi><mi mathvariant="normal">/</mi><mi>I</mi></mrow><annotation encoding="application/x-tex">R/I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span> 也<mark>构成环</mark>(基于上面定义的加法和乘法),称为环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> <mark>关于理想 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi></mrow><annotation encoding="application/x-tex">I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span> 的商环</mark>(quotient ring),仍记为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi><mi mathvariant="normal">/</mi><mi>I</mi></mrow><annotation encoding="application/x-tex">R/I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span> 。</p> -<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>R</mi><mi mathvariant="normal">/</mi><mi>I</mi><mo>=</mo><mo stretchy="false">{</mo><mi>x</mi><mo>+</mo><mi>I</mi><mi mathvariant="normal">∣</mi><mi>x</mi><mo>∈</mo><mi>R</mi><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">R/I=\{x+I|x\in R\} -</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord">∣</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mclose">}</span></span></span></span></span></p> -<p>基本性质:</p> -<ul> -<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi>a</mi><mo stretchy="true">‾</mo></mover><mo>=</mo><mi>a</mi><mo>+</mo><mi>I</mi></mrow><annotation encoding="application/x-tex">\overline{a}=a+I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.63056em;vertical-align:0em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.63056em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span></span></span><span style="top:-3.55056em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span>;</li> -<li>商环的(加法)零元:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mn>0</mn><mo stretchy="true">‾</mo></mover><mo>=</mo><mn>0</mn><mo>+</mo><mi>I</mi></mrow><annotation encoding="application/x-tex">\overline{0}=0+I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8444400000000001em;vertical-align:0em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8444400000000001em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.76444em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.72777em;vertical-align:-0.08333em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span>;</li> -<li>商环的(加法)单位元:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi>e</mi><mo stretchy="true">‾</mo></mover><mo>=</mo><mi>e</mi><mo>+</mo><mi>I</mi></mrow><annotation encoding="application/x-tex">\overline{e}=e+I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.63056em;vertical-align:0em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.63056em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">e</span></span></span><span style="top:-3.55056em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span>;</li> -</ul> -<h1 id="环同态"><a class="anchor" href="#环同态">#</a> 环同态</h1> -<div class="note primary"> -<p>环的同态就是与环的加法与乘法都可交换的函数</p> +<p>如果存在经过 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 的每个顶点恰好一次的路,称这样的图为<mark>半哈密尔顿图</mark>,称该路为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 的<mark>哈密尔顿路</mark>,简称 <mark><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span> 路</mark></p> +<h3 id="小结论-2"><a class="anchor" href="#小结论-2">#</a> 小结论💡</h3> +<ul> +<li>当 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>≥</mo><mn>3</mn></mrow><annotation encoding="application/x-tex">n\geq3</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719400000000001em;vertical-align:-0.13597em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">3</span></span></span></span> 时,完全图 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>K</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">K_n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">K</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.07153em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 是否为哈密尔顿图? <strong>是</strong></li> +<li>当 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>≥</mo><mn>2</mn></mrow><annotation encoding="application/x-tex">n\geq2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719400000000001em;vertical-align:-0.13597em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">2</span></span></span></span> 时, 方体 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>Q</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">Q_n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8777699999999999em;vertical-align:-0.19444em;"></span><span class="mord"><span class="mord mathnormal">Q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 是否为哈密尔顿图? <strong>是</strong></li> +<li>若完全二部图 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>K</mi><mrow><mi>a</mi><mo separator="true">,</mo><mi>b</mi></mrow></msub></mrow><annotation encoding="application/x-tex">K_{a,b}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.969438em;vertical-align:-0.286108em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">K</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361079999999999em;"><span style="top:-2.5500000000000003em;margin-left:-0.07153em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">b</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span></span></span></span> 为哈密尔顿图,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">a</span></span></span></span> 和 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>b</mi></mrow><annotation encoding="application/x-tex">b</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal">b</span></span></span></span> 需满足什么条件?<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⇒</mo><mi>a</mi><mo>=</mo><mi>b</mi><mo>≥</mo><mn>2</mn></mrow><annotation encoding="application/x-tex">\Rightarrow a=b\geq2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.36687em;vertical-align:0em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.83041em;vertical-align:-0.13597em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">2</span></span></span></span>!</li> +<li>是否存在一个具有奇数个顶点的连通图,它既是二部图,也是哈密尔顿图? <strong>不存在,否则二部图中出现了奇圈</strong></li> +<li>若二部图是哈密尔顿图,则它的二部划分 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>X</mi><mo separator="true">,</mo><mi>Y</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(X,Y)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span></span></span></span> 满足什么条件?<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⇒</mo><mi mathvariant="normal">∣</mi><mi>X</mi><mi mathvariant="normal">∣</mi><mo>=</mo><mi mathvariant="normal">∣</mi><mi>Y</mi><mi mathvariant="normal">∣</mi></mrow><annotation encoding="application/x-tex">\Rightarrow|X|=|Y|</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.36687em;vertical-align:0em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord">∣</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mord">∣</span></span></span></span>!</li> +</ul> +<p>哈密顿图目前为止没有充要条件,实际上图的 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span> 性判定是 NP - 困难问题,下面介绍一个必要条件和一些充分条件</p> +<h2 id="必要条件"><a class="anchor" href="#必要条件">#</a> 必要条件</h2> +<p>若 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span> 图,则对于 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>V</mi></mrow><annotation encoding="application/x-tex">V</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span></span></span></span> 的每个非空真子集 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>S</mi></mrow><annotation encoding="application/x-tex">S</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span></span>,均有:</p> +<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>ω</mi><mo stretchy="false">(</mo><mi>G</mi><mo>−</mo><mi>S</mi><mo stretchy="false">)</mo><mo>≤</mo><mi mathvariant="normal">∣</mi><mi>S</mi><mi mathvariant="normal">∣</mi></mrow><annotation encoding="application/x-tex">\omega(G-S)\leq|S| +</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">ω</span><span class="mopen">(</span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord">∣</span></span></span></span></span></p> +<div class="note information"> +<p>💡别忘了 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ω</mi><mo stretchy="false">(</mo><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\omega(...)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">ω</span><span class="mopen">(</span><span class="mord">.</span><span class="mord">.</span><span class="mord">.</span><span class="mclose">)</span></span></span></span> 的意思是连通分支数,这里还容易得到 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span> 图不存在<strong>割点</strong>。</p> </div> -<p>设 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>R</mi><mo separator="true">,</mo><mo>+</mo><mo separator="true">,</mo><mo>⋅</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(R,+,\cdot)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">+</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">⋅</span><span class="mclose">)</span></span></span></span> 和 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><msup><mi>R</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><mo separator="true">,</mo><mo>⊕</mo><mo separator="true">,</mo><mo>⊗</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(R&#x27;,\oplus,\otimes)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.001892em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">⊕</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">⊗</span><span class="mclose">)</span></span></span></span> 是环,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>φ</mi><mo>:</mo><mi>R</mi><mo>→</mo><msup><mi>R</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">\varphi:R\to R&#x27;</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.751892em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 到 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>R</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">R&#x27;</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.751892em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span> 的函数,若对 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>a</mi><mo separator="true">,</mo><mi>b</mi><mo>∈</mo><mi>R</mi></mrow><annotation encoding="application/x-tex">\forall a,b\in R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="mord">∀</span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 有:</p> -<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>φ</mi><mo stretchy="false">(</mo><mi>a</mi><mo>+</mo><mi>b</mi><mo stretchy="false">)</mo><mo>=</mo><mi>φ</mi><mo stretchy="false">(</mo><mi>a</mi><mo stretchy="false">)</mo><mo>⊕</mo><mi>φ</mi><mo stretchy="false">(</mo><mi>b</mi><mo stretchy="false">)</mo><mspace linebreak="newline"></mspace><mi>φ</mi><mo stretchy="false">(</mo><mi>a</mi><mo>⋅</mo><mi>b</mi><mo stretchy="false">)</mo><mo>=</mo><mi>φ</mi><mo stretchy="false">(</mo><mi>a</mi><mo stretchy="false">)</mo><mo>⊗</mo><mi>φ</mi><mo stretchy="false">(</mo><mi>b</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\varphi(a+b)=\varphi(a)\oplus\varphi(b)\\ -\varphi(a\cdot b)=\varphi(a)\otimes\varphi(b) -</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">b</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">b</span><span class="mclose">)</span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">b</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⊗</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">b</span><span class="mclose">)</span></span></span></span></span></p> -<p>则称 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>φ</mi></mrow><annotation encoding="application/x-tex">\varphi</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">φ</span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 到 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>R</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">R&#x27;</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.751892em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span> 的<mark>同态</mark>。</p> -<ul> -<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>φ</mi></mrow><annotation encoding="application/x-tex">\varphi</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">φ</span></span></span></span> 是单函数,则称为<mark>单同态</mark></li> -<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>φ</mi></mrow><annotation encoding="application/x-tex">\varphi</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">φ</span></span></span></span> 是满函数,则称为<mark>满同态</mark></li> -<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>φ</mi></mrow><annotation encoding="application/x-tex">\varphi</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">φ</span></span></span></span> 是双函数,则称为<mark>同构</mark>,记为:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi><mo>≅</mo><msup><mi>R</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">R\cong R&#x27;</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≅</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.751892em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span>。</li> -</ul> -<p>设 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 和 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>R</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">R&#x27;</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.751892em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span> 是两个环,定义函数 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>φ</mi><mo>:</mo><mi>R</mi><mo>→</mo><msup><mi>R</mi><mtext>′</mtext></msup></mrow><annotation encoding="application/x-tex">φ:R→R^′</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.751892em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span>:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>a</mi><mo>∈</mo><mi>R</mi><mo separator="true">,</mo><mi>φ</mi><mo stretchy="false">(</mo><mi>a</mi><mo stretchy="false">)</mo><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">∀a\in R,φ(a)= 0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.73354em;vertical-align:-0.0391em;"></span><span class="mord">∀</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">0</span></span></span></span>,这里 0 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>R</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">R&#x27;</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.751892em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span> 的零元,则容易验证 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>φ</mi></mrow><annotation encoding="application/x-tex">φ</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">φ</span></span></span></span> 是同态,这个同态称为<mark>零同态</mark> (zero homomorphism)</p> -<p>设 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 是环,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi></mrow><annotation encoding="application/x-tex">I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的理想,则很自然地有同态 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ρ</mi><mo>:</mo><mi>R</mi><mo>→</mo><mi>R</mi><mi mathvariant="normal">/</mi><mi>I</mi></mrow><annotation encoding="application/x-tex">ρ:R→R/I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">ρ</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span> ,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>a</mi><mo>∈</mo><mi>R</mi><mo separator="true">,</mo><mi>ρ</mi><mo stretchy="false">(</mo><mi>a</mi><mo stretchy="false">)</mo><mo>=</mo><mover accent="true"><mi>a</mi><mo stretchy="true">‾</mo></mover></mrow><annotation encoding="application/x-tex">∀a\in R,ρ(a)=\overline a</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.73354em;vertical-align:-0.0391em;"></span><span class="mord">∀</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">ρ</span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.63056em;vertical-align:0em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.63056em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal">a</span></span><span style="top:-3.55056em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span></span></span></span>,这里 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi>a</mi><mo stretchy="true">‾</mo></mover></mrow><annotation encoding="application/x-tex">\overline a</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.63056em;vertical-align:0em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.63056em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal">a</span></span><span style="top:-3.55056em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">a</span></span></span></span> 所在的等价类,即 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo>+</mo><mi>I</mi></mrow><annotation encoding="application/x-tex">a+I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span> 。这个同态称为商环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi><mi mathvariant="normal">/</mi><mi>I</mi></mrow><annotation encoding="application/x-tex">R/I</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span> 的<mark>自然同态</mark> (natural morphism)</p> -<p>零同态、自然同态都是满同态。</p> -<p>自然同态一个例子:</p> -<ul> -<li>整数环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">Z</mi></mrow><annotation encoding="application/x-tex">\mathbb Z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68889em;vertical-align:0em;"></span><span class="mord mathbb">Z</span></span></span></span> 到模 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">m</span></span></span></span> 剩余类环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="double-struck">Z</mi><mi>m</mi></msub></mrow><annotation encoding="application/x-tex">\mathbb Z_m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83889em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathbb">Z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 有很自然的满同态 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>φ</mi><mo>:</mo><mi mathvariant="double-struck">Z</mi><mo>→</mo><msub><mi mathvariant="double-struck">Z</mi><mi>m</mi></msub></mrow><annotation encoding="application/x-tex">φ:\mathbb Z→\mathbb Z_m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.68889em;vertical-align:0em;"></span><span class="mord mathbb">Z</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.83889em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathbb">Z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>z</mi><mo>∈</mo><mi mathvariant="double-struck">Z</mi><mo separator="true">,</mo><mi>φ</mi><mo stretchy="false">(</mo><mi>z</mi><mo stretchy="false">)</mo><mo>=</mo><mi>z</mi><mtext> </mtext><mo lspace="0.22em" rspace="0.22em"><mrow><mi mathvariant="normal">m</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">d</mi></mrow></mo><mtext> </mtext><mi>m</mi></mrow><annotation encoding="application/x-tex">∀z\in \mathbb Z, φ(z)=z\bmod m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.73354em;vertical-align:-0.0391em;"></span><span class="mord">∀</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathbb">Z</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.05555555555555555em;"></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin"><span class="mord"><span class="mord mathrm">m</span><span class="mord mathrm">o</span><span class="mord mathrm">d</span></span></span><span class="mspace" style="margin-right:0.05555555555555555em;"></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">m</span></span></span></span></li> -</ul> +<p>只是必要条件而不是充分条件,经典例子 ——<mark> 彼得森图</mark></p> +<p>用于判断非 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span> 图:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∃</mi><mi>S</mi><mo>⊂</mo><mi>V</mi><mo separator="true">,</mo><mtext>  </mtext><mi>ω</mi><mo stretchy="false">(</mo><mi>G</mi><mo>−</mo><mi>S</mi><mo stretchy="false">)</mo><mo>&gt;</mo><mi mathvariant="normal">∣</mi><mi>S</mi><mi mathvariant="normal">∣</mi></mrow><annotation encoding="application/x-tex">\exist S\subset V,\ \ \omega(G-S)\gt|S|</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.73354em;vertical-align:-0.0391em;"></span><span class="mord">∃</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">⊂</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="mpunct">,</span><span class="mspace"> </span><span class="mspace"> </span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">ω</span><span class="mopen">(</span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord">∣</span></span></span></span> ,则 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 不是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span> 图。</p> +<h2 id="充分条件"><a class="anchor" href="#充分条件">#</a> 充分条件</h2> +<h3 id="dirac"><a class="anchor" href="#dirac">#</a> Dirac</h3> +<p>对于 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>≥</mo><mn>3</mn></mrow><annotation encoding="application/x-tex">n≥3</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719400000000001em;vertical-align:-0.13597em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">3</span></span></span></span> 的简单图 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> , 如果 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 中有:</p> +<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>δ</mi><mo stretchy="false">(</mo><mi>G</mi><mo stretchy="false">)</mo><mo>≥</mo><mfrac><mi>n</mi><mn>2</mn></mfrac></mrow><annotation encoding="application/x-tex">\delta(G)\geq\frac{n}{2} +</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03785em;">δ</span><span class="mopen">(</span><span class="mord mathnormal">G</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.7935600000000003em;vertical-align:-0.686em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.10756em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">2</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p> +<p>那么 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span> 图。</p> +<h3 id="ore"><a class="anchor" href="#ore">#</a> Ore</h3> +<p>对于 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>≥</mo><mn>3</mn></mrow><annotation encoding="application/x-tex">n≥3</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719400000000001em;vertical-align:-0.13597em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">3</span></span></span></span> 的单图 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> , 如果 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 中的任意两个<mark>不相邻</mark>顶点 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>u</mi></mrow><annotation encoding="application/x-tex">u</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">u</span></span></span></span> 与 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi></mrow><annotation encoding="application/x-tex">v</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span></span></span></span> ,有:</p> +<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>d</mi><mo stretchy="false">(</mo><mi>u</mi><mo stretchy="false">)</mo><mo>+</mo><mi>d</mi><mo stretchy="false">(</mo><mi>v</mi><mo stretchy="false">)</mo><mo>≥</mo><mi>n</mi></mrow><annotation encoding="application/x-tex">d(u)+d(v)\geq n +</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mopen">(</span><span class="mord mathnormal">u</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span></span></span></span></span></p> +<p>那么 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span> 图。</p> <div class="note primary"> -<p>零同态全部映射到零元,单同态给出子代数,满同态给出商代数</p> +<p>该定理证明和 Dirac 定理可以完全一致!</p> +<p>该定理的条件是紧的。例如:设 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 是由 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="normal">K</mi><mrow><mi>k</mi><mo>+</mo><mn>1</mn></mrow></msub></mrow><annotation encoding="application/x-tex">Κ_{k+1}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.891661em;vertical-align:-0.208331em;"></span><span class="mord"><span class="mord">K</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361079999999999em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.208331em;"><span></span></span></span></span></span></span></span></span></span> 的一个顶点和另一个 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="normal">K</mi><mrow><mi>k</mi><mo>+</mo><mn>1</mn></mrow></msub></mrow><annotation encoding="application/x-tex">Κ_{k+1}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.891661em;vertical-align:-0.208331em;"></span><span class="mord"><span class="mord">K</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361079999999999em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.208331em;"><span></span></span></span></span></span></span></span></span></span> 的一个顶点重合得到的图,那么对于 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 的任意两个不相邻顶点 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>u</mi></mrow><annotation encoding="application/x-tex">u</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">u</span></span></span></span> 与 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi></mrow><annotation encoding="application/x-tex">v</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span></span></span></span>,有:</p> +<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>d</mi><mo stretchy="false">(</mo><mi>u</mi><mo stretchy="false">)</mo><mo>+</mo><mi>d</mi><mo stretchy="false">(</mo><mi>v</mi><mo stretchy="false">)</mo><mo>=</mo><mn>2</mn><mi>k</mi><mo>=</mo><mi>n</mi><mo>−</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">d(u)+d(v)=2k=n-1 +</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mopen">(</span><span class="mord mathnormal">u</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord">2</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">1</span></span></span></span></span></p> +<p>但 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 是非 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span> 图。</p> </div> -<p>环同态保持:</p> -<ul> -<li>加法单位元</li> -<li>子环</li> -</ul> -<p>不保持:</p> -<ul> -<li>理想</li> -</ul> -<h2 id="mathbbz_m到mathbbz_n的同态"><a class="anchor" href="#mathbbz_m到mathbbz_n的同态">#</a> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="double-struck">Z</mi><mi>m</mi></msub></mrow><annotation encoding="application/x-tex">\mathbb{Z}_m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83889em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord"><span class="mord mathbb">Z</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 到<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="double-struck">Z</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">\mathbb{Z}_n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83889em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord"><span class="mord mathbb">Z</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 的同态</h2> -<p><img data-src="/assets/math/discrete-math/algebra/ring/zm%E5%88%B0zn%E7%9A%84%E5%90%8C%E6%80%81%E7%AC%A6%E5%8F%B7%E7%BA%A6%E5%AE%9A.png" alt="zm到zn的同态符号约定" /></p> -<p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>φ</mi><mo>:</mo><msub><mi mathvariant="double-struck">Z</mi><mi>m</mi></msub><mo>→</mo><msub><mi mathvariant="double-struck">Z</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">\varphi:\mathbb{Z}_m\to\mathbb{Z}_n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.83889em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord"><span class="mord mathbb">Z</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.83889em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord"><span class="mord mathbb">Z</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="double-struck">Z</mi><mi>m</mi></msub></mrow><annotation encoding="application/x-tex">\mathbb{Z}_m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83889em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord"><span class="mord mathbb">Z</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 到 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="double-struck">Z</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">\mathbb{Z}_n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83889em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord"><span class="mord mathbb">Z</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 的同态,当且仅当:</p> -<ul> -<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>φ</mi><mo stretchy="false">(</mo><mover accent="true"><mn>1</mn><mo stretchy="true">‾</mo></mover><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">[</mo><mi>a</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">\varphi(\overline1)=[a]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.09444em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8444400000000001em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord">1</span></span><span style="top:-3.76444em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord mathnormal">a</span><span class="mclose">]</span></span></span></span>;(环同态由该值决定)</li> -<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>φ</mi><mo stretchy="false">(</mo><mover accent="true"><mi>x</mi><mo stretchy="true">‾</mo></mover><mo stretchy="false">)</mo><mo>=</mo><mi>x</mi><mo stretchy="false">[</mo><mi>a</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">\varphi(\overline{x})=x[a]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.63056em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">x</span></span></span><span style="top:-3.55056em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">x</span><span class="mopen">[</span><span class="mord mathnormal">a</span><span class="mclose">]</span></span></span></span>;(乘法陪集)</li> -<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi><mo stretchy="false">[</mo><mi>a</mi><mo stretchy="false">]</mo><mo>=</mo><mo stretchy="false">[</mo><mn>0</mn><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">m[a]=[0]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">m</span><span class="mopen">[</span><span class="mord mathnormal">a</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord">0</span><span class="mclose">]</span></span></span></span>;</li> -<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">[</mo><mi>a</mi><msup><mo stretchy="false">]</mo><mn>2</mn></msup><mo>=</mo><mo stretchy="false">[</mo><mi>a</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">[a]^2=[a]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.064108em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord mathnormal">a</span><span class="mclose"><span class="mclose">]</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141079999999999em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord mathnormal">a</span><span class="mclose">]</span></span></span></span>;(<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">[</mo><mi>a</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">[a]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord mathnormal">a</span><span class="mclose">]</span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="double-struck">Z</mi><mi>m</mi></msub></mrow><annotation encoding="application/x-tex">\mathbb{Z}_m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83889em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord"><span class="mord mathbb">Z</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 的幂等元)</li> -</ul> -<h1 id="环扩张"><a class="anchor" href="#环扩张">#</a> 环扩张</h1> -<p>环的扩张定理,也称为挖补定理</p> -<p><img data-src="/assets/math/discrete-math/algebra/ring/%E7%8E%AF%E6%89%A9%E5%BC%A0%E5%AE%9A%E7%90%86.jpg" alt="环扩张定理" /></p> -<p>如图,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 和 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>S</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">S&#x27;</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.751892em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span> 是 2 个没有公共元素的环,存在 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 到 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>S</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">S&#x27;</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.751892em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span> 的单同态:</p> -<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>ψ</mi><mo>:</mo><mi>R</mi><mo>→</mo><msup><mi>S</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">\psi:R\to S&#x27; -</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">ψ</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.801892em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.801892em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span></p> -<p>并且:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ψ</mi><mo stretchy="false">(</mo><mi>R</mi><mo stretchy="false">)</mo><mo>=</mo><mi>S</mi></mrow><annotation encoding="application/x-tex">\psi(R)=S</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">ψ</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span></span>。</p> -<p>那么 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 可以扩张为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>R</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">R&#x27;</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.751892em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span> ,满足:</p> -<ul> -<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>R</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><mo>−</mo><mi>R</mi><mo>=</mo><msup><mi>S</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><mo>−</mo><mi>S</mi></mrow><annotation encoding="application/x-tex">R&#x27;-R=S&#x27;-S</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.835222em;vertical-align:-0.08333em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.835222em;vertical-align:-0.08333em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span></span>;</li> -<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>S</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><mo>≅</mo><msup><mi>R</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">S&#x27;\cong R&#x27;</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.751892em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≅</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.751892em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span>;</li> -</ul> -<p>设 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 是一个没有单位元的环,则存在一个有单位元的环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>R</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">R&#x27;</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.751892em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span> ,使得 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>R</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">R&#x27;</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.751892em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span> 的子环。</p> -<h1 id="特征"><a class="anchor" href="#特征">#</a> 特征</h1> -<p>设 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 是环。若存在最小正整数 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span></span></span></span> 使得对所有 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo>∈</mo><mi>R</mi></mrow><annotation encoding="application/x-tex">a\in R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 有 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mi>a</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">na=0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">0</span></span></span></span> ,则称 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span></span></span></span> 为环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的<mark>特征</mark>。如果不存在这样的正整数,则称 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的特征为 0。环 R 的特征记为 <mark>Char <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span></mark>。</p> -<p>数域 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">Z</mi><mo separator="true">,</mo><mi mathvariant="double-struck">Q</mi><mo separator="true">,</mo><mi mathvariant="double-struck">R</mi><mo separator="true">,</mo><mi mathvariant="double-struck">C</mi></mrow><annotation encoding="application/x-tex">\mathbb Z, \mathbb Q, \mathbb R, \mathbb C</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.88333em;vertical-align:-0.19444em;"></span><span class="mord mathbb">Z</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathbb">Q</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathbb">R</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathbb">C</span></span></span></span> 的特征都是 0,而模 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">m</span></span></span></span> 剩余类环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="double-struck">Z</mi><mi>m</mi></msub></mrow><annotation encoding="application/x-tex">\mathbb Z_m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83889em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathbb">Z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 的特征是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">m</span></span></span></span>。</p> -<p>【定理】设 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 是有单位元 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">e</span></span></span></span> 的环。若 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">e</span></span></span></span> 关于加法的阶为无穷大,则 Char <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">R=0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">0</span></span></span></span>,否则 Char <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi><mo>=</mo><mi mathvariant="normal">∣</mi><mi>e</mi><mi mathvariant="normal">∣</mi></mrow><annotation encoding="application/x-tex">R=|e|</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal">e</span><span class="mord">∣</span></span></span></span>,这里 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∣</mi><mi>e</mi><mi mathvariant="normal">∣</mi></mrow><annotation encoding="application/x-tex">|e|</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal">e</span><span class="mord">∣</span></span></span></span> 在环的加群中的阶。</p> -<p>证明 若 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">e</span></span></span></span> 的加法的阶为无穷大,则不存在正整数 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span></span></span></span> 使得 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mi>e</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">ne=0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">0</span></span></span></span> ,从而 Char <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">R= 0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">0</span></span></span></span>,否则,若 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∣</mi><mi>e</mi><mi mathvariant="normal">∣</mi><mo>=</mo><mi>n</mi></mrow><annotation encoding="application/x-tex">|e|=n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal">e</span><span class="mord">∣</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span></span></span></span> ,则 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mi>e</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">ne=0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">0</span></span></span></span> ,从而对任意 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo>∈</mo><mi>R</mi></mrow><annotation encoding="application/x-tex">a\in R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> ,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mi>a</mi><mo>=</mo><mi>n</mi><mo stretchy="false">(</mo><mi>e</mi><mi>a</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi>n</mi><mi>e</mi><mo stretchy="false">)</mo><mi>a</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">na=n(ea)=(ne)a=0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">n</span><span class="mopen">(</span><span class="mord mathnormal">e</span><span class="mord mathnormal">a</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mord mathnormal">e</span><span class="mclose">)</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">0</span></span></span></span>。</p> -<p>整环的特征是 0 或是一个素数,进而域的特征也只能是 0 或是素数。</p> +<h3 id="bondy"><a class="anchor" href="#bondy">#</a> Bondy</h3> +<h4 id="引理"><a class="anchor" href="#引理">#</a> 引理</h4> +<p>对于单图 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> ,如果 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 中有两个不相邻顶点 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>u</mi></mrow><annotation encoding="application/x-tex">u</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">u</span></span></span></span> 与 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi></mrow><annotation encoding="application/x-tex">v</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span></span></span></span> ,满足:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mo stretchy="false">(</mo><mi>u</mi><mo stretchy="false">)</mo><mo>+</mo><mi>d</mi><mo stretchy="false">(</mo><mi>v</mi><mo stretchy="false">)</mo><mo>≥</mo><mi>n</mi></mrow><annotation encoding="application/x-tex">d(u)+d(v)≥n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mopen">(</span><span class="mord mathnormal">u</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span></span></span></span>,那么 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span> 图当且仅当 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi><mo>+</mo><mi>u</mi><mi>v</mi></mrow><annotation encoding="application/x-tex">G+uv</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.76666em;vertical-align:-0.08333em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">u</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span> 图。</p> +<h4 id="闭图"><a class="anchor" href="#闭图">#</a> 闭图</h4> +<p>在 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span></span></span></span> 阶简单图中,若对 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mo stretchy="false">(</mo><mi>u</mi><mo stretchy="false">)</mo><mo>+</mo><mi>d</mi><mo stretchy="false">(</mo><mi>v</mi><mo stretchy="false">)</mo><mo>≥</mo><mi>n</mi></mrow><annotation encoding="application/x-tex">d(u)+d(v)≥n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mopen">(</span><span class="mord mathnormal">u</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span></span></span></span> 的任意一对顶点 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>u</mi></mrow><annotation encoding="application/x-tex">u</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">u</span></span></span></span> 与 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi></mrow><annotation encoding="application/x-tex">v</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span></span></span></span> ,均有 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>u</mi><mtext> adj </mtext><mi>v</mi></mrow><annotation encoding="application/x-tex">u\ \text{adj}\ v</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">u</span><span class="mspace"> </span><span class="mord text"><span class="mord">adj</span></span><span class="mspace"> </span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span></span></span></span> , 则称 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 是闭图。</p> +<h5 id="引理-2"><a class="anchor" href="#引理-2">#</a> 引理</h5> +<p>若 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>G</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">G_1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 和 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>G</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">G_2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 是同一个点集 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>V</mi></mrow><annotation encoding="application/x-tex">V</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span></span></span></span> 的两个闭图,则 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>G</mi><mn>1</mn></msub><mo>∩</mo><msub><mi>G</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">G_1\cap G_2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">∩</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 是闭图,但 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>G</mi><mn>1</mn></msub><mo>∪</mo><msub><mi>G</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">G_1\cup G_2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 不一定是闭图。</p> +<h4 id="闭包"><a class="anchor" href="#闭包">#</a> 闭包</h4> +<p>称 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi>G</mi><mo stretchy="true">‾</mo></mover></mrow><annotation encoding="application/x-tex">\overline G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8833300000000001em;vertical-align:0em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8833300000000001em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal">G</span></span><span style="top:-3.80333em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span></span></span></span> 是图 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 的闭包,如果它是包含 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 的极小闭图,即对 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>H</mi></mrow><annotation encoding="application/x-tex">∀H</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord">∀</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span>,若有 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi><mo>⊆</mo><mi>H</mi><mo>⊂</mo><mover accent="true"><mi>G</mi><mo stretchy="true">‾</mo></mover></mrow><annotation encoding="application/x-tex">G\subseteq H \subset\overline G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.13597em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">⊆</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.72243em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">⊂</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.8833300000000001em;vertical-align:0em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8833300000000001em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal">G</span></span><span style="top:-3.80333em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span></span></span></span>,则 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span> 不是闭图。</p> +<ul> +<li>如果 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 本身是闭图,则其闭包是它本身;</li> +<li>否则由定义可以通过在度和 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≥</mo><mi>n</mi></mrow><annotation encoding="application/x-tex">\geq n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719400000000001em;vertical-align:-0.13597em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span></span></span></span> 的不相邻顶点对间<mark>加边</mark>来构造 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 的闭图;加边之后还要继续检查是否需要加边。</li> +</ul> +<p>图 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 的闭包是唯一的。</p> +<h4 id="闭包定理"><a class="anchor" href="#闭包定理">#</a> 闭包定理</h4> <blockquote> -<p>根据 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的特征构造 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">Z</mi></mrow><annotation encoding="application/x-tex">\mathbb Z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68889em;vertical-align:0em;"></span><span class="mord mathbb">Z</span></span></span></span> 到 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的同态</p> +<p>由闭包定理也可以推出 Dirac 和 Ore 定理</p> </blockquote> -<p>【定理】设 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 是有单位元 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">e</span></span></span></span> 的环,定义函数 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>φ</mi><mo>:</mo><mi mathvariant="double-struck">Z</mi><mo>→</mo><mi>R</mi></mrow><annotation encoding="application/x-tex">φ:\mathbb Z→R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.68889em;vertical-align:0em;"></span><span class="mord mathbb">Z</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span>,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>n</mi><mo>∈</mo><mi mathvariant="double-struck">Z</mi><mo separator="true">,</mo><mi>φ</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mi>n</mi><mi>e</mi></mrow><annotation encoding="application/x-tex">∀n\in \mathbb Z, φ(n)=ne</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.73354em;vertical-align:-0.0391em;"></span><span class="mord">∀</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathbb">Z</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span><span class="mord mathnormal">e</span></span></span></span>,则 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>φ</mi></mrow><annotation encoding="application/x-tex">φ</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">φ</span></span></span></span> 是环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">Z</mi></mrow><annotation encoding="application/x-tex">\mathbb Z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68889em;vertical-align:0em;"></span><span class="mord mathbb">Z</span></span></span></span> 到 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的同态。</p> -<p>【推论】设 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 是有单位元 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">e</span></span></span></span> 的环。</p> -<ol> -<li> -<p>如果 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的特征为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>&gt;</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">n&gt;0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">0</span></span></span></span>,则 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 包含一个与 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="double-struck">Z</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">\mathbb Z_n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83889em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathbb">Z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 同构的子环;</p> -</li> -<li> -<p>如果 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的特征为 0 ,则 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 包含一个与 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">Z</mi></mrow><annotation encoding="application/x-tex">\mathbb Z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68889em;vertical-align:0em;"></span><span class="mord mathbb">Z</span></span></span></span> 同构的子环。</p> -<ul> -<li>所以特征为 0 的环一定是无穷环</li> -</ul> -</li> -</ol> -<p>⭐️每个有限域的阶必为素数的幂,即有限域的阶可表示为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>p</mi><mi>n</mi></msup></mrow><annotation encoding="application/x-tex">p^n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.858832em;vertical-align:-0.19444em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.664392em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span></span></span></span> ( <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi></mrow><annotation encoding="application/x-tex">p</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">p</span></span></span></span> 是素数、<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">n</span></span></span></span> 是正整数),该有限域通常称为 Galois 域 (Galois Fields),记为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi><mi>F</mi><mo stretchy="false">(</mo><msup><mi>p</mi><mi>n</mi></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">GF(p^n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">G</span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.664392em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>。</p> -<p>【推论】设 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span> 是域。</p> -<p>1. 如果 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span> 的特征为 0 ,则 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span> 包含一个与有理数域同构的子域;</p> -<p>2. 如果 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span> 的特征是素数 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi></mrow><annotation encoding="application/x-tex">p</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">p</span></span></span></span> ,则 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span> 包含一个与模 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi></mrow><annotation encoding="application/x-tex">p</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">p</span></span></span></span> 剩余类环 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="double-struck">Z</mi><mi>p</mi></msub></mrow><annotation encoding="application/x-tex">\mathbb Z_p</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.974998em;vertical-align:-0.286108em;"></span><span class="mord"><span class="mord mathbb">Z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.15139200000000003em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">p</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span></span></span></span> 同构的子域。</p> -<h1 id="素域"><a class="anchor" href="#素域">#</a> 素域</h1> -<p>若域 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span> 不包含任何真子域,则称 F 是素域 (prime field)。</p> -<p>特征为素数 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi></mrow><annotation encoding="application/x-tex">p</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">p</span></span></span></span> 的<mark>交换环</mark>中:</p> -<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo stretchy="false">(</mo><mi>a</mi><mo>±</mo><mi>b</mi><msup><mo stretchy="false">)</mo><msup><mi>p</mi><mi>n</mi></msup></msup><mo>=</mo><msup><mi>a</mi><msup><mi>p</mi><mi>n</mi></msup></msup><mo>+</mo><msup><mi>b</mi><msup><mi>p</mi><mi>n</mi></msup></msup></mrow><annotation encoding="application/x-tex">(a\pm b)^{p^n}=a^{p^n}+b^{p^n} -</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">±</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1.17998em;vertical-align:-0.25em;"></span><span class="mord mathnormal">b</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.92998em;"><span style="top:-3.1130000000000004em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7385428571428572em;"><span style="top:-2.931em;margin-right:0.07142857142857144em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.01331em;vertical-align:-0.08333em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.92998em;"><span style="top:-3.1130000000000004em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7385428571428572em;"><span style="top:-2.931em;margin-right:0.07142857142857144em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.92998em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.92998em;"><span style="top:-3.1130000000000004em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7385428571428572em;"><span style="top:-2.931em;margin-right:0.07142857142857144em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p> -<hr /> -<p>证明思路</p> -<p>交换环中也有二项式定理,以此证明 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>a</mi><mo>±</mo><mi>b</mi><msup><mo stretchy="false">)</mo><mi>p</mi></msup><mo>=</mo><msup><mi>a</mi><mi>p</mi></msup><mo>+</mo><msup><mi>b</mi><mi>p</mi></msup></mrow><annotation encoding="application/x-tex">(a\pm b)^{p}=a^{p}+b^{p}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">±</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">b</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.664392em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.747722em;vertical-align:-0.08333em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.664392em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.664392em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span></span></span></span></span></span></span></span></span></span></span></span> ,然后数学归纳法即可。</p> +<p>图 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span> 图当且仅当它的闭包是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span> 图</p> +<h3 id="chavatal"><a class="anchor" href="#chavatal">#</a> Chavatal</h3> +<blockquote> +<p>度序列判定法</p> +<p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span> 图充分条件</p> +</blockquote> +<p>设简单图 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 的度序列是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mo stretchy="false">(</mo><msub><mi>d</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>d</mi><mn>2</mn></msub><mo separator="true">,</mo><mo>⋯</mo><mtext> </mtext><mo separator="true">,</mo><msub><mi>d</mi><mi>n</mi></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">d(d_1,d_2,\cdots,d_n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">d</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">d</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">d</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>,这里,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>d</mi><mn>1</mn></msub><mo>≤</mo><msub><mi>d</mi><mn>2</mn></msub><mo>≤</mo><mo>⋯</mo><mo>≤</mo><msub><mi>d</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">d_1≤d_2≤⋯≤d_n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.84444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">d</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.84444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">d</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.7719400000000001em;vertical-align:-0.13597em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.84444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">d</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>,并且 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>≥</mo><mn>3</mn></mrow><annotation encoding="application/x-tex">n≥3</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719400000000001em;vertical-align:-0.13597em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.64444em;vertical-align:0em;"></span><span class="mord">3</span></span></span></span>。若对任意的 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi><mo>&lt;</mo><mfrac><mi>n</mi><mn>2</mn></mfrac></mrow><annotation encoding="application/x-tex">m&lt;\frac{n}{2}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.040392em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.695392em;"><span style="top:-2.6550000000000002em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span>:</p> +<ul> +<li>或有 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>d</mi><mi>m</mi></msub><mo>&gt;</mo><mi>m</mi></mrow><annotation encoding="application/x-tex">d_m&gt;m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.84444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">d</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">m</span></span></span></span>;</li> +<li>或有 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>d</mi><mrow><mi>n</mi><mo>−</mo><mi>m</mi></mrow></msub><mo>≥</mo><mi>n</mi><mo>−</mo><mi>m</mi></mrow><annotation encoding="application/x-tex">d_{n-m}≥n-m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.902771em;vertical-align:-0.208331em;"></span><span class="mord"><span class="mord mathnormal">d</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.25833100000000003em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mathnormal mtight">m</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.208331em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal">m</span></span></span></span>;</li> +</ul> +<p>则 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span> 图。(<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 的闭包是<mark>完全图</mark>!证明也是证明这个)</p> +<h1 id="tsp"><a class="anchor" href="#tsp">#</a> TSP</h1> +<h2 id="边交换"><a class="anchor" href="#边交换">#</a> 边交换</h2> +<h3 id="最优h圈下界"><a class="anchor" href="#最优h圈下界">#</a> 最优 H 圈下界</h3> +<p>可以通过如下方法求出最优 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span> 圈的一个下界:(不是下确界,不一定达得到!)</p> +<p>(1) 在 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 中删掉一点 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi></mrow><annotation encoding="application/x-tex">v</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span></span></span></span> (任意的) 得图 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>G</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">G_1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>;</p> +<p>(2) 在图 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>G</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">G_1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 中求出一棵最小生成树 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi></mrow><annotation encoding="application/x-tex">T</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span></span></span></span>;</p> +<p>(3) 在 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi></mrow><annotation encoding="application/x-tex">v</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span></span></span></span> 的关联边中选出两条权值最小者 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">e_1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.58056em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 与 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">e_2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.58056em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>;</p> +<p>若 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span> 是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi></mrow><annotation encoding="application/x-tex">G</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">G</span></span></span></span> 的最优圈,则有权值下界:</p> +<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>W</mi><mo stretchy="false">(</mo><mi>H</mi><mo stretchy="false">)</mo><mo>≥</mo><mi>W</mi><mo stretchy="false">(</mo><mi>T</mi><mo stretchy="false">)</mo><mo>+</mo><mi>W</mi><mo stretchy="false">(</mo><msub><mi>e</mi><mn>1</mn></msub><mo stretchy="false">)</mo><mo>+</mo><mi>W</mi><mo stretchy="false">(</mo><msub><mi>e</mi><mn>2</mn></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">W(H)\geq W(T)+W(e_1)+W(e_2) +</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></p> <script type="text&#x2F;javascript" src="https://unpkg.com/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.css"> - + - - + 2024-05-16T16:00:00.000Z diff --git a/categories/ACGN/index.html b/categories/ACGN/index.html index ab7dc268..d0067dfe 100644 --- a/categories/ACGN/index.html +++ b/categories/ACGN/index.html @@ -1 +1 @@ -Category: ACGN | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: ACGN | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/ai/index.html b/categories/cs/ai/index.html index 2a13cb7d..acb543a4 100644 --- a/categories/cs/ai/index.html +++ b/categories/cs/ai/index.html @@ -1 +1 @@ -Category: 人工智能 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 人工智能 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/ctf/index.html b/categories/cs/ctf/index.html index 1af8960d..64f3a701 100644 --- a/categories/cs/ctf/index.html +++ b/categories/cs/ctf/index.html @@ -1 +1 @@ -Category: CTF | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: CTF | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/data-structure-and-algorithm/index.html b/categories/cs/data-structure-and-algorithm/index.html index 27a53e6a..c47567f1 100644 --- a/categories/cs/data-structure-and-algorithm/index.html +++ b/categories/cs/data-structure-and-algorithm/index.html @@ -1 +1 @@ -Category: 数据结构与算法 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 数据结构与算法 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/data-structure-and-algorithm/page/2/index.html b/categories/cs/data-structure-and-algorithm/page/2/index.html index 3a4ce5ee..dec09986 100644 --- a/categories/cs/data-structure-and-algorithm/page/2/index.html +++ b/categories/cs/data-structure-and-algorithm/page/2/index.html @@ -1 +1 @@ -Category: 数据结构与算法 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 数据结构与算法 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/devops/index.html b/categories/cs/devops/index.html index 0eac2d34..f3471bb3 100644 --- a/categories/cs/devops/index.html +++ b/categories/cs/devops/index.html @@ -1 +1 @@ -Category: DevOps | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: DevOps | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/devops/page/2/index.html b/categories/cs/devops/page/2/index.html index b5fe6a8f..5eb8fbe4 100644 --- a/categories/cs/devops/page/2/index.html +++ b/categories/cs/devops/page/2/index.html @@ -1 +1 @@ -Category: DevOps | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: DevOps | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/front-end/index.html b/categories/cs/front-end/index.html index ab07ed18..645f6beb 100644 --- a/categories/cs/front-end/index.html +++ b/categories/cs/front-end/index.html @@ -1 +1 @@ -Category: 前端 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 前端 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/index.html b/categories/cs/index.html index 14d9e0b9..1b1687cd 100644 --- a/categories/cs/index.html +++ b/categories/cs/index.html @@ -1 +1 @@ -Category: 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/languages/index.html b/categories/cs/languages/index.html index 2501bd9c..126aaff8 100644 --- a/categories/cs/languages/index.html +++ b/categories/cs/languages/index.html @@ -1 +1 @@ -Category: 编程语言 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 编程语言 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/os/index.html b/categories/cs/os/index.html index f8a35f64..ec826f16 100644 --- a/categories/cs/os/index.html +++ b/categories/cs/os/index.html @@ -1 +1 @@ -Category: 操作系统 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 操作系统 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/os/page/2/index.html b/categories/cs/os/page/2/index.html index d2f30aee..a78f663f 100644 --- a/categories/cs/os/page/2/index.html +++ b/categories/cs/os/page/2/index.html @@ -1 +1 @@ -Category: 操作系统 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 操作系统 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/os/ysosv2/index.html b/categories/cs/os/ysosv2/index.html index 38a18471..3fb91ecc 100644 --- a/categories/cs/os/ysosv2/index.html +++ b/categories/cs/os/ysosv2/index.html @@ -1 +1 @@ -Category: YSOSv2 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: YSOSv2 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/page/2/index.html b/categories/cs/page/2/index.html index 7d75fb40..fd712058 100644 --- a/categories/cs/page/2/index.html +++ b/categories/cs/page/2/index.html @@ -1 +1 @@ -Category: 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/page/3/index.html b/categories/cs/page/3/index.html index 6761e669..1842d460 100644 --- a/categories/cs/page/3/index.html +++ b/categories/cs/page/3/index.html @@ -1 +1 @@ -Category: 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/page/4/index.html b/categories/cs/page/4/index.html index 30152e79..e2ee90df 100644 --- a/categories/cs/page/4/index.html +++ b/categories/cs/page/4/index.html @@ -1 +1 @@ -Category: 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/page/5/index.html b/categories/cs/page/5/index.html index e89c8f13..2169dfb2 100644 --- a/categories/cs/page/5/index.html +++ b/categories/cs/page/5/index.html @@ -1 +1 @@ -Category: 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/page/6/index.html b/categories/cs/page/6/index.html index 844ac1df..fcdfcbc4 100644 --- a/categories/cs/page/6/index.html +++ b/categories/cs/page/6/index.html @@ -1 +1 @@ -Category: 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/page/7/index.html b/categories/cs/page/7/index.html index ee6b57af..1b33ca23 100644 --- a/categories/cs/page/7/index.html +++ b/categories/cs/page/7/index.html @@ -1 +1 @@ -Category: 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/page/8/index.html b/categories/cs/page/8/index.html index a9a02ba2..b9bf7a32 100644 --- a/categories/cs/page/8/index.html +++ b/categories/cs/page/8/index.html @@ -1 +1 @@ -Category: 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/principles-of-computer-composition/index.html b/categories/cs/principles-of-computer-composition/index.html index a1a1de60..b7d6a2ab 100644 --- a/categories/cs/principles-of-computer-composition/index.html +++ b/categories/cs/principles-of-computer-composition/index.html @@ -1 +1 @@ -Category: 计算机组成原理 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 计算机组成原理 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/principles-of-computer-composition/page/2/index.html b/categories/cs/principles-of-computer-composition/page/2/index.html index 544b1345..724a5a1b 100644 --- a/categories/cs/principles-of-computer-composition/page/2/index.html +++ b/categories/cs/principles-of-computer-composition/page/2/index.html @@ -1 +1 @@ -Category: 计算机组成原理 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 计算机组成原理 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/principles-of-computer-composition/yatcpu/index.html b/categories/cs/principles-of-computer-composition/yatcpu/index.html index 5554a3a7..b060d503 100644 --- a/categories/cs/principles-of-computer-composition/yatcpu/index.html +++ b/categories/cs/principles-of-computer-composition/yatcpu/index.html @@ -1 +1 @@ -Category: YatCPU | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: YatCPU | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/raspberrypi/index.html b/categories/cs/raspberrypi/index.html index 9408952a..d62baaa1 100644 --- a/categories/cs/raspberrypi/index.html +++ b/categories/cs/raspberrypi/index.html @@ -1 +1 @@ -Category: 树莓派 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 树莓派 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/cs/tools/index.html b/categories/cs/tools/index.html index 6f9be72e..583501c4 100644 --- a/categories/cs/tools/index.html +++ b/categories/cs/tools/index.html @@ -1 +1 @@ -Category: 工具 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 工具 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git "a/categories/cs/\345\271\266\350\241\214\347\250\213\345\272\217\350\256\276\350\256\241/index.html" "b/categories/cs/\345\271\266\350\241\214\347\250\213\345\272\217\350\256\276\350\256\241/index.html" index 1384a077..3517f440 100644 --- "a/categories/cs/\345\271\266\350\241\214\347\250\213\345\272\217\350\256\276\350\256\241/index.html" +++ "b/categories/cs/\345\271\266\350\241\214\347\250\213\345\272\217\350\256\276\350\256\241/index.html" @@ -1 +1 @@ -Category: 并行程序设计 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 并行程序设计 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/ie/de/index.html b/categories/ie/de/index.html index c3d8dcce..c36e708b 100644 --- a/categories/ie/de/index.html +++ b/categories/ie/de/index.html @@ -1 +1 @@ -Category: 数字逻辑电路 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 数字逻辑电路 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/ie/index.html b/categories/ie/index.html index b3a4d204..479e5eaf 100644 --- a/categories/ie/index.html +++ b/categories/ie/index.html @@ -1 +1 @@ -Category: 电子信息 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 电子信息 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/ie/page/2/index.html b/categories/ie/page/2/index.html index 70c9321a..931137c4 100644 --- a/categories/ie/page/2/index.html +++ b/categories/ie/page/2/index.html @@ -1 +1 @@ -Category: 电子信息 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 电子信息 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/ie/signals-and-systems/index.html b/categories/ie/signals-and-systems/index.html index d0d02c89..27b21380 100644 --- a/categories/ie/signals-and-systems/index.html +++ b/categories/ie/signals-and-systems/index.html @@ -1 +1 @@ -Category: 信号与系统 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 信号与系统 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/index.html b/categories/index.html index ce0dca86..0b179179 100644 --- a/categories/index.html +++ b/categories/index.html @@ -1 +1 @@ -AllCategory | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +AllCategory | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/math/cryptography/index.html b/categories/math/cryptography/index.html index b3c3d69d..ac754703 100644 --- a/categories/math/cryptography/index.html +++ b/categories/math/cryptography/index.html @@ -1 +1 @@ -Category: 密码学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 密码学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/math/discrete-math/graph/index.html b/categories/math/discrete-math/graph/index.html index 3dd4de0a..26f8ccef 100644 --- a/categories/math/discrete-math/graph/index.html +++ b/categories/math/discrete-math/graph/index.html @@ -1 +1 @@ -Category: 图论 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 图论 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/math/discrete-math/index.html b/categories/math/discrete-math/index.html index c7eafc2a..ce9d2bc5 100644 --- a/categories/math/discrete-math/index.html +++ b/categories/math/discrete-math/index.html @@ -1 +1 @@ -Category: 离散数学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 离散数学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/math/discrete-math/page/2/index.html b/categories/math/discrete-math/page/2/index.html index fdcae17d..9f2b93c0 100644 --- a/categories/math/discrete-math/page/2/index.html +++ b/categories/math/discrete-math/page/2/index.html @@ -1 +1 @@ -Category: 离散数学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 离散数学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/math/discrete-math/page/3/index.html b/categories/math/discrete-math/page/3/index.html index 6c517008..3ae245dd 100644 --- a/categories/math/discrete-math/page/3/index.html +++ b/categories/math/discrete-math/page/3/index.html @@ -1 +1 @@ -Category: 离散数学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 离散数学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git "a/categories/math/discrete-math/\344\273\243\346\225\260\347\273\223\346\236\204/index.html" "b/categories/math/discrete-math/\344\273\243\346\225\260\347\273\223\346\236\204/index.html" index 78429585..a0d0dd38 100644 --- "a/categories/math/discrete-math/\344\273\243\346\225\260\347\273\223\346\236\204/index.html" +++ "b/categories/math/discrete-math/\344\273\243\346\225\260\347\273\223\346\236\204/index.html" @@ -1 +1 @@ -Category: 代数结构 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 代数结构 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git "a/categories/math/discrete-math/\347\246\273\346\225\243\346\225\260\345\255\246\345\237\272\347\241\200/index.html" "b/categories/math/discrete-math/\347\246\273\346\225\243\346\225\260\345\255\246\345\237\272\347\241\200/index.html" index 62e39e69..a415dabe 100644 --- "a/categories/math/discrete-math/\347\246\273\346\225\243\346\225\260\345\255\246\345\237\272\347\241\200/index.html" +++ "b/categories/math/discrete-math/\347\246\273\346\225\243\346\225\260\345\255\246\345\237\272\347\241\200/index.html" @@ -1 +1 @@ -Category: 离散数学基础 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 离散数学基础 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/math/index.html b/categories/math/index.html index f870b8f9..637a245c 100644 --- a/categories/math/index.html +++ b/categories/math/index.html @@ -1 +1 @@ -Category: 数学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 数学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/math/page/2/index.html b/categories/math/page/2/index.html index 1bd91bba..6314d18f 100644 --- a/categories/math/page/2/index.html +++ b/categories/math/page/2/index.html @@ -1 +1 @@ -Category: 数学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 数学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/math/page/3/index.html b/categories/math/page/3/index.html index 45c0f05d..d910da23 100644 --- a/categories/math/page/3/index.html +++ b/categories/math/page/3/index.html @@ -1 +1 @@ -Category: 数学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 数学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/si-zheng/index.html b/categories/si-zheng/index.html index e18b1cb4..748a06f9 100644 --- a/categories/si-zheng/index.html +++ b/categories/si-zheng/index.html @@ -1 +1 @@ -Category: 思政 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 思政 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/categories/si-zheng/ma-yuan/index.html b/categories/si-zheng/ma-yuan/index.html index 5d41d191..761765de 100644 --- a/categories/si-zheng/ma-yuan/index.html +++ b/categories/si-zheng/ma-yuan/index.html @@ -1 +1 @@ -Category: 马克思主义基本原理 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +Category: 马克思主义基本原理 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/cs/ai/agent/index.html b/cs/ai/agent/index.html index 7ec44fb2..ad1048c8 100644 --- a/cs/ai/agent/index.html +++ b/cs/ai/agent/index.html @@ -1 +1 @@ -Agent - 人工智能 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 智能体

# 定义

Agent 是指驻留在某一环境下能够自主(Autonomous)、灵活(Flexible)地执行动作以满足设计目标的行为实体。

上述定义具有如下二个特点。

  • (1) 定义方式 : Agent 概念定义是基于 Agent 的外部可观察行为特征,而不是其内部的结构
  • (2) 抽象层次 : Agent 概念更加贴近于人们对现实世界(而不是计算机世界)中行为实体的理解

# 特点

# 驻留性

# 自主性

智能体能在没有人类或其他智能体的干涉和指导的情况下运行,并能根据其内部状态和感知到的环境信息来决定该实施什么样的动作,进而控制自身的行为

# 灵活性

智能体行为的灵活性主要体现为以下三方面:

# 反应性

(Reactive)

反应性是指智能体能够感知所处的环境,并能对环境中发生的相关事件(比如智能体间的交互、用户的指令等)作出适时反应,以满足系统设计目标

# 自发性

(Pro-active)

自发性是指智能体不仅具有目标并根据目标行事,而且能够主动地产生目标,进而实施自发的行为

# 社会性

(Social)

社会性是指智能体所驻留的环境可能存在其他智能体,它拥有这些智能体的有关信息和知识(比如这些智能体的物理位置、所拥有的资源和能力等),并能与它们进行交互和通信,实现灵活多样和复杂的合作、协商和竞争,以满足系统的设计目标

# 其他特性

Agent 与分布式人工智能系统一样具有协作性、适应性等特性

  • (1) 行为自主性
  • (2) 作用交互性(也称反应性)
  • (3) 环境协调性
  • (4) 面向目标性
  • (5) 存在社会性
  • (6) 工作协作性
  • (7) 运行持续性
  • (8) 系统适应性
  • (9) 结构分布性
  • (10) 功能智能性

# BDI 模型

Agent 必须利用知识修改其内部状态 (心理状态),以适应环境变化和协作求解的需要。

人类心理状态的要素可分为以下三种

  • 认知 (信念、知识、学习等)
  • 情感 (愿望、兴趣、爱好等)
  • 意向 (意图、目标和承诺等)

受人类心理启发,传统 Agent 理论模型研究的主要方向为:

  • 信念 (Belief)
  • 愿望 (Desire)
  • 意图 (Intention)

的关系及其形式化描述,力图建立 Agent 的 BDI 模型

# 结构

计算机系统为 Agent 的开发和运行提供软件和硬件环境支持,使各个 Agent 依据全局状态协调地完成各项任务。具体地说:

(1) 在计算机系统中,Agent 相当于一个独立的功能模块、独立的计算机应用系统,它含有独立的外部设备、输入输出驱动装备、操作系统、数据结构和相应的输出。

(2) Agent 程序的核心部分叫做决策生成器问题求解器,起到主控作用。

(3) Agent 的运行是一个或多个进程,并接受总体调度。

(4) 各个 Agent 在多个计算机 CPU 上并行运行,其运行环境由体系结构支持。

# 知识型体系结构

将智能体视为一个定理证明器,智能体的行为决策是一个基于知识库的定理证明过程

智能体的内部状态对应于智能体所拥有的知识

各个知识条目用逻辑语言(比如经典的一阶谓词逻辑或者 Hoare 逻辑)来表示

知识型体系结构

基于知识型体系结构的智能体开发方法、技术和工具,代表性工作包括:

  • Lesperance 等人基于格局演算(Situation Calculus)理论的 ConGolog ,它是 Golog(Goal-Oriented Language)的扩展
  • Fisher 基于可执行时序逻辑(Temporal Logic)的多智能体系统编程语言 Concurrent MetateM

知识型体系结构的不足:

  • 表达能力问题
  • 计算复杂性问题
  • 易用性问题

# Concurrent MetateM

一个由 Concurrent MetateM 实现的系统包含一组可并发、异步执行的智能体:

  • 每个智能体由一组可直接执行的时序逻辑公式加以描述
  • 多个智能体间通过广播消息进行通信

对智能体进行编程的本质实际上就是用逻辑符号来定义智能体规约。一个智能体规约对应于一组时序逻辑公式,它描述了智能体行为。

由 Concurrent MetateM 所定义的智能体实际上是一个迭代地建立关于智能体规约逻辑模型的过程。因此,Concurrent MetateM 中的智能体类似于一个定理证明器

Concurrent MetateM 中的每一个智能体包含以下二个主要的部件:

  • 一个描述智能体行为的规约,每一个智能体规约均包含有一个接口(Interface)定义,用来描述智能体是如何与其所驻留的环境(即其他智能体)进行通信的;
  • 一个计算引擎,它负责执行智能体规约。

# 反应型体系结构

智能体对环境事件的响应是通过一组简单的反应式规则来实现的,这些规则描述了智能体的感知输入与响应动作之间的映射关系。

基于这些反应式规则,智能体无需通过复杂的推理和证明就可针对环境事件作出简单、快速地响应。

反应型体系结构

# 多智能体系统

多智能体系统是指由多个相对独立同时又相互作用的智能体所构成的系统

# 特点

# 独立性

每个智能体都是自主的行为实体,封装了行为以及行为控制机制,可以在无需外部指导的情况下实施行为;

# 协同性

这些智能体并不是孤立的,它们之间存在各种关系,需要相互交互和协同进而达成问题的求解

# 无全局视角

对于绝大多数多智能体系统而言,系统中的智能体要获得关于系统以及环境的完整、准确和及时的信息是非常困难的。这是由于智能体所驻留的环境可能会比较复杂,具有以下特点:

  • 开放性
  • 不确定性
  • 动态性
  • ......

# 不可预测和不确定性

在多智能体系统中,由于智能体行为的自主性、智能体行为对环境影响的有限性、系统中无全局控制智能体、智能体间交互行为的动态性,多智能体系统的运行具有不可预测性和不确定性的特点。

# Agent 研究分类

# 知识表示与推理 / 规划

核心假设:人工智能可以通过符号推理形式化刻画。

研究目的:将知识表达为计算机可处理(computer-tractable)的形式,以供智能体使用。

# 非合作博弈

Non-cooperative Game Theory

  • Actions are taken by individual agents
  • No binding agreements

# 拍卖理论

四种类型拍卖:

  • (1) 英式拍卖 (English Auction):又叫升价拍卖,竞价者在一起公开竞标,往上拾价,出价最高者获得拍品。这是我们最常见到的拍卖。
  • (2) 荷式拍卖 (Dutch Auction):又叫降价拍卖,价格由高往低降,第一个接受价格的人获得拍品。
  • (3) 第一价格拍卖 (Fist-price Auction):每个竞买人对拍品进行单独密封报价,但相互不知道其他竞买人的出价,标的装在信封里交上去,然后拍卖人拆开信封,拍卖人按各个标价的大小排序,最后在规定的时间、地点宜布标价,出价最高的竞买人获胜。
  • (4) 第二价格拍卖 (Second-price Auction):二级价格拍卖与一级价格拍卖类似,不同的是最后出价最高的竞买人获得拍品,但只需要按照排位第二高的价格进行支付,即第二价格,因此这种拍卖方式被称为二级密封价格拍卖或 “维克里拍卖”。

四种拍卖形式奠定了拍卖的基本类型,其他无论什么形式的拍卖都只是这四种形式的变型与组合:

拍卖

# 收益等价定理

在一些合理的约束条件保证下,四种拍卖形式最终的收益是相等的。

给定买方人数,假定所有买方都是风险中性的,各买方的价值独立且具有相同的连续分布,而且分布函数严格递增。

那么,任何满足下列两个条件的拍卖机制对于卖方都会产生相同的期望收益(对于买方则产生相同的期望支出):

  • 条件 1:标的物总是为最高信号的买方获得;
  • 条件 2:如果买方的信号位于信号区间的下限,那么他的期望剩余为零。

“收益等价定理” 是整个拍卖理论研究的起点。它表明:对于委托人来说,只要拍卖品不变,购买对象不变,无论采用什么拍卖方式,最终收益都是一样的。

当然 “收益等价定理” 说的是理想状态,这里我们千万不要忘记约束条件。在现实中,虽然拍卖品是共同的,但由于参与竞标的人不同、不同的拍卖流程和规则,结果产生拍卖结果的巨大差异。甚至同样一种拍卖办法,放到不同的国家,结果也会有天壤之别,原因在于现实的约束条件不同。

# 合作博弈

Cooperative / Colitional Game Theory

  • Actions are taken by groups of agents
  • Binding agreements are possible

合作博弈是一种侧重于玩家群体行为的模型。与非合作博弈不同,合作博弈中的战略互动没有被明确建模。

# 基本过程

  • Agent 们组成多个联盟(coalitions)
  • 每个联盟隐性地选择动作
  • 可转让效用(TU)博弈:联盟行动的选择(由所有联盟决定) 决定了每个联盟的回报 —— 联盟中的 Agents 随后需要决定如何分配这个总回报

# 人 - Agent 交互

仅仅拥有自主性(Autonomy)的 Agent 并不足以作为人 - Agent 交互的研究对象

当人们塑造他们与物体或技术的互动,好像它们有目的、动机或意图时,我们就有了人 - Agent 交互

通常,技术被设计成鼓励人们赋予它们 Agent 的性质,尽管这并非 Agent 的必要条件。人们会将 Agent 的性质赋予许多日常生活中的事物和技术,这是一个常见的研究领域

人机互补 —— 人类和 agent 各自互补缺点,利用优点

Edited on Views times
\ No newline at end of file +Agent - 人工智能 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 智能体

# 定义

Agent 是指驻留在某一环境下能够自主(Autonomous)、灵活(Flexible)地执行动作以满足设计目标的行为实体。

上述定义具有如下二个特点。

  • (1) 定义方式 : Agent 概念定义是基于 Agent 的外部可观察行为特征,而不是其内部的结构
  • (2) 抽象层次 : Agent 概念更加贴近于人们对现实世界(而不是计算机世界)中行为实体的理解

# 特点

# 驻留性

# 自主性

智能体能在没有人类或其他智能体的干涉和指导的情况下运行,并能根据其内部状态和感知到的环境信息来决定该实施什么样的动作,进而控制自身的行为

# 灵活性

智能体行为的灵活性主要体现为以下三方面:

# 反应性

(Reactive)

反应性是指智能体能够感知所处的环境,并能对环境中发生的相关事件(比如智能体间的交互、用户的指令等)作出适时反应,以满足系统设计目标

# 自发性

(Pro-active)

自发性是指智能体不仅具有目标并根据目标行事,而且能够主动地产生目标,进而实施自发的行为

# 社会性

(Social)

社会性是指智能体所驻留的环境可能存在其他智能体,它拥有这些智能体的有关信息和知识(比如这些智能体的物理位置、所拥有的资源和能力等),并能与它们进行交互和通信,实现灵活多样和复杂的合作、协商和竞争,以满足系统的设计目标

# 其他特性

Agent 与分布式人工智能系统一样具有协作性、适应性等特性

  • (1) 行为自主性
  • (2) 作用交互性(也称反应性)
  • (3) 环境协调性
  • (4) 面向目标性
  • (5) 存在社会性
  • (6) 工作协作性
  • (7) 运行持续性
  • (8) 系统适应性
  • (9) 结构分布性
  • (10) 功能智能性

# BDI 模型

Agent 必须利用知识修改其内部状态 (心理状态),以适应环境变化和协作求解的需要。

人类心理状态的要素可分为以下三种

  • 认知 (信念、知识、学习等)
  • 情感 (愿望、兴趣、爱好等)
  • 意向 (意图、目标和承诺等)

受人类心理启发,传统 Agent 理论模型研究的主要方向为:

  • 信念 (Belief)
  • 愿望 (Desire)
  • 意图 (Intention)

的关系及其形式化描述,力图建立 Agent 的 BDI 模型

# 结构

计算机系统为 Agent 的开发和运行提供软件和硬件环境支持,使各个 Agent 依据全局状态协调地完成各项任务。具体地说:

(1) 在计算机系统中,Agent 相当于一个独立的功能模块、独立的计算机应用系统,它含有独立的外部设备、输入输出驱动装备、操作系统、数据结构和相应的输出。

(2) Agent 程序的核心部分叫做决策生成器问题求解器,起到主控作用。

(3) Agent 的运行是一个或多个进程,并接受总体调度。

(4) 各个 Agent 在多个计算机 CPU 上并行运行,其运行环境由体系结构支持。

# 知识型体系结构

将智能体视为一个定理证明器,智能体的行为决策是一个基于知识库的定理证明过程

智能体的内部状态对应于智能体所拥有的知识

各个知识条目用逻辑语言(比如经典的一阶谓词逻辑或者 Hoare 逻辑)来表示

知识型体系结构

基于知识型体系结构的智能体开发方法、技术和工具,代表性工作包括:

  • Lesperance 等人基于格局演算(Situation Calculus)理论的 ConGolog ,它是 Golog(Goal-Oriented Language)的扩展
  • Fisher 基于可执行时序逻辑(Temporal Logic)的多智能体系统编程语言 Concurrent MetateM

知识型体系结构的不足:

  • 表达能力问题
  • 计算复杂性问题
  • 易用性问题

# Concurrent MetateM

一个由 Concurrent MetateM 实现的系统包含一组可并发、异步执行的智能体:

  • 每个智能体由一组可直接执行的时序逻辑公式加以描述
  • 多个智能体间通过广播消息进行通信

对智能体进行编程的本质实际上就是用逻辑符号来定义智能体规约。一个智能体规约对应于一组时序逻辑公式,它描述了智能体行为。

由 Concurrent MetateM 所定义的智能体实际上是一个迭代地建立关于智能体规约逻辑模型的过程。因此,Concurrent MetateM 中的智能体类似于一个定理证明器

Concurrent MetateM 中的每一个智能体包含以下二个主要的部件:

  • 一个描述智能体行为的规约,每一个智能体规约均包含有一个接口(Interface)定义,用来描述智能体是如何与其所驻留的环境(即其他智能体)进行通信的;
  • 一个计算引擎,它负责执行智能体规约。

# 反应型体系结构

智能体对环境事件的响应是通过一组简单的反应式规则来实现的,这些规则描述了智能体的感知输入与响应动作之间的映射关系。

基于这些反应式规则,智能体无需通过复杂的推理和证明就可针对环境事件作出简单、快速地响应。

反应型体系结构

# 多智能体系统

多智能体系统是指由多个相对独立同时又相互作用的智能体所构成的系统

# 特点

# 独立性

每个智能体都是自主的行为实体,封装了行为以及行为控制机制,可以在无需外部指导的情况下实施行为;

# 协同性

这些智能体并不是孤立的,它们之间存在各种关系,需要相互交互和协同进而达成问题的求解

# 无全局视角

对于绝大多数多智能体系统而言,系统中的智能体要获得关于系统以及环境的完整、准确和及时的信息是非常困难的。这是由于智能体所驻留的环境可能会比较复杂,具有以下特点:

  • 开放性
  • 不确定性
  • 动态性
  • ......

# 不可预测和不确定性

在多智能体系统中,由于智能体行为的自主性、智能体行为对环境影响的有限性、系统中无全局控制智能体、智能体间交互行为的动态性,多智能体系统的运行具有不可预测性和不确定性的特点。

# Agent 研究分类

# 知识表示与推理 / 规划

核心假设:人工智能可以通过符号推理形式化刻画。

研究目的:将知识表达为计算机可处理(computer-tractable)的形式,以供智能体使用。

# 非合作博弈

Non-cooperative Game Theory

  • Actions are taken by individual agents
  • No binding agreements

# 拍卖理论

四种类型拍卖:

  • (1) 英式拍卖 (English Auction):又叫升价拍卖,竞价者在一起公开竞标,往上拾价,出价最高者获得拍品。这是我们最常见到的拍卖。
  • (2) 荷式拍卖 (Dutch Auction):又叫降价拍卖,价格由高往低降,第一个接受价格的人获得拍品。
  • (3) 第一价格拍卖 (Fist-price Auction):每个竞买人对拍品进行单独密封报价,但相互不知道其他竞买人的出价,标的装在信封里交上去,然后拍卖人拆开信封,拍卖人按各个标价的大小排序,最后在规定的时间、地点宜布标价,出价最高的竞买人获胜。
  • (4) 第二价格拍卖 (Second-price Auction):二级价格拍卖与一级价格拍卖类似,不同的是最后出价最高的竞买人获得拍品,但只需要按照排位第二高的价格进行支付,即第二价格,因此这种拍卖方式被称为二级密封价格拍卖或 “维克里拍卖”。

四种拍卖形式奠定了拍卖的基本类型,其他无论什么形式的拍卖都只是这四种形式的变型与组合:

拍卖

# 收益等价定理

在一些合理的约束条件保证下,四种拍卖形式最终的收益是相等的。

给定买方人数,假定所有买方都是风险中性的,各买方的价值独立且具有相同的连续分布,而且分布函数严格递增。

那么,任何满足下列两个条件的拍卖机制对于卖方都会产生相同的期望收益(对于买方则产生相同的期望支出):

  • 条件 1:标的物总是为最高信号的买方获得;
  • 条件 2:如果买方的信号位于信号区间的下限,那么他的期望剩余为零。

“收益等价定理” 是整个拍卖理论研究的起点。它表明:对于委托人来说,只要拍卖品不变,购买对象不变,无论采用什么拍卖方式,最终收益都是一样的。

当然 “收益等价定理” 说的是理想状态,这里我们千万不要忘记约束条件。在现实中,虽然拍卖品是共同的,但由于参与竞标的人不同、不同的拍卖流程和规则,结果产生拍卖结果的巨大差异。甚至同样一种拍卖办法,放到不同的国家,结果也会有天壤之别,原因在于现实的约束条件不同。

# 合作博弈

Cooperative / Colitional Game Theory

  • Actions are taken by groups of agents
  • Binding agreements are possible

合作博弈是一种侧重于玩家群体行为的模型。与非合作博弈不同,合作博弈中的战略互动没有被明确建模。

# 基本过程

  • Agent 们组成多个联盟(coalitions)
  • 每个联盟隐性地选择动作
  • 可转让效用(TU)博弈:联盟行动的选择(由所有联盟决定) 决定了每个联盟的回报 —— 联盟中的 Agents 随后需要决定如何分配这个总回报

# 人 - Agent 交互

仅仅拥有自主性(Autonomy)的 Agent 并不足以作为人 - Agent 交互的研究对象

当人们塑造他们与物体或技术的互动,好像它们有目的、动机或意图时,我们就有了人 - Agent 交互

通常,技术被设计成鼓励人们赋予它们 Agent 的性质,尽管这并非 Agent 的必要条件。人们会将 Agent 的性质赋予许多日常生活中的事物和技术,这是一个常见的研究领域

人机互补 —— 人类和 agent 各自互补缺点,利用优点

Edited on Views times
\ No newline at end of file diff --git a/cs/ai/concepts/index.html b/cs/ai/concepts/index.html index ff891aae..f4618981 100644 --- a/cs/ai/concepts/index.html +++ b/cs/ai/concepts/index.html @@ -1 +1 @@ -人工智能绪论 - 人工智能 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 人工智能的概念

人工智能(Artificial Intelligence - AI):研究如何通过计算机技术实现一个智能体,让智能体完成类似于人类智能的行为。

# 智能体 Agent

完成智能行为的主体,是物理或抽象实体,可以感知世界并对世界施加作用。

大模型智能体 LLM Agent

在近几年随 ChatGPT 兴起的新概念

# 智能体的两大目标

  • 能否使智能体像人一样思考、理性地思考?
  • 能否使智能体像人一样行动、理性地行动?

# 智能体可否像人一样思考

首先,需要测量人如何思考的方法:内省、心理实验、 脑成像。

# 认知科学

交叉学科,融合人工智能的计算机模型和心理学实验技术,试图构建一种精确可测试的人类思维理论。

# 认知神经科学

交叉学科,以认知科学的理论以及神经心理学、神经科学及计算机模型的实验证据为基础。

# 智能体如何像人一样行动

# 图林测试

1950 年,英国数学家图灵 (Alan Turing) 提出了一个测试方法来确定一个机器是否具有人类智能。

# 图林测试内容
  • 两个人对机器进行测试:一人扮演提问者,另外一人作为被测者。
  • 这两人与机器分别处在三个不同的房间,提问者通过打印问题和接受打印问题来与被测者和被测机器进行通迅。提问者可以向被测机器和被测者提问,但他只知道接受提问的是 A 或 B,而并不知道他是人还是机器。
  • 若超过 30% 的测试者不能确定出被测试者是人还是机器,那么这台机器就通过了测试,并被认为具有人类智能。
# 图灵提出了 AI 的几大元素
  • 知识
  • 推理
  • 语言
  • 理解
  • 学习
# 图灵测试存在的问题
  • 图灵测试不可重复
  • 无法数学分析

# ⭐️三大主流学派

# 逻辑学派

符号主义 / 功能主义方法,模拟大脑逻辑思维功能

原理主要为物理符号系统 (即符号操作系统) 假设和有限合理性原理。

# 仿生学派

联结主义 / 结构主义方法,模拟大脑结构

原理主要为神经网络及神经网络间的连接机制与学习算法

# 控制论学派

行为主义 / 进化主义方法,模拟智能系统行为

原理为控制论及感知 — 动作型控制系统

# 理论基础

# 物理符号系统的假设

一个完善的符号系统应具有下列 6 种功能

  • 输入 (input) 符号
  • 输出 (output) 符号
  • 存储 (store) 符号
  • 复制 (copy) 符号
  • 建立符号结构:通过找出各符号间的关系,在符号系统中形成符号结构
  • 条件性迁移 (conditional transfer) : 根据已有符号,继续完成活动过程

任何一个系统,如果它能够表现出智能,那么它就必定能够执行上述 6 种功能。反之,任何系统如果具有这 6 种功能,那么它就能够表现出智能;这种智能指的是人类所具有的那种智能。

物理符号系统的假设伴随 3 个推论,或称为附带条件

  • 既然人具有智能,那么他就 一定是 一个物理符号系统。人之所以能够表现出智能,就是基 于他的信息处理过程
  • 既 然 计 算 机 是 一个 物 理 符 号 系 统 ,它 就 一定 能 够 表 现 出 智 能 。这 是 人 工 智能的基本条件。
  • 既然人是 一个物理符号系统,计算机也是 一个物理符号系统,那么就能够 用计算机模拟人的活动

# 人工智能的内涵

  • 搜索
  • 知识
  • 推理
  • 归纳
  • 演绎
  • ...

# 强 / 弱 人工智能

# 强人工智能

一个机器和人的思考行为都完全一样

# 弱人工智能

只能表面上执行看上去的智能行为

# 泛 / 狭义 人工智能

# 泛人工智能

智能体拥有在任何问题上应用智能的能力

# 狭义人工智能

只能完成一项具体任务的人工智能

# 人工智能的发展历史

# 不同阶段

# 1950-1970

早期爆发阶段,巨大期望

  • 1952:Samuel 写了一个能学习的五子棋程序
  • 1955:Newell 和 Simon 写了一个推理的程序

# 1970-1990

知识就是力量,知识工程

  • 1980-1988:专家系统工业爆发
  • 1988-1993: 日本第五代计算机系统项目失败

# 1990-

机器学习兴起,人工智能的春天

# 2010-

深度学习获得工业投资和应用

# 三次大跃进

  1. 智能系统代替人完成部分逻辑推理工作,如机器 定理证明和专家系统
  2. 智能系统能够和环境交互,从运行的环境中获取信息,代替人完成包括不定性在内的部分思维 工作,通过自身的动作,对环境施加影响,并适应环境的变化,如智能机器人
  3. 智 能 系 统 具 有 人 类 的 认 知 和 思 维 能 力 ,能 够 发 现 新 的 知 识 ,完 成 面 临 的 任 务 ,如 基 于 数 据 挖 掘 的 系 统

# 人工智能研究课题

# 智 能 感 知

# 模式识别

# 计算机视觉

# 自然语言处理

# 智 能 推 理

# 搜索技术

# 问题求解

# 定理证明

# 专家系统和知识库

# 大数据知识工程

# 智 能 学 习

# 记忆与联想

# 神经网络

# 深度学习、迁移学习

# 计算智能与进化计算

# 遗传算法

# 数据挖掘与知识发现

# 智 能 行 动

# 智能检索

# 智能调度与指挥

# 智能控制

# 人机对话系统

# 智能机器人

# 分布式人工智能与 Agent

# 游戏

# 人机智能融合

# 人工智能实例

  • 专家系统:在专门的领域(医疗、探矿、财务等领域)内的咨询服务系统
  • 自然语言处理:在有限范围内的问题回答系统。
  • 程序验证系统:通过定理证明途径验证程序的正确性。
  • 智能机器人:通过计算机视觉和智能控制完成具体行动任务
Edited on Views times
\ No newline at end of file +人工智能绪论 - 人工智能 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 人工智能的概念

人工智能(Artificial Intelligence - AI):研究如何通过计算机技术实现一个智能体,让智能体完成类似于人类智能的行为。

# 智能体 Agent

完成智能行为的主体,是物理或抽象实体,可以感知世界并对世界施加作用。

大模型智能体 LLM Agent

在近几年随 ChatGPT 兴起的新概念

# 智能体的两大目标

  • 能否使智能体像人一样思考、理性地思考?
  • 能否使智能体像人一样行动、理性地行动?

# 智能体可否像人一样思考

首先,需要测量人如何思考的方法:内省、心理实验、 脑成像。

# 认知科学

交叉学科,融合人工智能的计算机模型和心理学实验技术,试图构建一种精确可测试的人类思维理论。

# 认知神经科学

交叉学科,以认知科学的理论以及神经心理学、神经科学及计算机模型的实验证据为基础。

# 智能体如何像人一样行动

# 图林测试

1950 年,英国数学家图灵 (Alan Turing) 提出了一个测试方法来确定一个机器是否具有人类智能。

# 图林测试内容
  • 两个人对机器进行测试:一人扮演提问者,另外一人作为被测者。
  • 这两人与机器分别处在三个不同的房间,提问者通过打印问题和接受打印问题来与被测者和被测机器进行通迅。提问者可以向被测机器和被测者提问,但他只知道接受提问的是 A 或 B,而并不知道他是人还是机器。
  • 若超过 30% 的测试者不能确定出被测试者是人还是机器,那么这台机器就通过了测试,并被认为具有人类智能。
# 图灵提出了 AI 的几大元素
  • 知识
  • 推理
  • 语言
  • 理解
  • 学习
# 图灵测试存在的问题
  • 图灵测试不可重复
  • 无法数学分析

# ⭐️三大主流学派

# 逻辑学派

符号主义 / 功能主义方法,模拟大脑逻辑思维功能

原理主要为物理符号系统 (即符号操作系统) 假设和有限合理性原理。

# 仿生学派

联结主义 / 结构主义方法,模拟大脑结构

原理主要为神经网络及神经网络间的连接机制与学习算法

# 控制论学派

行为主义 / 进化主义方法,模拟智能系统行为

原理为控制论及感知 — 动作型控制系统

# 理论基础

# 物理符号系统的假设

一个完善的符号系统应具有下列 6 种功能

  • 输入 (input) 符号
  • 输出 (output) 符号
  • 存储 (store) 符号
  • 复制 (copy) 符号
  • 建立符号结构:通过找出各符号间的关系,在符号系统中形成符号结构
  • 条件性迁移 (conditional transfer) : 根据已有符号,继续完成活动过程

任何一个系统,如果它能够表现出智能,那么它就必定能够执行上述 6 种功能。反之,任何系统如果具有这 6 种功能,那么它就能够表现出智能;这种智能指的是人类所具有的那种智能。

物理符号系统的假设伴随 3 个推论,或称为附带条件

  • 既然人具有智能,那么他就 一定是 一个物理符号系统。人之所以能够表现出智能,就是基 于他的信息处理过程
  • 既 然 计 算 机 是 一个 物 理 符 号 系 统 ,它 就 一定 能 够 表 现 出 智 能 。这 是 人 工 智能的基本条件。
  • 既然人是 一个物理符号系统,计算机也是 一个物理符号系统,那么就能够 用计算机模拟人的活动

# 人工智能的内涵

  • 搜索
  • 知识
  • 推理
  • 归纳
  • 演绎
  • ...

# 强 / 弱 人工智能

# 强人工智能

一个机器和人的思考行为都完全一样

# 弱人工智能

只能表面上执行看上去的智能行为

# 泛 / 狭义 人工智能

# 泛人工智能

智能体拥有在任何问题上应用智能的能力

# 狭义人工智能

只能完成一项具体任务的人工智能

# 人工智能的发展历史

# 不同阶段

# 1950-1970

早期爆发阶段,巨大期望

  • 1952:Samuel 写了一个能学习的五子棋程序
  • 1955:Newell 和 Simon 写了一个推理的程序

# 1970-1990

知识就是力量,知识工程

  • 1980-1988:专家系统工业爆发
  • 1988-1993: 日本第五代计算机系统项目失败

# 1990-

机器学习兴起,人工智能的春天

# 2010-

深度学习获得工业投资和应用

# 三次大跃进

  1. 智能系统代替人完成部分逻辑推理工作,如机器 定理证明和专家系统
  2. 智能系统能够和环境交互,从运行的环境中获取信息,代替人完成包括不定性在内的部分思维 工作,通过自身的动作,对环境施加影响,并适应环境的变化,如智能机器人
  3. 智 能 系 统 具 有 人 类 的 认 知 和 思 维 能 力 ,能 够 发 现 新 的 知 识 ,完 成 面 临 的 任 务 ,如 基 于 数 据 挖 掘 的 系 统

# 人工智能研究课题

# 智 能 感 知

# 模式识别

# 计算机视觉

# 自然语言处理

# 智 能 推 理

# 搜索技术

# 问题求解

# 定理证明

# 专家系统和知识库

# 大数据知识工程

# 智 能 学 习

# 记忆与联想

# 神经网络

# 深度学习、迁移学习

# 计算智能与进化计算

# 遗传算法

# 数据挖掘与知识发现

# 智 能 行 动

# 智能检索

# 智能调度与指挥

# 智能控制

# 人机对话系统

# 智能机器人

# 分布式人工智能与 Agent

# 游戏

# 人机智能融合

# 人工智能实例

  • 专家系统:在专门的领域(医疗、探矿、财务等领域)内的咨询服务系统
  • 自然语言处理:在有限范围内的问题回答系统。
  • 程序验证系统:通过定理证明途径验证程序的正确性。
  • 智能机器人:通过计算机视觉和智能控制完成具体行动任务
Edited on Views times
\ No newline at end of file diff --git a/cs/ai/knowledge-presentation-and-resolution/index.html b/cs/ai/knowledge-presentation-and-resolution/index.html index ba1680ca..3edfca14 100644 --- a/cs/ai/knowledge-presentation-and-resolution/index.html +++ b/cs/ai/knowledge-presentation-and-resolution/index.html @@ -1 +1 @@ -知识表示与推理 - 人工智能 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 知识和知识表示

# 知识

  • 数据一般指单独的事实,是信息的载体
  • 信息由符号组成,如文字和数字,但是对符号赋予了一定的意义,因此有一定的用途或价值
  • 知识是由经验总结升华出来的,因此知识是经验的结晶。知识在信息的基础上增加了上下文信息,提供了更多的意义,因此也就更加有用和有价值。知识是随着时间的变化而动态变化的,新的知识可以根据规则和已有的知识推导出来。

知识是经过加工的信息,它包括:

  • 事实:是关于对象和物体的知识。
  • 规则:是有关问题中与事物的行动、动作相联系的因果关系的知识。
  • 元知识:是有关知识的知识,是知识库中的高层知识。
  • 常识性知识:泛指普遍存在而且被普遍认识了的客观事实一类知识。

# 策略

策略 —— 关于如何解决问题的政策方略,包括在什么时间、什么地点、由什么主体采取什么行动、达到什么目标、注意什么事项等等一整套完整而具体的行动计划规划、行动步骤、工作方式和工作方法

# 智能

在给定的 问题 - 问题环境 - 主体目的 的条件下,智能就是有针对性地获取 问题 - 环境 的信息,恰当地对这些信息进行处理以提炼知识达到认知,在此基础上,把已有的知识与主体的目的信息相结合,合理地产生解决问题的策略信息,并利用所得到的策略信息在给定的环境下成功地解决问题达到主体的目的 (行为)。

省流:信息经加工提炼而成知识,知识被目的激活而成智能。

智能具有 4 个能力:

  • 获取有用信息的能力
  • 由信息生成 == 知识 (认知)== 的能力
  • 由知识和目的生成 == 策略 (决策)== 的能力
  • 实施策略取得效果 (施效) 的能力

# 知识表示语言问题

  • 语法 —— 语言的语法描述了组成语句的可能的搭配关系。
  • 语义 —— 语义定义了语句所指的世界中的事实。

从语法和语义,可以给出使用该语言的 Agent 的必要的推理机制。

基于该推理机制,Agent 可以从已知的语句推导出结论,或判断某条信息是不是已蕴涵在现有的知识当中。

知识表示语言需要:

  • 语法规则
  • 语义解释
  • 用于演绎和推导的规则

知识表示语言应该支持知识不完全的情况。不能表达这种不完全性的语言是表达能力不够的语言

程序设计语言比较善于描述算法和具体的数据结构

# 现代逻辑学的基本研究方法

逻辑学 (logic) 是研究人类思维规律的科学,而现代逻辑学则是用数学 (符号化、公理化、形式化) 的方法来研究这些规律。

# 符号化

所谓符号化即是用 “一种只作整体认读的记号 (signs)”—— 符号 (symbols) 表示量、数及数量关系。也有用字母、符号表示思维的物理对象、概念对象、判断对象等。

语言化是符号化的初级阶段。

现代逻辑学对思维的研究,需要更加彻底的符号化过程。

# 公理化

欧氏几何公理系统中的所有概念都有鲜明的直观背景,其公理、定理也都有强烈的客观意义。像欧氏几何这样的公理系统,常被称为具体公理系统。

始于 Aristotle 的逻辑学被符号化、公理化,逐步演化为现代逻辑学。

# 形式化

所谓形式化,就是彻头彻尾的 “符号化 + 抽象公理化

现代逻辑学形式系统组成:

  • 用于将概念符号化的符号语言,通常为一形式语言,包括一符号表∑及语言的文法,可生成表示对象的语言成分项,表示概念、判断的公式;
  • 表示思维规律的逻辑学公理模式和推理规则模式 (抽象公理系统),及其依据它们推演可得到的全部定理组成的理论体系。

# 命题逻辑

以下讨论实际上均为二值逻辑

# 基本概念

# 命题

命题是具有真假意义的陈述句。

在特殊的情况下都具有 “真 (True)” 和 “假(False)” 的意义句子,都是命题。真值 —— 用 T 和 F 表示。

命题有两种类型:

  • 原子命题
  • 复合命题 —— 由以下内容复合构成的命题:
    • 联结词
    • 标点符号
    • 原子命题

# 命题逻辑

命题逻辑就是研究命题和命题之间关系的符号逻辑系统。

# 命题逻辑的符号

命题逻辑的符号:

  • 命题常元:True (T) 和 False (F)
  • 命题标识符:P、Q、R 等;
  • 联结词:
    • ¬(否定)
    • \land(合取)
    • \lor (析取)
    • →(蕴含)
    • ↔︎(等价)
  • 括号:( )

# 命题标识符

用 P、Q、R、S 等来表示命题。可分为:

  • 命题常量(表示确定的命题的命题标识符)
  • 命题变元(只表示任意命题的位置标志的命题标识符)
    • 当命题变元表示原子命题时,该变元称为原子变元

因为命题变元可以表示任意命题,所以它不能确定真值,故命题变元不是命题。

# 联结词

复合命题的意义是命题组成成份的函数。

联结词的语义可以定义如下:

  • ¬P 为真,当且仅当 P 为假
  • PQP \land Q 为真,当且仅当 P 和 Q 都为真
  • PQP \lor Q 为真,当且仅当 P 为真,或者 Q 为真
  • P → Q 为真,当且仅当 P 为假,或者 Q 为真
  • P ↔︎ Q 为真,当且仅当 P→Q 为真,并且 Q→P 为真

# 指派

当命题变元 P 用一个特定的命题取代时,P 才能确定真值,这时也称为对命题变元 P 进行指派

设 G 是公式,A1, ... , An, 为 G 中出现的所有原子命题。公式 G 的一种指派是对 A1, ... , An 赋予的一组真值,其中每个 Ai (i=1 , ... , n) 或者为 T 或者为 F。

公式 G 称为在一种指派下为真,当且仅当 G 按该指派算出的真值为 T,否则称为在该指派下为假

若在公式中有 n 个不同的原子 A1 , ... , An,那么该公式就有 2n2^n 个不同的指派。

# 永真 / 可满足 / 永假

公式 AA 称为永真式重言式 (tautology),如果对任意指派 α,α 均弄真 A,即 α(A)=T 。

公式 AA 称为可满足的 (satisfiable), 如果存在指派 α 使 α(A)=T,否则称 AA不可满足的 (unsatisfiable),或永假式

永真式是可满足的

AA 为永真式 (永假式) 时, ¬A\neg A 为永假式 (永真式)

# 蕴含 / 等价

称公式 AA 逻辑蕴涵公式 B,记为 ABA\to B ,如果所有弄真 AA 的指派亦必弄真公式 B

称公式集 Γ\Gamma 逻辑蕴涵公式 B,记为 ΓB\Gamma \to B ,如果弄真 Γ\Gamma 中所有公式的指派亦必弄真公式 B

称公式 AA 逻辑等价公式 B,记为 ABA\lrarr B ,如果 ABA\to BBAB\to A

  • 逻辑蕴涵关系具有
    • 自反性
    • 反对称性
    • 传递性
  • 逻辑等价关系具有
    • 自反性
    • 对称性
    • 传递性

# 代换

设 A 为含有命题变元 p 的永真式,那么将 A 中 p 的所有出现均代换为命题公式 B,所得公式 (称为 A 的代入实例) 仍为永真式。

# 替换

设命题公式 AA 含有子公式 C (C 为 A 中的符号串,且 C 为命题公式),如果 CDC\lrarr D,那么将 AA 中子公式 C 的某些出现 (未必全部) 用 D 替换后所得公式 B 满足 ABA\lrarr B

# 合 / 析 取范式

命题公式 B 称为命题公式 AA合取(或析取范式,如果 BAB\lrarr A,且 B 呈如下形式:

C1C2Cm(C1C2Cm),Ci(i=1,2,...,m)C_1\land C_2\land …\land C_m(或 C_1\lor C_2\lor …\lor C_m)\ \ ,\ \ C_i (i=1, 2,...,m)

其中 CiC_i 形如:

L1L2...Ln(L1L2Ln),Lj(j=l,2,...,n)L_1\lor L_2\lor ...\lor L_n (或L_1\land L_2\land …\land L_n)\ \ ,\ \ L_j(j=l,2,...,n)

其中 LiL_i 为原子公式或原子公式的否定,并称 LjL_j文字

【定理】

任一命题公式 φ 有其对应的合取 (析取) 范式。

# 主 合 / 析 取范式

命题公式 B 称为公式 A 的主合取 (或主析取) 范式,如果:

  • B 是 AA 的合取 (或析取) 范式
  • B 中每一子句均有 AA 中命题变元的全部出现,且仅出现一次。

n 元命题公式的全体可以划分为 22n2^{2^n} 个等价类,每一类中的公式彼此逻辑等价,并等价于它们共同的主合取范式 (或主析取范式)。

# 命题演算形式系统 PC

# 合式公式

pl,p2,p3,...p_l,p_2,p_3,... 为命题逻辑的合式公式

如果 A,B 是公式,那么这些也是命题逻辑的合式公式:

  • (¬A)(\neg A)
  • (AB)(A→B)

# 形式系统 PC 的组成

命题逻辑的形式系统 PC 包括 3 条公理模式 (A1A3)(A_1-A_3) 和 1 条推理规则(即分离规则rmpr_{mp}

  • A1:A(BA)A_1 : A\to(B\to A)
  • A2:A(BC)(AB)(AC)A_2 : A\to(B\to C)\to (A\to B)\to(A\to C)
  • A3:(¬A¬B)(BA)A_3 : (\neg A\to\neg B)\to(B\to A)
  • rmp:A,ABBr_{mp}:\frac{A,A\to B}{B}

# 证明

称下列公式序列为公式 AA 在 PC 中的一个证明 (proof):

A1,A2,...,Am(=A)A_1,A_2,...,A_m(=A)

其中 Ai(i=1,2,...,m)A_i (i=1,2,...,m)

  • 或者是 PC 的公理
  • 或者是 Aj(j<i)A_j (j\lt i)
  • 或者是由 Aj,Ak(j,k<i)A_j,A_k (j,k\lt i) 使用分离规则所导出
  • $A_m =A $

# 定理

AA 为 PC 中的定理,记为 PCA\vdash_{PC} A,如果公式 AA 在 PC 中有一个证明。

\vdash ( \vdash ) 断定符,表示可被推导出,可被证明

A\vDash A ( \vDash ) 表示 AA 永真

# 演绎

Γ\Gamma 为一公式集,称以下公式序列为公式 AA 的,以 Γ\Gamma 为前提的演绎

A1,A2,...,Am=A,Ai(i=1,2,...,m)A_1,A_2,...,A_m=A\ \ ,\ \ A_i (i=1,2,...,m)

其中 AiA_i 满足:

  • 或者是 PC 的公理
  • 或者是 Γ\Gamma 的成员
  • 或者是 Aj(j<i)A_j (j<i)
  • 或者是由 Aj,Ak(j,k<i)A_j, A_k (j,k\lt i) 使用分离规则所导出
  • Am=AA_m=A

# 带前提的演绎

AA 为前提 Γ\Gamma 的演绎结果,如果公式 AA 有以 Γ\Gamma 为前提的演绎。记为:

ΓPCA\Gamma\vdash_{PC}A

Γ={B}\Gamma=\{B\}ΓPCA\Gamma\vdash_{PC}A 可以表示为:

BPCAB\vdash_{PC}A

BPCAB\vdash_{PC}AAPCBA\vdash_{PC}B 则记为:

ABA\vdash\dashv B

# 演绎定理

对应离散数学课程中的 “附加前提证明法”

对 PC 中任意公式集 Γ\Gamma 和公式 A,BA,B

Γ{A}PCBΓPC(AB)\Gamma\cup\{A\}\vdash_{PC}B\lrArr\Gamma\vdash_{PC}(A\to B)

# 可靠性定理

PC 是可靠的,即对任意公式集 Γ\Gamma 及公式 AA

ΓAΓA\Gamma\vdash A\to \Gamma\vDash A

特别地,若 AA 为 PC 的定理 (A)(\vdash A) ,则 AA 永真 (A)(\vDash A) :

AA\vdash A\to \vDash A

# 一致性定理

PC 是一致的 (consistent),即不存在公式 A,使得 AA¬A\neg A 均为 PC 之定理。

# 完全性定理

PC 是完全的,即对任意公式集 Γ\Gamma 和公式 AA

ΓAΓA\Gamma\vDash A\to \Gamma\vdash A

特别地,若 AA 永真 (A)(\vDash A) ,A 必为 PC 的定理 (A)(\vdash A)

AA\vDash A\to \vdash A

# 谓词逻辑

谓词逻辑的语法元素表示如下。

  • 常量符号: A、B、张三、李四 等,通常是对象名称
  • 变量符号:通常用小写字母表示,如 x、 y、z 等
  • 函数符号:通常用小写英文字母或小写英文字母串表示,如 plus、f、g
    • 一元函数、二元函数、...... n 元函数
  • 谓词符号:通常用大写英文字母或 (首字母) 大写英文字母串表示
    • 一元谓词、二元谓词、...... n 元谓词
  • 联结词: ......
  • 量词:全称量词 \forall、存在量詞 \existx\forall x 表示 “対个体域中所有 xx”、x\exist x 表示 “在个 体域中存在个体 xx ”。\forall\exist 后面跟的 xx 叫作量词的指导变元

一般一元谓词表达了个体的性质,而多元谓词表达了个体之间的关系

# 谓词的阶

如果谓词 P 中的所有个体都是:

  • 个体常量
  • 变元
  • 函数

则该谓词为一阶谓词,如果某个个体本身又是一个一阶谓词,则称 PP二阶谓词,以此类推递归定义 nn 阶谓词

#

项可递归定义如下:

  1. 单独一个个体是项 (包括常量和变量)
  2. ffnn 元函数符号,而 t1,t2,...,tnt_1,t_2,...,t_n 是项,则 f(t1,t2,...,tn)f(t_1,t_2,...,t_n) 是项
  3. 任何项仅由规则 (1)、(2) 生成。

# 原子公式

PPnn 元谓词符号,t1,t2,...,tnt_1,t_2,...,t_n 都是项,则称 P(t1,t2,...,tn)P(t_1,t_2,...,t_n) 为原子公式。在原子公式中,若 t1,t2,...,tnt_1,t_2,...,t_n 都不含变量,则 P(t1,t2,...,tn)P(t_1,t_2,...,t_n) 是命题。

# 归结推理

# 最一般合一算法

给定公式集 S={S1,S2}S=\{S_1,S_2\} 进行合一,就是对 S1,S2S_1,S_2 进行合一。

DEMO:S={P(a,x,f(g(y))),P(z,h(z,u),f(u))}S=\{P(a,x,f(g(y))),P(z,h(z,u),f(u))\}

    • δ0=ϵ\delta_0=\epsilon
    • W0=S={P(a,x,f(g(y))),P(z,h(z,u),f(u))}W_0=S=\{P(a,x,f(g(y))),P(z,h(z,u),f(u))\}
    • D0={a,z}D_0=\{a,z\}
    • δ1=a/z\delta_1=a/z
    • W1={P(a,x,f(g(y)),P(a,h(a,u),f(u))}W_1=\{P(a,x,f(g(y)),P(a,h(a,u),f(u))\}
    • W1W_1 未合一,令 D1={x,h(a,u)}D_1=\{x,h(a,u)\}
    • δ2={a/z,h(a,u)/x}\delta_2=\{a/z,h(a,u)/x\}
    • W2={P(a,h(a,u),f(g(y))),P(a,h(a,u),f(u))}W_2=\{P(a,h(a,u),f(g(y))),P(a,h(a,u),f(u))\}
    • W2W_2 未合一,令 D2={g(y),u}D_2=\{g(y),u\}
    • δ3={a/z,h(a,u)/x,u/g(y)}\delta_3=\{a/z,h(a,u)/x,u/g(y)\}
    • W3={P(a,h(a,u)f(u)),P(a,h(a,u),f(u))}W_3=\{P(a,h(a,u)f(u)),P(a,h(a,u),f(u))\}
    • W3W_3 合一。所以 δ3={a/z,h(a,u)/x,u/g(y)}\delta_3=\{a/z,h(a,u)/x,u/g(y)\} 为最一般合一。

# 归结推理解题步骤

求证一个目标 GG 时,利用归结反演:若子句集 SS 是不可满足的,则可以使用归结规则由 SS 产生空子句 NIL ,具体解题步骤:

  1. 谓词公式表示问题

    1. (optional,定义常量)

    2. 定义谓词

    3. 将前提表示成谓词公式

      • 规则:

        R1:R_1:\cdots

        R2:R_2:\cdots

        ......

      • 事实

    4. 将要求证的问题表示成谓词公式

      • G=G=\cdots (target)
  2. 问题化为子句集

    1. R1:S1=R_1:\cdots \rArr S_1=\dots

      R1:S1=R_1:\cdots \rArr S_1=\cdots

      ......

    2. 事实:Si=S_i=\cdots

    3. 目标:SG=S_{\sim G}=\cdots(⚠️注意是 G\sim G⚠️)

    4. 得到 S=S1S2SG={,}S=S_1\cup S_2\cup\cdots\cup S_{\sim G}=\{\cdots\lor\cdots,\cdots\}

  3. 利用归结原理进行归结

    (1)S1(2)S2(k)(1)(2)归结,σ={a/x,b/y}(k+1)(3)(k)归结,σ={c/u,d/v}NIL\begin{aligned} &(1) S_1\\ &(2) S_2\\ &\cdots\\ &(k)\cdots &(1)(2)\text{归结}&,\sigma=\{a/x,b/y\}\\ &(k+1)\cdots &(3)(k)\text{归结}&,\sigma=\{c/u,d/v\}\\ &\cdots\\ &\text{NIL} \end{aligned}

# 搜索策略

对子句集进行归结时,一个关键问题是决定选取哪两个子句作归结,为此需要研究有效的归结控制策略。

# 排序策略

假设原始子句 (包括待证明合式公式的否定的子句) 称为 00 层归结式。(i+1)(i+1) 层的归结式是一个 ii 层归结式和一个 j(ji)j(j≤i) 层归结式进行归结所得到的归结式。

# 宽度优先

宽度优先就是先生成第 11 层所有的归结式,然后是第 22 层所有的归结式,以此类推,直到产生空子句结束,或不能再进行归结为止。

# 深度优先

深度优先是产生一个第 11 层的归结式,然后用第 11 层的归结式和第 00 层的归结式进行归结,得到第 22 层的归结式,直到产生空子句结束,否则,用第 22 层及其以下各层进行归结,产生第 33 层,以此类推。

# 单元优先

单元优先 (unit preference) 策略,即在归结过程中优先考虑仅由一个文字构成的子句,这样的子句称为单元子句。

# 精确策略

精确策略不涉及被归结子句的排序,它们只允许某些归结发生。

# 支持集

支持集 (set of support) 策略,实际是一种目标制导的反向推理

每次归结时,参与归结的子句中至少应有一个是:

  • 由目标公式的否定得到的子句
  • 或者是它们的后裔

所谓后裔是说,如果 SiS_iSi+1S_{i+1} 与另外某子句的归结式,或者 Si+1S_{i+1}SiS_i 的后裔与其他子句的归结式,则称 Si+1S_{i+1}SiS_i 的后裔, SiS_iSi+1S_{i+1} 的祖先。

支持集策略是完备的,即假如对一个不可满足的子句集合运用支持集策略进行归结,那么最终会导出空子句。

# 线性输入

线性输人 (linear input) 策略中参与归结的两个子句中至少有一个是原始子句集中的子句 (包括那些待证明的合式公式的否定)。

线性输人策略是高效的,但是不完备的,如子句集合 {PQ,PQ,PQ,PQ}\{P\lor Q,\ P\lor \sim Q,\ \sim P\lor Q,\ \sim P\lor \sim Q\} 不可满足,但是无法用线性输入归结推出。

# 线性归结

在归结过程中,除第一次归结都用给定的子句集中的子句外,其后每次归结则至少要有一个亲本子句是上次归结的结果。线性归结策略是完备的高效的

# 祖先过滤

由于线性输入策略是不完备的,改进该策略得到祖先过滤 (ancestry filtering) 策略,该策略是完备的而且是高效的。参与归结的两个子句中:

  • 至少有一个是初始子句集中的句子
  • 或者一个子句是另一个子句的祖先

# 单元归结

不完备但是高效,与单元优先的区别在于每次只考虑单元子句进行归结。

# 例题

实际上是我的作业

# 不是兄弟

已知:

  • 规则 1: 任何人的兄弟不是女性
  • 规则 2: 任何人的姐妹必是女性
  • 事实:Mary 是 Bill 的姐妹

用归结推理方法证明 Mary 不是 Tom 的兄弟


定义谓词:

  • F(x)F(x) : xx 是女性;(female)
  • M(x)M(x) : xx 是男性;(male)
  • B(x,y)B(x,y) : xxyy 的兄弟;(brother)
  • S(x,y)S(x,y) : xxyy 的姐妹;(sister)

问题用谓词公式表示:

R1:(x)(y)(B(x,y)F(x))R2:(x)(y)(S(x,y)F(x))Fact:(S(Marry,Bill))G:B(Marry,Tom)\begin{aligned} &R_1:(\forall x)(\forall y)(B(x,y)\to\sim F(x))\\ &R_2:(\forall x)(\forall y)(S(x,y)\to F(x))\\ &Fact:(S(Marry,Bill))\\ &\rArr\\ &G:\sim B(Marry,Tom) \end{aligned}

再将问题化为子句集:

R1:S1={B(x,y)F(x)}R2:S2={S(x,y)F(x)}Fact:S3={S(Marry,Bill)}G:S4=SG={B(Marry,Tom)}S=S1S2S3S4\begin{aligned} &R_1:S_1=\{\sim B(x,y)\lor\sim F(x)\}\\ &R_2:S_2=\{\sim S(x,y)\lor F(x)\}\\ &Fact:S_3=\{S(Marry,Bill)\}\\ &\sim G:S_4=S_{\sim G}=\{B(Marry,Tom)\}\\ &S=S_1\cup S_2\cup S_3\cup S_4 \end{aligned}

归结过程:

(1)B(x,y)F(x)(2)S(x,y)F(x)(3)S(Marry,Bill)(4)B(Marry,Tom)(5)F(x)(1)(4)归结,σ={Marry/x,Tom/y}(6)S(x,y)(2)(5)归结(7)NIL(3)(6)归结,σ={Marry/x,Bill/y}\begin{aligned} (1)& \sim B(x,y)\lor\sim F(x)\\ (2)& \sim S(x,y)\lor F(x)\\ (3)& S(Marry,Bill)\\ (4)& B(Marry,Tom)\\ (5)& \sim F(x) &(1)(4)\text{归结}&,\sigma=\{Marry/x,Tom/y\}\\ (6)& \sim S(x,y) &(2)(5)\text{归结}&\\ (7)&\text{NIL}&(3)(6)\text{归结}&,\sigma=\{Marry/x,Bill/y\}\\ \end{aligned}

程序验证:

ResolutionFOLeg1

# John 偷东西

用谓词逻辑的子句集表示下述刑侦知识,并用反演归结的支持集策略证明结论。

(1) 用子句集表示下述知识。

  1. John 是贼;
  2. Paul 喜欢酒 (wine);
  3. Paul (也) 喜欢奶酪 (cheese);
  4. 如果 Paul 喜欢某物,则 John 也喜欢;
  5. 如果某人是贼,而且喜欢某物,则他就可能会偷窃该物。

(2) 求:John 可能会偷窃什么?

# 用子句集表示知识

定义常量:

  • JohnJohn
  • PaulPaul
  • winewine:酒
  • cheesecheese:奶酪

定义谓词:

  • T(x)T(x) : xx 是贼;(thief)
  • L(x,y)L(x,y) : xx 喜欢 yy ;(like)
  • S(x,y)S(x,y) : xx 可能会偷窃 yy ; (stole)

用谓词逻辑的子句集表示:

S1={T(John)}S2={L(Paul,wine)}S3={L(Paul,cheese)}S4={L(Paul,x)L(John,x)}S5={T(x)L(x,y)S(x,y)}\begin{aligned} &S_1=\{T(John)\}\\ &S_2=\{L(Paul,wine)\}\\ &S_3=\{L(Paul,cheese)\}\\ &S_4=\{\sim L(Paul,x)\lor L(John,x)\}\\ &S_5=\{\sim T(x)\lor\sim L(x,y)\lor S(x,y)\} \end{aligned}

# 求解问题

这个 ANSWER(z)ANSWER(z) 是我按照网上答案做的,实际上我觉得不需要这么麻烦,用 S(John,z)S(John,z) 就可以了...

定义谓词 ANSWER(z)ANSWER(z) : zz 是所求问题的一个答案;

则问题 "John 可能会偷窃什么?" 可以表示为 S(John,z)ANSWER(z)S(John,z)\to ANSWER(z) 也就是析取式: S(John,z)ANSWER(z)\sim S(John,z)\lor ANSWER(z)

所有可能的答案包括:

  • ANSWER(wine)ANSWER(wine)
  • ANSWER(cheese)ANSWER(cheese)

证明 G=ANSWER(wine)ANSWER(cheese)G=ANSWER(wine)\land ANSWER(cheese) 问题,化为子句集:

S1={T(John)}S2={L(Paul,wine)}S3={L(Paul,cheese)}S4={L(Paul,x)L(John,x)}S5={T(x)L(x,y)S(x,y)}S6={S(John,z)ANSWER(z)}S7=SG=ANSWER(wine)ANSWER(cheese)S=S1S7\begin{aligned} &S_1=\{T(John)\}\\ &S_2=\{L(Paul,wine)\}\\ &S_3=\{L(Paul,cheese)\}\\ &S_4=\{\sim L(Paul,x)\lor L(John,x)\}\\ &S_5=\{\sim T(x)\lor\sim L(x,y)\lor S(x,y)\}\\ &S_6=\{\sim S(John,z)\lor ANSWER(z)\}\\ &S_7=S_{\sim G}=\sim ANSWER(wine)\lor\sim ANSWER(cheese)\\ &S=S_1\cup\cdots\cup S_7 \end{aligned}

支持集策略归结过程:

(1)T(John)(2)L(Paul,wine)(3)L(Paul,cheese)(4)L(Paul,x)L(John,x)(5)T(x)L(x,y)S(x,y)(6)S(John,z)ANSWER(z)(7)ANSWER(wine)ANSWER(cheese)(8)T(John)L(John,z)ANSWER(z)(5)(6)归结,σ={John/x,z/y}(9)T(John)L(Paul,z)ANSWER(z)(4)(8)归结,σ={z/x}(10)L(Paul,z)ANSWER(z)(1)(9)归结(11)ANSWER(wine)(2)(10)归结,σ={wine/z}(12)ANSWER(cheese)(7)(11)归结(13)ANSWER(cheese)(3)(10)归结,σ={cheese/z}(14)NIL(12)(13)归结\begin{aligned} (1)& T(John)\\ (2)& L(Paul,wine)\\ (3)& L(Paul,cheese)\\ (4)& \sim L(Paul,x)\lor L(John,x)\\ (5)& \sim T(x)\lor\sim L(x,y)\lor S(x,y)\\ (6)& \sim S(John,z)\lor ANSWER(z)\\ (7)& \sim ANSWER(wine)\lor\sim ANSWER(cheese)\\ (8)& \sim T(John)\lor\sim L(John,z)\lor ANSWER(z) &(5)(6)\text{归结}&,\sigma=\{John/x,z/y\}\\ (9)& \sim T(John)\lor\sim L(Paul,z)\lor ANSWER(z) &(4)(8)\text{归结}&,\sigma=\{z/x\}\\ (10)& \sim L(Paul,z)\lor ANSWER(z) &(1)(9)\text{归结}\\ (11)& ANSWER(wine) &(2)(10)\text{归结}&,\sigma=\{wine/z\}\\ (12)& \sim ANSWER(cheese) &(7)(11)\text{归结}\\ (13)& ANSWER(cheese) &(3)(10)\text{归结}&,\sigma=\{cheese/z\}\\ (14)& \text{NIL} &(12)(13)\text{归结} \end{aligned}

可证得:John 可能会偷酒(wine)和奶酪(cheese)

程序验证:

ResolutionFOLeg2

# 小张是快乐的

任何通过了历史考试并中了彩票的人都是快乐的。任何肯学习或幸运的人都可以通过所有考试,小张不学习,但很幸运,任何人只要是幸运的,就能中彩。

求证:小张是快乐的。


定义常量;

  • aa 表示小张
  • hh 表示历史考试(history)

定义谓词:

  • P(x,y)P(x,y) : xx 可以通过考试 yy(pass)
  • F(x)F(x) : xx 是幸运的(fortune)
  • S(x)S(x) : xx 肯学习(study)
  • H(x)H(x) : xx 是快乐的(happy)
  • L(x)L(x) : xx 中了彩票(lottery)

用谓词公式表示问题:

R1:(x)(P(x,h)L(x)H(x))R2:(x)(S(x)(y)(P(x,y)))R3:(x)(F(x)(y)(P(x,y)))R4:(x)(F(x)L(x))F1:S(a)F2:F(a)\begin{aligned} & R_1:(\forall x)(P(x,h)\land L(x)\to H(x))\\ & R_2:(\forall x)(S(x)\to(\forall y)(P(x,y)))\\ & R_3:(\forall x)(F(x)\to(\forall y)(P(x,y)))\\ & R_4:(\forall x)(F(x)\to L(x))\\ & F_1:\sim S(a)\\ & F_2:F(a) \end{aligned}

求证目标为:

G:H(a)G:H(a)

反演归结,将问题表示为子句集:

S1={P(x,h)L(x)H(x)}S2={S(x)P(x,y)}S3={F(x)P(x,y)}S4={F(x)L(x)}S5={S(a)}S6={F(a)}S7=SG={H(a)}S=S1S7\begin{aligned} & S_1=\{\sim P(x,h)\lor\sim L(x)\lor H(x)\}\\ & S_2=\{\sim S(x)\lor P(x,y)\}\\ & S_3=\{\sim F(x)\lor P(x,y)\}\\ & S_4=\{\sim F(x)\lor L(x)\}\\ & S_5=\{\sim S(a)\}\\ & S_6=\{F(a)\}\\ & S_7=S_{\sim G}=\{\sim H(a)\}\\ & S=S_1\cup\cdots\cup S_7 \end{aligned}

归结推理过程;

(1)P(x,h)L(x)H(x)(2)S(x)P(x,y)(3)F(x)P(x,y)(4)F(x)L(x)(5)S(a)(6)F(a)(7)H(a)(8)P(a,y)(3)(6)归结,σ={a/x}(9)L(a)(4)(6)归结,σ={a/x}(10)L(a)H(a)(1)(8)归结,σ={a/x,h/y}(11)H(a)(9)(10)归结(12)NIL(7)(11)归结\begin{aligned} (1)& \sim P(x,h)\lor\sim L(x)\lor H(x)\\ (2)& \sim S(x)\lor P(x,y)\\ (3)& \sim F(x)\lor P(x,y)\\ (4)& \sim F(x)\lor L(x)\\ (5)& \sim S(a)\\ (6)& F(a)\\ (7)& \sim H(a)\\ (8)& P(a,y) &(3)(6)\text{归结}&,\sigma=\{a/x\}\\ (9)& L(a) &(4)(6)\text{归结}&,\sigma=\{a/x\}\\ (10)& \sim L(a)\lor H(a) &(1)(8)\text{归结}&,\sigma=\{a/x,h/y\}\\ (11)& H(a) &(9)(10)\text{归结}\\ (12)& \text{NIL} &(7)(11)\text{归结} \end{aligned}

由此证得了:小张是快乐的。

程序验证:

ResolutionFOLeg3

# 程序实现

实际上是我的作业

python
import queue
def parse(KB: str):
    KB = KB.replace("{(", "").replace(")}", "")
    items = KB.split("),(")
    resolution_steps = map(lambda x: f'{items.index(x) + 1} ({x})', items)
    clauses = []
    for item in items:
        if item.endswith(')'):
            item = item[:-1]
        clause = []
        elements = item.split("),")
        if elements[-1] == '':
            elements.pop()
        for i in range(len(elements)):
            key, value = elements[i].split("(")
            clause.append([key, value.split(',')])
        clauses.append(clause)
    return clauses, list(resolution_steps)
def MGU(l1, l2):
    variants = ('x', 'y', 'z', 'u', 'v', 'w', 'xx', 'yy', 'zz', 'uu', 'vv', 'ww')
    dimension = len(l1)
    mapdict = {}
    for i in range(dimension):
        if l1[i] in variants and l2[i] not in variants:
            if mapdict.get(l1[i]) is None or mapdict[l1[i]] == l2[i]:
                mapdict[l1[i]] = l2[i]
            else:
                return None
        elif l1[i] not in variants and l2[i] in variants:
            if mapdict.get(l2[i]) is None or mapdict[l2[i]] == l1[i]:
                mapdict[l2[i]] = l1[i]
            else:
                return None
        elif l1[i] not in variants and l2[i] not in variants and l1[i] != l2[i]:
            return None
        else:
            if l1[i] != l2[i]:
                mapdict[l1[i]] = l2[i]
    return mapdict
# 以下是广度优先搜索策略
def resolve(c1, c2):
    list_c1keys = [sublist[0] for sublist in c1]
    list_c2keys = [sublist[0] for sublist in c2]
    for i in range(len(list_c1keys)):
        c1key: str = list_c1keys[i]
        idx_c1key = i
        flag = c1key.startswith('~')
        if flag:
            complement = c1key[1:]
        else:
            complement = '~' + c1key
        if complement in list_c2keys:
            idx_complement = list_c2keys.index(complement)
            mapdict = None
            if c1[idx_c1key][1] != c2[idx_complement][1]:
                result = MGU(c1[idx_c1key][1], c2[idx_complement][1])
                if result is None:
                    return None
                else:
                    mapdict = result
            if len(c1) > 1:
                char1 = chr(ord('a') + idx_c1key)
            else:
                char1 = '0'
            if len(c2) > 1:
                char2 = chr(ord('a') + idx_complement)
            else:
                char2 = '0'
            c1_to_del = list(c1)
            c2_to_del = list(c2)
            del c1_to_del[idx_c1key]
            del c2_to_del[idx_complement]
            c1_to_del.extend(c2_to_del)
            return c1_to_del, char1, char2, mapdict
    return None
def resolution(KB: str):
    clauses, resolution_steps = parse(KB)
    steps_idx = list(range(1, len(clauses) + 1))
    min_len = len(clauses)
    while True:
        l = len(clauses)
        for i in range(len(clauses)):
            for j in range(i + 1, len(clauses)):
                if i == j:
                    continue
                result = resolve(clauses[i], clauses[j])
                if result is None:
                    continue
                resolvent = result[0]
                if resolvent is None or resolvent in clauses:
                    continue
                clauses.append(resolvent)
                steps_idx.append([i, j])
                char1 = result[1]
                char2 = result[2]
                mapdict = result[3]
                if char1 == '0' and char2 == '0':
                    pre_string = f"R[{i + 1},{j + 1}]"
                elif char1 != '0' and char2 == '0':
                    pre_string = f"R[{i + 1}{char1},{j + 1}]"
                elif char1 == '0' and char2 != '0':
                    pre_string = f"R[{i + 1},{j + 1}{char2}]"
                else:
                    pre_string = f"R[{i + 1}{char1},{j + 1}{char2}]"
                map_string = ''
                if mapdict is not None:
                    pairs = []
                    for key, value in mapdict.items():
                        pairs.append(f"{key}={value}")
                    map_string = "{" + ",".join(pairs) + "}"
                result_string = ''
                for [key, value] in resolvent:
                    result_string += f'{key}({",".join(value)}),'
                if len(resolvent) > 1:
                    result_string = result_string[:-1]
                result_string = f'({result_string})'
                resolution_steps.append(f"{len(resolution_steps) + 1} {pre_string}{map_string} = {result_string}")
                if len(resolvent) == 0:
                    return resolution_steps, steps_idx, min_len
        if l == len(clauses):
            return None
def simplify_steps(steps, steps_idx, min_len):
    q = queue.Queue()
    not_del = [len(steps) - 1]
    q.put(steps_idx[len(steps) - 1][0])
    q.put(steps_idx[len(steps) - 1][1])
    while not q.empty():
        i = q.get()
        if i < min_len:
            continue
        not_del.append(i)
        q.put(steps_idx[i][0])
        q.put(steps_idx[i][1])
    for i in range(len(steps) - 1, min_len - 1, -1):
        if i not in not_del:
            del steps[i]
    num_map = dict()
    for i in range(len(steps)):
        num = (steps[i].split(' '))[0]
        num_map[num] = f'{i+1}'
        for t in list(num_map.keys()):
            steps[i] = steps[i].replace(t, num_map[t])
    return steps
def ResolutionFOL(KB):
    result = resolution(KB)
    if result is None:
        print("Can't be resolved!")
    else:
        (steps, steps_idx, min_len) = result
        steps = simplify_steps(steps, steps_idx, min_len)
        for step in steps:
            print(step)
if __name__ == '__main__':
    KB0 = "{(GradStudent(sue),),(~GradStudent(x),Student(x)),(~Student(x),HardWorker(x)),(~HardWorker(sue),)}"
    KB1 = "{(A(tony),),(A(mike),),(A(john),),(L(tony,rain),),(L(tony,snow),),(~A(x),S(x),C(x)),(~C(y),~L(y,rain)),(L(z,snow),~S(z)),(~L(tony,u),~L(mike,u)),(L(tony,v),L(mike,v)),(~A(w),~C(w),S(w))}"
    KB2 = "{(On(tony,mike),),(On(mike,john),),(Green(tony),),(~Green(john),),(~On(xx,yy),~Green(xx),Green(yy))}"
    KB3 = "{(~B(x,y),~F(x)),(~S(x,y),F(x)),(S(Marry,Bill)),(B(Marry,Tom))}"
    KB4 = "{(T(John),),(L(Paul,wine),),(L(Paul,cheese),),(~L(Paul,x),L(John,x)),(~T(x),~L(x,y),S(x,y)),(~S(John,z),ANSWER(z)),(~ANSWER(wine),~ANSWER(cheese))}"
    KB5 = "{(~P(x,h),~L(x),H(x)),(~S(x),P(x,y)),(~F(x),P(x,y)),(~F(x),L(x)),(~S(a)),(F(a)),(~H(a))}"
    ResolutionFOL(KB0)
    print("\x1B[31m--------------------\x1B[m")
    ResolutionFOL(KB1)
    print("\x1B[31m--------------------\x1B[m")
    ResolutionFOL(KB2)
    print("\x1B[31m--------------------\x1B[m")
    ResolutionFOL(KB3) # 不是兄弟
    print("\x1B[31m--------------------\x1B[m")
    ResolutionFOL(KB4) # John 偷东西
    print("\x1B[31m--------------------\x1B[m")
    ResolutionFOL(KB5) # 小张是快乐的
# 以下为单元归结策略
def resolve_2(c1, c2):
    list_c1keys = [sublist[0] for sublist in c1]
    list_c2keys = [sublist[0] for sublist in c2]
    c1key: str = list_c1keys[0]
    idx_c1key = list_c1keys.index(c1key)
    flag = c1key.startswith('~')
    if flag:
        complement = c1key[1:]
    else:
        complement = '~' + c1key
    if complement in list_c2keys:
        idx_complement = list_c2keys.index(complement)
        mapdict = None
        if c1[idx_c1key][1] != c2[idx_complement][1]:
            result = MGU(c1[idx_c1key][1], c2[idx_complement][1])
            if result is None:
                return None
            else:
                mapdict = result
        if len(c1) > 1:
            char1 = chr(ord('a') + idx_c1key)
        else:
            char1 = '0'
        if len(c2) > 1:
            char2 = chr(ord('a') + idx_complement)
        else:
            char2 = '0'
        c2_to_del = list(c2)
        del c2_to_del[idx_complement]
        return c2_to_del, char1, char2, mapdict
    return None
def resolution_2(KB: str):
    clauses, resolution_steps = parse(KB)
    singles = set()
    for i in range(len(clauses)):
        if len(clauses[i]) == 1:
            singles.add(i)
    while True:
        l = len(clauses)
        for i in range(len(clauses)):
            if i not in singles:
                continue
            for j in range(len(clauses)):
                if i == j:
                    continue
                result = resolve_2(clauses[i], clauses[j])
                if result is None:
                    continue
                resolvent = result[0]
                if resolvent is None or resolvent in clauses:
                    continue
                clauses.append(resolvent)
                char1 = result[1]
                char2 = result[2]
                mapdict = result[3]
                if char1 == '0' and char2 == '0':
                    pre_string = f"R[{i + 1},{j + 1}]"
                elif char1 != '0' and char2 == '0':
                    pre_string = f"R[{i + 1}{char1},{j + 1}]"
                elif char1 == '0' and char2 != '0':
                    pre_string = f"R[{i + 1},{j + 1}{char2}]"
                else:
                    pre_string = f"R[{i + 1}{char1},{j + 1}{char2}]"
                map_string = ''
                if mapdict is not None:
                    pairs = []
                    for key, value in mapdict.items():
                        pairs.append(f"{key}={value}")
                    map_string = "{" + ",".join(pairs) + "}"
                result_string = ''
                for [key, value] in resolvent:
                    result_string += f'{key}({",".join(value)}),'
                if len(resolvent) > 1:
                    result_string = result_string[:-1]
                result_string = f'({result_string})'
                resolution_steps.append(f"{len(resolution_steps) + 1} {pre_string}{map_string} = {result_string}")
                if len(resolvent) == 0:
                    return resolution_steps
                elif len(resolvent) == 1:
                    singles.add(len(clauses) - 1)
        if l == len(clauses):
            return None
def ResolutionFOL_2(KB):
    result = resolution_2(KB)
    if result is None:
        print("Can't be resolved!")
    else:
        for step in result:
            print(step)
\ No newline at end of file +知识表示与推理 - 人工智能 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 知识和知识表示

# 知识

  • 数据一般指单独的事实,是信息的载体
  • 信息由符号组成,如文字和数字,但是对符号赋予了一定的意义,因此有一定的用途或价值
  • 知识是由经验总结升华出来的,因此知识是经验的结晶。知识在信息的基础上增加了上下文信息,提供了更多的意义,因此也就更加有用和有价值。知识是随着时间的变化而动态变化的,新的知识可以根据规则和已有的知识推导出来。

知识是经过加工的信息,它包括:

  • 事实:是关于对象和物体的知识。
  • 规则:是有关问题中与事物的行动、动作相联系的因果关系的知识。
  • 元知识:是有关知识的知识,是知识库中的高层知识。
  • 常识性知识:泛指普遍存在而且被普遍认识了的客观事实一类知识。

# 策略

策略 —— 关于如何解决问题的政策方略,包括在什么时间、什么地点、由什么主体采取什么行动、达到什么目标、注意什么事项等等一整套完整而具体的行动计划规划、行动步骤、工作方式和工作方法

# 智能

在给定的 问题 - 问题环境 - 主体目的 的条件下,智能就是有针对性地获取 问题 - 环境 的信息,恰当地对这些信息进行处理以提炼知识达到认知,在此基础上,把已有的知识与主体的目的信息相结合,合理地产生解决问题的策略信息,并利用所得到的策略信息在给定的环境下成功地解决问题达到主体的目的 (行为)。

省流:信息经加工提炼而成知识,知识被目的激活而成智能。

智能具有 4 个能力:

  • 获取有用信息的能力
  • 由信息生成 == 知识 (认知)== 的能力
  • 由知识和目的生成 == 策略 (决策)== 的能力
  • 实施策略取得效果 (施效) 的能力

# 知识表示语言问题

  • 语法 —— 语言的语法描述了组成语句的可能的搭配关系。
  • 语义 —— 语义定义了语句所指的世界中的事实。

从语法和语义,可以给出使用该语言的 Agent 的必要的推理机制。

基于该推理机制,Agent 可以从已知的语句推导出结论,或判断某条信息是不是已蕴涵在现有的知识当中。

知识表示语言需要:

  • 语法规则
  • 语义解释
  • 用于演绎和推导的规则

知识表示语言应该支持知识不完全的情况。不能表达这种不完全性的语言是表达能力不够的语言

程序设计语言比较善于描述算法和具体的数据结构

# 现代逻辑学的基本研究方法

逻辑学 (logic) 是研究人类思维规律的科学,而现代逻辑学则是用数学 (符号化、公理化、形式化) 的方法来研究这些规律。

# 符号化

所谓符号化即是用 “一种只作整体认读的记号 (signs)”—— 符号 (symbols) 表示量、数及数量关系。也有用字母、符号表示思维的物理对象、概念对象、判断对象等。

语言化是符号化的初级阶段。

现代逻辑学对思维的研究,需要更加彻底的符号化过程。

# 公理化

欧氏几何公理系统中的所有概念都有鲜明的直观背景,其公理、定理也都有强烈的客观意义。像欧氏几何这样的公理系统,常被称为具体公理系统。

始于 Aristotle 的逻辑学被符号化、公理化,逐步演化为现代逻辑学。

# 形式化

所谓形式化,就是彻头彻尾的 “符号化 + 抽象公理化

现代逻辑学形式系统组成:

  • 用于将概念符号化的符号语言,通常为一形式语言,包括一符号表∑及语言的文法,可生成表示对象的语言成分项,表示概念、判断的公式;
  • 表示思维规律的逻辑学公理模式和推理规则模式 (抽象公理系统),及其依据它们推演可得到的全部定理组成的理论体系。

# 命题逻辑

以下讨论实际上均为二值逻辑

# 基本概念

# 命题

命题是具有真假意义的陈述句。

在特殊的情况下都具有 “真 (True)” 和 “假(False)” 的意义句子,都是命题。真值 —— 用 T 和 F 表示。

命题有两种类型:

  • 原子命题
  • 复合命题 —— 由以下内容复合构成的命题:
    • 联结词
    • 标点符号
    • 原子命题

# 命题逻辑

命题逻辑就是研究命题和命题之间关系的符号逻辑系统。

# 命题逻辑的符号

命题逻辑的符号:

  • 命题常元:True (T) 和 False (F)
  • 命题标识符:P、Q、R 等;
  • 联结词:
    • ¬(否定)
    • \land(合取)
    • \lor (析取)
    • →(蕴含)
    • ↔︎(等价)
  • 括号:( )

# 命题标识符

用 P、Q、R、S 等来表示命题。可分为:

  • 命题常量(表示确定的命题的命题标识符)
  • 命题变元(只表示任意命题的位置标志的命题标识符)
    • 当命题变元表示原子命题时,该变元称为原子变元

因为命题变元可以表示任意命题,所以它不能确定真值,故命题变元不是命题。

# 联结词

复合命题的意义是命题组成成份的函数。

联结词的语义可以定义如下:

  • ¬P 为真,当且仅当 P 为假
  • PQP \land Q 为真,当且仅当 P 和 Q 都为真
  • PQP \lor Q 为真,当且仅当 P 为真,或者 Q 为真
  • P → Q 为真,当且仅当 P 为假,或者 Q 为真
  • P ↔︎ Q 为真,当且仅当 P→Q 为真,并且 Q→P 为真

# 指派

当命题变元 P 用一个特定的命题取代时,P 才能确定真值,这时也称为对命题变元 P 进行指派

设 G 是公式,A1, ... , An, 为 G 中出现的所有原子命题。公式 G 的一种指派是对 A1, ... , An 赋予的一组真值,其中每个 Ai (i=1 , ... , n) 或者为 T 或者为 F。

公式 G 称为在一种指派下为真,当且仅当 G 按该指派算出的真值为 T,否则称为在该指派下为假

若在公式中有 n 个不同的原子 A1 , ... , An,那么该公式就有 2n2^n 个不同的指派。

# 永真 / 可满足 / 永假

公式 AA 称为永真式重言式 (tautology),如果对任意指派 α,α 均弄真 A,即 α(A)=T 。

公式 AA 称为可满足的 (satisfiable), 如果存在指派 α 使 α(A)=T,否则称 AA不可满足的 (unsatisfiable),或永假式

永真式是可满足的

AA 为永真式 (永假式) 时, ¬A\neg A 为永假式 (永真式)

# 蕴含 / 等价

称公式 AA 逻辑蕴涵公式 B,记为 ABA\to B ,如果所有弄真 AA 的指派亦必弄真公式 B

称公式集 Γ\Gamma 逻辑蕴涵公式 B,记为 ΓB\Gamma \to B ,如果弄真 Γ\Gamma 中所有公式的指派亦必弄真公式 B

称公式 AA 逻辑等价公式 B,记为 ABA\lrarr B ,如果 ABA\to BBAB\to A

  • 逻辑蕴涵关系具有
    • 自反性
    • 反对称性
    • 传递性
  • 逻辑等价关系具有
    • 自反性
    • 对称性
    • 传递性

# 代换

设 A 为含有命题变元 p 的永真式,那么将 A 中 p 的所有出现均代换为命题公式 B,所得公式 (称为 A 的代入实例) 仍为永真式。

# 替换

设命题公式 AA 含有子公式 C (C 为 A 中的符号串,且 C 为命题公式),如果 CDC\lrarr D,那么将 AA 中子公式 C 的某些出现 (未必全部) 用 D 替换后所得公式 B 满足 ABA\lrarr B

# 合 / 析 取范式

命题公式 B 称为命题公式 AA合取(或析取范式,如果 BAB\lrarr A,且 B 呈如下形式:

C1C2Cm(C1C2Cm),Ci(i=1,2,...,m)C_1\land C_2\land …\land C_m(或 C_1\lor C_2\lor …\lor C_m)\ \ ,\ \ C_i (i=1, 2,...,m)

其中 CiC_i 形如:

L1L2...Ln(L1L2Ln),Lj(j=l,2,...,n)L_1\lor L_2\lor ...\lor L_n (或L_1\land L_2\land …\land L_n)\ \ ,\ \ L_j(j=l,2,...,n)

其中 LiL_i 为原子公式或原子公式的否定,并称 LjL_j文字

【定理】

任一命题公式 φ 有其对应的合取 (析取) 范式。

# 主 合 / 析 取范式

命题公式 B 称为公式 A 的主合取 (或主析取) 范式,如果:

  • B 是 AA 的合取 (或析取) 范式
  • B 中每一子句均有 AA 中命题变元的全部出现,且仅出现一次。

n 元命题公式的全体可以划分为 22n2^{2^n} 个等价类,每一类中的公式彼此逻辑等价,并等价于它们共同的主合取范式 (或主析取范式)。

# 命题演算形式系统 PC

# 合式公式

pl,p2,p3,...p_l,p_2,p_3,... 为命题逻辑的合式公式

如果 A,B 是公式,那么这些也是命题逻辑的合式公式:

  • (¬A)(\neg A)
  • (AB)(A→B)

# 形式系统 PC 的组成

命题逻辑的形式系统 PC 包括 3 条公理模式 (A1A3)(A_1-A_3) 和 1 条推理规则(即分离规则rmpr_{mp}

  • A1:A(BA)A_1 : A\to(B\to A)
  • A2:A(BC)(AB)(AC)A_2 : A\to(B\to C)\to (A\to B)\to(A\to C)
  • A3:(¬A¬B)(BA)A_3 : (\neg A\to\neg B)\to(B\to A)
  • rmp:A,ABBr_{mp}:\frac{A,A\to B}{B}

# 证明

称下列公式序列为公式 AA 在 PC 中的一个证明 (proof):

A1,A2,...,Am(=A)A_1,A_2,...,A_m(=A)

其中 Ai(i=1,2,...,m)A_i (i=1,2,...,m)

  • 或者是 PC 的公理
  • 或者是 Aj(j<i)A_j (j\lt i)
  • 或者是由 Aj,Ak(j,k<i)A_j,A_k (j,k\lt i) 使用分离规则所导出
  • $A_m =A $

# 定理

AA 为 PC 中的定理,记为 PCA\vdash_{PC} A,如果公式 AA 在 PC 中有一个证明。

\vdash ( \vdash ) 断定符,表示可被推导出,可被证明

A\vDash A ( \vDash ) 表示 AA 永真

# 演绎

Γ\Gamma 为一公式集,称以下公式序列为公式 AA 的,以 Γ\Gamma 为前提的演绎

A1,A2,...,Am=A,Ai(i=1,2,...,m)A_1,A_2,...,A_m=A\ \ ,\ \ A_i (i=1,2,...,m)

其中 AiA_i 满足:

  • 或者是 PC 的公理
  • 或者是 Γ\Gamma 的成员
  • 或者是 Aj(j<i)A_j (j<i)
  • 或者是由 Aj,Ak(j,k<i)A_j, A_k (j,k\lt i) 使用分离规则所导出
  • Am=AA_m=A

# 带前提的演绎

AA 为前提 Γ\Gamma 的演绎结果,如果公式 AA 有以 Γ\Gamma 为前提的演绎。记为:

ΓPCA\Gamma\vdash_{PC}A

Γ={B}\Gamma=\{B\}ΓPCA\Gamma\vdash_{PC}A 可以表示为:

BPCAB\vdash_{PC}A

BPCAB\vdash_{PC}AAPCBA\vdash_{PC}B 则记为:

ABA\vdash\dashv B

# 演绎定理

对应离散数学课程中的 “附加前提证明法”

对 PC 中任意公式集 Γ\Gamma 和公式 A,BA,B

Γ{A}PCBΓPC(AB)\Gamma\cup\{A\}\vdash_{PC}B\lrArr\Gamma\vdash_{PC}(A\to B)

# 可靠性定理

PC 是可靠的,即对任意公式集 Γ\Gamma 及公式 AA

ΓAΓA\Gamma\vdash A\to \Gamma\vDash A

特别地,若 AA 为 PC 的定理 (A)(\vdash A) ,则 AA 永真 (A)(\vDash A) :

AA\vdash A\to \vDash A

# 一致性定理

PC 是一致的 (consistent),即不存在公式 A,使得 AA¬A\neg A 均为 PC 之定理。

# 完全性定理

PC 是完全的,即对任意公式集 Γ\Gamma 和公式 AA

ΓAΓA\Gamma\vDash A\to \Gamma\vdash A

特别地,若 AA 永真 (A)(\vDash A) ,A 必为 PC 的定理 (A)(\vdash A)

AA\vDash A\to \vdash A

# 谓词逻辑

谓词逻辑的语法元素表示如下。

  • 常量符号: A、B、张三、李四 等,通常是对象名称
  • 变量符号:通常用小写字母表示,如 x、 y、z 等
  • 函数符号:通常用小写英文字母或小写英文字母串表示,如 plus、f、g
    • 一元函数、二元函数、...... n 元函数
  • 谓词符号:通常用大写英文字母或 (首字母) 大写英文字母串表示
    • 一元谓词、二元谓词、...... n 元谓词
  • 联结词: ......
  • 量词:全称量词 \forall、存在量詞 \existx\forall x 表示 “対个体域中所有 xx”、x\exist x 表示 “在个 体域中存在个体 xx ”。\forall\exist 后面跟的 xx 叫作量词的指导变元

一般一元谓词表达了个体的性质,而多元谓词表达了个体之间的关系

# 谓词的阶

如果谓词 P 中的所有个体都是:

  • 个体常量
  • 变元
  • 函数

则该谓词为一阶谓词,如果某个个体本身又是一个一阶谓词,则称 PP二阶谓词,以此类推递归定义 nn 阶谓词

#

项可递归定义如下:

  1. 单独一个个体是项 (包括常量和变量)
  2. ffnn 元函数符号,而 t1,t2,...,tnt_1,t_2,...,t_n 是项,则 f(t1,t2,...,tn)f(t_1,t_2,...,t_n) 是项
  3. 任何项仅由规则 (1)、(2) 生成。

# 原子公式

PPnn 元谓词符号,t1,t2,...,tnt_1,t_2,...,t_n 都是项,则称 P(t1,t2,...,tn)P(t_1,t_2,...,t_n) 为原子公式。在原子公式中,若 t1,t2,...,tnt_1,t_2,...,t_n 都不含变量,则 P(t1,t2,...,tn)P(t_1,t_2,...,t_n) 是命题。

# 归结推理

# 最一般合一算法

给定公式集 S={S1,S2}S=\{S_1,S_2\} 进行合一,就是对 S1,S2S_1,S_2 进行合一。

DEMO:S={P(a,x,f(g(y))),P(z,h(z,u),f(u))}S=\{P(a,x,f(g(y))),P(z,h(z,u),f(u))\}

    • δ0=ϵ\delta_0=\epsilon
    • W0=S={P(a,x,f(g(y))),P(z,h(z,u),f(u))}W_0=S=\{P(a,x,f(g(y))),P(z,h(z,u),f(u))\}
    • D0={a,z}D_0=\{a,z\}
    • δ1=a/z\delta_1=a/z
    • W1={P(a,x,f(g(y)),P(a,h(a,u),f(u))}W_1=\{P(a,x,f(g(y)),P(a,h(a,u),f(u))\}
    • W1W_1 未合一,令 D1={x,h(a,u)}D_1=\{x,h(a,u)\}
    • δ2={a/z,h(a,u)/x}\delta_2=\{a/z,h(a,u)/x\}
    • W2={P(a,h(a,u),f(g(y))),P(a,h(a,u),f(u))}W_2=\{P(a,h(a,u),f(g(y))),P(a,h(a,u),f(u))\}
    • W2W_2 未合一,令 D2={g(y),u}D_2=\{g(y),u\}
    • δ3={a/z,h(a,u)/x,u/g(y)}\delta_3=\{a/z,h(a,u)/x,u/g(y)\}
    • W3={P(a,h(a,u)f(u)),P(a,h(a,u),f(u))}W_3=\{P(a,h(a,u)f(u)),P(a,h(a,u),f(u))\}
    • W3W_3 合一。所以 δ3={a/z,h(a,u)/x,u/g(y)}\delta_3=\{a/z,h(a,u)/x,u/g(y)\} 为最一般合一。

# 归结推理解题步骤

求证一个目标 GG 时,利用归结反演:若子句集 SS 是不可满足的,则可以使用归结规则由 SS 产生空子句 NIL ,具体解题步骤:

  1. 谓词公式表示问题

    1. (optional,定义常量)

    2. 定义谓词

    3. 将前提表示成谓词公式

      • 规则:

        R1:R_1:\cdots

        R2:R_2:\cdots

        ......

      • 事实

    4. 将要求证的问题表示成谓词公式

      • G=G=\cdots (target)
  2. 问题化为子句集

    1. R1:S1=R_1:\cdots \rArr S_1=\dots

      R1:S1=R_1:\cdots \rArr S_1=\cdots

      ......

    2. 事实:Si=S_i=\cdots

    3. 目标:SG=S_{\sim G}=\cdots(⚠️注意是 G\sim G⚠️)

    4. 得到 S=S1S2SG={,}S=S_1\cup S_2\cup\cdots\cup S_{\sim G}=\{\cdots\lor\cdots,\cdots\}

  3. 利用归结原理进行归结

    (1)S1(2)S2(k)(1)(2)归结,σ={a/x,b/y}(k+1)(3)(k)归结,σ={c/u,d/v}NIL\begin{aligned} &(1) S_1\\ &(2) S_2\\ &\cdots\\ &(k)\cdots &(1)(2)\text{归结}&,\sigma=\{a/x,b/y\}\\ &(k+1)\cdots &(3)(k)\text{归结}&,\sigma=\{c/u,d/v\}\\ &\cdots\\ &\text{NIL} \end{aligned}

# 搜索策略

对子句集进行归结时,一个关键问题是决定选取哪两个子句作归结,为此需要研究有效的归结控制策略。

# 排序策略

假设原始子句 (包括待证明合式公式的否定的子句) 称为 00 层归结式。(i+1)(i+1) 层的归结式是一个 ii 层归结式和一个 j(ji)j(j≤i) 层归结式进行归结所得到的归结式。

# 宽度优先

宽度优先就是先生成第 11 层所有的归结式,然后是第 22 层所有的归结式,以此类推,直到产生空子句结束,或不能再进行归结为止。

# 深度优先

深度优先是产生一个第 11 层的归结式,然后用第 11 层的归结式和第 00 层的归结式进行归结,得到第 22 层的归结式,直到产生空子句结束,否则,用第 22 层及其以下各层进行归结,产生第 33 层,以此类推。

# 单元优先

单元优先 (unit preference) 策略,即在归结过程中优先考虑仅由一个文字构成的子句,这样的子句称为单元子句。

# 精确策略

精确策略不涉及被归结子句的排序,它们只允许某些归结发生。

# 支持集

支持集 (set of support) 策略,实际是一种目标制导的反向推理

每次归结时,参与归结的子句中至少应有一个是:

  • 由目标公式的否定得到的子句
  • 或者是它们的后裔

所谓后裔是说,如果 SiS_iSi+1S_{i+1} 与另外某子句的归结式,或者 Si+1S_{i+1}SiS_i 的后裔与其他子句的归结式,则称 Si+1S_{i+1}SiS_i 的后裔, SiS_iSi+1S_{i+1} 的祖先。

支持集策略是完备的,即假如对一个不可满足的子句集合运用支持集策略进行归结,那么最终会导出空子句。

# 线性输入

线性输人 (linear input) 策略中参与归结的两个子句中至少有一个是原始子句集中的子句 (包括那些待证明的合式公式的否定)。

线性输人策略是高效的,但是不完备的,如子句集合 {PQ,PQ,PQ,PQ}\{P\lor Q,\ P\lor \sim Q,\ \sim P\lor Q,\ \sim P\lor \sim Q\} 不可满足,但是无法用线性输入归结推出。

# 线性归结

在归结过程中,除第一次归结都用给定的子句集中的子句外,其后每次归结则至少要有一个亲本子句是上次归结的结果。线性归结策略是完备的高效的

# 祖先过滤

由于线性输入策略是不完备的,改进该策略得到祖先过滤 (ancestry filtering) 策略,该策略是完备的而且是高效的。参与归结的两个子句中:

  • 至少有一个是初始子句集中的句子
  • 或者一个子句是另一个子句的祖先

# 单元归结

不完备但是高效,与单元优先的区别在于每次只考虑单元子句进行归结。

# 例题

实际上是我的作业

# 不是兄弟

已知:

  • 规则 1: 任何人的兄弟不是女性
  • 规则 2: 任何人的姐妹必是女性
  • 事实:Mary 是 Bill 的姐妹

用归结推理方法证明 Mary 不是 Tom 的兄弟


定义谓词:

  • F(x)F(x) : xx 是女性;(female)
  • M(x)M(x) : xx 是男性;(male)
  • B(x,y)B(x,y) : xxyy 的兄弟;(brother)
  • S(x,y)S(x,y) : xxyy 的姐妹;(sister)

问题用谓词公式表示:

R1:(x)(y)(B(x,y)F(x))R2:(x)(y)(S(x,y)F(x))Fact:(S(Marry,Bill))G:B(Marry,Tom)\begin{aligned} &R_1:(\forall x)(\forall y)(B(x,y)\to\sim F(x))\\ &R_2:(\forall x)(\forall y)(S(x,y)\to F(x))\\ &Fact:(S(Marry,Bill))\\ &\rArr\\ &G:\sim B(Marry,Tom) \end{aligned}

再将问题化为子句集:

R1:S1={B(x,y)F(x)}R2:S2={S(x,y)F(x)}Fact:S3={S(Marry,Bill)}G:S4=SG={B(Marry,Tom)}S=S1S2S3S4\begin{aligned} &R_1:S_1=\{\sim B(x,y)\lor\sim F(x)\}\\ &R_2:S_2=\{\sim S(x,y)\lor F(x)\}\\ &Fact:S_3=\{S(Marry,Bill)\}\\ &\sim G:S_4=S_{\sim G}=\{B(Marry,Tom)\}\\ &S=S_1\cup S_2\cup S_3\cup S_4 \end{aligned}

归结过程:

(1)B(x,y)F(x)(2)S(x,y)F(x)(3)S(Marry,Bill)(4)B(Marry,Tom)(5)F(x)(1)(4)归结,σ={Marry/x,Tom/y}(6)S(x,y)(2)(5)归结(7)NIL(3)(6)归结,σ={Marry/x,Bill/y}\begin{aligned} (1)& \sim B(x,y)\lor\sim F(x)\\ (2)& \sim S(x,y)\lor F(x)\\ (3)& S(Marry,Bill)\\ (4)& B(Marry,Tom)\\ (5)& \sim F(x) &(1)(4)\text{归结}&,\sigma=\{Marry/x,Tom/y\}\\ (6)& \sim S(x,y) &(2)(5)\text{归结}&\\ (7)&\text{NIL}&(3)(6)\text{归结}&,\sigma=\{Marry/x,Bill/y\}\\ \end{aligned}

程序验证:

ResolutionFOLeg1

# John 偷东西

用谓词逻辑的子句集表示下述刑侦知识,并用反演归结的支持集策略证明结论。

(1) 用子句集表示下述知识。

  1. John 是贼;
  2. Paul 喜欢酒 (wine);
  3. Paul (也) 喜欢奶酪 (cheese);
  4. 如果 Paul 喜欢某物,则 John 也喜欢;
  5. 如果某人是贼,而且喜欢某物,则他就可能会偷窃该物。

(2) 求:John 可能会偷窃什么?

# 用子句集表示知识

定义常量:

  • JohnJohn
  • PaulPaul
  • winewine:酒
  • cheesecheese:奶酪

定义谓词:

  • T(x)T(x) : xx 是贼;(thief)
  • L(x,y)L(x,y) : xx 喜欢 yy ;(like)
  • S(x,y)S(x,y) : xx 可能会偷窃 yy ; (stole)

用谓词逻辑的子句集表示:

S1={T(John)}S2={L(Paul,wine)}S3={L(Paul,cheese)}S4={L(Paul,x)L(John,x)}S5={T(x)L(x,y)S(x,y)}\begin{aligned} &S_1=\{T(John)\}\\ &S_2=\{L(Paul,wine)\}\\ &S_3=\{L(Paul,cheese)\}\\ &S_4=\{\sim L(Paul,x)\lor L(John,x)\}\\ &S_5=\{\sim T(x)\lor\sim L(x,y)\lor S(x,y)\} \end{aligned}

# 求解问题

这个 ANSWER(z)ANSWER(z) 是我按照网上答案做的,实际上我觉得不需要这么麻烦,用 S(John,z)S(John,z) 就可以了...

定义谓词 ANSWER(z)ANSWER(z) : zz 是所求问题的一个答案;

则问题 "John 可能会偷窃什么?" 可以表示为 S(John,z)ANSWER(z)S(John,z)\to ANSWER(z) 也就是析取式: S(John,z)ANSWER(z)\sim S(John,z)\lor ANSWER(z)

所有可能的答案包括:

  • ANSWER(wine)ANSWER(wine)
  • ANSWER(cheese)ANSWER(cheese)

证明 G=ANSWER(wine)ANSWER(cheese)G=ANSWER(wine)\land ANSWER(cheese) 问题,化为子句集:

S1={T(John)}S2={L(Paul,wine)}S3={L(Paul,cheese)}S4={L(Paul,x)L(John,x)}S5={T(x)L(x,y)S(x,y)}S6={S(John,z)ANSWER(z)}S7=SG=ANSWER(wine)ANSWER(cheese)S=S1S7\begin{aligned} &S_1=\{T(John)\}\\ &S_2=\{L(Paul,wine)\}\\ &S_3=\{L(Paul,cheese)\}\\ &S_4=\{\sim L(Paul,x)\lor L(John,x)\}\\ &S_5=\{\sim T(x)\lor\sim L(x,y)\lor S(x,y)\}\\ &S_6=\{\sim S(John,z)\lor ANSWER(z)\}\\ &S_7=S_{\sim G}=\sim ANSWER(wine)\lor\sim ANSWER(cheese)\\ &S=S_1\cup\cdots\cup S_7 \end{aligned}

支持集策略归结过程:

(1)T(John)(2)L(Paul,wine)(3)L(Paul,cheese)(4)L(Paul,x)L(John,x)(5)T(x)L(x,y)S(x,y)(6)S(John,z)ANSWER(z)(7)ANSWER(wine)ANSWER(cheese)(8)T(John)L(John,z)ANSWER(z)(5)(6)归结,σ={John/x,z/y}(9)T(John)L(Paul,z)ANSWER(z)(4)(8)归结,σ={z/x}(10)L(Paul,z)ANSWER(z)(1)(9)归结(11)ANSWER(wine)(2)(10)归结,σ={wine/z}(12)ANSWER(cheese)(7)(11)归结(13)ANSWER(cheese)(3)(10)归结,σ={cheese/z}(14)NIL(12)(13)归结\begin{aligned} (1)& T(John)\\ (2)& L(Paul,wine)\\ (3)& L(Paul,cheese)\\ (4)& \sim L(Paul,x)\lor L(John,x)\\ (5)& \sim T(x)\lor\sim L(x,y)\lor S(x,y)\\ (6)& \sim S(John,z)\lor ANSWER(z)\\ (7)& \sim ANSWER(wine)\lor\sim ANSWER(cheese)\\ (8)& \sim T(John)\lor\sim L(John,z)\lor ANSWER(z) &(5)(6)\text{归结}&,\sigma=\{John/x,z/y\}\\ (9)& \sim T(John)\lor\sim L(Paul,z)\lor ANSWER(z) &(4)(8)\text{归结}&,\sigma=\{z/x\}\\ (10)& \sim L(Paul,z)\lor ANSWER(z) &(1)(9)\text{归结}\\ (11)& ANSWER(wine) &(2)(10)\text{归结}&,\sigma=\{wine/z\}\\ (12)& \sim ANSWER(cheese) &(7)(11)\text{归结}\\ (13)& ANSWER(cheese) &(3)(10)\text{归结}&,\sigma=\{cheese/z\}\\ (14)& \text{NIL} &(12)(13)\text{归结} \end{aligned}

可证得:John 可能会偷酒(wine)和奶酪(cheese)

程序验证:

ResolutionFOLeg2

# 小张是快乐的

任何通过了历史考试并中了彩票的人都是快乐的。任何肯学习或幸运的人都可以通过所有考试,小张不学习,但很幸运,任何人只要是幸运的,就能中彩。

求证:小张是快乐的。


定义常量;

  • aa 表示小张
  • hh 表示历史考试(history)

定义谓词:

  • P(x,y)P(x,y) : xx 可以通过考试 yy(pass)
  • F(x)F(x) : xx 是幸运的(fortune)
  • S(x)S(x) : xx 肯学习(study)
  • H(x)H(x) : xx 是快乐的(happy)
  • L(x)L(x) : xx 中了彩票(lottery)

用谓词公式表示问题:

R1:(x)(P(x,h)L(x)H(x))R2:(x)(S(x)(y)(P(x,y)))R3:(x)(F(x)(y)(P(x,y)))R4:(x)(F(x)L(x))F1:S(a)F2:F(a)\begin{aligned} & R_1:(\forall x)(P(x,h)\land L(x)\to H(x))\\ & R_2:(\forall x)(S(x)\to(\forall y)(P(x,y)))\\ & R_3:(\forall x)(F(x)\to(\forall y)(P(x,y)))\\ & R_4:(\forall x)(F(x)\to L(x))\\ & F_1:\sim S(a)\\ & F_2:F(a) \end{aligned}

求证目标为:

G:H(a)G:H(a)

反演归结,将问题表示为子句集:

S1={P(x,h)L(x)H(x)}S2={S(x)P(x,y)}S3={F(x)P(x,y)}S4={F(x)L(x)}S5={S(a)}S6={F(a)}S7=SG={H(a)}S=S1S7\begin{aligned} & S_1=\{\sim P(x,h)\lor\sim L(x)\lor H(x)\}\\ & S_2=\{\sim S(x)\lor P(x,y)\}\\ & S_3=\{\sim F(x)\lor P(x,y)\}\\ & S_4=\{\sim F(x)\lor L(x)\}\\ & S_5=\{\sim S(a)\}\\ & S_6=\{F(a)\}\\ & S_7=S_{\sim G}=\{\sim H(a)\}\\ & S=S_1\cup\cdots\cup S_7 \end{aligned}

归结推理过程;

(1)P(x,h)L(x)H(x)(2)S(x)P(x,y)(3)F(x)P(x,y)(4)F(x)L(x)(5)S(a)(6)F(a)(7)H(a)(8)P(a,y)(3)(6)归结,σ={a/x}(9)L(a)(4)(6)归结,σ={a/x}(10)L(a)H(a)(1)(8)归结,σ={a/x,h/y}(11)H(a)(9)(10)归结(12)NIL(7)(11)归结\begin{aligned} (1)& \sim P(x,h)\lor\sim L(x)\lor H(x)\\ (2)& \sim S(x)\lor P(x,y)\\ (3)& \sim F(x)\lor P(x,y)\\ (4)& \sim F(x)\lor L(x)\\ (5)& \sim S(a)\\ (6)& F(a)\\ (7)& \sim H(a)\\ (8)& P(a,y) &(3)(6)\text{归结}&,\sigma=\{a/x\}\\ (9)& L(a) &(4)(6)\text{归结}&,\sigma=\{a/x\}\\ (10)& \sim L(a)\lor H(a) &(1)(8)\text{归结}&,\sigma=\{a/x,h/y\}\\ (11)& H(a) &(9)(10)\text{归结}\\ (12)& \text{NIL} &(7)(11)\text{归结} \end{aligned}

由此证得了:小张是快乐的。

程序验证:

ResolutionFOLeg3

# 程序实现

实际上是我的作业

python
import queue
def parse(KB: str):
    KB = KB.replace("{(", "").replace(")}", "")
    items = KB.split("),(")
    resolution_steps = map(lambda x: f'{items.index(x) + 1} ({x})', items)
    clauses = []
    for item in items:
        if item.endswith(')'):
            item = item[:-1]
        clause = []
        elements = item.split("),")
        if elements[-1] == '':
            elements.pop()
        for i in range(len(elements)):
            key, value = elements[i].split("(")
            clause.append([key, value.split(',')])
        clauses.append(clause)
    return clauses, list(resolution_steps)
def MGU(l1, l2):
    variants = ('x', 'y', 'z', 'u', 'v', 'w', 'xx', 'yy', 'zz', 'uu', 'vv', 'ww')
    dimension = len(l1)
    mapdict = {}
    for i in range(dimension):
        if l1[i] in variants and l2[i] not in variants:
            if mapdict.get(l1[i]) is None or mapdict[l1[i]] == l2[i]:
                mapdict[l1[i]] = l2[i]
            else:
                return None
        elif l1[i] not in variants and l2[i] in variants:
            if mapdict.get(l2[i]) is None or mapdict[l2[i]] == l1[i]:
                mapdict[l2[i]] = l1[i]
            else:
                return None
        elif l1[i] not in variants and l2[i] not in variants and l1[i] != l2[i]:
            return None
        else:
            if l1[i] != l2[i]:
                mapdict[l1[i]] = l2[i]
    return mapdict
# 以下是广度优先搜索策略
def resolve(c1, c2):
    list_c1keys = [sublist[0] for sublist in c1]
    list_c2keys = [sublist[0] for sublist in c2]
    for i in range(len(list_c1keys)):
        c1key: str = list_c1keys[i]
        idx_c1key = i
        flag = c1key.startswith('~')
        if flag:
            complement = c1key[1:]
        else:
            complement = '~' + c1key
        if complement in list_c2keys:
            idx_complement = list_c2keys.index(complement)
            mapdict = None
            if c1[idx_c1key][1] != c2[idx_complement][1]:
                result = MGU(c1[idx_c1key][1], c2[idx_complement][1])
                if result is None:
                    return None
                else:
                    mapdict = result
            if len(c1) > 1:
                char1 = chr(ord('a') + idx_c1key)
            else:
                char1 = '0'
            if len(c2) > 1:
                char2 = chr(ord('a') + idx_complement)
            else:
                char2 = '0'
            c1_to_del = list(c1)
            c2_to_del = list(c2)
            del c1_to_del[idx_c1key]
            del c2_to_del[idx_complement]
            c1_to_del.extend(c2_to_del)
            return c1_to_del, char1, char2, mapdict
    return None
def resolution(KB: str):
    clauses, resolution_steps = parse(KB)
    steps_idx = list(range(1, len(clauses) + 1))
    min_len = len(clauses)
    while True:
        l = len(clauses)
        for i in range(len(clauses)):
            for j in range(i + 1, len(clauses)):
                if i == j:
                    continue
                result = resolve(clauses[i], clauses[j])
                if result is None:
                    continue
                resolvent = result[0]
                if resolvent is None or resolvent in clauses:
                    continue
                clauses.append(resolvent)
                steps_idx.append([i, j])
                char1 = result[1]
                char2 = result[2]
                mapdict = result[3]
                if char1 == '0' and char2 == '0':
                    pre_string = f"R[{i + 1},{j + 1}]"
                elif char1 != '0' and char2 == '0':
                    pre_string = f"R[{i + 1}{char1},{j + 1}]"
                elif char1 == '0' and char2 != '0':
                    pre_string = f"R[{i + 1},{j + 1}{char2}]"
                else:
                    pre_string = f"R[{i + 1}{char1},{j + 1}{char2}]"
                map_string = ''
                if mapdict is not None:
                    pairs = []
                    for key, value in mapdict.items():
                        pairs.append(f"{key}={value}")
                    map_string = "{" + ",".join(pairs) + "}"
                result_string = ''
                for [key, value] in resolvent:
                    result_string += f'{key}({",".join(value)}),'
                if len(resolvent) > 1:
                    result_string = result_string[:-1]
                result_string = f'({result_string})'
                resolution_steps.append(f"{len(resolution_steps) + 1} {pre_string}{map_string} = {result_string}")
                if len(resolvent) == 0:
                    return resolution_steps, steps_idx, min_len
        if l == len(clauses):
            return None
def simplify_steps(steps, steps_idx, min_len):
    q = queue.Queue()
    not_del = [len(steps) - 1]
    q.put(steps_idx[len(steps) - 1][0])
    q.put(steps_idx[len(steps) - 1][1])
    while not q.empty():
        i = q.get()
        if i < min_len:
            continue
        not_del.append(i)
        q.put(steps_idx[i][0])
        q.put(steps_idx[i][1])
    for i in range(len(steps) - 1, min_len - 1, -1):
        if i not in not_del:
            del steps[i]
    num_map = dict()
    for i in range(len(steps)):
        num = (steps[i].split(' '))[0]
        num_map[num] = f'{i+1}'
        for t in list(num_map.keys()):
            steps[i] = steps[i].replace(t, num_map[t])
    return steps
def ResolutionFOL(KB):
    result = resolution(KB)
    if result is None:
        print("Can't be resolved!")
    else:
        (steps, steps_idx, min_len) = result
        steps = simplify_steps(steps, steps_idx, min_len)
        for step in steps:
            print(step)
if __name__ == '__main__':
    KB0 = "{(GradStudent(sue),),(~GradStudent(x),Student(x)),(~Student(x),HardWorker(x)),(~HardWorker(sue),)}"
    KB1 = "{(A(tony),),(A(mike),),(A(john),),(L(tony,rain),),(L(tony,snow),),(~A(x),S(x),C(x)),(~C(y),~L(y,rain)),(L(z,snow),~S(z)),(~L(tony,u),~L(mike,u)),(L(tony,v),L(mike,v)),(~A(w),~C(w),S(w))}"
    KB2 = "{(On(tony,mike),),(On(mike,john),),(Green(tony),),(~Green(john),),(~On(xx,yy),~Green(xx),Green(yy))}"
    KB3 = "{(~B(x,y),~F(x)),(~S(x,y),F(x)),(S(Marry,Bill)),(B(Marry,Tom))}"
    KB4 = "{(T(John),),(L(Paul,wine),),(L(Paul,cheese),),(~L(Paul,x),L(John,x)),(~T(x),~L(x,y),S(x,y)),(~S(John,z),ANSWER(z)),(~ANSWER(wine),~ANSWER(cheese))}"
    KB5 = "{(~P(x,h),~L(x),H(x)),(~S(x),P(x,y)),(~F(x),P(x,y)),(~F(x),L(x)),(~S(a)),(F(a)),(~H(a))}"
    ResolutionFOL(KB0)
    print("\x1B[31m--------------------\x1B[m")
    ResolutionFOL(KB1)
    print("\x1B[31m--------------------\x1B[m")
    ResolutionFOL(KB2)
    print("\x1B[31m--------------------\x1B[m")
    ResolutionFOL(KB3) # 不是兄弟
    print("\x1B[31m--------------------\x1B[m")
    ResolutionFOL(KB4) # John 偷东西
    print("\x1B[31m--------------------\x1B[m")
    ResolutionFOL(KB5) # 小张是快乐的
# 以下为单元归结策略
def resolve_2(c1, c2):
    list_c1keys = [sublist[0] for sublist in c1]
    list_c2keys = [sublist[0] for sublist in c2]
    c1key: str = list_c1keys[0]
    idx_c1key = list_c1keys.index(c1key)
    flag = c1key.startswith('~')
    if flag:
        complement = c1key[1:]
    else:
        complement = '~' + c1key
    if complement in list_c2keys:
        idx_complement = list_c2keys.index(complement)
        mapdict = None
        if c1[idx_c1key][1] != c2[idx_complement][1]:
            result = MGU(c1[idx_c1key][1], c2[idx_complement][1])
            if result is None:
                return None
            else:
                mapdict = result
        if len(c1) > 1:
            char1 = chr(ord('a') + idx_c1key)
        else:
            char1 = '0'
        if len(c2) > 1:
            char2 = chr(ord('a') + idx_complement)
        else:
            char2 = '0'
        c2_to_del = list(c2)
        del c2_to_del[idx_complement]
        return c2_to_del, char1, char2, mapdict
    return None
def resolution_2(KB: str):
    clauses, resolution_steps = parse(KB)
    singles = set()
    for i in range(len(clauses)):
        if len(clauses[i]) == 1:
            singles.add(i)
    while True:
        l = len(clauses)
        for i in range(len(clauses)):
            if i not in singles:
                continue
            for j in range(len(clauses)):
                if i == j:
                    continue
                result = resolve_2(clauses[i], clauses[j])
                if result is None:
                    continue
                resolvent = result[0]
                if resolvent is None or resolvent in clauses:
                    continue
                clauses.append(resolvent)
                char1 = result[1]
                char2 = result[2]
                mapdict = result[3]
                if char1 == '0' and char2 == '0':
                    pre_string = f"R[{i + 1},{j + 1}]"
                elif char1 != '0' and char2 == '0':
                    pre_string = f"R[{i + 1}{char1},{j + 1}]"
                elif char1 == '0' and char2 != '0':
                    pre_string = f"R[{i + 1},{j + 1}{char2}]"
                else:
                    pre_string = f"R[{i + 1}{char1},{j + 1}{char2}]"
                map_string = ''
                if mapdict is not None:
                    pairs = []
                    for key, value in mapdict.items():
                        pairs.append(f"{key}={value}")
                    map_string = "{" + ",".join(pairs) + "}"
                result_string = ''
                for [key, value] in resolvent:
                    result_string += f'{key}({",".join(value)}),'
                if len(resolvent) > 1:
                    result_string = result_string[:-1]
                result_string = f'({result_string})'
                resolution_steps.append(f"{len(resolution_steps) + 1} {pre_string}{map_string} = {result_string}")
                if len(resolvent) == 0:
                    return resolution_steps
                elif len(resolvent) == 1:
                    singles.add(len(clauses) - 1)
        if l == len(clauses):
            return None
def ResolutionFOL_2(KB):
    result = resolution_2(KB)
    if result is None:
        print("Can't be resolved!")
    else:
        for step in result:
            print(step)
\ No newline at end of file diff --git a/cs/ai/ml/index.html b/cs/ai/ml/index.html index fd77fd0a..4f52d7d9 100644 --- a/cs/ai/ml/index.html +++ b/cs/ai/ml/index.html @@ -1,5 +1,5 @@ -机器学习 - 人工智能 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 概述

# 机器学习范式

  • 监督学习(归纳学习)
    • 给定训练数据 training data
    • 和期望的输出(标签)desired outputs (with labels)
  • 半监督学习
    • 给定训练数据 training data
    • 和部分期望的输出 some labels
  • 无监督学习
    • 仅给定训练数据 training data
    • without labels
  • 强化学习 Reinforce Learning (RL)
    • 从序列决策中获取奖励 observations and periodic rewards as the agent takes sequential actions;

# 监督学习

# 回归问题

给定 (x1,y1),(x2,y2),,(xn,yn)(x_1,y_1),(x_2, y_2),\cdots,(x_n,y_n) ,学习一个函数 f(x)f(x) 能够根据输入 xx 预测 yy ,其中 yy数值,即回归

# 分类问题

给定 (x1,y1),(x2,y2),,(xn,yn)(x_1,y_1),(x_2, y_2),\cdots,(x_n,y_n) ,学习一个函数 f(x)f(x) 能够根据输入 xx 预测 yy ,其中 yy类别,即分类

# 聚类问题

给定 x1,x2,,xnx_1,x_2,\cdots,x_n(无标签),xx 是多维的,每一维对应一个属性,输出 xx 的隐变量

# 无监督学习

独立分量分析(ICA):一种用于分离混合信号中不同独立源的方法

e g :

  • 构建计算集群
  • 社交网络分析
  • 天文数据分析
  • 市场分割

# 强化学习

输入一组包括状态、动作、延迟奖励的序列,输出一个策略

策略是一个从状态到行动的映射函数,表明每个状态下所采取的行动或行动的分布

e g :

  • 分配问题
  • 游戏 AI
  • 机器人走迷宫
  • 控制平衡问题

# 机器学习归纳

现如今已有数以万计的机器学习算法,每年仍有数百种新方法。万变不离其宗,每种机器学习都由以下三部分组成:

  • 表征(模型)
  • 优化 / 搜索
  • 评估

# 表征 (模型)

# 数值函数

线性回归

神经网络

支持向量机

# 符号函数

决策树

命题逻辑中的规则

一阶谓语逻辑中的规则

# 基于实例的函数

最近邻

基于案例求解

# 概率图解模型

朴素贝叶斯

贝叶斯网络

隐性马尔可夫模型(HMMs)

概率上下文自由语法(PCFGs)

马尔可夫网络

# 优化 / 搜索

# 梯度下降

感知机

反向传播算法

# 动态编程

HMM 学习

PCFG 学习

# 分而治之

决策树归纳法

规则学习

# 进化计算

遗传算法(GA)

遗传编程(GP)

神经进化算法

# 评估方法

准确率

精度和召回率

均方误差

先验概率

后验概率

成本 / 效率

边际效用

KL 散度

......

# 一些经验

机器学习可以被看作是利用直接或间接的经验来逼近一个选定的目标函数。

函数近似可以看作是在假定的空间(函数的表征)中寻找最适合一组参数。

不同的学习方法设定不同的假定空间(表征语言)和 / 或 采用不同的搜索技术

# 基本方法

机器学习的开发流程:

  1. 数据搜集
  2. 数据清洗
  3. 特征工程
  4. 数据建模

# 模型

机器学习首先要考虑使用什么样的模型,直观理解就是使用什么分布函数拟合数据。

模型的类别,大致有两种:

  • 概率模型 (Probabilistic Model)
    • 决策树、朴素贝叶斯、隐马尔科夫模型、高斯混合模型
  • 非概率模型 (Non-Probabilistic Model)
    • 感知机、支持向量机、KNN、AdaBoost、K-means 以及神经网络

# 损失函数

  • 0-1 损失函数 (0-1 Loss Function)

L(Y,f(X))={1,Yf(x)0,Y=f(X)L(Y,f(X))=\begin{cases} 1,Y\ne f(x)\\ 0,Y=f(X) \end{cases}

  • 平方损失函数 (Quadratic Loss Function)

L(Y,f(X))=(Yf(X))2L(Y,f(X))=(Y-f(X))^2

  • 绝对损失函数 (Absolute Loss Function)

L(Y,f(X))=Yf(X)L(Y,f(X))=|Y-f(X)|

  • 对数损失函数 (Logarithmic Loss Function)

L(Y,P(YX))=logP(YX)L(Y,P(Y|X))=-\log P(Y|X)

根据上述损失函数模型,我们可知,损失函数值越小,模型性能越好。给定一个数据集,我们将训练数据集的平均损失称为经验风险

基于经验风险最小化原则,可构建全局损失函数求解最优化问题:

minf1Nn=1NL(yn,f(xn))\min_{f}\frac{1}{N}\sum_{n=1}^{N}L(y_n,f(x_n))

当样本数量足够大时,根据大数定理,经验风险会近似于模型的期望风险。此时,经验风险最小化能确保有好的学习性能。

然而,当样本数量不足时,单单利用经验风险最小化可能会导致 “过拟合” 的问题。为此,我们在原有基础上加上用于控制模型复杂度的正则项 (Regularizer),得到结构最小化准则。

# 优化算法

定义了损失函数计算 loss 之后,问题就转化为了求 loss 最小化的问题;如何使得 loss 最小化?就需要使用优化算法。

算法指的是模型学习中的具体计算方法。

一般来说,基于参数模型构建的统计学习问题都为最优化问题,它们都具有显式的解析解。

现有的优化方法主要有:

  • 梯度下降法⭐️
    • 一阶导数为 0 的点,不断下降寻找极小值
  • 牛顿法
  • 拟牛顿法
  • ADAM
  • ......

# 回归

# 损失函数

y(i)y^{(i)}y^(i)\hat{y}^{(i)} 分别表示第 ii 个样本的真实值和预测值, mm 为样本个数

# MSE

均方误差 (Mean Square Error, MSE)

MSE(y,y^)=1mi=1m(y(i)y^(i))2MSE(y,\hat y)=\frac 1m \sum_{i=1}^m (y^{(i)}-\hat{y}^{(i)})^2

# RMSE

均方根误差 (Root Mean Square Error, RMSE)

RMSE(y,y^)=1mi=1m(y(i)y^(i))2RMSE(y,\hat y)=\sqrt{\frac 1m \sum_{i=1}^m (y^{(i)}-\hat{y}^{(i)})^2}

# 概述

# 机器学习范式

  • 监督学习(归纳学习)
    • 给定训练数据 training data
    • 和期望的输出(标签)desired outputs (with labels)
  • 半监督学习
    • 给定训练数据 training data
    • 和部分期望的输出 some labels
  • 无监督学习
    • 仅给定训练数据 training data
    • without labels
  • 强化学习 Reinforce Learning (RL)
    • 从序列决策中获取奖励 observations and periodic rewards as the agent takes sequential actions;

# 监督学习

# 回归问题

给定 (x1,y1),(x2,y2),,(xn,yn)(x_1,y_1),(x_2, y_2),\cdots,(x_n,y_n) ,学习一个函数 f(x)f(x) 能够根据输入 xx 预测 yy ,其中 yy数值,即回归

# 分类问题

给定 (x1,y1),(x2,y2),,(xn,yn)(x_1,y_1),(x_2, y_2),\cdots,(x_n,y_n) ,学习一个函数 f(x)f(x) 能够根据输入 xx 预测 yy ,其中 yy类别,即分类

# 聚类问题

给定 x1,x2,,xnx_1,x_2,\cdots,x_n(无标签),xx 是多维的,每一维对应一个属性,输出 xx 的隐变量

# 无监督学习

独立分量分析(ICA):一种用于分离混合信号中不同独立源的方法

e g :

  • 构建计算集群
  • 社交网络分析
  • 天文数据分析
  • 市场分割

# 强化学习

输入一组包括状态、动作、延迟奖励的序列,输出一个策略

策略是一个从状态到行动的映射函数,表明每个状态下所采取的行动或行动的分布

e g :

  • 分配问题
  • 游戏 AI
  • 机器人走迷宫
  • 控制平衡问题

# 机器学习归纳

现如今已有数以万计的机器学习算法,每年仍有数百种新方法。万变不离其宗,每种机器学习都由以下三部分组成:

  • 表征(模型)
  • 优化 / 搜索
  • 评估

# 表征 (模型)

# 数值函数

线性回归

神经网络

支持向量机

# 符号函数

决策树

命题逻辑中的规则

一阶谓语逻辑中的规则

# 基于实例的函数

最近邻

基于案例求解

# 概率图解模型

朴素贝叶斯

贝叶斯网络

隐性马尔可夫模型(HMMs)

概率上下文自由语法(PCFGs)

马尔可夫网络

# 优化 / 搜索

# 梯度下降

感知机

反向传播算法

# 动态编程

HMM 学习

PCFG 学习

# 分而治之

决策树归纳法

规则学习

# 进化计算

遗传算法(GA)

遗传编程(GP)

神经进化算法

# 评估方法

准确率

精度和召回率

均方误差

先验概率

后验概率

成本 / 效率

边际效用

KL 散度

......

# 一些经验

机器学习可以被看作是利用直接或间接的经验来逼近一个选定的目标函数。

函数近似可以看作是在假定的空间(函数的表征)中寻找最适合一组参数。

不同的学习方法设定不同的假定空间(表征语言)和 / 或 采用不同的搜索技术

# 基本方法

机器学习的开发流程:

  1. 数据搜集
  2. 数据清洗
  3. 特征工程
  4. 数据建模

# 模型

机器学习首先要考虑使用什么样的模型,直观理解就是使用什么分布函数拟合数据。

模型的类别,大致有两种:

  • 概率模型 (Probabilistic Model)
    • 决策树、朴素贝叶斯、隐马尔科夫模型、高斯混合模型
  • 非概率模型 (Non-Probabilistic Model)
    • 感知机、支持向量机、KNN、AdaBoost、K-means 以及神经网络

# 损失函数

  • 0-1 损失函数 (0-1 Loss Function)

L(Y,f(X))={1,Yf(x)0,Y=f(X)L(Y,f(X))=\begin{cases} 1,Y\ne f(x)\\ 0,Y=f(X) \end{cases}

  • 平方损失函数 (Quadratic Loss Function)

L(Y,f(X))=(Yf(X))2L(Y,f(X))=(Y-f(X))^2

  • 绝对损失函数 (Absolute Loss Function)

L(Y,f(X))=Yf(X)L(Y,f(X))=|Y-f(X)|

  • 对数损失函数 (Logarithmic Loss Function)

L(Y,P(YX))=logP(YX)L(Y,P(Y|X))=-\log P(Y|X)

根据上述损失函数模型,我们可知,损失函数值越小,模型性能越好。给定一个数据集,我们将训练数据集的平均损失称为经验风险

基于经验风险最小化原则,可构建全局损失函数求解最优化问题:

minf1Nn=1NL(yn,f(xn))\min_{f}\frac{1}{N}\sum_{n=1}^{N}L(y_n,f(x_n))

当样本数量足够大时,根据大数定理,经验风险会近似于模型的期望风险。此时,经验风险最小化能确保有好的学习性能。

然而,当样本数量不足时,单单利用经验风险最小化可能会导致 “过拟合” 的问题。为此,我们在原有基础上加上用于控制模型复杂度的正则项 (Regularizer),得到结构最小化准则。

# 优化算法

定义了损失函数计算 loss 之后,问题就转化为了求 loss 最小化的问题;如何使得 loss 最小化?就需要使用优化算法。

算法指的是模型学习中的具体计算方法。

一般来说,基于参数模型构建的统计学习问题都为最优化问题,它们都具有显式的解析解。

现有的优化方法主要有:

  • 梯度下降法⭐️
    • 一阶导数为 0 的点,不断下降寻找极小值
  • 牛顿法
  • 拟牛顿法
  • ADAM
  • ......

# 回归

# 损失函数

y(i)y^{(i)}y^(i)\hat{y}^{(i)} 分别表示第 ii 个样本的真实值和预测值, mm 为样本个数

# MSE

均方误差 (Mean Square Error, MSE)

MSE(y,y^)=1mi=1m(y(i)y^(i))2MSE(y,\hat y)=\frac 1m \sum_{i=1}^m (y^{(i)}-\hat{y}^{(i)})^2

# RMSE

均方根误差 (Root Mean Square Error, RMSE)

RMSE(y,y^)=1mi=1m(y(i)y^(i))2RMSE(y,\hat y)=\sqrt{\frac 1m \sum_{i=1}^m (y^{(i)}-\hat{y}^{(i)})^2}

# MAE

平均绝对误差 (Mean Absolute Error, MAE)

MAE(y,y^)=1mi=1my(i)y^(i)MAE(y,\hat y)=\frac 1m \sum_{i=1}^m |y^{(i)}-\hat{y}^{(i)}|

# 线性回归

线性回归(Linear Regression)

是一种通过属性的线性组合来进行预测的线性模型,其目的是找到一条直线或者一个平面或者更高维的超平面,使得预测值与真实值之间的误差最小化。

  • 损失函数(Loss Function)度量单样本预测的错误程度,损失函数值越小,模型就越好。
  • 代价函数(Cost Function)度量全部样本集的平均误差。常用的代价函数包括均方误差、均方根误差、平均绝对误差等。
  • 目标函数(Object Function)代价函数和正则化函数,最终要优化的函数。
  • 学习率 α\alpha ,可以理解为步长

learning-rate

# 梯度下降

  • 批量梯度下降 BGD(Batch Gradient Descent)
    • 梯度下降的每一步中,都用到了所有的训练样本
  • 随机梯度下降 SGD(Stochastic Gradient Descent)
    • 梯度下降的每一步中,用到一个样本,在每一次计算之后便更新参数 ,而不需要首先将所有的训练集求和
  • 小批量梯度下降 MBGD(Mini-Batch Gradient Descent)
    • 梯度下降的每一步中,用到了一定批量的训练样本

wj:=wjα1bk=ii+b1(h(x(k))y(k))xj(k)w_{j}:=w_{j}-\alpha\frac{1}{b}\sum_{k=i}^{i+b-1}\big(h\big(x^{(k)}\big)-y^{(k)}\big)x_{j}^{(k)}

b=1b=1 为随机梯度下降 (SGD, Stochastic Gradient Descent)

b=mb=m 为批量梯度下降 (BGD, Batch Gradient Descent)

b=batch_sizeb=batch\_ size 为小批量梯度下降 (MBGD, Mini-Batch Gradient Descent)

归一化

数据归一化的目的是使得各特征对目标变量的影响一致,会将特征数据进行伸缩变化,所以数据归一化是会改变特征数据分布的

将数据映射到 [0,1][0,1] 区间

Z-Score

数据标准化为了不同特征之间具备可比性,经过标准化变换之后的特征数据分布没有发生改变。

就是当数据特征取值范围或单位差异较大时,最好是做一下标准化处理

处理后的数据均值为 0,方差为 1

欠拟合过拟合

# 过拟合的处理

# 交叉验证

交叉验证 Cross Validation

最常见的缓解过拟合问题的方法,将数据集分为训练用的和测试用的两份数据集(大多是 训练:测试 = 9:1 )

多重交叉验证 N-fold Cross Validation

迁移学习

# 获得更多的训练数据

使用更多的训练数据是解决过拟合问题最有效的手段,因为更多的样本能够让模型学习到更多更有效的特征,减小噪声的影响

# 降维

即丢弃一些不能帮助我们正确预测的特征。可以是手工选择保留哪些特征,或者使用一些模型选择的算法来帮忙(例如 PCA)。

# 正则化

正则化 (regularization) 的技术,保留所有的特征,但是减少参数的大小(magnitude),它可以改善或者减少过拟合问题。

# 集成学习方法

集成学习是把多个模型集成在一起,来降低单一模型的过拟合风险。

# 欠拟合的处理

# 添加新特征

当特征不足或者现有特征与样本标签的相关性不强时,模型容易出现欠拟合。通过挖掘组合特征等新的特征,往往能够取得更好的效果。

# 增加模型复杂度

简单模型的学习能力较差,通过增加模型的复杂度可以使模型拥有更强的拟合能力。例如,在线性模型中添加高次项,在神经网络模型中增加网络层数或神经元个数等。

# 减小正则化系数

正则化是用来防止过拟合的,但当模型出现欠拟合现象时,则需要有针对性地减小正则化系数。

# 分类问题

分类问题和回归问题有一定的相似性,都是通过对数据集的学习来对未知结果进行预测,区别在于输出值不同。

  • 分类问题的输出值是离散值(如垃圾邮件和正常邮件)。
  • 回归问题的输出值是连续值(例如房子的价格)。

在回归问题的基础上,对预测结果值进行量化,即将连续值量化为离散值,就能解决分类问题。

# 逻辑回归

逻辑回归是线性回归的一种扩展,用来处理分类问题。

常用的逻辑函数 Sigmoid 及其导函数:

σ(x)=11+exσ(x)=σ(x)[1σ(x)]\sigma(x)=\frac{1}{1+e^{-x}}\\ \sigma'(x)=\sigma(x)\cdot[1-\sigma(x)]

损失函数:

J(w)=1ml(w)=1mi=1m[y(i)ln(y^(i))+(1y(i))ln(1y^(i))]J(w)=-\frac{1}{m}l(w)=-\frac{1}{m}\sum_{i=1}^{m}\big[y^{(i)}\ln(\hat y^{(i)})+(1-y^{(i)})\ln(1-\hat y^{(i)})\big]

梯度为:

1mi=1m(y^(i)y(i))xj(i)\frac{1}{m}\sum_{i=1}^{m}(\hat y^{(i)}-y^{(i)})x^{(i)}_j

梯度下降更新参数 wjw_j

wj:=wjαJ(w)wjw_{j}:=w_{j}-\alpha\frac{\partial J(w)}{\partial w_j}

# SVM

支持向量机,Support Vector Machines,SVM

  • 支持向量:支撑平面上把两类类别划分开来的超平面的向量点
  • 机:一个算法

# 聚类问题

只考 K-means

# K-means

K-means 算法是一种无监督学习方法,是最普及的聚类算法,算法使用一个没有标签的数据集,然后将数据聚类成不同的组。

# 算法流程

  1. 初试化簇质心为的任意点(KK 个)。初试化时,必须注意簇的质心必须小于训练数据点的数目。

  2. 遍历所有数据点,计算所有质心与数据点的距离。这些簇将根据质心的最小距离而形成。

  3. 移动质心,因为上面步骤中形成的簇没有优化,所以需要形成优化的簇。为此需要迭代地将质心移动到一个新位置。取一个簇的数据点,计算平均值,然后将簇的质心移动到这个新位置。所有簇重复相同的步骤。

  4. 重复上述步骤,直至收敛。

# 优点缺点

  • 优点

    • 原理简单,实现容易,收敛速度快

    • 聚类效果较优

    • 算法的可解释度比较强

    • 主要需要调参的参数仅仅时簇数 K

  • 缺点

    • 需要预先指定簇的数量

    • 如果有两个高度重叠的数据,那么它就无法区分,也不能判断有两个簇

    • 欧几里得距离限制了能处理的数据变量类型

    • 随机选择质心并不能带来理想的结果

    • 无法处理异常值和噪声数据

    • 不适用于非线性数据

    • 对特征尺度敏感

    • 如果遇到非常大的数据集,那么计算机可能回崩溃

# 决策树模型

决策树基于 “树” 结构进行决策

  • 每个 “内部结点” 对应于某个属性上的 “测试”(test)
  • 每个分支对应于该测试的一种可能结果 (即该属性的某个取值)
  • 每个 “叶结点” 对应于一个 “预测结果”

学习过程:通过对训练样本的分析来确定 “划分属性”(即内部结点所对应的属性 )

预测过程:将测试示例从根结点开始沿着划分属性所构成的 “判定测试序列” 下行,直到叶结点

策略:“分而治之”( divide-and-conquer)

自根至叶的递归过程在每个中间结点寻找一个 “划分”( split or test) 属性。

三种停止条件

  • 当前结点包含的样本全属于同一类别,无需划分
  • 当前属性集为空,或是所有样本在所有属性上取值相同,无法划分
  • 当前结点包含的样本集合为空,不能划分

# 伪代码

  • 输入:

    • 训练集 D={(x1,y1),(x2,y2),,(xm,ym)}D=\{(x_1,y_1),(x_2,y_2),\cdots,(x_m,y_m)\}
    • 属性集 A={a1,a2,,ad}A=\{a_1,a_2,\cdots,a_d\}
  • 过程:

    • 函数 TreeGenerate(D,A)
  • 输出:

    • 以 node 为根结点的一棵决策树
伪代码
生成结点 node;
if D 中样本全属于同一类别 C then:
		将 node 标记为 C 类叶结点;
  	return;
end if;
if A is not None or D 中样本在 A 上取值相同 then:
		将 node 标记为叶结点,其类别标记为 D 中样本数最多的类;  # 利用当前结点的后验分布
  	return;
end if;
从 A 中选择最优划分属性 a ;
for a  的每一个值 a(i) do
		为 node 生成一个分支;
  	令 D(i) 表示 D 中在 a 上取值为 a(i) 的样本子集;
    if D(i) is None then:
    		将分支结点标记为叶结点,其类别标记为 D 中样本最多的类;  # 将父结点的样本分布作为当前结点的先验分布
      	return;
    else:
				以 TreeGenerate(D(i), A\{a}) 为分支结点
    end if;
end for;

# 信息增益 (ID3)

(ID3 算法)

一个离散属性 aa 的取值:{a1,a2,,aV}\{a^1,a^2,\cdots,a^V\}

DD 的信息熵定义为

Ent(D)=k=1ypklog2(pk)\text{Ent}(D)=-\sum_{k=1}^{|y|}p_k\log_2(p_k)

Ent(D)\text{Ent}(D) 的值越小,则 DD 的纯度越高

以属性 aa 对数据集 DD 进行划分,DvD^vDDaa 上取值为 ava_v 的样本集合,获得属性 aa信息增益为:

Gain(D,a)=Ent(D)v=1VDvDEnt(Dv)\text{Gain}(D,a)=\text{Ent}(D)-\sum_{v=1}^{V}\frac{|D^v|}{|D|}\text{Ent}(D^v)

其中:

  • Ent(D)\text{Ent}(D) 是划分前的信息熵;
  • v=1VDvD\sum_{v=1}^{V}\frac{|D^v|}{|D|} 是第 vv 个分支的权重,样本越多权重越大,该分支也就越重要;
  • Ent(Dv)\text{Ent}(D^v) 是划分后的信息熵;

Ent(D)\text{Ent}(D) 满足以下性质

Ent(D)=k=1ypklog2(pk)=k=1ypklog2(1pk)log2(k=1ypk1pk)=log2(y)\begin{aligned} \text{Ent}(D)&=-\sum_{k=1}^{|y|}p_k\log_2(p_k)=\sum_{k=1}^{|y|}p_k\log_2(\frac 1{p_k})\\ &\le \log_2\bigg(\sum_{k=1}^{|y|}p_k\frac 1{p_k}\bigg)=\log_2(|y|) \end{aligned}

# 增益率 (C4.5)

(C4.5 算法)

信息增益对可取值数目较多的属性有所偏好,有明显弱点,例如考虑将 “编号” 作为一个属性。所以引入增益率

GainRatio(D,a)=Gain(D,a)IV(a)\text{GainRatio}(D,a)=\frac{\text{Gain}(D,a)}{\text{IV}(a)}

其中:

IV(a)=v=1VDvDlog2DvD\text{IV}(a)=-\sum_{v=1}^{V}\frac{|D^v|}{|D|}\log_2\frac{|D^v|}{|D|}

属性 a 的可能取值数目越多 (即 V 越大),则 IV (a) 的值通常就越大

启发式:先从候选划分属性中找出信息增益高于平均水平的,再从中选取增益率最高的。

# 基尼系数 (CART)

(CART 算法)

样本集(数据集)DD 的基尼系数定义如下:

Gini(D)=k=1ykkpkpk=1k=1ypk2\text{Gini}(D)=\sum_{k=1}^{|y|}\sum_{k'\neq k}p_kp_{k'}=1-\sum_{k=1}^{|y|}p_k^2

反映了从 D 中随机抽取两个样例,其类别标记不一致的概率。

样本集(数据集)DD 的属性 aa 的基尼系数定义如下:

Gini(D,a)=v=1VDvDGini(D)\text{Gini}(D,a)=\sum_{v=1}^{V}\frac{|D^v|}{|D|}\text{Gini}(D)

建立决策树时,在候选属性集合中,选取那个使划分后基尼指数最小的属性。

# 剪枝

为了尽可能正确分类训练样本,有可能造成分支过多,也就是决策树的过拟合问题,可通过主动去掉一些分支来降低过拟合的风险

基本策略 :

  • 预剪枝 (pre-pruning) : 提前终止某些分支的生长

    在构造决策树的过程中,先对每个结点在划分前进行估计,如果当前结点的划分不能带来决策树模型泛化性能的提升,则不对当前结点进行划分并且将当前结点标记为叶结点。(泛化性能可根据在测试集上的准确率衡量)

    • 训练时间开销降低,测试时间开销降低
    • : 过拟合风险降低,欠拟合风险增加
  • 后剪枝 (post-pruning) : 生成一棵完全树,再 “回头” 剪枝

    先把整颗决策树构造完毕,然后自底向上的对非叶结点进行考察,若将该结点对应的子树换为叶结点能够带来泛化性能的提升,则把该子树替换为叶结点。

    • 训练时间开销增加,测试时间开销降低
    • 过拟合风险降低,欠拟合风险基本不变

泛化性能:后剪枝通常优于预剪枝

剪枝过程中需评估剪枝前后决策树的优劣

  • 现在我们假定使用 “留出法”

推荐阅读 https://blog.csdn.net/u012328159/article/details/79285214

Edited on Views times
\ No newline at end of file +219 661 l218 661zM702 80H400000v40H742z"/>

# MAE

平均绝对误差 (Mean Absolute Error, MAE)

MAE(y,y^)=1mi=1my(i)y^(i)MAE(y,\hat y)=\frac 1m \sum_{i=1}^m |y^{(i)}-\hat{y}^{(i)}|

# 线性回归

线性回归(Linear Regression)

是一种通过属性的线性组合来进行预测的线性模型,其目的是找到一条直线或者一个平面或者更高维的超平面,使得预测值与真实值之间的误差最小化。

  • 损失函数(Loss Function)度量单样本预测的错误程度,损失函数值越小,模型就越好。
  • 代价函数(Cost Function)度量全部样本集的平均误差。常用的代价函数包括均方误差、均方根误差、平均绝对误差等。
  • 目标函数(Object Function)代价函数和正则化函数,最终要优化的函数。
  • 学习率 α\alpha ,可以理解为步长

learning-rate

# 梯度下降

  • 批量梯度下降 BGD(Batch Gradient Descent)
    • 梯度下降的每一步中,都用到了所有的训练样本
  • 随机梯度下降 SGD(Stochastic Gradient Descent)
    • 梯度下降的每一步中,用到一个样本,在每一次计算之后便更新参数 ,而不需要首先将所有的训练集求和
  • 小批量梯度下降 MBGD(Mini-Batch Gradient Descent)
    • 梯度下降的每一步中,用到了一定批量的训练样本

wj:=wjα1bk=ii+b1(h(x(k))y(k))xj(k)w_{j}:=w_{j}-\alpha\frac{1}{b}\sum_{k=i}^{i+b-1}\big(h\big(x^{(k)}\big)-y^{(k)}\big)x_{j}^{(k)}

b=1b=1 为随机梯度下降 (SGD, Stochastic Gradient Descent)

b=mb=m 为批量梯度下降 (BGD, Batch Gradient Descent)

b=batch_sizeb=batch\_ size 为小批量梯度下降 (MBGD, Mini-Batch Gradient Descent)

归一化

数据归一化的目的是使得各特征对目标变量的影响一致,会将特征数据进行伸缩变化,所以数据归一化是会改变特征数据分布的

将数据映射到 [0,1][0,1] 区间

Z-Score

数据标准化为了不同特征之间具备可比性,经过标准化变换之后的特征数据分布没有发生改变。

就是当数据特征取值范围或单位差异较大时,最好是做一下标准化处理

处理后的数据均值为 0,方差为 1

欠拟合过拟合

# 过拟合的处理

# 交叉验证

交叉验证 Cross Validation

最常见的缓解过拟合问题的方法,将数据集分为训练用的和测试用的两份数据集(大多是 训练:测试 = 9:1 )

多重交叉验证 N-fold Cross Validation

迁移学习

# 获得更多的训练数据

使用更多的训练数据是解决过拟合问题最有效的手段,因为更多的样本能够让模型学习到更多更有效的特征,减小噪声的影响

# 降维

即丢弃一些不能帮助我们正确预测的特征。可以是手工选择保留哪些特征,或者使用一些模型选择的算法来帮忙(例如 PCA)。

# 正则化

正则化 (regularization) 的技术,保留所有的特征,但是减少参数的大小(magnitude),它可以改善或者减少过拟合问题。

# 集成学习方法

集成学习是把多个模型集成在一起,来降低单一模型的过拟合风险。

# 欠拟合的处理

# 添加新特征

当特征不足或者现有特征与样本标签的相关性不强时,模型容易出现欠拟合。通过挖掘组合特征等新的特征,往往能够取得更好的效果。

# 增加模型复杂度

简单模型的学习能力较差,通过增加模型的复杂度可以使模型拥有更强的拟合能力。例如,在线性模型中添加高次项,在神经网络模型中增加网络层数或神经元个数等。

# 减小正则化系数

正则化是用来防止过拟合的,但当模型出现欠拟合现象时,则需要有针对性地减小正则化系数。

# 分类问题

分类问题和回归问题有一定的相似性,都是通过对数据集的学习来对未知结果进行预测,区别在于输出值不同。

  • 分类问题的输出值是离散值(如垃圾邮件和正常邮件)。
  • 回归问题的输出值是连续值(例如房子的价格)。

在回归问题的基础上,对预测结果值进行量化,即将连续值量化为离散值,就能解决分类问题。

# 逻辑回归

逻辑回归是线性回归的一种扩展,用来处理分类问题。

常用的逻辑函数 Sigmoid 及其导函数:

σ(x)=11+exσ(x)=σ(x)[1σ(x)]\sigma(x)=\frac{1}{1+e^{-x}}\\ \sigma'(x)=\sigma(x)\cdot[1-\sigma(x)]

损失函数:

J(w)=1ml(w)=1mi=1m[y(i)ln(y^(i))+(1y(i))ln(1y^(i))]J(w)=-\frac{1}{m}l(w)=-\frac{1}{m}\sum_{i=1}^{m}\big[y^{(i)}\ln(\hat y^{(i)})+(1-y^{(i)})\ln(1-\hat y^{(i)})\big]

梯度为:

1mi=1m(y^(i)y(i))xj(i)\frac{1}{m}\sum_{i=1}^{m}(\hat y^{(i)}-y^{(i)})x^{(i)}_j

梯度下降更新参数 wjw_j

wj:=wjαJ(w)wjw_{j}:=w_{j}-\alpha\frac{\partial J(w)}{\partial w_j}

# SVM

支持向量机,Support Vector Machines,SVM

  • 支持向量:支撑平面上把两类类别划分开来的超平面的向量点
  • 机:一个算法

# 聚类问题

只考 K-means

# K-means

K-means 算法是一种无监督学习方法,是最普及的聚类算法,算法使用一个没有标签的数据集,然后将数据聚类成不同的组。

# 算法流程

  1. 初试化簇质心为的任意点(KK 个)。初试化时,必须注意簇的质心必须小于训练数据点的数目。

  2. 遍历所有数据点,计算所有质心与数据点的距离。这些簇将根据质心的最小距离而形成。

  3. 移动质心,因为上面步骤中形成的簇没有优化,所以需要形成优化的簇。为此需要迭代地将质心移动到一个新位置。取一个簇的数据点,计算平均值,然后将簇的质心移动到这个新位置。所有簇重复相同的步骤。

  4. 重复上述步骤,直至收敛。

# 优点缺点

  • 优点

    • 原理简单,实现容易,收敛速度快

    • 聚类效果较优

    • 算法的可解释度比较强

    • 主要需要调参的参数仅仅时簇数 K

  • 缺点

    • 需要预先指定簇的数量

    • 如果有两个高度重叠的数据,那么它就无法区分,也不能判断有两个簇

    • 欧几里得距离限制了能处理的数据变量类型

    • 随机选择质心并不能带来理想的结果

    • 无法处理异常值和噪声数据

    • 不适用于非线性数据

    • 对特征尺度敏感

    • 如果遇到非常大的数据集,那么计算机可能回崩溃

# 决策树模型

决策树基于 “树” 结构进行决策

  • 每个 “内部结点” 对应于某个属性上的 “测试”(test)
  • 每个分支对应于该测试的一种可能结果 (即该属性的某个取值)
  • 每个 “叶结点” 对应于一个 “预测结果”

学习过程:通过对训练样本的分析来确定 “划分属性”(即内部结点所对应的属性 )

预测过程:将测试示例从根结点开始沿着划分属性所构成的 “判定测试序列” 下行,直到叶结点

策略:“分而治之”( divide-and-conquer)

自根至叶的递归过程在每个中间结点寻找一个 “划分”( split or test) 属性。

三种停止条件

  • 当前结点包含的样本全属于同一类别,无需划分
  • 当前属性集为空,或是所有样本在所有属性上取值相同,无法划分
  • 当前结点包含的样本集合为空,不能划分

# 伪代码

  • 输入:

    • 训练集 D={(x1,y1),(x2,y2),,(xm,ym)}D=\{(x_1,y_1),(x_2,y_2),\cdots,(x_m,y_m)\}
    • 属性集 A={a1,a2,,ad}A=\{a_1,a_2,\cdots,a_d\}
  • 过程:

    • 函数 TreeGenerate(D,A)
  • 输出:

    • 以 node 为根结点的一棵决策树
伪代码
生成结点 node;
if D 中样本全属于同一类别 C then:
		将 node 标记为 C 类叶结点;
  	return;
end if;
if A is not None or D 中样本在 A 上取值相同 then:
		将 node 标记为叶结点,其类别标记为 D 中样本数最多的类;  # 利用当前结点的后验分布
  	return;
end if;
从 A 中选择最优划分属性 a ;
for a  的每一个值 a(i) do
		为 node 生成一个分支;
  	令 D(i) 表示 D 中在 a 上取值为 a(i) 的样本子集;
    if D(i) is None then:
    		将分支结点标记为叶结点,其类别标记为 D 中样本最多的类;  # 将父结点的样本分布作为当前结点的先验分布
      	return;
    else:
				以 TreeGenerate(D(i), A\{a}) 为分支结点
    end if;
end for;

# 信息增益 (ID3)

(ID3 算法)

一个离散属性 aa 的取值:{a1,a2,,aV}\{a^1,a^2,\cdots,a^V\}

DD 的信息熵定义为

Ent(D)=k=1ypklog2(pk)\text{Ent}(D)=-\sum_{k=1}^{|y|}p_k\log_2(p_k)

Ent(D)\text{Ent}(D) 的值越小,则 DD 的纯度越高

以属性 aa 对数据集 DD 进行划分,DvD^vDDaa 上取值为 ava_v 的样本集合,获得属性 aa信息增益为:

Gain(D,a)=Ent(D)v=1VDvDEnt(Dv)\text{Gain}(D,a)=\text{Ent}(D)-\sum_{v=1}^{V}\frac{|D^v|}{|D|}\text{Ent}(D^v)

其中:

  • Ent(D)\text{Ent}(D) 是划分前的信息熵;
  • v=1VDvD\sum_{v=1}^{V}\frac{|D^v|}{|D|} 是第 vv 个分支的权重,样本越多权重越大,该分支也就越重要;
  • Ent(Dv)\text{Ent}(D^v) 是划分后的信息熵;

Ent(D)\text{Ent}(D) 满足以下性质

Ent(D)=k=1ypklog2(pk)=k=1ypklog2(1pk)log2(k=1ypk1pk)=log2(y)\begin{aligned} \text{Ent}(D)&=-\sum_{k=1}^{|y|}p_k\log_2(p_k)=\sum_{k=1}^{|y|}p_k\log_2(\frac 1{p_k})\\ &\le \log_2\bigg(\sum_{k=1}^{|y|}p_k\frac 1{p_k}\bigg)=\log_2(|y|) \end{aligned}

# 增益率 (C4.5)

(C4.5 算法)

信息增益对可取值数目较多的属性有所偏好,有明显弱点,例如考虑将 “编号” 作为一个属性。所以引入增益率

GainRatio(D,a)=Gain(D,a)IV(a)\text{GainRatio}(D,a)=\frac{\text{Gain}(D,a)}{\text{IV}(a)}

其中:

IV(a)=v=1VDvDlog2DvD\text{IV}(a)=-\sum_{v=1}^{V}\frac{|D^v|}{|D|}\log_2\frac{|D^v|}{|D|}

属性 a 的可能取值数目越多 (即 V 越大),则 IV (a) 的值通常就越大

启发式:先从候选划分属性中找出信息增益高于平均水平的,再从中选取增益率最高的。

# 基尼系数 (CART)

(CART 算法)

样本集(数据集)DD 的基尼系数定义如下:

Gini(D)=k=1ykkpkpk=1k=1ypk2\text{Gini}(D)=\sum_{k=1}^{|y|}\sum_{k'\neq k}p_kp_{k'}=1-\sum_{k=1}^{|y|}p_k^2

反映了从 D 中随机抽取两个样例,其类别标记不一致的概率。

样本集(数据集)DD 的属性 aa 的基尼系数定义如下:

Gini(D,a)=v=1VDvDGini(D)\text{Gini}(D,a)=\sum_{v=1}^{V}\frac{|D^v|}{|D|}\text{Gini}(D)

建立决策树时,在候选属性集合中,选取那个使划分后基尼指数最小的属性。

# 剪枝

为了尽可能正确分类训练样本,有可能造成分支过多,也就是决策树的过拟合问题,可通过主动去掉一些分支来降低过拟合的风险

基本策略 :

  • 预剪枝 (pre-pruning) : 提前终止某些分支的生长

    在构造决策树的过程中,先对每个结点在划分前进行估计,如果当前结点的划分不能带来决策树模型泛化性能的提升,则不对当前结点进行划分并且将当前结点标记为叶结点。(泛化性能可根据在测试集上的准确率衡量)

    • 训练时间开销降低,测试时间开销降低
    • : 过拟合风险降低,欠拟合风险增加
  • 后剪枝 (post-pruning) : 生成一棵完全树,再 “回头” 剪枝

    先把整颗决策树构造完毕,然后自底向上的对非叶结点进行考察,若将该结点对应的子树换为叶结点能够带来泛化性能的提升,则把该子树替换为叶结点。

    • 训练时间开销增加,测试时间开销降低
    • 过拟合风险降低,欠拟合风险基本不变

泛化性能:后剪枝通常优于预剪枝

剪枝过程中需评估剪枝前后决策树的优劣

  • 现在我们假定使用 “留出法”

推荐阅读 https://blog.csdn.net/u012328159/article/details/79285214

Edited on Views times
\ No newline at end of file diff --git a/cs/ai/rl/index.html b/cs/ai/rl/index.html index e3913eaa..3eda9c98 100644 --- a/cs/ai/rl/index.html +++ b/cs/ai/rl/index.html @@ -1 +1 @@ -强化学习基础 - 人工智能 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

强烈推荐:https://hrl.boyuai.com/

# 基本概念

RL, in a nutshell, is to “learn to make good sequences of decisions through trail-and-errors”

# 机器学习范式

  • 监督

    • 给定训练数据 training data
    • 和期望的输出(标签)desired outputs (with labels)
  • 半监督

    • 给定训练数据 training data
    • 和部分期望的输出 some labels
  • 无监督

    • 仅给定训练数据 training data
    • without labels
  • 强化学习 Reinforce Learning (RL)

    • 从序列决策中获取奖励 observations and periodic rewards as the agent takes sequential actions;

强化学习是一种自动化目标导向的计算方法,与其他机器学习范式最大的区别在于:

  • 交互:与环境之间存在交互,从环境中学习
  • 决策序列:以前的决策会影响以后的决策,也就是学习的过程
  • 探索:不断试错、探索的学习过程

# 强化学习算法构成

# 给定

# 三大集合

  • 状态集合
  • 动作集合
  • 奖励值集合

# 两大模型 (两大主角)

两大模型

# 环境模型(optional)

述了环境的具体表现。在给定状态和动作情况下,模型可能会预测结果的下一个状态和下一个奖励

  • 有环境模型:定义了环境模型
  • 无环境模型:不定义环境模型,靠智能体感知实时状态来理解环境
# 主角模型(智能体)

概念来源于分布式人工智能思想。通常意义上,智能体是一个能够感知并施加某种作用到自身和环境、有生命周期的一个物理的或抽象的计算实体。智能体接受一个任务指令后,经过学习,可自主完成该任务

# 目标

智能体获取从任务开始到任务结束过程中每一步的最优动作

# 三大特征

  • 探索试错
  • 延迟回报
  • 长期目标

强化学习的关键特征是长期目标优化,智能体关注整体学习问题,优化整个过程

大多强化学习算法的关键特征是值函数的使用

# 特有挑战

探索和开发 (exploration and exploitation):短期和长期目标的权衡

# 强化学习的问题建模

# 问题模型

# 状态空间

智能体所处的实际环境所有状态集合

# 当前状态

智能体感知到的环境当前所处的状态

# 动作策略

智能体在某时间的行为

# 奖励信号

智能体收到的关于动作效果的反馈

# 价值函数

奖励信号 只能说明 动作的即时效果,而 价值函数 则指明什么策略的 长期效果 是好还是差。

# 马尔科夫决策问题模型

# 马尔可夫奖励过程 (MRP)

马尔可夫奖励过程(Markov reward process)

# 动作序列集

动作序列集(Action Sequence Set)是指一组按特定顺序排列的动作序列。它通常用于描述某个系统、机器人或智能体在特定环境中的行为。动作序列集可以包含一系列离散的动作步骤,也可以包含连续的动作序列。

动作序列集可以被分为两类:

  • 有终止态的离散动作(动作幕)
  • 无终止态的连续动作

# 动作幕 (Episode)

一个完整的有起始终止状态动作序列集(Episode,简称动作幕

  • 从标准起始态或从标准分布的初始态集合中抽取初始态开始
  • 以终止态结束
  • 不同动作序列集都可以认为是在同一个终止态结束,只是序列具体元素不同

区分奖励和收益

# 简单收益

Return (aka cumulative future reward) ,未来的累积奖励,也就是简单收益

# 折扣回报

Discounted Return ,折扣回报,也就是引入了折扣因子的简单收益。

# 马尔科夫决策过程 (MDP)

马尔可夫决策过程(Markov decision process,MDP)

MDP 与 MRP 非常相像,主要区别为 MDP 中的状态转移函数和奖励函数都比 MRP 多了动作 aa 作为自变量。

# 问题模型

MDP(马尔科夫决策过程)是一个描述智能体和环境交互的四元组 (S, A, 𝑅, 𝑝)

  • S :Status 状态的集合

  • A :Action 动作的集合

  • R :Reward 奖励的集合

  • p :当前状态执行了一个动作跳转到下一个状态的概率

  • 对象

    • 智能体
    • 环境
  • 交互

    • 动作
    • 状态
    • 奖励

MDP模型

# 状态 - 奖励表

扫地机器人状态 - 奖励表

扫地机器人状态-奖励表

# 状态迁移图

扫地机器人状态迁移图

扫地机器人状态迁移图

# 游戏轨迹

(state, action, reward) trajectory 游戏轨迹

s1,a1,r1,s2,a2,r2,sT,aT,rTs_1,a_1,r_1,s_2,a_2,r_2,\cdots s_T,a_T,r_T

即时奖励和长期目标的关系

某一决策的即时奖励较高不一定带来较高的长期目标

追求长期目标 ≠ 追求即时奖励

# 强化学习的值函数

# 基础概统知识

以下定义针对离散型随机变量:

# 概率

随机变量 A = a 发生的概率

p(A=a)p(A=a)

# 条件概率

在 C = c 条件下,A = a 的概率

p(A=aC=c)p(A=a|C=c)

智能体处于状态 s(S=s)s(S=s) 时,它的策略 π\pi 执行动作 a(A=a)a(A=a) 的概率

π(as)\pi(a|s)

# 期望

也称随机变量 𝑿 的期待值

E[X]=ixip(X=xi)\mathbb{E}[X]=\sum_i x_i p(X=x_i)

# 条件期望

Y=y 条件下,X 的期望

E[XY=y]=ixip(X=xiY=y)\mathbb{E}[X|Y=y]=\sum_i x_i p (X=x_i |Y=y)

# 简单值函数

直觉上看,为找到一个好的动作决策,需为每个动作赋值,只考虑了即时奖励,未考虑长期过程

有了值函数 q (a) ,决策问题即可转为优化问题求解,找最优动作:

argmaxaq(a)\underset{a}{argmax} \ q(a)

# 定义

q(a)=E[RA=a]a{1,...,k}=rp(ra)rq(a)=\mathbb{E}[R|A=a]\forall a\in \{ 1,...,k \}=\sum_r p(r|a)r

其中 p (r | a) 是在执行 a 动作情况下观察到智能体获得奖励 r 的概率;R 字母表示 Reward 奖励。

# 采样平均

除了按定义方法计算,还可以通过采样平均方法计算,即通过以往动作所获奖励情况来估算值函数

Q(a)=获得奖励的总和动作a的执行次数Q(a)=\frac{\text{获得奖励的总和}}{\text{动作a的执行次数}}

具体计算公式为:

Q(a)=i=1n1Ri1Ai=ai=1n11Ai=aQ(a)=\frac{\sum_{i=1}^{n-1}R_i \mathbb{1}_{A_i = a}}{\sum_{i=1}^{n-1}\mathbb{1}_{A_i = a}}

其中 1Ai=a\mathbb{1}_{A_i = a} 表示 Ai=aA_i =a 时取 1 ,否则取 0

# 问题

未考虑长期过程,实际并不采用

# 简单收益

# 简单收益的定义

G 字母表示 Gain 收益,也叫做回报 Return

Gt=Rt+1+Rt+2+Rt+3+...+RTG_t= R_{t+1}+R_{t+2}+R_{t+3}+...+R_T

# 简单收益的期望

# 离散动作的简单收益

E[Gt]=E[Rt+1+Rt+2+Rt+3+...+RT]\mathbb{E}[G_t]=\mathbb{E}[R_{t+1}+R_{t+2}+R_{t+3}+...+R_T]

# 连续动作的简单收益

E[Gt]=E[Rt+1+Rt+2+Rt+3+...]\mathbb{E}[G_t]=\mathbb{E}[R_{t+1}+R_{t+2}+R_{t+3}+...]

# 存在问题

若奖励都是非负的,收益会不会是无穷大?

# 折扣目标收益

引入折扣因子 γ\gammaγ<1\gamma \lt 1,得到折扣回报(Discounted Return):

Gt=Rt+1+γRt+2+γ2Rt+3+...+γk1Rt+k+...=k=0γkRt+k+1G_t= R_{t+1}+\gamma R_{t+2}+\gamma^2 R_{t+3}+...+ \gamma^{k-1}R_{t+k}+...=\sum_{k=0}^{\infin}\gamma^k R_{t+k+1}

γ=0\gamma =0 时:

Gt=Rt+1+0Rt+2+02Rt+3+...+0k1Rt+k+...=Rt+1G_t= R_{t+1}+0 R_{t+2}+0^2 R_{t+3}+...+ 0^{k-1}R_{t+k}+...=R_{t+1}

RmaxR_{max} 为智能体所能获取的最大奖励,则:

Rt+k+1RmaxR_{t+k+1}\leq R_{max}

Gt=k=0γkRt+k+1k=0γkRmax=Rmaxk=0γk=Rmax1γG_t = \sum_{k=0}^{\infin}\gamma^k R_{t+k+1} \leq \sum_{k=0}^{\infin}\gamma^k R_{max} = R_{max}\sum_{k=0}^{\infin}\gamma^k = \frac{R_{max}}{1-\gamma}

# 目标收益的递归计算

定义 GT=0,tTG_T = 0\ ,\ t\leq T

Gt=Rt+1+γRt+2+γ2Rt+3+...+γk1Rt+k+...=Rt+1+γ(Rt+2+γRt+3+...+γk2Rt+k+...)=Rt+1+γGt+1\begin{aligned} G_t &= R_{t+1}+\gamma R_{t+2}+\gamma^2 R_{t+3}+...+ \gamma^{k-1}R_{t+k}+... \\ &= R_{t+1}+\gamma (R_{t+2}+\gamma R_{t+3}+...+ \gamma^{k-2}R_{t+k}+...) \\ &= R_{t+1}+\gamma G_{t+1} \end{aligned}

从而有:

Gt=Rt+1+γGt+1G_t =R_{t+1}+\gamma G_{t+1}

特别地,t = T 时有 GT=0G_T = 0 ;t = T-1 时有 Gt1=RT+γGTG_{t-1} = R_T +\gamma G_T

# 标准状态值函数

一个状态在策略 𝝅 下的值函数,记作:vπ(s)v_\pi(s),是指该策略 𝝅 下,智能体在时间步 t 和所处状态 s 所能获得的奖励的期望值,即该值是从 s 开始,按照策略 𝝅 执行动作的预期收益

vπ(s)Eπ[GtSt=s]=Eπ[k=0γkRt+k+1St=s]v_\pi(s)\doteq \mathbb{E}_\pi[G_t|S_t=s]=\mathbb{E}_\pi[\sum_{k=0}^{\infin}\gamma^k R_{t+k+1} |S_t=s]

符号 \doteq 表示两个数值、表达式、模型之间的近似等于关系。这个符号通常用于数学和工程领域,在数值计算中,表示两个量非常接近或几乎相等,但并非完全相等。

# 标准动作值函数

一个动作在某个策略下的值函数,记作:qπ(s,a)q_\pi(s,a) ,是指该策略 𝝅 下,智能体在时间步 t 和所处状态 s,执行动作 𝒂 所获得的奖励的期望值,即从 s 开始,按照策略 𝝅 执行动作 𝒂 ,能获得的预期收益

qπ(s,a)Eπ[GtSt=s,At=a]=Eπ[k=0γkRt+k+1St=s,At=a]q_\pi(s,a)\doteq \mathbb{E}_\pi[G_t|S_t=s,A_t=a]=\mathbb{E}_\pi[\sum_{k=0}^{\infin}\gamma^k R_{t+k+1} |S_t=s,A_t=a]

两种值函数的区别在于:

  • 状态值函数相当于将当前状态 s 所有可能执行的动作都执行一遍,求奖励总和的期望
  • 动作值函数相当于只求当前状态 s 下某一个动作 a 的奖励的期望

# V 值的递归计算 (贝尔曼方程)

由目标收益的递归计算可以得到 V 值的递归计算:

V(s)=R(s)+γsSP(ss)V(s)V(s)=R(s)+\gamma\cdot\sum_{s'\in S}P(s'|s)\cdot V(s')

其中:

  • V(s)V(s)ss 状态的 V 值;
  • R(s)R(s)ss 状态的奖励
  • P(ss)P(s'|s) 是从 ss 状态转变为到 ss' 的概率;
  • γ\gamma 是折扣因子。

该式子也就是贝尔曼方程 (?)

# 从值函数计算最优策略

  • 策略:在每一个状态下执行何种动作?
  • 最优策略:能够最大化收益的动作执行决策

# 策略

# 确定性策略

在某一状态下智能体的策略采取动作 a 的概率是 100% ,即 π(s)=a\pi(s)=a

确定性策略

# 不确定性策略(随机策略)

也叫随机策略

π(as)\pi (a|s) 是在状态 ss 上采取的动作的概率分布,也可以表示某一状态 s 采取可能的行为 a 的概率,满足:

aA(s)π(as)=1π(as)0\sum_{a\in \mathcal{A}(s)}\pi (a|s)=1 \\ \pi (a|s)\geq 0

# 值函数的应用

值函数最高值的策略

无终止态MDP的状态值函数求法举例

# 贝尔曼期望方程

贝尔曼方程 (Bellman Equation) 就是递归计算值函数得到的值函数的方程。

贝尔曼期望方程(Bellman Expectation Equation)是为了与接下来的贝尔曼最优方程进行区分

# 状态值函数

v 值

vπ(s)Eπ[GtSt=s]=Eπ[Rt+1+γGt+1St=s]=Eπ[Rt+1]+γEπ[Gt+1St=s]Eπ[Rt+1]=aπ(as)srp(s,rs,a)[r]γEπ[Gt+1St=s]=aπ(as)srp(s,rs,a)[γEπ[Gt+1St+1=s]]=aπ(as)srp(s,rs,a)[γvπ(s)]vπ(s)=aπ(as)srp(s,rs,a)[r+γvπ(s)]\begin{aligned} v_\pi(s) &\doteq \mathbb{E}_\pi[G_t|S_t=s] \\ &= \mathbb{E}_\pi[R_{t+1}+\gamma G_{t+1}|S_t =s] \\ &= \mathbb{E}_\pi[R_{t+1}] + \gamma \mathbb{E}_\pi [G_{t+1}|S_t =s] \\ \mathbb{E}_\pi[R_{t+1}] &=\sum_a \pi (a|s)\sum_{s'}\sum_{r}p(s',r|s,a)[r] \\ \gamma \mathbb{E}_\pi [G_{t+1}|S_t =s] &= \sum_a \pi (a|s)\sum_{s'}\sum_{r}p(s',r|s,a)[\gamma \mathbb{E}_\pi [G_{t+1}|S_{t+1} =s']]\\ &= \sum_a \pi (a|s)\sum_{s'}\sum_{r}p(s',r|s,a)[\gamma v_{\pi}(s')]\\ v_\pi(s) &= \sum_a \pi (a|s)\sum_{s'}\sum_{r}p(s',r|s,a)[r+\gamma v_{\pi}(s')] \end{aligned}

其中 St+1=sS_{t+1}=s'

# 动作值函数

q 值

qπ(s,a)Eπ[GtSt=s,At=a]=srp(s,rs,a)[r+γEπ[Gt+1St+1=s]]=srp(s,rs,a)[r+γaπ(as)Eπ[Gt+1St+1=s,At+1=a]]qπ(s,a)=srp(s,rs,a)[r+γaπ(as)qπ(s,a)]\begin{aligned} q_\pi(s,a) &\doteq \mathbb{E}_\pi[G_t|S_t=s ,A_t=a] \\ &=\sum_{s'}\sum_{r}p(s',r|s,a)[r+\gamma \mathbb{E}_\pi [G_{t+1}|S_{t+1} =s']]\\ &=\sum_{s'}\sum_{r}p(s',r|s,a)[r+\gamma\sum_{a'}\pi (a'|s') \mathbb{E}_\pi [G_{t+1}|S_{t+1} =s',A_{t+1}=a']]\\ q_\pi(s,a) &=\sum_{s'}\sum_{r}p(s',r|s,a)[r+\gamma\sum_{a'}\pi (a'|s') q_{\pi}(s',a')]\\ \end{aligned}

其中 St+1=s,At+1=aS_{t+1}=s',A_{t+1}=a'

# 最优策略的数学表达

sS:π1π2vπ1(s)vπ2(s)\forall s\in \mathcal{S}:\pi_1\geq\pi_2\lrArr v_{\pi_1}(s)\geq v_{\pi_2}(s)

sS,aA:π1π2qπ1(s,a)qπ2(s,a)\forall s\in \mathcal{S},\forall a\in\mathcal{A}:\pi_1\geq\pi_2\lrArr q_{\pi_1}(s,a)\geq q_{\pi_2}(s,a)

从而有:

vπ(s)Eπ[GtSt=s]=maxπvπ(s),sSv_{\pi_*}(s)\doteq\mathbb{E}_{\pi_*}[G_t|S_t=s]=\max_\pi v_{\pi}(s),\forall s\in\mathcal{S}

qπ(s,a)=Eπ[GtSt=s,At=a]=maxπqπ(s,a),sS,aAq_{\pi_*}(s,a)=\mathbb{E}_{\pi_*}[G_{t}|S_{t} =s,A_{t}=a]=\max_\pi q_{\pi}(s,a),\forall s\in\mathcal{S},\forall a\in\mathcal{A}

* 表示最优的,这里 π\pi_* 表示最优策略

# 贝尔曼最优方程

v(s)=vπ(s)?v_*(s)=v_{\pi_*}(s)? 代替原来的 vπ(s)v_{\pi}(s)qπ(s,a)q_{\pi_*}(s,a) 代替原来的 qπ(s,a)q_{\pi}(s,a) ,那么原本的贝尔曼方程就变成贝尔曼最优方程,得到的表达式就是最优值函数

参考:https://blog.csdn.net/november_chopin/article/details/106589197,有 demo 更方便掌握。

# 最优状态值函数

v(s)=a=π(s)π(as)srp(s,rs,a)[r+γv(s)]=maxasrp(s,rs,a)[r+γv(s)]\begin{aligned} v_{*}(s) &= \sum_{a=\pi_{*}(s)} \pi_{*} (a|s)\sum_{s'}\sum_{r}p(s',r|s,a)[r+\gamma v_{*} (s')]\\ &= \max_{a}\sum_{s'}\sum_{r}p(s',r|s,a)[r+\gamma v_{*} (s')] \end{aligned}

# 最优状态值函数

qπ(s,a)=srp(s,rs,a)[r+γa=π(s)π(as)qπ(s,a)]=srp(s,rs,a)[r+γmaxaqπ(s,a)]\begin{aligned} q_{\pi_*}(s,a)&=\sum_{s'}\sum_{r}p(s',r|s,a)[r+\gamma\sum_{a'=\pi_*(s')}\pi_* (a'|s') q_{\pi_*}(s',a')]\\ &=\sum_{s'}\sum_{r}p(s',r|s,a)[r+\gamma \max_{a'} q_{\pi_*}(s',a')] \end{aligned}

# 两种最优值函数的关系

v(s)=maxasrp(s,rs,a)[r+γv(s)]=maxaEπ[Rt+1+γv(St+1)St=s,At=a]=maxaEπ[Rt+1+γGt+1St=s,At=a]=maxaEπ[GtSt=s,At=a]v(s)=maxaA(s)qπ(s,a)\begin{aligned} v_{*}(s) &= \max_{a}\sum_{s'}\sum_{r}p(s',r|s,a)[r+\gamma v_{*} (s')]\\ &= \max_{a}\mathbb{E}_\pi[R_{t+1}+\gamma v_{*}(S_{t+1})|S_t =s,A_t=a]\\ &= \max_{a}\mathbb{E}_{\pi_*}[R_{t+1}+\gamma G_{t+1}|S_t =s,A_t=a]\\ &= \max_{a}\mathbb{E}_{\pi_*}[G_t|S_t =s,A_t=a]\\ v_{*}(s) &= \max_{a\in\mathcal{A(s)}}q_{\pi_{*}}(s,a) \end{aligned}

# TDL

Temporal Difference Learning 差分学习

TD target :

yt=rt+γQ(st+1,at+1;w)=rt+γmaxaQ(st+1,a;w)\begin{aligned} y_t&=r_t+\gamma\cdot Q(s_{t+1},a_{t+1};w)\\ &=r_t+\gamma\cdot \max_aQ(s_{t+1},a;w) \end{aligned}

损失函数:

L=12[Q(w)y]2L=\frac{1}{2}[Q(w)-y]^2

梯度:

Lw=[Q(w)y]Q(w)w\frac{\partial L}{\partial w}=[Q(w)-y]\cdot\frac{\partial Q(w)}{\partial w}

梯度下降计算:

wt+1=wtαLtww=wtw_{t+1}=w_t-\alpha\cdot\frac{\partial L_t}{\partial w}\large|_{w=w_t}

# 算法流程

  1. Observe state St=stS_t=s_t and perform action At=atA_t=a_t
  2. Predict the value: qt=Q(st,at;wt)q_t=Q(s_t,a_t;w_t)
  3. Differentiate the value network: dt=Q(st,at;w)ww=wtd_t=\frac{\partial Q(s_t,a_t;w)}{\partial w}\large|_{w=w_t}
  4. Environment provides new state st+1s_{t+1} and reward rtr_t
  5. Compute TD target: yt=rt+γmaxa𝑄(st+1,a;wt)y_t=r_t+\gamma\cdot\max_a𝑄(s_{t+1},a;w_t)
  6. Gradient descent: wt+1=wtα(qtyt)dtw_{t+1}=w_t-\alpha\cdot(q_t-y_t)\cdot d_t

# 值估计

# Sarsa

State-Action-Reward-State-Action (SARSA)

使用 (st,at,rt,at+1)(s_t,a_t,r_t,a_{t+1}) 更新 QπQ_{\pi}

# 表格

Tabular version

# 神经网络

Value network version

# Q-Learning

# 表格

Tabular version

# 神经网络

DQN version

# 策略

Edited on Views times
\ No newline at end of file +强化学习基础 - 人工智能 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

强烈推荐:https://hrl.boyuai.com/

# 基本概念

RL, in a nutshell, is to “learn to make good sequences of decisions through trail-and-errors”

# 机器学习范式

  • 监督

    • 给定训练数据 training data
    • 和期望的输出(标签)desired outputs (with labels)
  • 半监督

    • 给定训练数据 training data
    • 和部分期望的输出 some labels
  • 无监督

    • 仅给定训练数据 training data
    • without labels
  • 强化学习 Reinforce Learning (RL)

    • 从序列决策中获取奖励 observations and periodic rewards as the agent takes sequential actions;

强化学习是一种自动化目标导向的计算方法,与其他机器学习范式最大的区别在于:

  • 交互:与环境之间存在交互,从环境中学习
  • 决策序列:以前的决策会影响以后的决策,也就是学习的过程
  • 探索:不断试错、探索的学习过程

# 强化学习算法构成

# 给定

# 三大集合

  • 状态集合
  • 动作集合
  • 奖励值集合

# 两大模型 (两大主角)

两大模型

# 环境模型(optional)

述了环境的具体表现。在给定状态和动作情况下,模型可能会预测结果的下一个状态和下一个奖励

  • 有环境模型:定义了环境模型
  • 无环境模型:不定义环境模型,靠智能体感知实时状态来理解环境
# 主角模型(智能体)

概念来源于分布式人工智能思想。通常意义上,智能体是一个能够感知并施加某种作用到自身和环境、有生命周期的一个物理的或抽象的计算实体。智能体接受一个任务指令后,经过学习,可自主完成该任务

# 目标

智能体获取从任务开始到任务结束过程中每一步的最优动作

# 三大特征

  • 探索试错
  • 延迟回报
  • 长期目标

强化学习的关键特征是长期目标优化,智能体关注整体学习问题,优化整个过程

大多强化学习算法的关键特征是值函数的使用

# 特有挑战

探索和开发 (exploration and exploitation):短期和长期目标的权衡

# 强化学习的问题建模

# 问题模型

# 状态空间

智能体所处的实际环境所有状态集合

# 当前状态

智能体感知到的环境当前所处的状态

# 动作策略

智能体在某时间的行为

# 奖励信号

智能体收到的关于动作效果的反馈

# 价值函数

奖励信号 只能说明 动作的即时效果,而 价值函数 则指明什么策略的 长期效果 是好还是差。

# 马尔科夫决策问题模型

# 马尔可夫奖励过程 (MRP)

马尔可夫奖励过程(Markov reward process)

# 动作序列集

动作序列集(Action Sequence Set)是指一组按特定顺序排列的动作序列。它通常用于描述某个系统、机器人或智能体在特定环境中的行为。动作序列集可以包含一系列离散的动作步骤,也可以包含连续的动作序列。

动作序列集可以被分为两类:

  • 有终止态的离散动作(动作幕)
  • 无终止态的连续动作

# 动作幕 (Episode)

一个完整的有起始终止状态动作序列集(Episode,简称动作幕

  • 从标准起始态或从标准分布的初始态集合中抽取初始态开始
  • 以终止态结束
  • 不同动作序列集都可以认为是在同一个终止态结束,只是序列具体元素不同

区分奖励和收益

# 简单收益

Return (aka cumulative future reward) ,未来的累积奖励,也就是简单收益

# 折扣回报

Discounted Return ,折扣回报,也就是引入了折扣因子的简单收益。

# 马尔科夫决策过程 (MDP)

马尔可夫决策过程(Markov decision process,MDP)

MDP 与 MRP 非常相像,主要区别为 MDP 中的状态转移函数和奖励函数都比 MRP 多了动作 aa 作为自变量。

# 问题模型

MDP(马尔科夫决策过程)是一个描述智能体和环境交互的四元组 (S, A, 𝑅, 𝑝)

  • S :Status 状态的集合

  • A :Action 动作的集合

  • R :Reward 奖励的集合

  • p :当前状态执行了一个动作跳转到下一个状态的概率

  • 对象

    • 智能体
    • 环境
  • 交互

    • 动作
    • 状态
    • 奖励

MDP模型

# 状态 - 奖励表

扫地机器人状态 - 奖励表

扫地机器人状态-奖励表

# 状态迁移图

扫地机器人状态迁移图

扫地机器人状态迁移图

# 游戏轨迹

(state, action, reward) trajectory 游戏轨迹

s1,a1,r1,s2,a2,r2,sT,aT,rTs_1,a_1,r_1,s_2,a_2,r_2,\cdots s_T,a_T,r_T

即时奖励和长期目标的关系

某一决策的即时奖励较高不一定带来较高的长期目标

追求长期目标 ≠ 追求即时奖励

# 强化学习的值函数

# 基础概统知识

以下定义针对离散型随机变量:

# 概率

随机变量 A = a 发生的概率

p(A=a)p(A=a)

# 条件概率

在 C = c 条件下,A = a 的概率

p(A=aC=c)p(A=a|C=c)

智能体处于状态 s(S=s)s(S=s) 时,它的策略 π\pi 执行动作 a(A=a)a(A=a) 的概率

π(as)\pi(a|s)

# 期望

也称随机变量 𝑿 的期待值

E[X]=ixip(X=xi)\mathbb{E}[X]=\sum_i x_i p(X=x_i)

# 条件期望

Y=y 条件下,X 的期望

E[XY=y]=ixip(X=xiY=y)\mathbb{E}[X|Y=y]=\sum_i x_i p (X=x_i |Y=y)

# 简单值函数

直觉上看,为找到一个好的动作决策,需为每个动作赋值,只考虑了即时奖励,未考虑长期过程

有了值函数 q (a) ,决策问题即可转为优化问题求解,找最优动作:

argmaxaq(a)\underset{a}{argmax} \ q(a)

# 定义

q(a)=E[RA=a]a{1,...,k}=rp(ra)rq(a)=\mathbb{E}[R|A=a]\forall a\in \{ 1,...,k \}=\sum_r p(r|a)r

其中 p (r | a) 是在执行 a 动作情况下观察到智能体获得奖励 r 的概率;R 字母表示 Reward 奖励。

# 采样平均

除了按定义方法计算,还可以通过采样平均方法计算,即通过以往动作所获奖励情况来估算值函数

Q(a)=获得奖励的总和动作a的执行次数Q(a)=\frac{\text{获得奖励的总和}}{\text{动作a的执行次数}}

具体计算公式为:

Q(a)=i=1n1Ri1Ai=ai=1n11Ai=aQ(a)=\frac{\sum_{i=1}^{n-1}R_i \mathbb{1}_{A_i = a}}{\sum_{i=1}^{n-1}\mathbb{1}_{A_i = a}}

其中 1Ai=a\mathbb{1}_{A_i = a} 表示 Ai=aA_i =a 时取 1 ,否则取 0

# 问题

未考虑长期过程,实际并不采用

# 简单收益

# 简单收益的定义

G 字母表示 Gain 收益,也叫做回报 Return

Gt=Rt+1+Rt+2+Rt+3+...+RTG_t= R_{t+1}+R_{t+2}+R_{t+3}+...+R_T

# 简单收益的期望

# 离散动作的简单收益

E[Gt]=E[Rt+1+Rt+2+Rt+3+...+RT]\mathbb{E}[G_t]=\mathbb{E}[R_{t+1}+R_{t+2}+R_{t+3}+...+R_T]

# 连续动作的简单收益

E[Gt]=E[Rt+1+Rt+2+Rt+3+...]\mathbb{E}[G_t]=\mathbb{E}[R_{t+1}+R_{t+2}+R_{t+3}+...]

# 存在问题

若奖励都是非负的,收益会不会是无穷大?

# 折扣目标收益

引入折扣因子 γ\gammaγ<1\gamma \lt 1,得到折扣回报(Discounted Return):

Gt=Rt+1+γRt+2+γ2Rt+3+...+γk1Rt+k+...=k=0γkRt+k+1G_t= R_{t+1}+\gamma R_{t+2}+\gamma^2 R_{t+3}+...+ \gamma^{k-1}R_{t+k}+...=\sum_{k=0}^{\infin}\gamma^k R_{t+k+1}

γ=0\gamma =0 时:

Gt=Rt+1+0Rt+2+02Rt+3+...+0k1Rt+k+...=Rt+1G_t= R_{t+1}+0 R_{t+2}+0^2 R_{t+3}+...+ 0^{k-1}R_{t+k}+...=R_{t+1}

RmaxR_{max} 为智能体所能获取的最大奖励,则:

Rt+k+1RmaxR_{t+k+1}\leq R_{max}

Gt=k=0γkRt+k+1k=0γkRmax=Rmaxk=0γk=Rmax1γG_t = \sum_{k=0}^{\infin}\gamma^k R_{t+k+1} \leq \sum_{k=0}^{\infin}\gamma^k R_{max} = R_{max}\sum_{k=0}^{\infin}\gamma^k = \frac{R_{max}}{1-\gamma}

# 目标收益的递归计算

定义 GT=0,tTG_T = 0\ ,\ t\leq T

Gt=Rt+1+γRt+2+γ2Rt+3+...+γk1Rt+k+...=Rt+1+γ(Rt+2+γRt+3+...+γk2Rt+k+...)=Rt+1+γGt+1\begin{aligned} G_t &= R_{t+1}+\gamma R_{t+2}+\gamma^2 R_{t+3}+...+ \gamma^{k-1}R_{t+k}+... \\ &= R_{t+1}+\gamma (R_{t+2}+\gamma R_{t+3}+...+ \gamma^{k-2}R_{t+k}+...) \\ &= R_{t+1}+\gamma G_{t+1} \end{aligned}

从而有:

Gt=Rt+1+γGt+1G_t =R_{t+1}+\gamma G_{t+1}

特别地,t = T 时有 GT=0G_T = 0 ;t = T-1 时有 Gt1=RT+γGTG_{t-1} = R_T +\gamma G_T

# 标准状态值函数

一个状态在策略 𝝅 下的值函数,记作:vπ(s)v_\pi(s),是指该策略 𝝅 下,智能体在时间步 t 和所处状态 s 所能获得的奖励的期望值,即该值是从 s 开始,按照策略 𝝅 执行动作的预期收益

vπ(s)Eπ[GtSt=s]=Eπ[k=0γkRt+k+1St=s]v_\pi(s)\doteq \mathbb{E}_\pi[G_t|S_t=s]=\mathbb{E}_\pi[\sum_{k=0}^{\infin}\gamma^k R_{t+k+1} |S_t=s]

符号 \doteq 表示两个数值、表达式、模型之间的近似等于关系。这个符号通常用于数学和工程领域,在数值计算中,表示两个量非常接近或几乎相等,但并非完全相等。

# 标准动作值函数

一个动作在某个策略下的值函数,记作:qπ(s,a)q_\pi(s,a) ,是指该策略 𝝅 下,智能体在时间步 t 和所处状态 s,执行动作 𝒂 所获得的奖励的期望值,即从 s 开始,按照策略 𝝅 执行动作 𝒂 ,能获得的预期收益

qπ(s,a)Eπ[GtSt=s,At=a]=Eπ[k=0γkRt+k+1St=s,At=a]q_\pi(s,a)\doteq \mathbb{E}_\pi[G_t|S_t=s,A_t=a]=\mathbb{E}_\pi[\sum_{k=0}^{\infin}\gamma^k R_{t+k+1} |S_t=s,A_t=a]

两种值函数的区别在于:

  • 状态值函数相当于将当前状态 s 所有可能执行的动作都执行一遍,求奖励总和的期望
  • 动作值函数相当于只求当前状态 s 下某一个动作 a 的奖励的期望

# V 值的递归计算 (贝尔曼方程)

由目标收益的递归计算可以得到 V 值的递归计算:

V(s)=R(s)+γsSP(ss)V(s)V(s)=R(s)+\gamma\cdot\sum_{s'\in S}P(s'|s)\cdot V(s')

其中:

  • V(s)V(s)ss 状态的 V 值;
  • R(s)R(s)ss 状态的奖励
  • P(ss)P(s'|s) 是从 ss 状态转变为到 ss' 的概率;
  • γ\gamma 是折扣因子。

该式子也就是贝尔曼方程 (?)

# 从值函数计算最优策略

  • 策略:在每一个状态下执行何种动作?
  • 最优策略:能够最大化收益的动作执行决策

# 策略

# 确定性策略

在某一状态下智能体的策略采取动作 a 的概率是 100% ,即 π(s)=a\pi(s)=a

确定性策略

# 不确定性策略(随机策略)

也叫随机策略

π(as)\pi (a|s) 是在状态 ss 上采取的动作的概率分布,也可以表示某一状态 s 采取可能的行为 a 的概率,满足:

aA(s)π(as)=1π(as)0\sum_{a\in \mathcal{A}(s)}\pi (a|s)=1 \\ \pi (a|s)\geq 0

# 值函数的应用

值函数最高值的策略

无终止态MDP的状态值函数求法举例

# 贝尔曼期望方程

贝尔曼方程 (Bellman Equation) 就是递归计算值函数得到的值函数的方程。

贝尔曼期望方程(Bellman Expectation Equation)是为了与接下来的贝尔曼最优方程进行区分

# 状态值函数

v 值

vπ(s)Eπ[GtSt=s]=Eπ[Rt+1+γGt+1St=s]=Eπ[Rt+1]+γEπ[Gt+1St=s]Eπ[Rt+1]=aπ(as)srp(s,rs,a)[r]γEπ[Gt+1St=s]=aπ(as)srp(s,rs,a)[γEπ[Gt+1St+1=s]]=aπ(as)srp(s,rs,a)[γvπ(s)]vπ(s)=aπ(as)srp(s,rs,a)[r+γvπ(s)]\begin{aligned} v_\pi(s) &\doteq \mathbb{E}_\pi[G_t|S_t=s] \\ &= \mathbb{E}_\pi[R_{t+1}+\gamma G_{t+1}|S_t =s] \\ &= \mathbb{E}_\pi[R_{t+1}] + \gamma \mathbb{E}_\pi [G_{t+1}|S_t =s] \\ \mathbb{E}_\pi[R_{t+1}] &=\sum_a \pi (a|s)\sum_{s'}\sum_{r}p(s',r|s,a)[r] \\ \gamma \mathbb{E}_\pi [G_{t+1}|S_t =s] &= \sum_a \pi (a|s)\sum_{s'}\sum_{r}p(s',r|s,a)[\gamma \mathbb{E}_\pi [G_{t+1}|S_{t+1} =s']]\\ &= \sum_a \pi (a|s)\sum_{s'}\sum_{r}p(s',r|s,a)[\gamma v_{\pi}(s')]\\ v_\pi(s) &= \sum_a \pi (a|s)\sum_{s'}\sum_{r}p(s',r|s,a)[r+\gamma v_{\pi}(s')] \end{aligned}

其中 St+1=sS_{t+1}=s'

# 动作值函数

q 值

qπ(s,a)Eπ[GtSt=s,At=a]=srp(s,rs,a)[r+γEπ[Gt+1St+1=s]]=srp(s,rs,a)[r+γaπ(as)Eπ[Gt+1St+1=s,At+1=a]]qπ(s,a)=srp(s,rs,a)[r+γaπ(as)qπ(s,a)]\begin{aligned} q_\pi(s,a) &\doteq \mathbb{E}_\pi[G_t|S_t=s ,A_t=a] \\ &=\sum_{s'}\sum_{r}p(s',r|s,a)[r+\gamma \mathbb{E}_\pi [G_{t+1}|S_{t+1} =s']]\\ &=\sum_{s'}\sum_{r}p(s',r|s,a)[r+\gamma\sum_{a'}\pi (a'|s') \mathbb{E}_\pi [G_{t+1}|S_{t+1} =s',A_{t+1}=a']]\\ q_\pi(s,a) &=\sum_{s'}\sum_{r}p(s',r|s,a)[r+\gamma\sum_{a'}\pi (a'|s') q_{\pi}(s',a')]\\ \end{aligned}

其中 St+1=s,At+1=aS_{t+1}=s',A_{t+1}=a'

# 最优策略的数学表达

sS:π1π2vπ1(s)vπ2(s)\forall s\in \mathcal{S}:\pi_1\geq\pi_2\lrArr v_{\pi_1}(s)\geq v_{\pi_2}(s)

sS,aA:π1π2qπ1(s,a)qπ2(s,a)\forall s\in \mathcal{S},\forall a\in\mathcal{A}:\pi_1\geq\pi_2\lrArr q_{\pi_1}(s,a)\geq q_{\pi_2}(s,a)

从而有:

vπ(s)Eπ[GtSt=s]=maxπvπ(s),sSv_{\pi_*}(s)\doteq\mathbb{E}_{\pi_*}[G_t|S_t=s]=\max_\pi v_{\pi}(s),\forall s\in\mathcal{S}

qπ(s,a)=Eπ[GtSt=s,At=a]=maxπqπ(s,a),sS,aAq_{\pi_*}(s,a)=\mathbb{E}_{\pi_*}[G_{t}|S_{t} =s,A_{t}=a]=\max_\pi q_{\pi}(s,a),\forall s\in\mathcal{S},\forall a\in\mathcal{A}

* 表示最优的,这里 π\pi_* 表示最优策略

# 贝尔曼最优方程

v(s)=vπ(s)?v_*(s)=v_{\pi_*}(s)? 代替原来的 vπ(s)v_{\pi}(s)qπ(s,a)q_{\pi_*}(s,a) 代替原来的 qπ(s,a)q_{\pi}(s,a) ,那么原本的贝尔曼方程就变成贝尔曼最优方程,得到的表达式就是最优值函数

参考:https://blog.csdn.net/november_chopin/article/details/106589197,有 demo 更方便掌握。

# 最优状态值函数

v(s)=a=π(s)π(as)srp(s,rs,a)[r+γv(s)]=maxasrp(s,rs,a)[r+γv(s)]\begin{aligned} v_{*}(s) &= \sum_{a=\pi_{*}(s)} \pi_{*} (a|s)\sum_{s'}\sum_{r}p(s',r|s,a)[r+\gamma v_{*} (s')]\\ &= \max_{a}\sum_{s'}\sum_{r}p(s',r|s,a)[r+\gamma v_{*} (s')] \end{aligned}

# 最优状态值函数

qπ(s,a)=srp(s,rs,a)[r+γa=π(s)π(as)qπ(s,a)]=srp(s,rs,a)[r+γmaxaqπ(s,a)]\begin{aligned} q_{\pi_*}(s,a)&=\sum_{s'}\sum_{r}p(s',r|s,a)[r+\gamma\sum_{a'=\pi_*(s')}\pi_* (a'|s') q_{\pi_*}(s',a')]\\ &=\sum_{s'}\sum_{r}p(s',r|s,a)[r+\gamma \max_{a'} q_{\pi_*}(s',a')] \end{aligned}

# 两种最优值函数的关系

v(s)=maxasrp(s,rs,a)[r+γv(s)]=maxaEπ[Rt+1+γv(St+1)St=s,At=a]=maxaEπ[Rt+1+γGt+1St=s,At=a]=maxaEπ[GtSt=s,At=a]v(s)=maxaA(s)qπ(s,a)\begin{aligned} v_{*}(s) &= \max_{a}\sum_{s'}\sum_{r}p(s',r|s,a)[r+\gamma v_{*} (s')]\\ &= \max_{a}\mathbb{E}_\pi[R_{t+1}+\gamma v_{*}(S_{t+1})|S_t =s,A_t=a]\\ &= \max_{a}\mathbb{E}_{\pi_*}[R_{t+1}+\gamma G_{t+1}|S_t =s,A_t=a]\\ &= \max_{a}\mathbb{E}_{\pi_*}[G_t|S_t =s,A_t=a]\\ v_{*}(s) &= \max_{a\in\mathcal{A(s)}}q_{\pi_{*}}(s,a) \end{aligned}

# TDL

Temporal Difference Learning 差分学习

TD target :

yt=rt+γQ(st+1,at+1;w)=rt+γmaxaQ(st+1,a;w)\begin{aligned} y_t&=r_t+\gamma\cdot Q(s_{t+1},a_{t+1};w)\\ &=r_t+\gamma\cdot \max_aQ(s_{t+1},a;w) \end{aligned}

损失函数:

L=12[Q(w)y]2L=\frac{1}{2}[Q(w)-y]^2

梯度:

Lw=[Q(w)y]Q(w)w\frac{\partial L}{\partial w}=[Q(w)-y]\cdot\frac{\partial Q(w)}{\partial w}

梯度下降计算:

wt+1=wtαLtww=wtw_{t+1}=w_t-\alpha\cdot\frac{\partial L_t}{\partial w}\large|_{w=w_t}

# 算法流程

  1. Observe state St=stS_t=s_t and perform action At=atA_t=a_t
  2. Predict the value: qt=Q(st,at;wt)q_t=Q(s_t,a_t;w_t)
  3. Differentiate the value network: dt=Q(st,at;w)ww=wtd_t=\frac{\partial Q(s_t,a_t;w)}{\partial w}\large|_{w=w_t}
  4. Environment provides new state st+1s_{t+1} and reward rtr_t
  5. Compute TD target: yt=rt+γmaxa𝑄(st+1,a;wt)y_t=r_t+\gamma\cdot\max_a𝑄(s_{t+1},a;w_t)
  6. Gradient descent: wt+1=wtα(qtyt)dtw_{t+1}=w_t-\alpha\cdot(q_t-y_t)\cdot d_t

# 值估计

# Sarsa

State-Action-Reward-State-Action (SARSA)

使用 (st,at,rt,at+1)(s_t,a_t,r_t,a_{t+1}) 更新 QπQ_{\pi}

# 表格

Tabular version

# 神经网络

Value network version

# Q-Learning

# 表格

Tabular version

# 神经网络

DQN version

# 策略

Edited on Views times
\ No newline at end of file diff --git a/cs/ai/search/index.html b/cs/ai/search/index.html index 290322e4..5cf9484f 100644 --- a/cs/ai/search/index.html +++ b/cs/ai/search/index.html @@ -1,4 +1,4 @@ -搜索技术 - 人工智能 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

思维导图

# 搜索相关概念

对于给定的问题,智能系统的行为一般是找到能够达到所希望目标的动作序列,并使其所付出的代价最小、性能最好。

基于给定的问题,问题求解的第一步是目标的表示。

搜索就是找到智能系统的动作序列的过程

搜索算法的:

  • 输入是给定的问题
    • 搜索什么(目标)
    • 在哪里搜索(搜索空间)
      • 和通常的搜索空间不同,人工智能中大多数问题的状态空间在问题求解之前不是全部知道的
  • 输出是表示为动作序列的方案。

一旦有了方案,就可以执行该方案所给出的动作了。(执行阶段)

求解问题包括:

  • 目标表示
  • 搜索
  • 执行

# 搜索的分类

根据是否使用启发式信息分为

  • 盲目搜索
    • 只是可以区分出哪个是目标状态
    • 一般是按预定的搜索策略进行搜索
    • 没有考虑到问题本身的特性,这种搜索具有很大的盲目性,效率不高,不便于复杂问题的求解
  • 启发式搜索
    • 是在搜索过程中加入了与问题有关的启发式信息,用于指导搜索朝着最有希望的方向前进,加速问题的求解并找到最优解。

按表示方式分为

  • 状态空间搜索
    • 用状态空间法来求解问题所进行的搜索
  • 与或树搜索
    • 用问题规约方法来求解问题时所进行的搜索

# 搜索策略评价标准

# 完备性

如果存在一个解答,该策略是否保证能够找到?

# 时间复杂性

需要多长时间可以找到解答?

# 空间复杂性

执行搜索需要多少存储空间?

# 最优性

如果存在不同的几个解答,该策略是否可以发现最高质量的解答?

# 搜索控制策略

  • 不可撤回的控制策略 —— 可能无解
  • 试探性控制策略
    • 回溯型
    • 图搜索

# 盲目搜索方法

定义一个四元组,以此来表示状态空间:

raw
{ nodes, arc, goal, current }
  • nodes 表示当前搜索空间中现有状态的集合
  • arc 表示可应用与当前状态的操作符,把当前状态转换为另一个状态
  • goal 表示需要到达的状态,是 nodes 中的一个状态
  • current 表示现在生成的用于和目标状态比较的状态(包括初始状态)

各种算法的完备性、时间复杂度、空间复杂度、能否找到最优解的比较如下:

盲目搜索算法评价

无论是宽度优先还是深度优先,都不适用于有环图

# 宽度优先搜索

优点:

目标节点如果存在,用宽度优先搜索算法总可以找到该目标节点,而且是最小(即最短路径)的节点。

问题:

宽度优先搜索是一种盲目搜索,时间和空间复杂度都比较高,当目标节点距离初始节点较时会产生许多无用的节点,搜索效率低。

宽度优先搜索中,时间需求是一个很大的问题,特别是当搜索的深度比较大时,尤为严重,但是空间需求是比执行时间更严重的问题。

# 双向宽度优先搜索法

Bidirectional search

双向广度优先搜索法适用于具有可逆性的问题。广度优先搜索法搜索时,结点不断扩张,深度越大,结点数越多。如果从两个方向向对方搜索,就会在路径中间某个地方相会,这样,双方的搜索的深度都不大,所搜索过的结点数就少得多,搜索时间也就节省不少。

同时进行两个搜索:

  • 一个是从初始状态向前搜索;
  • 另一个则从目标向后搜索;

同时从初始状态和目标状态出发,采用广度优先搜索的策略,向对方搜索,如果问题存在解,则两个方向的搜索会在中途相遇,即搜索到同一个结点。将两个方向的搜索路径连接起来,就可以得到从初始结点到目标结点的搜索路径。

# 深度优先搜索

也称为回溯搜索,它总是首先扩展树的最深层次上的某个节点,只是当搜索遇到一个死亡节点(非目标节点而且不可扩展),搜索方法才会返回并扩展浅层次的节点

上述原理对树中的每一节点是递归实现的 (实现该递归用栈)

优点:

是比宽度优先搜索算法需要较少的空间,该算法只需要保存搜索树的一部分,它由当前正在搜索的路径和该路径上还没有完全展开的节点标志所组成

⚠️但是对于现实中很多问题深度可能是无穷的!这种时候认为深度优先搜索是不完备的。后面的 (迭代) 有界深度优先搜索就是为了解决这一问题。

深度优先搜索的存储器要求深度约束的线性函数。

# 有界深度优先搜索

Deep-limited Search

若状态空间无限,DFS 可能会出现循环,搜索失败;通过预定一个深度限制来解决这个问题

有界深度优先搜索过程总体上按深度优先算法方法进行,但对搜索深度需要给出一个深度限制 dmd_m ,当深度达到了 dmd_m 的时候,如果还没有找到解答,就停止对该分支的搜索,换到另外一个分支进行搜索

深度限制 dmd_m 很重要。当问题有解,且解的路径长度小于或等于 dmd_m 时,则搜索过程一定能够找到解,但是和深度优先搜索一样这并不能保证最先找到的是最优解

  • 但是当 dmd_m 取得太小,解的路径长度大于 dmd_m 时,则搜索过程中就找不到解,即这时搜索过程甚至是不完备的
  • dmd_m 不能太大。当 dmd_m 太大时,搜索过程会产生过多的无用节点,既浪费了计算机资源,又降低了搜索效率

有界深度搜索的主要问题是深度限制值 dmd_m 的选取

# 迭代加深搜索

Iterative Deepening Search

在有界深度优先搜索的基础上改进,试图尝试所有可能的深度限制

先任意给定一个较小的数作为 dmd_m,然后按有界深度算法搜索,通过典型的深度优先算法,生成深度为 m 的树:

  • 若在此深度限制内找到了解,则算法结束
  • 若在此限制内没有找到问题的解,则增大深度限制 dmd_m ,继续搜索
  • 宽度优先搜索需要指数数量的空间
  • 深度优先搜索的空间复杂度和最大搜索深度呈线性关系
  • 迭代加深搜索对一棵深度受控的树采用深度优先的搜索。它结合了宽度优先和深度优先搜索的优点:
    • 和宽度优先搜索一样,它是最优的,也是完备的
    • 但对空间要求和深度优先搜索一样是适中的

# 启发式搜索

启发式搜索用于两种不同类型的问题:

  • 前向推理
    • 一般用于状态空间的搜索。在前向推理中,推理是从预选定义的初始状态出发向目标状态方向执行
  • 反向推理
    • 反向推理一般用于问题规约中。在反向推理中,推理是从给定的目标状态向初始状态执行

启发式搜索:如果在选择节点时能充分利用与问题有关的特征信息,估计出节点的重要性,就能在搜索时选择重要性较高的节点,以便求得最优解。

# 启发性信息和评估函数

# 评估函数

用来评估节点重要性的函数称为评估函数 f(x)f(x) ,定义为从初始节点 S0S_0 出发,约束地经过节点 xx 到达目标节点 SgS_g 的所有路径中最小路径代价的估计值:

f(x)=g(x)+h(x)f(x)=g(x)+h(x)

  • g(x)g(x)—— 从初始节点 S0S_0 到节点 xx实际代价

  • h(x)h(x)—— 从xx 到目标节点 SgS_g 的最优路径的评估代价,它体现了问题的启发式信息,其形式要根据问题的特性确定,h(x)h(x) 称为启发式函数

  • 在正方形网格中,允许向 44 邻域的移动,使用曼哈顿距离(L1L1

  • 在正方形网格中,允许向 88 邻域的移动,使用对角线距离(LL∞)等等

# OR 图

大多数前向推理问题可以表示为 OR 图,其中图中的节点表示问题的状态,弧表示应用于当前状态的规则,该规则引起状态的转换;

当有多个规则可用于当前状态的时候,可以从该状态的各个子状态中选择一个比较好的状态作为下一个状态。

# 最好优先搜索算法

最好优先搜索算法是一个通用图搜索算法框架,不是一个具体的算法。将其 f(n)f(n) 评估函数具体化,就能得到后面的 AA 算法、AA* 算法。

图搜索算法只记录状态空间中那些被搜索过的状态,它们组成一个搜索图 GG

GG 由两种节点组成:

  • Open 节点,如果该节点已经生成,而且启发式函数值 h(x)h(x) 已经计算出来,但是它没有扩展。这些节点也称为未考察节点
  • Closed 节点,如果该节点已经扩展并生成了其子节点。Closed 节点是已经考察过的节点。

可以给出两个数据结构 OPEN 和 CLOSED 表,分别存放了 Open 节点和 Closed 节点。

节点 xx 总的费用函数 f(x)f(x)g(x)g(x)h(x)h(x) 之和。

生成费用 g(x)g(x) 可以比较容易地得到,如, 如果节点 xx 是从初始节点经过 mm 步得到,则 g(x)g(x) 应该和 mm 成正比(或者就是 mm )。

h(x)h(x) 只是一个预测值。

上述图搜索算法生成一个明确的图 GG(称为搜索图)和一个 GG 的子集 TT(称为搜索树),图 GG 中的每一个节点也在树 TT 上。

搜索树是由返回指针来确定的。

GG 中的每一个节点(除了初始节点 S0S_0)都有一个指向 GG 中一个父辈节点的指针。该父辈节点就是树中那个节点的惟一父辈节点。

从最有希望的节点开始,并且生成其所有的子节点

  • 计算每个节点的性能(合适性)
  • 选择最有希望的节点进行扩展,而不是仅仅从当前节点所生成的子节点中进行选择
  • 如果在早期选择了一个错误的节点,最好优先搜索就提供了一个修改的机会

最好优先搜索算法并没有显式地给出如何定义启发式函数,

它不能保证当从起始节点到目标节点的最短路径存在时,一定能够找到它。

最好优先搜索算法伪代码:

最好优先搜索算法伪代码

算法的特例:

f(n)=g(n)+h(n)f(n)=g(n)+h(n)

  • g(n)=0g(n)=0 时,f(n)=h(n)f(n)=h(n),称为贪婪最好优先搜索算法
  • h(n)=0h(n)=0 时,f(n)=g(n)f(n)=g(n),变成宽度优先搜索算法。

# A 算法和 A * 算法

如果最好优先搜索算法中的 f(n)f(n) 被实例化为 f(n)=g(n)+h(n)f(n)=g(n)+h(n),则称为 AA 算法

进一步细化,将 AA 算法中能够保证找到最优解的这一类称为 AA* 算法,如果:

  • 启发函数 hh 满足对于任一结点 nnh(n)h(n) 的值都不大于 nn 到目标结点的最优代价;
    • 也就是 h(n)h(n)h(n)\leq h^*(n)
  • 搜索空间中的每个结点都具有有限个后继。
  • 搜索空间中的每个有向边的代价均为正值。
    称以上 3 个条件为 “运行条件”。

定义评估函数 ff^*

f(n)=g(n)+h(n)f^*(n)=g^*(n)+h^*(n)

其中:

  • g(n)g^*(n) 为起始节点到节点 nn最短路径的代价
  • h(n)h^*(n) 是从 nn 到目标节点的最短路径的代价。

这样 f(n)f^*(n) 就是从起始节点出发通过节点 nn 到达目标节点的最佳路径的总代价的估值。

把估价函数 f(n)f(n)f(n)f^*(n) 相比较,g(n)g^*(n) 是对 g(n)g(n) 的估价;h(n)h^*(n) 是对 h(n)h(n) 的估价。

在这两个估价中,尽管 g(n)g(n) 容易计算,但它不一定就是从起始节点 S0S_0 到节点 nn 的真正的最短路径的代价,很可能从初始节点 S0S_0 到节点 nn 的真正最短路径还没有找到,所以一般都有:

g(n)g(n)g(n)\geq g^*(n)

最好优先搜索算法框架中保证了能够计算出更好的 g(n)g(n)

AA* 算法中要求 h(n)h(n)h(n)h^*(n) 的下界,即对任意节点 nn 均有 h(n)h(n)h(n)\leq h^*(n)。称这个时候 h(n)h(n)可采纳的,这保证了 AA* 算法是收敛的!

# IDA * 算法

也叫迭代加深 A * 算法

  • 迭代加深搜索算法,它以深度优先的方式在有限制的深度内搜索目标节点。在每个深度上,该算法在每个深度上检查目标节点是否出现,如果出现则停止,否则深度加 1 继续搜索。
  • AA* 算法是选择具有最小估价函数值的节点扩展。

迭代加深 AA* 搜索算法 是 上述两种算法的结合,这里启发式函数用做深度的限制,而不是选择扩展节点的排序

伪代码:

IDA_star伪代码

# 问题归约和 AND-OR 图启发式搜索

# 问题归约的描述

问题归约可以用三元组表示:(S0,O,P)(S_0,O,P) ,其中:

  • S0S_0 是初始问题
  • PP 是本原问题集 (不用证明的,公理、已知事实,或已证明过的问题)
  • OO 是操作算子集 (操作算子把一个问题化成若干个子问题)

问题归约表示方法就是由初始问题出发,运用操作算子产生一些子问题,对子问题再运用操作算子产生子问题的子问题,这样一直进行到产生的问题均为本原问题,则问题得解。所有问题归约的最终目的是产生本原问题

# ⭐️AND-OR 图

# 超图

这个不考

超图

qq 指向 pptt 的两条有向边被一个圆弧连接,用于表示 qq 被分解 (归约) 为 pptt : 只有当 pptt 对应的问题都被解决时,qq 才能被解决。把圆弧连接的有向边看作 一个整体,把有向边 q,m\langle q,m\rangle 看作另一个整体,这两个整体表示可以将 qq 按照前一个整体进行分解,或者,将 qq 按照后一个整体进行分解

超图 (hypergrah) 用二元组 (N,H)(N,H) 表示,其中 :

  • NN 为结点的有穷集合
  • HH 为 “超边” (Hyperarce) 的集合

一个超边表示为 s,D\langle s,D\rangle,也称为 “k 连接符”(k-conector),其中 k=Dk=|D| 其中 :

  • sNs\in N ,称 ss 为该超边的源结点
  • DND\in N ,称 D 该超边的目的结点集。每个超边 s,D\langle s,D\rangle 都表示结点 ss 对应的问题的一个可行的分 解方法.
    • D=1|D|=1 ,则该超边称为 “或弧”,同时称 DD 中的结点为 ss 的 “或子结点”(OR-node),也称它为 s 的 “或后继”(OR-descendents),也就是或节点
    • D>1|D|>1 ,则该超边称为 “与弧”,同时称 DD 中的结点为 ss 的 “与子结点”(AND-node),也称它们为 s 的 “与后继”(AND-descendents),也就是与节点

# 与或图 (AND-OR)

用 AND-OR 图把问题归约为子问题替换集合,将:

  • 初始节点表示初始问题描述
  • 对应于本原问题的节点称为叶节点

它的四元组表示为 (N,n0,H,T)(N,n_0,H,T) ,其中:

  • N 是结点集合,其中每个结点都对应一个唯一的问题
  • n0Nn_0\in N ,对应于初始问题
  • H 是超边的集合,其中每个超边 S,D\langle S,D\rangle 都表示结点 s 对应的问题的一个可行的分解方法
    • D=1|D|=1,则该超边称为 “或弧”,同时称 DD 中的结点为;的 “或子结点”(OR-node),也称它为 ss 的 “或后继”(OR-descendents),也就是或节点
    • D>1|D|>1,则该超边称为 “与弧”,同时称 DD 中的结点为;的 “与子结点”(AND-node),也称它们力;的 “与后继”(AND-descendents),也就是与节点
  • ttNN 的子集,其中每个结点对应的问题都为本原问题,TT 中的结点也称为叶结点

# 可解节点

可解节点可递归地定义如下:

  • 叶节点是可解节点
  • 如果某节点为或子节点,那么该节点可解当且仅当至少有一个子节点为可解节点
  • 如果某节点为与子节点,那么该节点可解当且仅当所有子节点均为可解节点

# 不可解节点

不可解节点可递归定义如下:

  • 有后裔节点的非叶节点是不可解节点
  • 或节点是不可解节点(含有或后继节点),当且仅当它的所有子节点都是不可解节点
  • 与节点是不可解节点(含有与后继节点),当且仅当它的子节点中至少有一个是不可解节点。

# 解图

能导致初始节点可解的那些可解节点及有关连线组成的子图称为该 AND-OR 图的解图

# 博弈

这里讲的博弈是二人博弈,二人零和、全信息、非偶然博弈,博弈双方的利益是完全对立的;

(1)对垒的双方 MAX 和 MIN 轮流采取行动,博弈的结果只能有 3 种情况:MAX 胜、MIN 败;MAX 败,MIN 胜;和局。

(2)在对垒过程中,任何一方都了解当前的格局和过去的历史。

(3)任何一方在采取行动前都要根据当前的实际情况,进行得失分析,选择对自己最为有利而对对方最不利的对策,在不存在 “碰运气” 的偶然因素,即双方都很理智地决定自己的行动。

# 博弈树

把双人博弈过程用图的形式表示出来,这样就可以得到一棵 AND-OR 树,这种 AND-OR 树称为博弈树;

博弈树特点:

  • 博弈的初始状态是初始节点
  • 博弈树的 “与” 节点 和 “或” 节点是逐层交替出现的
  • 向前看 nn 步,则博弈树有 2n2n 层(2n2n 层树枝,2n+12n+1 层节点)

整个博弈过程始终站在某一方的立场上,不同立场决定节点的性质:

  • 能使自己一方获胜的终局都是本原问题,相应的节点也是可解节点;
  • 所有使对方获胜的节点都是不可解节点
  • 轮到自己一方走的节点都是节点
  • 轮到对方走的节点都是节点

从 MAX 一方的角度来看,也就是希望 MAX 获胜,博弈树中的节点分为:

  • MAX 节点 —— 下一步该 MAX 走的节点,所有 MAX 节点都是或节点
  • MIN 节点 —— 下一步该 MIN 走的节点,所有 MIN 节点都是与节点

# 极大极小过程

极大极小过程是考虑双方对弈若干步之后,从可能的走法中选一步相对好的走法来走,即在有限的搜索深度范围内进行求解

定义一个静态估价函数 ff , 以便对棋局的态势做出评估,这个函数可以根据棋局的态势特征进行定义。假定对弈双方分别为 MAX 和 MIN ,规定:

  • 有利于 MAX 方的态势:f(p)f(p) 取正值
  • 有利于 MIN 方的态势:f(p)f(p) 取负值
  • 态势均衡的时候:f(p)f(p) 取零

其中 pp 代表棋局

MINMAX 基本思想:

  1. 当轮到 MIN 走步的节点时,MIN 应考虑最坏的情况(即 f(p)f(p) 取极小值)
  2. 当轮到 MAX 走步的节点时,MAX 应考虑最好的情况(即 f(p)f(p) 取极大值)
  3. 评价往回倒推时,相应于两位棋手的对抗策略,交替使用(1)和(2)两种方法传递倒推值

所以这种方法称为极大极小过程

# 井字棋

设只进行两层,即每方只走一步

估价函数 e(p)e(p)

  • 若格局 p 对任何一方都不是获胜的,则:e(p)e(p) = (所有空格都放上 MAX 的棋子之后三子成一线的总数) –(所有空格都放上 MIN 的棋子后三子成一线的总数)
  • pp 是 MAX 获胜,则:e(p)=+e(p) = +∞
  • pp 是 MIN 获胜,则:e(p)=e(p) = -∞

井字棋

在生成后继节点时,可以利用棋盘的对称性,省略了从对称上看是相同的格局

极大极小方法是把搜索树的生成和估值这两个过程完全分开,只有在已经生成树之后才开始进行估值,这一分离导致了低效率的策略

# α\alpha-β\beta 过程

α\alpha-β\beta 剪枝技术是极大极小方法的改进,是一种提高博弈树搜索效率的方法

α\alpha-β\beta 剪枝技术是一种边生成节点,边计算估值和倒推值的方法,从而剪去某些分枝

  • 对于一个 “与”(MIN)节点,它取当前子节点中的最小的倒推值作为它的倒推值的上界,称此值为 β\beta 值。也就是说 β\beta 值可以等于其后继节点当前最小的最终倒推值.“与” 节点的 β\beta 值是永远不会增加的
  • 对于一个 “或”(MAX)节点,它取当前子节点中得最大的倒推值作为它的倒推值的下界,称此值为 α\alpha 值。也就是说 α\alpha 值可以等于其后继节点当前最大的最终倒推值.“或” 节点的 α\alpha 值是永远不会减少的.

β\beta 剪枝:任何 “或”(MAX)节点 x 的 α\alpha 值如果大于等于其父节点的 β\beta 值,则:

  • 对节点 x 以下的分枝可以停止搜索
  • 并使 x 的倒推值为 α\alpha

α\alpha 剪枝:任何 “与”(MIN)节点 x 的 β\beta 值如果小于等于其父节点的 α\alpha 值,则:

  • 对节点 x 以下的分枝可以停止搜索
  • 并使 x 的倒推值为 β\beta

要进行 α\alpha-β\beta 剪枝,至少必须使某一部分的搜索树生长到最大深度。因为 α\alphaβ\beta 值必须以某个端节点的静态估值为依据。因此采用 α\alpha-β\beta 过程都要使用某种深度优先的搜索方法

alpha-beta剪枝

剪枝并不影响最后的结果

好的招数序列可以改进剪枝的效率

对于最佳情况,即 MIN 结点先扩展出最小估值的后继结点,MAX 结点先扩展出最大估值的后继结点。这种情况 可使得修剪的枝数最大:

  • 时间复杂度为:O(bm2)O(b^{\frac{m}{2}})
  • 有效的分支系数为 b\sqrt{b} ;在实际中通常可凭经验选择;
  • tt 代表仿真总次数,等于所有 nin_i 的和;

目前蒙特卡洛树搜索的实现大多是基于 UCT 的一些变形

# 拓展 (Expansion)

在选择阶段结束时候,我们查找到了一个最迫切被拓展的节点 N,以及他一个尚未拓展的动作 A。在搜索树中创建一个新的节点NnN_n 作为 N 的一个新子节点。NnN_n 的局面就是节点 N 在执行了动作 A 之后的局面

# 模拟 (Simulation)

为了让NnN_n 得到一个初始的评分。我们从NnN_n 开始,让游戏随机进行,直到得到一个游戏结局,这个结局将作为NnN_n 的初始评分。一般使用胜利 / 失败来作为评分,只有 1 或者 0。

# 反向传播 (Back Propagation)

NnN_n 的模拟结束之后,它的父节点 N 以及从根节点到 N 的路径上的所有节点都会根据本次模拟的结果来添加自己的累计评分


有些搜索算法在内存中保留一条或多条路径,并且记录哪些是已经探索过的,哪些是还没有探索过的。当找到目标时,到达目标的路径同时也构成了这个问题的一个解。

但是在许多问题中,问题的与到达目标的路径无关的。例如,在八皇后问题中,重要的是最终皇后的布局,而不是加入皇后的次序

局部搜索算法从单独的一个当前状态出发,通常只移动到与之相邻的状态。典型情况下,搜索的路径是不保留的

  • 只用很少的内存
  • 通常能在很大状态空间中找到合理的解

# 爬山法

贪婪局部搜索

一直向值增加的方向持续移动,将会在到达一个 “峰顶” 时终止

爬山法有许多变化的形式:

  • 随机爬山法,它在上山移动中随机地选择下一步;选择的概率随着上山移动的陡峭程度而变化。
  • 首选爬山法,它在实现随机爬山法的基础上,采用的方式是随机地生成后继节点直到生成一个优于当前节点的后继。这个算法在有很多后继节点的情况下有很好的效果。
  • 随机重新开始爬山法,它通过随机生成的初始状态来进行一系列的爬山法搜索,找到目标时停止搜索。这个算法是完备的,概率接近于 1

# 模拟退火算法

S.A. (Simulated annealing) 算法,是一种通用概率算法,适用于一定时间内寻找在一个很大搜寻空间中的近似最优解

P=eδtP=e^{-\frac{\delta}{t}}

其中 δ\delta 为邻近解与当前解的目标函数之差;tt温度参数

# 初始化

由一个产生函数从当前解产生一个位于解空间的新解,并定义一个足够大的数值作为初始温度。

# 迭代过程

迭代过程是模拟退火算法的核心步骤,分为新解的产生接受新解两部分:

  1. 由一个产生函数从当前解产生一个位于解空间的新解;为便于后续的计算和接受,减少算法耗时,通常选择由当前新解经过简单地变换即可产生新解的方法,如对构成新解的全部或部分元素进行置换、互换等,注意到产生新解的变换方法决定了当前新解的邻域结构,因而对冷却进度表的选取有一定的影响。
    • 计算与新解所对应的目标函数差。因为目标函数差仅由变换部分产生,所以目标函数差的计算最好按增量计算。事实表明,对大多数应用而言,这是计算目标函数差的最快方法。
  2. 判断新解是否被接受,判断的依据是一个接受准则
    • 最常用的接受准则是 Metropolis 准则:
      • δ<0\delta\lt0 则接受 SS' 作为新的当前解 SS
      • 否则以概率 P=eδtP=e^{-\frac{\delta}{t}} 接受 SS' 作为新的当前解 SS
    • 当新解被确定接受时,用新解代替当前解,这只需将当前解中对应于产生新解时的变换部分予以实现,同时修正目标函数值即可。此时,当前解实现了一次迭代。可在此基础上开始下一轮试验。
    • 而当新解被判定为舍弃时,则在原当前解的基础上继续下一轮试验。

模拟退火算法与初始值无关,算法求得的解与初始解状态 S(是算法迭代的起点)无关;模拟退火算法具有渐近收敛性,已在理论上被证明是一种以概率 1 收敛于全局最优解的全局优化算法;模拟退火算法具有并行性。

# 停止准则

迭代过程的一般停止准则:温度 T 降低至某阈值时,或连续若干次迭代均未接受新解时,停止迭代,接受当前寻找的最优解为最终解。

# 退火方案

在某个温度状态 TT 下,当一定数量的迭代操作完成后,降低温度 T,在新的温度状态下执行下一个批次的迭代操作。

# 伪代码

伪代码
// Initialization
// Randomly generate a solution X0,
// and calculate its fitness value f(X0).
Xbest=X0;
k=0;
t(k)=T;
while not stop
  //The search loop under the temperature tk
  for i=1 to L : //The loop times
    // Generate a new solution Xnew based on the current
    // solution Xk, and calculate its fitness value f(Xnew).
    if f(Xnew) < f(X(k)) :
    	Xk = Xnew;
    if f(X(k)) < f(Xbest) Xbest=X(k) :
      continue;
    end if
    Calculate P(tk) = exp[(f(Xnew)-f(X(k)))/t(k)];
    if random(0,1) < $p$ :
      X(k) = Xnew;
    end if
  end for
  //Drop down the temperature
  t(k+1) = drop(t(k));
  k=k+1;
  end while
print Xbest

# 遗传算法⭐️

遗传算法的特点:

  • 自组织、自适应和自学习性 (智能性)
  • 遗传算法具有并行性 —— 遗传算法按并行方式搜索一个种群数目的点,而不是单点
  • 遗传算法不需要求导或其他辅助知识,而只需要影响搜索方向的目标函数和相应的适应度函数
  • 遗传算法强调概率转换规则,而不是确定的转换规则
  • 遗传算法可以更加直接地被应用
  • 遗传算法对给定问题,可以产生许多潜在解,最终的选择由使用者确定

由于遗传算法是基于随机搜索的算法,遗传算法对给定问题,可以产生许多的潜在解,最终由使用者决定最终解。只运行一次算法的结果并不能反映算法的性能。为了更好地分析遗传算法的性能,应该以不同的初始随机种子或用不同的参数 (例如种群数量,变异概率等) 多次运行算法

(在某些特殊不止一个解存在情况下,如多目标优化问题有一组 pareto 最优解。这种遗传算法对于确认可替代解集而言是特别合适的)

采用多种群 (即有子种群) 的算法往往会获得更好的结果。每个子种群像单种群遗传算法一样独立地演算若干代后,在子种群之间进行个体交换。这种多种群遗传算法更贴近于自然种族的进化,称为并行遗传算法 (ParallelingGeneticAlgorithm,PGA)。

遗传算法包括 3 个基本操作:

  • 选择
  • 交叉或基因重组
  • 变异

# 编码

解的染色体表示

  • 随机排列

    对于 NN 个城市的 TSP 问题,对 NN 个城市从 1 开始编号,解表示为 1 到 NN 的排列

    染色体表示1

  • 随机数排序

    生成 NN(0,1)(0,1) 范围内的随机数对 NN 个城市编号,这 NN 个随机数的排序对应旅游城市的顺序

    染色体表示2

# 选择

选择是用来确定重组或交叉个体,以及被选个体将产生多少个子代个体。

首先计算适应度:

  • (1) 按比例的适应度计算;
  • (2) 基于排序的适应 s 计算;

适应度计算之后是实际的选择,按照适应度进行父代个体的选择。

选择策略如下:

# 轮盘赌选择

(Roulette-wheel selection)

# 锦标赛选择

(Tournament selection)

遗传算法中最流行的选择策略

  • 更小的复杂度
  • 易并行化处理
  • 不易陷入局部最优点
  • 不需要对所有的适应度值进行排序处理

# 截断选择

(Truncation selection)

# 蒙特卡洛选择

(Monte Carlo selection)

# 概率选择

(Probability selection)

# 线性排序选择

(Linear-rank selection)

# 指数排序选择

(Exponential-rank selection)

# 玻尔兹曼选择

(Boltzmann selection)

# 随机遍历选择

(Stochastic-universal selection)

# 精英选择

(Elite selection)

# 交叉 (基因重组)

# 单点交叉

随机产生一个交叉点位置,父个体 1 和父个体 2 在交叉点位置之右 (后) 的部分基因码互换,形成子个体 1 和子个体 2。

# 部分映射交叉

(Partial-Mapped Crossover ,PMX)

  • step 1 : 随机选择下标 s,t
  • step 2 : 交叉子串,2 个 parent 的 s-t 部分子串交换
  • step 3 : 确定映射关系,参考置换群的操作
  • step 4 : 生成后代染色体

# 其他交叉操作

order crossover (OX)

cycle crossover (CX)

position-based crossover

order-based crossover

# 变异

(mutation)

交叉之后子代经历的变异,实际上是子代基因按小概率扰动产生的变化。

# 倒置变异

(Inversion Mutation)

  • step 1: 随机选择下标 s,t
  • step 2 : 将 parent 的 s-t 中间部分倒置,得到 offspring

# 流程

遗传算法流程图

  1. 随机产生初始种群,个体数目一定,每个个体表示为染色体的基因编码
  2. 计算个体的适应度,并判断是否符合优化准则,若符合,输出最佳个体及其代表的最优解,并结束计算;否则转向第 3 步
  3. 依据适应度选择再生个体,适应度高的个体被选中的概率高,适应度低的个体可能被淘汰
  4. 按照一定的交叉概率和交叉方法,生成新的个体
  5. 按照一定的变异概率和变异方法,生成新的个体
  6. 由交叉和变异产生新一代的种群,返回到第 2 步

# 伪代码

伪代码
输入 $N$ 个城市的坐标 (这里单纯以欧式距离作为路程代价)
(还可以输入距离矩阵,在算法运行前计算距离)
随机生成10个不同个体的初始种群 P(0)
for t=0 to 最大选代轮数 :
  初始化后代种群 C(t)
  for i = 1 to 每一代后代数目 :
    依据适应度,从 P(t) 中选取一对父母 p1,p2
    利用交叉操作,从 p1,p2 产生后代 c1,c2
    以一定概率对 c1,c2 进行变异操作
    C(t) <= {c1,c2}
  end for
  依据适应度,从 Union{P(t),C(t)} 选取优异个体作为 P(t+1)
end for
依据适应度,从最后一代种群中选择最优个体作问题的解

# TSP⭐️

用遗传算法 (GA) 旅行商问题 (TSP) 。(python 中可以直接用 GA.tsp ...)

可供测试的数据集:National Traveling Salesman Problems (uwaterloo.ca)

# 自然启发式优化搜索算法

群体智能(Swarm intelligence,SI)和生物启发(u)

This part is to be completed

Edited on Views times
\ No newline at end of file diff --git a/cs/ai/uncentain-knowledge-presentation-and-resolution/index.html b/cs/ai/uncentain-knowledge-presentation-and-resolution/index.html index c729a6bc..4fcb0c42 100644 --- a/cs/ai/uncentain-knowledge-presentation-and-resolution/index.html +++ b/cs/ai/uncentain-knowledge-presentation-and-resolution/index.html @@ -1 +1 @@ -不确定性知识表示与推理 - 人工智能 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

按照所用知识的确定性,可以分为确定性和不确定性推理:

  • 确定性推理是建立在经典逻辑基础上的,经典逻辑的基础之一就是集合论。这在很多实际情况中是很难做到的,如高、矮、胖、瘦就很难精确地分开;
  • 不确定性推理就是从不确定性初始证据出发,通过运用不确定性的知识,最终推出具有一定程度的不确定性但却是合理或者近乎合理的结论的思维过程。

常识(common sense)具有不确定性。一个常识可能有众多的例外,一个常识可能是一种尚无理论依据或者缺乏充分验证的经验。常识往往对环境有极强的依存性。

不确定知识表示和推理方法:

  • 确定性理论
    • 可信度表示不确定性
  • 证据理论
    • 信任函数度量不确定性
  • 模糊逻辑和模糊推理
    • 模糊集合论应用于近似或模糊推理,形成了可能性理论
    • 模糊逻辑可以看作是多值逻辑的扩展。模糊推理是在一组可能不精确的前提下推出一个可能不精确的结论
  • 概率论处理的是由随机性引起的不确定性;
  • 可能性理论处理的是由模糊性引起的不确定性

# 概率图模型

# 基础知识

这是概率论与图论结合的产物,为统计推理和学习提供了一个统一的灵活框架

  • 节点表示变量节点
  • 之间的边表示局部变量间的概率依赖关系
  • 局部变量分布的连乘积表示系统的联合概率分布

该表示框架不仅避免了对复杂系统的联合概率分布直接进行建模,而且易于引入先验知识

概率图模型统一了目前广泛应用的许多统计模型和方法:

  • 马尔科夫随机场(MRF)
  • 条件随机场(CRF)
  • 隐马尔科夫模型(HMM)
  • 多元高斯模型
  • 卡尔曼滤波、粒子滤波、变分推理 \cdots \cdots

概率论基础【回顾】

  • 频率论学派
    • 事件的概率是当我们无限次重复试验时,事件发生次数的比值
      • 投掷硬币、掷骰子等
  • 贝叶斯学派
    • 将事件的概率视为一种主观置信度
      • 我认为明天下雨的概率是 30%;他认为明天下雨的概率是 80%

基础:

  • 乘法 / 链式法则 求 联合概率
  • 加法法则
  • 贝叶斯定理:后验概率=先验概率×似然度标准化常量\text{后验概率}=\frac{\text{先验概率}\times\text{似然度}}{\text{标准化常量}}

三个概念:

  • 联合概率分布
  • 边缘概率分布
  • 最大后验概率状态

# 分类

贝叶斯网络以外不作重点,那基本是不考了

  • 有向图模型 Directed graphs
    • ⭐️贝叶斯网络
    • 隐马尔科夫模型
    • 卡尔曼滤波
  • 无向图模型 Undirected graphs
    • 马尔可夫随机场
    • 条件随机场
  • 因子图模型 Factor graphs

# 贝叶斯网络⭐️

a,ba,b 相互独立:a\perp\llap{\perp}b;

a,ba,b 在给定 cc 的条件下相互独立(条件独立):a\perp\llap{\perp}b|c;

# 定义

贝叶斯网络(Bayesian Network,简称 BN)是不确定知识表示与推理的一种有效方法,属于有向图模型,它由这些组成:

  • 一个有向无环图(Directed Acyclic Graph, DAG)
  • 一系列条件概率表(衡量了上述关系的强度)

G 为定义在 {X1,X2,,XN}\{X_1,X_2,\cdots,X_N\} 上的一个贝叶斯网络,其联合概率分布可以表示为各个节点的条件概率分布的乘积

p(X)=ipi(XiParG(Xi))p(X)=\prod_{i}p_i(X_i|Par_G(X_i))

联合概率分布结构化分解,原本表示 nn 个二元随机变量的联合分布需要 2n12^n-1 个参数,用贝叶斯网络建模,假设每个节点最多有 kk 个父节点,所需要的参数最多为 n2kn\ 2^k ,所需参数大幅减少


贝叶斯网络举例

节点定义:

  • 试题难度(Difficulty)
  • 智力(Intelligence)
  • 考试等级(SAT)
  • 高考成绩(Grade)
  • 是否得到推荐信(Letter)

贝叶斯网络

# 盘式记法

贝叶斯网络的一种简洁的表示方法,其将相互独立的、由相同机制生成的多个变量放在一个方框(盘)内,并在方框中标出类似变量重复出现的个数。方框可以嵌套,且通常用阴影标注出可观察到的变量

盘式记法

# 举例

# 一元语言模型

假设文本中每个词都和其他词独立,和它的上下文无关。通过一元语言模型,我们可以计算一个序列的概率,从而判断该序列是否符合自然语言的语法和语义规则。

# 一元混合语言模型

假设给定文本主题(z)的前提下,该文本中的每个词都和其他词条件独立。其中,z 为隐变量。

# 概率潜在语义分析

# 潜在狄利克雷分配

# 构建步骤

  • 步骤 1:

    在某种变量顺序下,对所有变量的联合概率应用链式法则

    Pr(X1,,Xn)=Pr(XnX1,,Xn1)Pr(Xn1X1,,Xn2)Pr(X1)Pr(X_1,\cdots ,X_n)=Pr(X_n|X_1,\cdots ,X_{n-1})Pr(X_{n-1}|X_1,\cdots ,X_{n-2})\cdots Pr(X_1)

  • 步骤 2:

    对于每个变量 XiX_i ,考虑该变量的条件集合 ${X_1,\cdots,X_{i-1}} $,采用如下方法递归地判断条件集合中的每个变量 XjX_j 是否可以删除:

    如果给定其余变量的集合,XiX_iXjX_j 是条件独立的,则将 XiX_iXjX_j 的条件集合中删除。

    经过这一步骤,可以得到下式:

    Pr(X1,,Xn)=Pr(XnPar(Xn))Pr(Xn1Par(Xn1))Pr(X1)Pr(X_1,\cdots,X_n)=Pr(X_n|Par(X_n))Pr(X_{n-1}|Par(X_{n-1}))\cdots Pr(X_1)

  • 步骤 3:

    基于上述公式,构建一个有向无环图。其中,对于每个用节点表示的变量 XiX_i ,其父节点为 Par(Xi)Par(X_i) 中的变量集合。

  • 步骤 4:

    为每个家庭(即变量及其父节点集合)确定条件概率表的取值

# D - 分离⭐️

对于一个有向无环图,D - 分离(D-Separation)是一种用来判断其变量是否条件独立的图形化方法。在基于贝叶斯网络的不确定性知识推理中,采用 D - 分离方法可以简化概率计算,提高运行速度

D - 分离可用于判断任意两个节点的相关性和独立性。

  • 若存在一条路径将这两个节点(直接)连通,则称这两个节点是有向连接(d-connected)的,即这两个节点是相关的
  • 若不存在这样的路径将这两个节点连通,则这两个节点不是有向连接的,则称这两个节点是有向分离的(d-separated),即这两个节点相互独立

定义:路径 𝑝 被限定集 𝑍 阻塞(block)当且仅当:

  • 路径 𝑝 含有链结构 A→𝐵→C 或分连结构 A←𝐵→C 且中间节点 𝐵 在 𝑍 中
  • 或者路径 𝑝 含有汇连结构 A→𝐵←C 且汇连节点 𝐵 及其后代都不在 𝑍 中

定义:若 𝑍 阻塞了节点 X 和节点 𝑌 之间的每一条路径,则称给定 𝑍 时,X 和 𝑌 是 D - 分离,即给定 𝑍 时,X 和 𝑌 条件独立

引理:父节点已知时,该节点与其所有非后代的节点( non-descendants)满足 D-separated

定理:父节点已知时,该节点与其所有非后代的节点( non-descendants)条件独立

# 具体例子

  • 单一:Naive Bayes(朴素贝叶斯)

  • 混合:GMM (混合高斯模型)

  • 加入时间维度

    • Markov Chain
    • Gaussian Process(无限维高斯分布)
  • 连续:Gaussian Bayesian Network

  • 混合模型与时间结合起来:动态模型

    • HMM(离散)
    • Karman Filter(连续 [高斯]、线性)
    • Particle Filter(非高斯、非线性)

总的来说,用两句话总结这些模型:从单一到混合、从有限到无限

两个角度:空间(随机变量的取值从离散到连续)、时间(加入时间维度,从某一时刻延长到无限时间)

# 概率图模型的推理

(贝叶斯网络为主)

# 变量消元算法 (VE)

变量消除(Variable Elimination,VE)基本思想:通过从联合概率分别逐步消除变量,来求边缘概率

给定一个贝叶斯网络的一系列条件概率表 F\mathbf F,查询变量 QQ,证据变量的取值 E=e\mathbf E=e ,剩余变量 Z\mathbf Z ,需要计算 Pr(QE)Pr(Q|\mathbf E)

# 因子及相关操作

f(X,Y)f(\mathbf{X},\mathbf{Y}) 指代涉及变量集合 XY\mathbf{X}\cup\mathbf{Y} 的因子,如条件概率表中的 Pr(CA)Pr(C|A) 可以用因子 f(C,A)f(C,A) 或者 f(A,C)f(A,C) 来表示;

  • 限制:给定 f(X,Y)f(X,\mathbf{Y})X=aX=a ,则 fX=a=h(Y)=f(a,Y)f_{X=a}=h(\mathbf{Y})=f(a,\mathbf{Y})

  • 相乘:给定 f(X,Y)f(\mathbf{X},\mathbf{Y})g(Y,Z)g(\mathbf{Y},\mathbf{Z}) ,则

    h(X,Y,Z)=f(X,Y)×g(Y,Z)h(\mathbf{X},\mathbf{Y},\mathbf{Z})=f(\mathbf{X},\mathbf{Y})\times g(\mathbf{Y},\mathbf{Z})

  • 求和:给定 f(X,Y)f(X,\mathbf{Y}) ,则该因子在变量 XX 上求和将得到

    h(Y)=xDom(X)f(x,Y)h(\mathbf{Y})=\sum_{x\in Dom(X)}f(x,\mathbf{Y})

# 算法流程

  • 对于任意因子 fFf\in\mathbf F ,如果该因子涉及 EE 中的一个或多个变量,则将其替换为限制后的因子 f_

  • 给定一个消元顺序,对于变量 ZjZZ_j\in\mathbf Z

    • f1,f2,,fkf_1,f_2,\cdots,f_kF\mathbf F 中包含 ZjZ_j 的所有因子;

    • 将这些因子相乘并在 ZjZ_j 上求和后得到新的因子:

      gj=Zjf1×f2××fkg_j=\sum_{Z_j}f_1\times f_2\times\cdots\times f_k

    • F\mathbf F 中删除 f1,f2,,fkf_1,f_2,\cdots,f_k ,并将 gjg_j 加入到 F\mathbf F

  • 剩下的因子将只涉及查询变量 QQ,对这些因子相乘并归一化后得到 Pr(QE)Pr(Q|\mathbf E)

# 算法理解

第一种角度是理解为乘法对加法的分配律

第二种角度是 message 的传播过程,也就是局部的消息传递

# 信念传播算法 (BP)

信念传播算法(Belief Propagation, BP),基于局部的消息传递,可以视为 VE 算法 + 缓存 的推广:BP = VE + Caching

  • 在树状图模型上能收敛,且能达到精确推理
  • 但在一般图模型上,BP 为近似推理算法

BP

mba(xa)=bφabφbmcb(xb)mdb(xb)m_{b\to a}(x_a)=\sum_{b}\varphi_{ab}\cdot\varphi_{b}\cdot m_{c\to b}(x_b)\cdot m_{d\to b}(x_b)

φbmcb(xb)mdb(xb)\varphi_{b}\cdot m_{c\to b}(x_b)\cdot m_{d\to b}(x_b)信念 (belief)

  • φb\varphi_{b} 来自 bb 自己;
  • mcb(xb)mdb(xb)m_{c\to b}(x_b)\cdot m_{d\to b}(x_b) 来自 bb 的 children

一般化形式:

mji(xi)=xjφijφjkNB(j)imkj(xj)P(xi)=φijNB(i)mji(xi)=φijNB(i)xjφijφjkNB(j)imkj(xj)\begin{aligned} m_{j\to i}(x_i) &=\sum_{x_j}\varphi_{ij}\cdot\varphi_{j}\prod_{k\in\text{NB}(j)-i}m_{k\to j}(x_j)\\ P(x_i) &=\varphi_i\prod_{j\in\text{NB}(i)}m_{j\to i}(x_i)\\ &=\varphi_i\prod_{j\in\text{NB}(i)}\sum_{x_j}\varphi_{ij}\cdot\varphi_{j}\prod_{k\in\text{NB}(j)-i}m_{k\to j}(x_j) \end{aligned}

# 因子图 BP

# 概率图模型的学习

(不考)

条件概率表的学习方法:

  • 极大似然
  • 期望最大化

贝叶斯网络结构学习常用方法:

  • 基于约束的结构学习 (constraint-based structure learning):将贝叶斯网络看作是一种独立关系的表示。尝试对数据中的条件依赖和条件独立关系进行检验,找到能够对这些依赖和独立关系给出最好解释的某个网络。
  • 基于得分的结构学习 (score-based structure learning):定义模型对观测数据拟合程度的得分函数,通过最大化得分函数完成结构学习。
    • 结构斯然得分
    • 贝叶斯得分
\ No newline at end of file +不确定性知识表示与推理 - 人工智能 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

按照所用知识的确定性,可以分为确定性和不确定性推理:

  • 确定性推理是建立在经典逻辑基础上的,经典逻辑的基础之一就是集合论。这在很多实际情况中是很难做到的,如高、矮、胖、瘦就很难精确地分开;
  • 不确定性推理就是从不确定性初始证据出发,通过运用不确定性的知识,最终推出具有一定程度的不确定性但却是合理或者近乎合理的结论的思维过程。

常识(common sense)具有不确定性。一个常识可能有众多的例外,一个常识可能是一种尚无理论依据或者缺乏充分验证的经验。常识往往对环境有极强的依存性。

不确定知识表示和推理方法:

  • 确定性理论
    • 可信度表示不确定性
  • 证据理论
    • 信任函数度量不确定性
  • 模糊逻辑和模糊推理
    • 模糊集合论应用于近似或模糊推理,形成了可能性理论
    • 模糊逻辑可以看作是多值逻辑的扩展。模糊推理是在一组可能不精确的前提下推出一个可能不精确的结论
  • 概率论处理的是由随机性引起的不确定性;
  • 可能性理论处理的是由模糊性引起的不确定性

# 概率图模型

# 基础知识

这是概率论与图论结合的产物,为统计推理和学习提供了一个统一的灵活框架

  • 节点表示变量节点
  • 之间的边表示局部变量间的概率依赖关系
  • 局部变量分布的连乘积表示系统的联合概率分布

该表示框架不仅避免了对复杂系统的联合概率分布直接进行建模,而且易于引入先验知识

概率图模型统一了目前广泛应用的许多统计模型和方法:

  • 马尔科夫随机场(MRF)
  • 条件随机场(CRF)
  • 隐马尔科夫模型(HMM)
  • 多元高斯模型
  • 卡尔曼滤波、粒子滤波、变分推理 \cdots \cdots

概率论基础【回顾】

  • 频率论学派
    • 事件的概率是当我们无限次重复试验时,事件发生次数的比值
      • 投掷硬币、掷骰子等
  • 贝叶斯学派
    • 将事件的概率视为一种主观置信度
      • 我认为明天下雨的概率是 30%;他认为明天下雨的概率是 80%

基础:

  • 乘法 / 链式法则 求 联合概率
  • 加法法则
  • 贝叶斯定理:后验概率=先验概率×似然度标准化常量\text{后验概率}=\frac{\text{先验概率}\times\text{似然度}}{\text{标准化常量}}

三个概念:

  • 联合概率分布
  • 边缘概率分布
  • 最大后验概率状态

# 分类

贝叶斯网络以外不作重点,那基本是不考了

  • 有向图模型 Directed graphs
    • ⭐️贝叶斯网络
    • 隐马尔科夫模型
    • 卡尔曼滤波
  • 无向图模型 Undirected graphs
    • 马尔可夫随机场
    • 条件随机场
  • 因子图模型 Factor graphs

# 贝叶斯网络⭐️

a,ba,b 相互独立:a\perp\llap{\perp}b;

a,ba,b 在给定 cc 的条件下相互独立(条件独立):a\perp\llap{\perp}b|c;

# 定义

贝叶斯网络(Bayesian Network,简称 BN)是不确定知识表示与推理的一种有效方法,属于有向图模型,它由这些组成:

  • 一个有向无环图(Directed Acyclic Graph, DAG)
  • 一系列条件概率表(衡量了上述关系的强度)

G 为定义在 {X1,X2,,XN}\{X_1,X_2,\cdots,X_N\} 上的一个贝叶斯网络,其联合概率分布可以表示为各个节点的条件概率分布的乘积

p(X)=ipi(XiParG(Xi))p(X)=\prod_{i}p_i(X_i|Par_G(X_i))

联合概率分布结构化分解,原本表示 nn 个二元随机变量的联合分布需要 2n12^n-1 个参数,用贝叶斯网络建模,假设每个节点最多有 kk 个父节点,所需要的参数最多为 n2kn\ 2^k ,所需参数大幅减少


贝叶斯网络举例

节点定义:

  • 试题难度(Difficulty)
  • 智力(Intelligence)
  • 考试等级(SAT)
  • 高考成绩(Grade)
  • 是否得到推荐信(Letter)

贝叶斯网络

# 盘式记法

贝叶斯网络的一种简洁的表示方法,其将相互独立的、由相同机制生成的多个变量放在一个方框(盘)内,并在方框中标出类似变量重复出现的个数。方框可以嵌套,且通常用阴影标注出可观察到的变量

盘式记法

# 举例

# 一元语言模型

假设文本中每个词都和其他词独立,和它的上下文无关。通过一元语言模型,我们可以计算一个序列的概率,从而判断该序列是否符合自然语言的语法和语义规则。

# 一元混合语言模型

假设给定文本主题(z)的前提下,该文本中的每个词都和其他词条件独立。其中,z 为隐变量。

# 概率潜在语义分析

# 潜在狄利克雷分配

# 构建步骤

  • 步骤 1:

    在某种变量顺序下,对所有变量的联合概率应用链式法则

    Pr(X1,,Xn)=Pr(XnX1,,Xn1)Pr(Xn1X1,,Xn2)Pr(X1)Pr(X_1,\cdots ,X_n)=Pr(X_n|X_1,\cdots ,X_{n-1})Pr(X_{n-1}|X_1,\cdots ,X_{n-2})\cdots Pr(X_1)

  • 步骤 2:

    对于每个变量 XiX_i ,考虑该变量的条件集合 ${X_1,\cdots,X_{i-1}} $,采用如下方法递归地判断条件集合中的每个变量 XjX_j 是否可以删除:

    如果给定其余变量的集合,XiX_iXjX_j 是条件独立的,则将 XiX_iXjX_j 的条件集合中删除。

    经过这一步骤,可以得到下式:

    Pr(X1,,Xn)=Pr(XnPar(Xn))Pr(Xn1Par(Xn1))Pr(X1)Pr(X_1,\cdots,X_n)=Pr(X_n|Par(X_n))Pr(X_{n-1}|Par(X_{n-1}))\cdots Pr(X_1)

  • 步骤 3:

    基于上述公式,构建一个有向无环图。其中,对于每个用节点表示的变量 XiX_i ,其父节点为 Par(Xi)Par(X_i) 中的变量集合。

  • 步骤 4:

    为每个家庭(即变量及其父节点集合)确定条件概率表的取值

# D - 分离⭐️

对于一个有向无环图,D - 分离(D-Separation)是一种用来判断其变量是否条件独立的图形化方法。在基于贝叶斯网络的不确定性知识推理中,采用 D - 分离方法可以简化概率计算,提高运行速度

D - 分离可用于判断任意两个节点的相关性和独立性。

  • 若存在一条路径将这两个节点(直接)连通,则称这两个节点是有向连接(d-connected)的,即这两个节点是相关的
  • 若不存在这样的路径将这两个节点连通,则这两个节点不是有向连接的,则称这两个节点是有向分离的(d-separated),即这两个节点相互独立

定义:路径 𝑝 被限定集 𝑍 阻塞(block)当且仅当:

  • 路径 𝑝 含有链结构 A→𝐵→C 或分连结构 A←𝐵→C 且中间节点 𝐵 在 𝑍 中
  • 或者路径 𝑝 含有汇连结构 A→𝐵←C 且汇连节点 𝐵 及其后代都不在 𝑍 中

定义:若 𝑍 阻塞了节点 X 和节点 𝑌 之间的每一条路径,则称给定 𝑍 时,X 和 𝑌 是 D - 分离,即给定 𝑍 时,X 和 𝑌 条件独立

引理:父节点已知时,该节点与其所有非后代的节点( non-descendants)满足 D-separated

定理:父节点已知时,该节点与其所有非后代的节点( non-descendants)条件独立

# 具体例子

  • 单一:Naive Bayes(朴素贝叶斯)

  • 混合:GMM (混合高斯模型)

  • 加入时间维度

    • Markov Chain
    • Gaussian Process(无限维高斯分布)
  • 连续:Gaussian Bayesian Network

  • 混合模型与时间结合起来:动态模型

    • HMM(离散)
    • Karman Filter(连续 [高斯]、线性)
    • Particle Filter(非高斯、非线性)

总的来说,用两句话总结这些模型:从单一到混合、从有限到无限

两个角度:空间(随机变量的取值从离散到连续)、时间(加入时间维度,从某一时刻延长到无限时间)

# 概率图模型的推理

(贝叶斯网络为主)

# 变量消元算法 (VE)

变量消除(Variable Elimination,VE)基本思想:通过从联合概率分别逐步消除变量,来求边缘概率

给定一个贝叶斯网络的一系列条件概率表 F\mathbf F,查询变量 QQ,证据变量的取值 E=e\mathbf E=e ,剩余变量 Z\mathbf Z ,需要计算 Pr(QE)Pr(Q|\mathbf E)

# 因子及相关操作

f(X,Y)f(\mathbf{X},\mathbf{Y}) 指代涉及变量集合 XY\mathbf{X}\cup\mathbf{Y} 的因子,如条件概率表中的 Pr(CA)Pr(C|A) 可以用因子 f(C,A)f(C,A) 或者 f(A,C)f(A,C) 来表示;

  • 限制:给定 f(X,Y)f(X,\mathbf{Y})X=aX=a ,则 fX=a=h(Y)=f(a,Y)f_{X=a}=h(\mathbf{Y})=f(a,\mathbf{Y})

  • 相乘:给定 f(X,Y)f(\mathbf{X},\mathbf{Y})g(Y,Z)g(\mathbf{Y},\mathbf{Z}) ,则

    h(X,Y,Z)=f(X,Y)×g(Y,Z)h(\mathbf{X},\mathbf{Y},\mathbf{Z})=f(\mathbf{X},\mathbf{Y})\times g(\mathbf{Y},\mathbf{Z})

  • 求和:给定 f(X,Y)f(X,\mathbf{Y}) ,则该因子在变量 XX 上求和将得到

    h(Y)=xDom(X)f(x,Y)h(\mathbf{Y})=\sum_{x\in Dom(X)}f(x,\mathbf{Y})

# 算法流程

  • 对于任意因子 fFf\in\mathbf F ,如果该因子涉及 EE 中的一个或多个变量,则将其替换为限制后的因子 f_

  • 给定一个消元顺序,对于变量 ZjZZ_j\in\mathbf Z

    • f1,f2,,fkf_1,f_2,\cdots,f_kF\mathbf F 中包含 ZjZ_j 的所有因子;

    • 将这些因子相乘并在 ZjZ_j 上求和后得到新的因子:

      gj=Zjf1×f2××fkg_j=\sum_{Z_j}f_1\times f_2\times\cdots\times f_k

    • F\mathbf F 中删除 f1,f2,,fkf_1,f_2,\cdots,f_k ,并将 gjg_j 加入到 F\mathbf F

  • 剩下的因子将只涉及查询变量 QQ,对这些因子相乘并归一化后得到 Pr(QE)Pr(Q|\mathbf E)

# 算法理解

第一种角度是理解为乘法对加法的分配律

第二种角度是 message 的传播过程,也就是局部的消息传递

# 信念传播算法 (BP)

信念传播算法(Belief Propagation, BP),基于局部的消息传递,可以视为 VE 算法 + 缓存 的推广:BP = VE + Caching

  • 在树状图模型上能收敛,且能达到精确推理
  • 但在一般图模型上,BP 为近似推理算法

BP

mba(xa)=bφabφbmcb(xb)mdb(xb)m_{b\to a}(x_a)=\sum_{b}\varphi_{ab}\cdot\varphi_{b}\cdot m_{c\to b}(x_b)\cdot m_{d\to b}(x_b)

φbmcb(xb)mdb(xb)\varphi_{b}\cdot m_{c\to b}(x_b)\cdot m_{d\to b}(x_b)信念 (belief)

  • φb\varphi_{b} 来自 bb 自己;
  • mcb(xb)mdb(xb)m_{c\to b}(x_b)\cdot m_{d\to b}(x_b) 来自 bb 的 children

一般化形式:

mji(xi)=xjφijφjkNB(j)imkj(xj)P(xi)=φijNB(i)mji(xi)=φijNB(i)xjφijφjkNB(j)imkj(xj)\begin{aligned} m_{j\to i}(x_i) &=\sum_{x_j}\varphi_{ij}\cdot\varphi_{j}\prod_{k\in\text{NB}(j)-i}m_{k\to j}(x_j)\\ P(x_i) &=\varphi_i\prod_{j\in\text{NB}(i)}m_{j\to i}(x_i)\\ &=\varphi_i\prod_{j\in\text{NB}(i)}\sum_{x_j}\varphi_{ij}\cdot\varphi_{j}\prod_{k\in\text{NB}(j)-i}m_{k\to j}(x_j) \end{aligned}

# 因子图 BP

# 概率图模型的学习

(不考)

条件概率表的学习方法:

  • 极大似然
  • 期望最大化

贝叶斯网络结构学习常用方法:

  • 基于约束的结构学习 (constraint-based structure learning):将贝叶斯网络看作是一种独立关系的表示。尝试对数据中的条件依赖和条件独立关系进行检验,找到能够对这些依赖和独立关系给出最好解释的某个网络。
  • 基于得分的结构学习 (score-based structure learning):定义模型对观测数据拟合程度的得分函数,通过最大化得分函数完成结构学习。
    • 结构斯然得分
    • 贝叶斯得分
\ No newline at end of file diff --git a/cs/ctf/w4terctf2024/index.html b/cs/ctf/w4terctf2024/index.html index c231237a..38c347c7 100644 --- a/cs/ctf/w4terctf2024/index.html +++ b/cs/ctf/w4terctf2024/index.html @@ -1,4 +1,4 @@ -W4terCTF2024 WP - CTF - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

年轻人的第一场 CTF ,学到了很多,比较走运拿了第五。最遗憾的是密码学板块了,认真学了不少抽象代数但还是没有做出几题。

rank

队友们:(我起了个整活队名,其实是抄袭另一个叫做 “憧憬成为 CTFer” 的 )

team

# AI

# Network Reverse

网络结构长这样:

Sequential(
+W4terCTF2024 WP - CTF - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

年轻人的第一场 CTF ,学到了很多,比较走运拿了第五。最遗憾的是密码学板块了,认真学了不少抽象代数但还是没有做出几题。

rank

队友们:(我起了个整活队名,其实是抄袭另一个叫做 “憧憬成为 CTFer” 的 )

team

# AI

# Network Reverse

网络结构长这样:

Sequential(
   (0): Conv2d(3, 4, kernel_size=(2, 2), stride=(1, 1))
   (1): GELU(approximate='none')
   (2): Conv2d(4, 8, kernel_size=(5, 5), stride=(1, 1))
@@ -48,4 +48,4 @@
  [49. 49. 49. 49. 49. 49. 49. 49. 49. 49. 32. 32. 49. 49. 32. 32. 32.]
  [32. 32. 49. 49. 49. 49. 49. 49. 49. 49. 32. 32. 49. 49. 32. 32. 32.]]
 

同样的方法,可以得到 byte_8020 的后 10 行

# sub_1483

代码的逻辑大致是根据输入的 flag 的后 17 位,构造 byte_8020

刚才已经求出了 byte_8020,可以用下面的脚本求出 flag 后 17 位

small_alpha_bet = [
'      11    11    111111111111111111    11    11       ',
'           111  1119911191119                          ',
'          11  11111111119999991111111111  11           ',
'  9   9111        9        111  9   99      9   111    ',
'            111111111199111111991111111111             ',
'111  9  9111  1111119111111   111         111  9       ',
'99111  111      9           111111  111  111         11',
'   111     9   111      1119            111   111  111 ',
'   9         111111      9      9      111  99111   111',
'   111     91111119     111         1119111   1119     ',
'    111         111   9  111      1119     111        1',
'        111   11191119    111   991119  111            ',
'     9111111111              111      9111   111   1119',
'1119  111111   111        111111111        9111  99111 ',
'                        1119        111111   111  111  ',
'999     111111        1119  111  11199   9        91119',
'111        111      9     9111     1119  99   111111111',
'        11    11111111111111111111111111    11         ',
'          11  11                      11  11           ',
'   99111     111111     111   111  9       111      9  ',
'        1111119  111111   111              9    111    ',
'   111      11191111119   111  99        111111   11111',
'             111   111     11199           9     991111',
'        9111      111      111111      9   99     111  ',
'9   9      1111119  1119111      111  11111199       11',
'        9   111111111     111111111      9111111    111']
upper_alpha_bet = [
'                   111111  99      111  111111111111111',
'      11  11    11                  11    11  11       ',
'  111     9  111      11199111111              11111111',
'  11111111  11      1199  11  1199      11  11111111111',
'1111111111119   999          111      9  9      111    ',
'111     99   9111                9111111           1119',
'     11111199111111        111111111      111  9111   1',
'      11  111111        111111        111111  111      ',
'        11111111111111111111111111111111111111         ',
'       1119        111     111   9      111            ',
'111   111         9      11199111      1119111         ',
'     111        999   111111111         99     1119111 ',
'  11          11111111      11111111          11    111',
'1111111111  11            11            11  11111111111',
'  1111  11    11        11  11        11    11  1111111',
'111   9           111111           1119111111   9      ',
'9111        11111191111111111119   111         111     ',
'  9111    111111   111   9           111111   111111   ',
'9111   911199     111111           9     9         9111',
'       111   111  9  9   99   1111119      111        1',
'  1111  11  11            11            11  11  1111111',
'111        111  111111111        111111111           11',
'    1111    11      9999  11  9999      1111  11111    ',
'111111     1119111       9      99111   1111119111     ',
'111     9   9   111        1119  111      1111111119111',
'  111     111111111111         1119   111111   1111119 ']
num_bet = [
'111  9   111     99  111111   111           111     111',
'   111   111111      111     9111   111   1111119111  1',
'             9   9   9111111  9      111111111     111 ',
'111       9111111111   111   111        1111111119  911',
'99  9111        1119        1119  111        1119     9',
'   9   111111   9111   9111111111                  9  1',
'     111   111   111  111111              9     9111111',
'          1111111111111111111111111111111111           ',
'       9      111111     9    1111111111111119         ',
'111   111111999111111  9   9111     111   9111        1']
matrix_8020 = [
[32, 32, 49, 49, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 49, 49, 49],
[32, 32, 49, 49, 49, 49, 32, 32, 49, 49, 32, 32, 32, 32, 49, 49, 32],
[32, 32, 49, 49, 49, 49, 32, 32, 49, 49, 32, 32, 49, 49, 32, 32, 32],
[49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 32, 32, 49, 49, 32, 32, 32],
[32, 32, 49, 49, 49, 49, 49, 49, 49, 49, 32, 32, 49, 49, 32, 32, 32],
[32, 32, 32, 32, 49, 49, 49, 49, 32, 32, 32, 32, 49, 49, 32, 32, 32],
[32, 32, 32, 32, 32, 32, 49, 49, 32, 32, 49, 49, 49, 49, 49, 49, 32],
[32, 32, 32, 32, 32, 32, 32, 32, 49, 49, 49, 49, 49, 49, 49, 49, 49],
[32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 49, 49, 49, 49, 49, 49, 49],
[32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 49, 49, 49, 49, 49],
[32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 49, 49, 32, 32, 49, 49, 49],
[32, 32, 32, 32, 32, 32, 32, 32, 49, 49, 32, 32, 32, 32, 49, 49, 49],
[32, 32, 32, 32, 32, 32, 49, 49, 32, 32, 32, 32, 49, 49, 32, 32, 32],
[32, 32, 32, 32, 32, 32, 49, 49, 32, 32, 49, 49, 32, 32, 32, 32, 49],
[32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 49, 49, 32, 32, 49, 49, 32]]
str_array_8020 = [ (''.join(chr(x) for x in line )) for line in matrix_8020]
# print(str_array_8020)
for line in str_array_8020:
    for i in range(26):
        if small_alpha_bet[i][0:17] == line:
            print(chr(i+ord('a')),end=' ')
    for i in range(26):
        if upper_alpha_bet[i][0:17] == line:
            print(chr(i+ord('A')), end=' ')
    for i in range(10):
        if num_bet[i][0:17] == line:
            print(chr(i+ord('0')), end=' ')

结果为

M O U N D W H I 7 e c r a B s

由此得到 flag

W4terCTF{1E7_US_drAW_a_plC7ur3_WITH_MA7Rix_4nd_MOUND_WHI7e_craBs}

# DouDou

爬了 js 下来,用了 restringer 反混淆,得到关键函数如下:

function check(q) {
  var V = JSON.parse(JSON.stringify(q)),
    x = []
  for (var P = 0; P < 12; P++) {
    x.push(
      e(q[P])
        .map((g) => g.toString(16).padStart(2, '0'))
        .join('')
    )
  }
  x = x.join('')
  if (x == r + A + s + y + B + F + w + Q + b + p + i + f) {
    // ...

最后 x == ... 后面的表达式也求出来了,是一个超长 16 进制字符串,太长不贴了。

分析前面调用 check(STEPS) 的环节可以得到, q 会是一个 [[int * 16] * 12] ,而函数 e ,结合 hint 最终判断为 AES 加密,key 是 W4terDr0pCTF2024 ,但是还没完,加密之前每个字节要先异或一个 153

最后生成的 x 要等于那个超长字符串,才会进入 if 内生成 flag 的过程,得到 flag:

flag = ''
    res = ''
    for (var P = 0; P < 12; P++) {
      res += V[P].map((g) => String.fromCharCode(g))
    }
    res = res.replaceAll(',', '')
    for (var P = 0; P < res.length; P += 4) {
      flag += String.fromCharCode(parseInt(res.slice(P, P + 4), 4))
    }

大概就是 res 四个一组,parse 成一个四位四进制整数,再转 ascii 即可。这也就意味着 res 必须是 ^[0123]*$ ,这也可以检验得到 res 的过程是否正确,反正我们一次就出来了:

final_x = "91d48f9e77505fe36b1537597d68a8be6ef1ced09bba7c9d4ea6a123042d47bbd5776d7b85eebbb7738de44b9af45f9b706640c8dac77d409ceb067e677e7290401e4852527e119b8095a636d0b628e1161142b7dfcbcf2ef890698ba5d279c78df2348e45d1aef635ebfb841284f6d67d1e9d0f0489bcdc5ba303bc791d0e18e46889fa856a463907d82a8137b7b2a863d1896d4dfcd6b84a2f55b50567f705ea7177187609da2e506182007b7e8244acf62c69de4f511760159ffc6dd8e9f5"
aes = AES.new(b"W4terDr0pCTF2024", AES.MODE_ECB)
l = []
while final_x:
    part_s = final_x[:32]
    final_x = final_x[32:]
    l2 = []
    while part_s:
        x = int(part_s[:2], 16)
        l2.append(x)
        part_s = part_s[2:]
    l.append(l2)
l = [[x ^ 153 for x in subl] for subl in l]
l = [bytes(subl) for subl in l]
l = [aes.decrypt(b) for b in l]
ans = ""
for s in l:
    while s:
        b = int(s[:4], 4)
        s = s[4:]
        ans += chr(b)
ans
'jS_ls_In7erEStlng_ANd_QuaTeRN4rY_IS_al50_1Unny!!'
-

# 古老的语言

用 VB 反编译器逆向,关键函数 Fxxxtel 如下:

Public Function Fxxxtel(raw) '40F35C
  'Data Table: 40E3A8
  Dim var_B0 As Long
  Dim var_B4 As Long
  Dim var_B8 As Long
  Dim var_BC As Long
  Dim var_86 As Integer
  loc_40F031: For var_AC = 0 To 9 Step 3: var_A6 = var_AC 'Integer
  loc_40F047:   var_B4 = raw(CLng(var_A6))
  loc_40F055:   var_B8 = raw(CLng((var_A6 + 1)))
  loc_40F063:   var_BC = raw(CLng((var_A6 + 2)))
  loc_40F06D:   For var_C0 = 1 To &H20: var_A8 = var_C0 'Integer
  loc_40F089:     var_B0 = AddLong(0, -1640531527)
  loc_40F0FB:     var_B4 = var_B4 Xor AddLong(AddLong(LeftRotateLong(var_B8, 4) Xor -559038737, var_B8 Xor var_B0), RightRotateLong(var_B8, 5) Xor -1161901314)
  loc_40F16D:     var_B8 = var_B8 Xor AddLong(AddLong(LeftRotateLong(var_BC, 4) Xor -559038737, var_BC Xor var_B0), RightRotateLong(var_BC, 5) Xor -1161901314)
  loc_40F1DF:     var_BC = var_BC Xor AddLong(AddLong(LeftRotateLong(var_B4, 4) Xor -559038737, var_B4 Xor var_B0), RightRotateLong(var_B4, 5) Xor -1161901314)
  loc_40F1E5:   Next var_C0 'Integer
  loc_40F1F4:   var_A0(CLng(var_A6)) = var_B4
  loc_40F202:   var_A0(CLng((var_A6 + 1))) = var_B8
  loc_40F210:   var_A0(CLng((var_A6 + 2))) = var_BC
  loc_40F214: Next var_AC 'Integer
  loc_40F21B: var_86 = &HFF

用 C 整理出的等价版本:

void encrypt(uint32_t *v) {
  uint32_t a = v[0], b = v[1], c = v[2];
  for (int i = 0; i < 32; i++) {
    a = a ^ round_fn(b);
    b = b ^ round_fn(c);
    c = c ^ round_fn(a);
  }
  v[0] = a;
  v[1] = b;
  v[2] = c;
}
uint32_t round_fn(uint32_t b) {
  const uint32_t delta = 0x9e3779b9;
  return ((left_rotate(b, 4) ^ (0xdeadbeef)) + (b ^ delta) +
          (right_rotate(b, 5) ^ (0xbabecafe)));

在这之后是一长串的 IF,判断 var_A0 的各个位是否等于一些硬编码的 32 位常数,将这些常数解密即可。

可以看出这和 TEA 加密非常像,但是是三个一组的循环混淆,而非经典 TEA 的两个一组,而且把 TEA 轮函数加法和异或交换了,以及每次异或的是固定的 delta 而不是 delta 的累加。每次取三个 u32 一组,像这样交叉异或 32 轮。

三个一组问题不大,把加密的顺序反过来异或回去可以了,原理是一样的:

void decrypt(uint32_t *v) {
  uint32_t a = v[0], b = v[1], c = v[2];
  for (int i = 0; i < 32; i++) {
    c = c ^ round_fn(a);
    b = b ^ round_fn(c);
    a = a ^ round_fn(b);
  }
  v[0] = a;
  v[1] = b;
  v[2] = c;
}

然而这样不对。hint 说要关掉的那个选项我看到了,关了之后重新复现了一遍,发现跟之前一点区别没有,心态炸了。

最后一天晚九点,突发奇想把轮函数改了一下,把 sum 做异或,相当于只把轮函数的加法和异或互换的 TEA 算法,保留 sum 的部分不改,然后居然过了,有瞎蒙的成分在。

事后注意到这一行:

loc_40F089:     var_B0 = AddLong(0, -1640531527)

那就意味着这一行的逆向是错的,应该是 var_B0 = AddLong(var_B0, -1640531527) ,不过没发现为什么。

Edited on Views times
\ No newline at end of file +

# 古老的语言

用 VB 反编译器逆向,关键函数 Fxxxtel 如下:

Public Function Fxxxtel(raw) '40F35C
  'Data Table: 40E3A8
  Dim var_B0 As Long
  Dim var_B4 As Long
  Dim var_B8 As Long
  Dim var_BC As Long
  Dim var_86 As Integer
  loc_40F031: For var_AC = 0 To 9 Step 3: var_A6 = var_AC 'Integer
  loc_40F047:   var_B4 = raw(CLng(var_A6))
  loc_40F055:   var_B8 = raw(CLng((var_A6 + 1)))
  loc_40F063:   var_BC = raw(CLng((var_A6 + 2)))
  loc_40F06D:   For var_C0 = 1 To &H20: var_A8 = var_C0 'Integer
  loc_40F089:     var_B0 = AddLong(0, -1640531527)
  loc_40F0FB:     var_B4 = var_B4 Xor AddLong(AddLong(LeftRotateLong(var_B8, 4) Xor -559038737, var_B8 Xor var_B0), RightRotateLong(var_B8, 5) Xor -1161901314)
  loc_40F16D:     var_B8 = var_B8 Xor AddLong(AddLong(LeftRotateLong(var_BC, 4) Xor -559038737, var_BC Xor var_B0), RightRotateLong(var_BC, 5) Xor -1161901314)
  loc_40F1DF:     var_BC = var_BC Xor AddLong(AddLong(LeftRotateLong(var_B4, 4) Xor -559038737, var_B4 Xor var_B0), RightRotateLong(var_B4, 5) Xor -1161901314)
  loc_40F1E5:   Next var_C0 'Integer
  loc_40F1F4:   var_A0(CLng(var_A6)) = var_B4
  loc_40F202:   var_A0(CLng((var_A6 + 1))) = var_B8
  loc_40F210:   var_A0(CLng((var_A6 + 2))) = var_BC
  loc_40F214: Next var_AC 'Integer
  loc_40F21B: var_86 = &HFF

用 C 整理出的等价版本:

void encrypt(uint32_t *v) {
  uint32_t a = v[0], b = v[1], c = v[2];
  for (int i = 0; i < 32; i++) {
    a = a ^ round_fn(b);
    b = b ^ round_fn(c);
    c = c ^ round_fn(a);
  }
  v[0] = a;
  v[1] = b;
  v[2] = c;
}
uint32_t round_fn(uint32_t b) {
  const uint32_t delta = 0x9e3779b9;
  return ((left_rotate(b, 4) ^ (0xdeadbeef)) + (b ^ delta) +
          (right_rotate(b, 5) ^ (0xbabecafe)));

在这之后是一长串的 IF,判断 var_A0 的各个位是否等于一些硬编码的 32 位常数,将这些常数解密即可。

可以看出这和 TEA 加密非常像,但是是三个一组的循环混淆,而非经典 TEA 的两个一组,而且把 TEA 轮函数加法和异或交换了,以及每次异或的是固定的 delta 而不是 delta 的累加。每次取三个 u32 一组,像这样交叉异或 32 轮。

三个一组问题不大,把加密的顺序反过来异或回去可以了,原理是一样的:

void decrypt(uint32_t *v) {
  uint32_t a = v[0], b = v[1], c = v[2];
  for (int i = 0; i < 32; i++) {
    c = c ^ round_fn(a);
    b = b ^ round_fn(c);
    a = a ^ round_fn(b);
  }
  v[0] = a;
  v[1] = b;
  v[2] = c;
}

然而这样不对。hint 说要关掉的那个选项我看到了,关了之后重新复现了一遍,发现跟之前一点区别没有,心态炸了。

最后一天晚九点,突发奇想把轮函数改了一下,把 sum 做异或,相当于只把轮函数的加法和异或互换的 TEA 算法,保留 sum 的部分不改,然后居然过了,有瞎蒙的成分在。

事后注意到这一行:

loc_40F089:     var_B0 = AddLong(0, -1640531527)

那就意味着这一行的逆向是错的,应该是 var_B0 = AddLong(var_B0, -1640531527) ,不过没发现为什么。

Edited on Views times
\ No newline at end of file diff --git a/cs/data-structure-and-algorithm/b-tree/index.html b/cs/data-structure-and-algorithm/b-tree/index.html index b423b227..dca00b87 100644 --- a/cs/data-structure-and-algorithm/b-tree/index.html +++ b/cs/data-structure-and-algorithm/b-tree/index.html @@ -1 +1 @@ -B - 树 - 数据结构与算法 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# Multiway Tree

多叉树任意节点的所有子树也都是有顺序的

多叉树可以按固定的方法向二叉树转化:

  1. 对所有节点只保留与最左侧子节点的连接,删除其他连接
  2. 从左到右依次连接同一层的兄弟节点 (siblings)

# B-Tree

Banlanced Multiway Tree, 顾名思义,B - 树是一种平衡的多路查找树,是平衡二叉树的外延概念。

B-Tree 是为外部查找(如磁盘)设计的一种平衡查找树。

系统从磁盘读取数据到内存时是以存储块 (block) 为基本单位的,位于同一个磁盘块中的数据会被一次性读取出来,而不是需要什么取什么。B-Tree 结构的数据可以让系统高效的找到数据所在的磁盘块。

为了描述 B-Tree,首先定义一条记录为一个二元组[key,data][key,data],key 为记录的健值,对应表中的主键值,data 为一行记录中除主键外的数据。对于不同的记录,key 值互不相同。

# 定义

一颗 m 阶 B - 树 (m 路 B - 树) 满足:

  1. 所有叶子节点在同一层 (level),所有叶节点实际上不存在,都是空节点,平衡因子 = 0
    • 根节点若非空 (不是叶节点 / 空节点),则有至少 2 颗子树
    • 除 根节点 以外所有 内部节点 的 子节点 / 子树 数量XX 满足: m2Xm\left\lceil\frac{m}{2}\right\rceil \leq X \leq m
    • 根节点至少有 11 个关键字,至多有 m1m-1 个关键字
    • 非根节点至少有 m21\left\lceil\frac{m}{2}\right\rceil-1 个关键字,至多有 m1m-1 个关键字
  2. 每个节点中的关键字都按照从小到大 (升序) 排列,每个关键字的左子树中的所有关键字都小于它,右子树中的所有关键字都大于它 (也可以反过来,只要满足查找树的定义)

# 推论

高度为hhmm 阶 B - 树关键字NN 取值范围为:
2m2h11Nmh12\left\lceil\frac{m}{2}\right\rceil^{h-1}-1\leq N\leq m^h-1

NN 个关键字的mm 阶 B - 树的高度hh 的取值范围为:
logm(N+1)hlogm2N+12+1log_m(N+1)\leq h\leq log_{\left\lceil\frac{m}{2}\right\rceil}\frac{N+1}{2}+1

\ No newline at end of file +B - 树 - 数据结构与算法 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# Multiway Tree

多叉树任意节点的所有子树也都是有顺序的

多叉树可以按固定的方法向二叉树转化:

  1. 对所有节点只保留与最左侧子节点的连接,删除其他连接
  2. 从左到右依次连接同一层的兄弟节点 (siblings)

# B-Tree

Banlanced Multiway Tree, 顾名思义,B - 树是一种平衡的多路查找树,是平衡二叉树的外延概念。

B-Tree 是为外部查找(如磁盘)设计的一种平衡查找树。

系统从磁盘读取数据到内存时是以存储块 (block) 为基本单位的,位于同一个磁盘块中的数据会被一次性读取出来,而不是需要什么取什么。B-Tree 结构的数据可以让系统高效的找到数据所在的磁盘块。

为了描述 B-Tree,首先定义一条记录为一个二元组[key,data][key,data],key 为记录的健值,对应表中的主键值,data 为一行记录中除主键外的数据。对于不同的记录,key 值互不相同。

# 定义

一颗 m 阶 B - 树 (m 路 B - 树) 满足:

  1. 所有叶子节点在同一层 (level),所有叶节点实际上不存在,都是空节点,平衡因子 = 0
    • 根节点若非空 (不是叶节点 / 空节点),则有至少 2 颗子树
    • 除 根节点 以外所有 内部节点 的 子节点 / 子树 数量XX 满足: m2Xm\left\lceil\frac{m}{2}\right\rceil \leq X \leq m
    • 根节点至少有 11 个关键字,至多有 m1m-1 个关键字
    • 非根节点至少有 m21\left\lceil\frac{m}{2}\right\rceil-1 个关键字,至多有 m1m-1 个关键字
  2. 每个节点中的关键字都按照从小到大 (升序) 排列,每个关键字的左子树中的所有关键字都小于它,右子树中的所有关键字都大于它 (也可以反过来,只要满足查找树的定义)

# 推论

高度为hhmm 阶 B - 树关键字NN 取值范围为:
2m2h11Nmh12\left\lceil\frac{m}{2}\right\rceil^{h-1}-1\leq N\leq m^h-1

NN 个关键字的mm 阶 B - 树的高度hh 的取值范围为:
logm(N+1)hlogm2N+12+1log_m(N+1)\leq h\leq log_{\left\lceil\frac{m}{2}\right\rceil}\frac{N+1}{2}+1

\ No newline at end of file diff --git a/cs/data-structure-and-algorithm/binary-tree/index.html b/cs/data-structure-and-algorithm/binary-tree/index.html index 296da48b..a510beb8 100644 --- a/cs/data-structure-and-algorithm/binary-tree/index.html +++ b/cs/data-structure-and-algorithm/binary-tree/index.html @@ -1 +1 @@ -二叉树 - 数据结构与算法 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 二叉树的一些规范 (考研)

节点的度数:节点出发指向下一层节点的边的数量 (出度)

N0,N1,N2N_0,N_1,N_2:分别表示度数为 1,2,3 的顶点数量

# 结论

任意二叉树满足:

  • n=N0+N1+N2n=N_0+N_1+N_2

  • n1=0×N0+1×N1+2×N2=N1+2N2n-1=0\times N_0+1\times N_1+2\times N_2=N_1+2N_2

  • n=1+N1+2N2n=1+N_1+2N_2

  • N2=N01N_2=N_0-1

正则二叉树还满足:

  • N1=0N_1=0

  • n+1=2N0n+1=2N_0

  • n1=2N2n-1=2N_2

# 树的遍历

  • 先序:根、左、右

  • 中序:左、根、右

  • 后序:左、右、根

# 递归做法

三行代码:遍历左子树、节点、右子树,变换顺序即可得到三种遍历方式

# 非递归做法

# 已知二叉树的两种遍历结果确定 (还原) 二叉树

  • 即还原这颗二叉树,当且仅当这两种遍历中有一个是中序遍历!

  • 如果遍历结果是打印出来的元素结果,还需要每个元素不一样?!结点序列的话由于是指针则不需要?

  • 基本思路:已知先序和后序遍历都能容易确定谁是树根,再由中序遍历才确定左右子树

# 线索二叉树 Threaded binary trees

一个具有 n 个结点的二叉树若采用二叉链表存储结构, 在 2n 个指针域中只有 n-1 个指针域是用来存储结点孩 子的地址,而另外 n+1 个指针域存放的都是 NULL。

因此,可以利用某结点空的左指针域 (lchild) 指出该 结点在某种遍历序列中的直接前驱结点的存储地址, 利用结点空的右指针域 (rchild) 指出该结点在某种遍历序列中的直接后继结点的存储地址;对于那些非空 的指针域,则仍然存放指向该结点左、右孩子的指针。 这样,就得到了一棵线索二叉树。

由于序列可由不同的遍历方法得到,因此,线索树有 先序线索二叉树、中序线索二叉树、后序线索二叉树 三种。把二叉树改造成线索二叉树的过程称为线索化。

# 哈夫曼树

哈夫曼树 (Huffman Tree) 是指对于一组带有确定权值的叶结点,构造的具有最小带权路径长度的二叉树,也称最优二叉树 (Optimal Binary Tree)。

设二叉树具有 n 个带权值的叶结点,那么从根结点到各个叶结点的路径长度与 相应结点权值的乘积之和,称为二叉树的带权路径长度,记为:

WPL=k=1nWPL=\sum_{k=1}^{n}

其中 WkW_k 为第 k 个叶结点的权值,LkL_k 为第 k 个叶结点的路径长度。

在给定一组具有确定权值的叶结点,可以构造出不同的带权二叉树。这些形状不同的二叉树的带权路径长度 WPL 将各不相同。

哈夫曼树是正则二叉树,即没有度数为 1 的顶点。

# 构造

由相同权值的一组叶结点所构成的二叉树有不同的形态和不同的带权路径长度,那么如何找到带权路径长度最小的二叉树呢?

根据哈夫曼树的定义,一棵二叉树要使其 WPL 值最小,必须使权值越大的叶结点越靠近根结点,而权值越小的叶结点越远离根结点。

哈夫曼 (Huffman) 依据这一特点提出了一种方法。

  1. 由给定的 n 个权值 {W1W_1,W2W_2,...,WnW_n} 构造 n 棵只有一个叶结点的二叉树,从而得到 一个二叉树的集合 F={T1T_1,T2T_2,...,TnT_n};

  2. 在 F 中选取根结点的权值最小和次小的两棵二叉树作为左、右子树构造一棵新的二叉树,这棵新的二叉树根结点的权值为其左、右子树根结点权值之和;

  3. 在集合 F 中删除作为左、右子树的两棵二叉树,并将新建立的二叉树加入到集合 F 中;

  4. 重复 (2)、(3) 两步,当 F 中只剩下一棵二叉树时,这棵二叉树便是所要建立的哈夫曼树。

# 哈夫曼编码

哈夫曼编码 (Huffman Coding) 是一种编码方式,是一种用于无损数据压 缩的熵编码 (权编码) 算法,是 David A. Huffman 发明的。

# 哈夫曼编码代码

c++
typedef struct  // 哈夫曼编码的存储结构
{ char bits[N];  // 保存编码的数组 
    int start;   // 编码有效起始位置,该位置之后的 01 串为字符的编码 
    char ch;  // 字符
} CodeType ;
CodeType code[N+1]; // 字符编码数组,下标为 0 的单元空出
c++
huffmanCode(HufmTree tree[],CodeType code[]) /* 利用哈夫曼树求字符的哈夫曼编码 */
{
    int i,c,p;
    for(i = 1; i<=N; i++)  // N 次循环,分别得到 N 个字符的编码
    {
        code[i].start = N; c = i;
        p = tree[i].parent; // 获取字符的双亲
        while (p != 0) // 一直往上层查找,直到根结束
        {
            code[i].start--;
            if ( tree[p].lchild ==c ) code[i].bits[code[i].start] = '0';
            else code[i].bits[code[i].start] = '1';
            c = p;
            p = tree[p].parent;
        }
    }
}

# 二叉查找树

BST (Binary Search Tree) 递归定义:

  1. 根节点:左子树所有节点的值 < 根节点的值 < 右子树所有节点的值

  2. 任何节点的左子树右子树也都是 BST

# 二叉树的查找 (二叉查找树实现二分查找函数)

递归实现:

c++
//Recursive auxiliary function
template <class Record>
Binary_node<Record>*
Search_tree<Record> :: search_for_node
(Binary_node<Record>*root1, const Record &target)const
{
    if (root1 == NULL || root1->data == target) return root;
    if (root1->data < target)return search_for_node(root1->right, target);
    return search_for_node(root1->left, target);
}
c++
//Nonrecursive version
template <elass Record>
Binary_node<Record>*
Search_tree<Record> :: search_for_node
(Binary_node<Record>*root1, const Record &target) const
{
    while (root1 != NULL && root1->data != target){
        if (root1->data < target) root1 = root1->right;
        else root1 = root1->left;
    }
    return root1:
}
c++
//Public method for tree search
template <class Record>
Error_code
Search_tree<Record> :: tree_search(Record &target) const
{
    Error_code_result = success;
    Binary_node<Record> *found = search_for_node(root, target);
    if (found == NULL) result = not_present;
    else target = found->data;
    return result;
}

# BST 的插入

c++
template <class Record>
Error_code
Search_tree<Record> :: insert(const Record & new_data)
{
    return search_and_insert(root, new_data);
}
c++
template <class Record>
Error_code
Search_tree<Record> :: search_and_insert
(Binary_node<Record> *&root1, const Record & new_data)
{
    if (root1 == NULL)
    {
        root1 = new Binary_node<Record>(new_data);
        return success;
    }
    if (root1->data == new_data) return duplicate_error;
    if (root1->data > new_data) return search_and_insert(root1->left, new_data);
    return search_and_insert root1->right, new_data);
}

# BST 的遍历

BST 中序遍历的结果就是所有数据升序排序结果

# BST 的排序

实际上与快排等价

平均情况下 BST 排序 (Treesort) 的时间复杂度为:

2nln(n)+O(n)1.39nlgn+O(n)2nln(n)+O(n)\approx1.39nlgn+O(n)

# BST 的删除

  1. 要删除的节点没有子节点
    直接删除即可

  2. 要删除的节点只有一个子节点(子树)
    以子树根节点替换该节点再删除该节点即可

  3. 要删除的节点有两个子节点(子树)
    要删除节点 x
    有两种互相对称的做法:

    沿着左子树的右链走到尽头的节点 w 的元素是 x 左子树里最大的元素
    只需将 w 元素赋值给 x,再删除 w 节点即可

    沿着右子树的左链走到尽头的节点 w 的元素是 x 右子树里最小的元素
    只需将 w 元素赋值给 x,再删除 w 节点即可

c++
template <class Record>
Error_code
Search_tree<Record> :: search_and_destroy
(Binary_node<Record>*&root1, const Record &target)
{
    if (root1 == NULL || root1->data == target)return remove_root(root1);
    if (target < root1->data)return search_and_destroy(root1->left, target);
    return search_and_destroy(root1->right, target);
}
c++
template <class Record>
Error_code
Search_tree<Record> :: remove_root
(Binary_node<Record>*&root1)
{
    if (root1 == NULL) return not_present;
    Binary_node<Record> *to_delete = root1;
    if (root1->right == NULL) root1 = root1->left;
    else if (root1->left == NULL) root1 = root1->right;
    else
    {
        to_delete = root1->left;
        Binary_node<Record> *parent= root1;
        while (to_delete->right != NULL)
        {
            parent = to_delete;
            to_delete = to_delete->right;
        }
        root1->data = to_delete->data;
        if (parent = root1) root1->left = to_delete->left; // 重点
        else parent->right = to_delete->left; // 重点
    }
    delete to_delete; return success;
}

# 平衡二叉树

  • 二叉树结构会影响查找效率

    • 二叉树结构越趋向于完全二叉树则时间复杂度越接近O(log(n))O(log(n)),效率越好

    • 二叉树结构越趋向于线性链表则时间复杂度越接近于O(n)O(n),效率越差

      • 最坏的情况会退化为O(n)O(n) 的线性查找复杂度

平均访问节点次数:2ln(n)1.39log(n)2ln(n)\approx1.39log(n)

平均比较节点次数:4ln(n)2.77log(n)4ln(n)\approx2.77log(n)

也就是为什么我们需要自平衡二叉查找树

# AVL Trees

AVL 是一种平衡二叉树 (自平衡二叉查找树),过于复杂,没有太大优势,实际更常用的是红黑树来实现

# 平衡因子 BF (Balance Factor)

BF=左子树深度右子树深度BF=左子树深度-右子树深度

# AVL 定义

任意节点的 BF 只能为 - 1、0 或 1

# 插入元素

插入元素会改变 BF,需要调整来维持二叉树的平衡

AVL 树采用四种 “旋转” 调整操作来实现

# 代码实现:

https://blog.csdn.net/weixin_57761086/article/details/127152576

此处定义:BF=右子树深度左子树深度BF=右子树深度-左子树深度

# 数据结构定义
c++
// 结点类
template <typename T>
struct AVLTreeNode {
	AVLTreeNode<T>* left;// 左孩子指针
	AVLTreeNode<T>* right;// 右孩子指针
	AVLTreeNode<T>* parent;// 双亲指针
	T value;// 存储元素的变量
	int bf;// 平衡因子
 
	// 用传入的值构造结点
	AVLTreeNode(const T& _value = T())
		:left(nullptr)
		,right(nullptr)
		,parent(nullptr)
		,value(_value)
		,bf(0)
	{}
};
c++
//AVL 树类
template<typename T>
class AVLTree {
	// 给结点类起别名,方便使用
	typedef AVLTreeNode<T> Node;
private:
	// 指向根结点的结点指针
	Node* root;
};
c++
// 无参构造
// 让根结点指针指向空即可
AVLTree():root(nullptr){}
# 左旋转(RR)

当新节点插入到较高右子树的右侧时 (右右 / RR),需要对最先失去平衡的节点进行一次左旋,使其右子树成为新的根节点,原根节点成为其左子树。

c++
// 左单旋
void RotateLeft(Node* parent) {
	// 这里的指针设计在讲解旋转的时候已经解释过
	Node* subR = parent->right;
	Node* subRL = subR->left;
 
	// 用 pparent (祖父结点) 来保存 parent 结点的双亲
	// 因为 parent 并不一定是整棵树的根,还有可能只是一棵子树的根
	Node* pparent = parent->parent;
 
	// 第一步:首先让双亲的右孩子指针指向 subRL
	parent->right = subRL;
 
	// 之所以要判断是因为 subRL 结点可能不存在
	if (subRL)
		// 更新双亲
		subRL->parent = parent;
 
	// 第二步:让 subR 的左孩子指针指向 parent
	subR->left = parent;
 
	// 不要忘记给这些结点更新它们的双亲
	parent->parent = subR;
	subR->parent = pparent;
 
	// 祖父结点是空,说明 parent 结点是整棵树的根结点
	if (pparent == nullptr) {
		root = subR;
	}
	// 说明 parent 是子树的根结点
	else {
		// 原本祖父结点的孩子是 parent
		// 经过旋转他的孩子变成了 subR
		// 需要判断 parent 是祖父结点的左孩子还是右孩子,然后让对应指针指向 subR 结点
		if (pparent->left == parent) {
			pparent->left = subR;
		}
		else {
			pparent->right = subR;
		}
	}
	// 更新平衡因子
	parent->bf = subR->bf = 0;
}
# 右旋转(LL)

当新节点插入到较高左子树的左侧时 (左左 / LL),需要对最先失去平衡的节点进行一次右旋,使其左子树成为新的根节点,原根节点成为其右子树。

c++
// 右单旋
void RotateRight(Node* parent) {
	Node* subL = parent->left;
	Node* subLR = subL->right;
 
	// 祖父结点
	Node* pparent = parent->parent;
 
	// 第一步:让 parent 的左孩子指针指向 subLR
	parent->left = subLR;
	// 之所以要判断是因为 subLR 结点可能不存在
	if (subLR)
		subLR->parent = parent;
	// 第二步:让 subL 的右孩子指针指向 parent
	subL->right = parent;
 
	// 更新双亲结点
	parent->parent = subL;
	subL->parent = pparent;
 
	// 祖父结点是空,说明 parent 是整棵树的根结点
	if (pparent == nullptr) {
		root = subL;
	}
	//parent 是子树的根结点
	else {
		// 这里和左单旋一样
		if (pparent->left == parent) {
			pparent->left = subL;
		}
		else {
			pparent->right = subL;
		}
	}
	// 更新平衡因子
	parent->bf = subL->bf = 0;
}
# 左右双旋(LR)

当新节点插入到较高左子树的右侧时 (左右 / LR),需要先对左子树进行一次左旋,这时就变为 RR 情形,再对最先失去平衡的节点进行一次右旋,使其左子树的右子树成为新的根节点。

c++
// 左右双旋
void RotateLR(Node* parent) {
	Node* subL = parent->left;
	Node* subLR = subL->right;
	// 保存 subLR 的平衡因子,后面需要根据它来更新别的平衡因子
	int BF = subLR->bf;
 
	// 对以 subL 为根结点的树进行左单旋
	RotateLeft(subL);
	// 对以 parent 为根结点的树进行右单旋
	RotateRight(parent);
 
	// 根据保存的平衡因子更新
	// 当 subLR 平衡因子为 - 1,将 parent 的平衡因子更新为 1
	if (BF == -1) parent->bf = 1;
	// 当 subLR 平衡因子不是 - 1,将 subL 的平衡因子更新为 - 1
	else subL->bf = -1;
}
# 右左双旋(RL)

当新节点插入到较高右子树的左侧时 (右左 / RL),需要先对右子树进行一次右旋,这时就变为 LL 情形,再对最先失去平衡的节点进行一次左旋,使其右子树的左子树成为新的根节点。

c++
// 右左双旋
void RotateRL(Node* parent) {
	Node* subR = parent->right;
	Node* subRL = subR->left;
	// 保存 subRL 的平衡因子,后面根据它更新其他结点平衡因子
	int BF = subRL->bf;
 
	// 对以 subR 为根的树进行右单旋
	RotateRight(subR);
	// 对以 parent 为根的树进行左单旋
	RotateLeft(parent);
 
	// 根据保存的 subRL 平衡因子的不同来进行不同的更新。
	if (BF == -1) subR->bf = 1;
	else parent->bf = -1;
}
# 插入过程
c++
// 插入函数
bool Insert(const T& _value) {
	// 树为空,将新结点作为根结点即可
	if (root == nullptr) {
		root = new Node(_value);
		return true;
	}
 
	// 树非空
	Node* cur = root;
	// 用来保存 cur 的双亲结点
	Node* parent = nullptr;
 
	// 为新结点的插入寻找合适的位置
	// 同时判断是否树中有相同结点
	while (cur) {
		parent = cur;
		if (_value < cur->value) {
			cur = cur->left;
		}
		else if (_value > cur->value) {
			cur = cur->right;
		}
		else {
			return false;
		}
	}
 
	// 构造新结点
	cur = new Node(_value);
	// 判断是新结点应该插在双亲的左边还是右边
	if (_value < parent->value) {
		parent->left = cur;
	}
	else {
		parent->right = cur;
	}
	// 更新新结点的双亲
	cur->parent = parent;
 
	// 更新平衡因子
	// 从下往上
	while (parent) {
		//cur 是双亲左孩子
		// 左子树高度变高,平衡因子就减 1
		// 平衡因子:右子树高度减左子树高度
		if (cur == parent->left) {
			parent->bf--;
		}
		// 右子树变高,平衡因子加 1
		else {
			parent->bf++;
		}
 
		// 判断更新后的平衡因子是否满足 AVL 树
		// 证明 parent 之前只有一个孩子,而新结点插到另一个空着的位置了
		if (parent->bf == 0) {
			break;
		}
		// 证明 parent 之前没有孩子,新结点插入后只有一个孩子
		else if (-1 == parent->bf || 1 == parent->bf) {
			cur = parent;
			parent = cur->parent;
		}
		// 如下就是 parent 的平衡因子变成 2 或 - 2 了
		// 需要根据图片进行理解
		else {
			// 说明 parent 的右子树高
			if (parent->bf == 2) {
				// 根据 cur 的平衡因子判断是左单旋还是右左双旋
				if (cur->bf == 1)
					RotateLeft(parent);
				else
					RotateRL(parent);
			}
			//parent 左子树高
			else {
				if (cur->bf == -1)
					RotateRight(parent);
				else
					RotateLR(parent);
			}
 
			// 使用双旋调整后就不需要向上继续调整了,可以直接退出循环
			break;
		}
	}
	return true;
}
\ No newline at end of file +二叉树 - 数据结构与算法 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 二叉树的一些规范 (考研)

节点的度数:节点出发指向下一层节点的边的数量 (出度)

N0,N1,N2N_0,N_1,N_2:分别表示度数为 1,2,3 的顶点数量

# 结论

任意二叉树满足:

  • n=N0+N1+N2n=N_0+N_1+N_2

  • n1=0×N0+1×N1+2×N2=N1+2N2n-1=0\times N_0+1\times N_1+2\times N_2=N_1+2N_2

  • n=1+N1+2N2n=1+N_1+2N_2

  • N2=N01N_2=N_0-1

正则二叉树还满足:

  • N1=0N_1=0

  • n+1=2N0n+1=2N_0

  • n1=2N2n-1=2N_2

# 树的遍历

  • 先序:根、左、右

  • 中序:左、根、右

  • 后序:左、右、根

# 递归做法

三行代码:遍历左子树、节点、右子树,变换顺序即可得到三种遍历方式

# 非递归做法

# 已知二叉树的两种遍历结果确定 (还原) 二叉树

  • 即还原这颗二叉树,当且仅当这两种遍历中有一个是中序遍历!

  • 如果遍历结果是打印出来的元素结果,还需要每个元素不一样?!结点序列的话由于是指针则不需要?

  • 基本思路:已知先序和后序遍历都能容易确定谁是树根,再由中序遍历才确定左右子树

# 线索二叉树 Threaded binary trees

一个具有 n 个结点的二叉树若采用二叉链表存储结构, 在 2n 个指针域中只有 n-1 个指针域是用来存储结点孩 子的地址,而另外 n+1 个指针域存放的都是 NULL。

因此,可以利用某结点空的左指针域 (lchild) 指出该 结点在某种遍历序列中的直接前驱结点的存储地址, 利用结点空的右指针域 (rchild) 指出该结点在某种遍历序列中的直接后继结点的存储地址;对于那些非空 的指针域,则仍然存放指向该结点左、右孩子的指针。 这样,就得到了一棵线索二叉树。

由于序列可由不同的遍历方法得到,因此,线索树有 先序线索二叉树、中序线索二叉树、后序线索二叉树 三种。把二叉树改造成线索二叉树的过程称为线索化。

# 哈夫曼树

哈夫曼树 (Huffman Tree) 是指对于一组带有确定权值的叶结点,构造的具有最小带权路径长度的二叉树,也称最优二叉树 (Optimal Binary Tree)。

设二叉树具有 n 个带权值的叶结点,那么从根结点到各个叶结点的路径长度与 相应结点权值的乘积之和,称为二叉树的带权路径长度,记为:

WPL=k=1nWPL=\sum_{k=1}^{n}

其中 WkW_k 为第 k 个叶结点的权值,LkL_k 为第 k 个叶结点的路径长度。

在给定一组具有确定权值的叶结点,可以构造出不同的带权二叉树。这些形状不同的二叉树的带权路径长度 WPL 将各不相同。

哈夫曼树是正则二叉树,即没有度数为 1 的顶点。

# 构造

由相同权值的一组叶结点所构成的二叉树有不同的形态和不同的带权路径长度,那么如何找到带权路径长度最小的二叉树呢?

根据哈夫曼树的定义,一棵二叉树要使其 WPL 值最小,必须使权值越大的叶结点越靠近根结点,而权值越小的叶结点越远离根结点。

哈夫曼 (Huffman) 依据这一特点提出了一种方法。

  1. 由给定的 n 个权值 {W1W_1,W2W_2,...,WnW_n} 构造 n 棵只有一个叶结点的二叉树,从而得到 一个二叉树的集合 F={T1T_1,T2T_2,...,TnT_n};

  2. 在 F 中选取根结点的权值最小和次小的两棵二叉树作为左、右子树构造一棵新的二叉树,这棵新的二叉树根结点的权值为其左、右子树根结点权值之和;

  3. 在集合 F 中删除作为左、右子树的两棵二叉树,并将新建立的二叉树加入到集合 F 中;

  4. 重复 (2)、(3) 两步,当 F 中只剩下一棵二叉树时,这棵二叉树便是所要建立的哈夫曼树。

# 哈夫曼编码

哈夫曼编码 (Huffman Coding) 是一种编码方式,是一种用于无损数据压 缩的熵编码 (权编码) 算法,是 David A. Huffman 发明的。

# 哈夫曼编码代码

c++
typedef struct  // 哈夫曼编码的存储结构
{ char bits[N];  // 保存编码的数组 
    int start;   // 编码有效起始位置,该位置之后的 01 串为字符的编码 
    char ch;  // 字符
} CodeType ;
CodeType code[N+1]; // 字符编码数组,下标为 0 的单元空出
c++
huffmanCode(HufmTree tree[],CodeType code[]) /* 利用哈夫曼树求字符的哈夫曼编码 */
{
    int i,c,p;
    for(i = 1; i<=N; i++)  // N 次循环,分别得到 N 个字符的编码
    {
        code[i].start = N; c = i;
        p = tree[i].parent; // 获取字符的双亲
        while (p != 0) // 一直往上层查找,直到根结束
        {
            code[i].start--;
            if ( tree[p].lchild ==c ) code[i].bits[code[i].start] = '0';
            else code[i].bits[code[i].start] = '1';
            c = p;
            p = tree[p].parent;
        }
    }
}

# 二叉查找树

BST (Binary Search Tree) 递归定义:

  1. 根节点:左子树所有节点的值 < 根节点的值 < 右子树所有节点的值

  2. 任何节点的左子树右子树也都是 BST

# 二叉树的查找 (二叉查找树实现二分查找函数)

递归实现:

c++
//Recursive auxiliary function
template <class Record>
Binary_node<Record>*
Search_tree<Record> :: search_for_node
(Binary_node<Record>*root1, const Record &target)const
{
    if (root1 == NULL || root1->data == target) return root;
    if (root1->data < target)return search_for_node(root1->right, target);
    return search_for_node(root1->left, target);
}
c++
//Nonrecursive version
template <elass Record>
Binary_node<Record>*
Search_tree<Record> :: search_for_node
(Binary_node<Record>*root1, const Record &target) const
{
    while (root1 != NULL && root1->data != target){
        if (root1->data < target) root1 = root1->right;
        else root1 = root1->left;
    }
    return root1:
}
c++
//Public method for tree search
template <class Record>
Error_code
Search_tree<Record> :: tree_search(Record &target) const
{
    Error_code_result = success;
    Binary_node<Record> *found = search_for_node(root, target);
    if (found == NULL) result = not_present;
    else target = found->data;
    return result;
}

# BST 的插入

c++
template <class Record>
Error_code
Search_tree<Record> :: insert(const Record & new_data)
{
    return search_and_insert(root, new_data);
}
c++
template <class Record>
Error_code
Search_tree<Record> :: search_and_insert
(Binary_node<Record> *&root1, const Record & new_data)
{
    if (root1 == NULL)
    {
        root1 = new Binary_node<Record>(new_data);
        return success;
    }
    if (root1->data == new_data) return duplicate_error;
    if (root1->data > new_data) return search_and_insert(root1->left, new_data);
    return search_and_insert root1->right, new_data);
}

# BST 的遍历

BST 中序遍历的结果就是所有数据升序排序结果

# BST 的排序

实际上与快排等价

平均情况下 BST 排序 (Treesort) 的时间复杂度为:

2nln(n)+O(n)1.39nlgn+O(n)2nln(n)+O(n)\approx1.39nlgn+O(n)

# BST 的删除

  1. 要删除的节点没有子节点
    直接删除即可

  2. 要删除的节点只有一个子节点(子树)
    以子树根节点替换该节点再删除该节点即可

  3. 要删除的节点有两个子节点(子树)
    要删除节点 x
    有两种互相对称的做法:

    沿着左子树的右链走到尽头的节点 w 的元素是 x 左子树里最大的元素
    只需将 w 元素赋值给 x,再删除 w 节点即可

    沿着右子树的左链走到尽头的节点 w 的元素是 x 右子树里最小的元素
    只需将 w 元素赋值给 x,再删除 w 节点即可

c++
template <class Record>
Error_code
Search_tree<Record> :: search_and_destroy
(Binary_node<Record>*&root1, const Record &target)
{
    if (root1 == NULL || root1->data == target)return remove_root(root1);
    if (target < root1->data)return search_and_destroy(root1->left, target);
    return search_and_destroy(root1->right, target);
}
c++
template <class Record>
Error_code
Search_tree<Record> :: remove_root
(Binary_node<Record>*&root1)
{
    if (root1 == NULL) return not_present;
    Binary_node<Record> *to_delete = root1;
    if (root1->right == NULL) root1 = root1->left;
    else if (root1->left == NULL) root1 = root1->right;
    else
    {
        to_delete = root1->left;
        Binary_node<Record> *parent= root1;
        while (to_delete->right != NULL)
        {
            parent = to_delete;
            to_delete = to_delete->right;
        }
        root1->data = to_delete->data;
        if (parent = root1) root1->left = to_delete->left; // 重点
        else parent->right = to_delete->left; // 重点
    }
    delete to_delete; return success;
}

# 平衡二叉树

  • 二叉树结构会影响查找效率

    • 二叉树结构越趋向于完全二叉树则时间复杂度越接近O(log(n))O(log(n)),效率越好

    • 二叉树结构越趋向于线性链表则时间复杂度越接近于O(n)O(n),效率越差

      • 最坏的情况会退化为O(n)O(n) 的线性查找复杂度

平均访问节点次数:2ln(n)1.39log(n)2ln(n)\approx1.39log(n)

平均比较节点次数:4ln(n)2.77log(n)4ln(n)\approx2.77log(n)

也就是为什么我们需要自平衡二叉查找树

# AVL Trees

AVL 是一种平衡二叉树 (自平衡二叉查找树),过于复杂,没有太大优势,实际更常用的是红黑树来实现

# 平衡因子 BF (Balance Factor)

BF=左子树深度右子树深度BF=左子树深度-右子树深度

# AVL 定义

任意节点的 BF 只能为 - 1、0 或 1

# 插入元素

插入元素会改变 BF,需要调整来维持二叉树的平衡

AVL 树采用四种 “旋转” 调整操作来实现

# 代码实现:

https://blog.csdn.net/weixin_57761086/article/details/127152576

此处定义:BF=右子树深度左子树深度BF=右子树深度-左子树深度

# 数据结构定义
c++
// 结点类
template <typename T>
struct AVLTreeNode {
	AVLTreeNode<T>* left;// 左孩子指针
	AVLTreeNode<T>* right;// 右孩子指针
	AVLTreeNode<T>* parent;// 双亲指针
	T value;// 存储元素的变量
	int bf;// 平衡因子
 
	// 用传入的值构造结点
	AVLTreeNode(const T& _value = T())
		:left(nullptr)
		,right(nullptr)
		,parent(nullptr)
		,value(_value)
		,bf(0)
	{}
};
c++
//AVL 树类
template<typename T>
class AVLTree {
	// 给结点类起别名,方便使用
	typedef AVLTreeNode<T> Node;
private:
	// 指向根结点的结点指针
	Node* root;
};
c++
// 无参构造
// 让根结点指针指向空即可
AVLTree():root(nullptr){}
# 左旋转(RR)

当新节点插入到较高右子树的右侧时 (右右 / RR),需要对最先失去平衡的节点进行一次左旋,使其右子树成为新的根节点,原根节点成为其左子树。

c++
// 左单旋
void RotateLeft(Node* parent) {
	// 这里的指针设计在讲解旋转的时候已经解释过
	Node* subR = parent->right;
	Node* subRL = subR->left;
 
	// 用 pparent (祖父结点) 来保存 parent 结点的双亲
	// 因为 parent 并不一定是整棵树的根,还有可能只是一棵子树的根
	Node* pparent = parent->parent;
 
	// 第一步:首先让双亲的右孩子指针指向 subRL
	parent->right = subRL;
 
	// 之所以要判断是因为 subRL 结点可能不存在
	if (subRL)
		// 更新双亲
		subRL->parent = parent;
 
	// 第二步:让 subR 的左孩子指针指向 parent
	subR->left = parent;
 
	// 不要忘记给这些结点更新它们的双亲
	parent->parent = subR;
	subR->parent = pparent;
 
	// 祖父结点是空,说明 parent 结点是整棵树的根结点
	if (pparent == nullptr) {
		root = subR;
	}
	// 说明 parent 是子树的根结点
	else {
		// 原本祖父结点的孩子是 parent
		// 经过旋转他的孩子变成了 subR
		// 需要判断 parent 是祖父结点的左孩子还是右孩子,然后让对应指针指向 subR 结点
		if (pparent->left == parent) {
			pparent->left = subR;
		}
		else {
			pparent->right = subR;
		}
	}
	// 更新平衡因子
	parent->bf = subR->bf = 0;
}
# 右旋转(LL)

当新节点插入到较高左子树的左侧时 (左左 / LL),需要对最先失去平衡的节点进行一次右旋,使其左子树成为新的根节点,原根节点成为其右子树。

c++
// 右单旋
void RotateRight(Node* parent) {
	Node* subL = parent->left;
	Node* subLR = subL->right;
 
	// 祖父结点
	Node* pparent = parent->parent;
 
	// 第一步:让 parent 的左孩子指针指向 subLR
	parent->left = subLR;
	// 之所以要判断是因为 subLR 结点可能不存在
	if (subLR)
		subLR->parent = parent;
	// 第二步:让 subL 的右孩子指针指向 parent
	subL->right = parent;
 
	// 更新双亲结点
	parent->parent = subL;
	subL->parent = pparent;
 
	// 祖父结点是空,说明 parent 是整棵树的根结点
	if (pparent == nullptr) {
		root = subL;
	}
	//parent 是子树的根结点
	else {
		// 这里和左单旋一样
		if (pparent->left == parent) {
			pparent->left = subL;
		}
		else {
			pparent->right = subL;
		}
	}
	// 更新平衡因子
	parent->bf = subL->bf = 0;
}
# 左右双旋(LR)

当新节点插入到较高左子树的右侧时 (左右 / LR),需要先对左子树进行一次左旋,这时就变为 RR 情形,再对最先失去平衡的节点进行一次右旋,使其左子树的右子树成为新的根节点。

c++
// 左右双旋
void RotateLR(Node* parent) {
	Node* subL = parent->left;
	Node* subLR = subL->right;
	// 保存 subLR 的平衡因子,后面需要根据它来更新别的平衡因子
	int BF = subLR->bf;
 
	// 对以 subL 为根结点的树进行左单旋
	RotateLeft(subL);
	// 对以 parent 为根结点的树进行右单旋
	RotateRight(parent);
 
	// 根据保存的平衡因子更新
	// 当 subLR 平衡因子为 - 1,将 parent 的平衡因子更新为 1
	if (BF == -1) parent->bf = 1;
	// 当 subLR 平衡因子不是 - 1,将 subL 的平衡因子更新为 - 1
	else subL->bf = -1;
}
# 右左双旋(RL)

当新节点插入到较高右子树的左侧时 (右左 / RL),需要先对右子树进行一次右旋,这时就变为 LL 情形,再对最先失去平衡的节点进行一次左旋,使其右子树的左子树成为新的根节点。

c++
// 右左双旋
void RotateRL(Node* parent) {
	Node* subR = parent->right;
	Node* subRL = subR->left;
	// 保存 subRL 的平衡因子,后面根据它更新其他结点平衡因子
	int BF = subRL->bf;
 
	// 对以 subR 为根的树进行右单旋
	RotateRight(subR);
	// 对以 parent 为根的树进行左单旋
	RotateLeft(parent);
 
	// 根据保存的 subRL 平衡因子的不同来进行不同的更新。
	if (BF == -1) subR->bf = 1;
	else parent->bf = -1;
}
# 插入过程
c++
// 插入函数
bool Insert(const T& _value) {
	// 树为空,将新结点作为根结点即可
	if (root == nullptr) {
		root = new Node(_value);
		return true;
	}
 
	// 树非空
	Node* cur = root;
	// 用来保存 cur 的双亲结点
	Node* parent = nullptr;
 
	// 为新结点的插入寻找合适的位置
	// 同时判断是否树中有相同结点
	while (cur) {
		parent = cur;
		if (_value < cur->value) {
			cur = cur->left;
		}
		else if (_value > cur->value) {
			cur = cur->right;
		}
		else {
			return false;
		}
	}
 
	// 构造新结点
	cur = new Node(_value);
	// 判断是新结点应该插在双亲的左边还是右边
	if (_value < parent->value) {
		parent->left = cur;
	}
	else {
		parent->right = cur;
	}
	// 更新新结点的双亲
	cur->parent = parent;
 
	// 更新平衡因子
	// 从下往上
	while (parent) {
		//cur 是双亲左孩子
		// 左子树高度变高,平衡因子就减 1
		// 平衡因子:右子树高度减左子树高度
		if (cur == parent->left) {
			parent->bf--;
		}
		// 右子树变高,平衡因子加 1
		else {
			parent->bf++;
		}
 
		// 判断更新后的平衡因子是否满足 AVL 树
		// 证明 parent 之前只有一个孩子,而新结点插到另一个空着的位置了
		if (parent->bf == 0) {
			break;
		}
		// 证明 parent 之前没有孩子,新结点插入后只有一个孩子
		else if (-1 == parent->bf || 1 == parent->bf) {
			cur = parent;
			parent = cur->parent;
		}
		// 如下就是 parent 的平衡因子变成 2 或 - 2 了
		// 需要根据图片进行理解
		else {
			// 说明 parent 的右子树高
			if (parent->bf == 2) {
				// 根据 cur 的平衡因子判断是左单旋还是右左双旋
				if (cur->bf == 1)
					RotateLeft(parent);
				else
					RotateRL(parent);
			}
			//parent 左子树高
			else {
				if (cur->bf == -1)
					RotateRight(parent);
				else
					RotateLR(parent);
			}
 
			// 使用双旋调整后就不需要向上继续调整了,可以直接退出循环
			break;
		}
	}
	return true;
}
\ No newline at end of file diff --git a/cs/data-structure-and-algorithm/critical-path/index.html b/cs/data-structure-and-algorithm/critical-path/index.html index 1ff7525c..af0b375c 100644 --- a/cs/data-structure-and-algorithm/critical-path/index.html +++ b/cs/data-structure-and-algorithm/critical-path/index.html @@ -1 +1 @@ -关键路径问题 - 数据结构与算法 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# AOV: Activity On Vertex

略(不考)

# AOE: Activity On Edge

与 AOV 网相对应的是 AOE (Activity On Edge) ,是边表示活动的有向无环图,如图所示。图中顶点表示事件 (Event),每个事件表示在其前的所有活动已经完成,其后的活动可以开始;弧表示活动,弧上的权值表示相应活动所需的时间或费用

与 AOE 有关的研究问题

  • 完成整个工程至少需要多少时间?
  • 哪些活动是影响工程进度 (费用) 的关键?

工程完成最短时间:从起点到终点的最长路径长度 (路径上各活动持续时间之和)

长度最长的路径称为关键路径,关键路径上的活动称为关键活动。 关键活动是影响整个工程的关键。

# 求 AOE 中关键路径和关键活动

v0v_0 是起点,从v0v_0viv_i 的最长路径长度称为事件viv_i 的最早发生时间,即是 以viv_i 为尾的所有活动的最早发生时间。

若活动aia_i 是弧<j,k><j,k>,持续时间是dut(<j,k>)dut(<j,k>), 设:

e(i)e(i): 表示活动aia_i 的最早开始时间;

l(i)l(i): 在不影响进度的前提下,表示活动aia_i 的最晚开始时间;

l(i)e(i)l(i)-e(i) 表示活动aia_i 的时间余量,若l(i)e(i)=0l(i)-e(i)=0,表示活动aia_i 是关键活动

ve(i)v_e(i): 表示事件viv_i 的最早发生时间,即从起点到顶点viv_i 的最长路径长度

vl(i)v_l(i): 表示事件viv_i 的最晚发生时间

则有以下关系:

e(i)=ve(j)l(i)=vl(k)dut(<j,k>)\begin{aligned} e(i) &= v_e(j)\\ l(i) &= v_l(k)-dut(<j,k>) \end{aligned}

并且:

ve(j)={0Max{ve(i)+dut(<i,j>)<vi,vj>是网中的弧}j=0,表示vj是起点j0\begin{aligned} v_e(j) = \left\{ \begin{aligned} &0\\ &Max\{ve(i)+dut(<i, j>)|<v_i, v_j>是网中的弧\} \end{aligned} \begin{aligned} j=0,表示vj是起点\\ j\neq 0 \end{aligned} \right. \end{aligned}

含义是:源点事件的最早发生时间设为 0; 除源点外,只有进入顶点vjv_j 的所有弧所代表的活 动全部结束后,事件vjv_j 才能发生。即只有vjv_j 的所有前驱事件viv_i 的最早发生时间ve(i)v_e(i) 计算出来 后,才能计算ve(j)v_e(j)

方法是:对所有事件进行拓扑排序,然后依次按拓扑顺序计算每个事件的最早发生时间。

vl(j)={ve(n1)Min{vl(k)dut(<j,k>)<vj,vk>是网中的弧}j=n1,表示vj是终点jn1\begin{aligned} v_l(j) = \left\{ \begin{aligned} &v_e(n-1) \\ &Min\{v_l(k)-dut(<j, k>)|<v_j, v_k>是网中的弧\} \end{aligned} \begin{aligned} j=n-1,表示v_j是终点\\ j\neq n-1 \end{aligned} \right. \end{aligned}

含义是:只有vjv_j 的所有后继事件vkv_k 的最晚发生时间vl(k)v_l(k) 计算出来后,才能计算vl(j)v_l(j)

方法是:按拓扑排序的逆顺序,依次计算每个事件的最晚发生时间。

# 算法思想

  1. 利用拓扑排序求出 AOE 网的一个拓扑序列;

  2. 从拓扑排序的序列的第一个顶点 (源点) 开始,按拓扑顺序依次计算每个事件的最早发生时间ve(i)v_e(i);

  3. 从拓扑排序的序列的最后一个顶点 (汇点) 开始,按逆拓扑顺序依次计算每个事件的最晚发生时间vl(i)v_l(i);

# 代码实现

c++
void critical_path(ALGraph *G) //Adjacency List Graph
{
    int j, k, m ; LinkNode *p ;
    if (Topologic_Sort(G)==-1)
        printf("\nAOE网中存在回路,错误!!\n\n");
    else   
    {
        for (j=0; j<G->vexnum; j++)
            ve[j]=0; // 事件最早发生时间初始化 
        for (m=0 ; m<G->vexnum; m++)
        {
            j=topol[m] ;
            p=G->adjlist[i].firstarc ;
            for(; pl=NULL; p=p->nextarc )
            {
                k=p->adjvex;
                if (ve[j]+p->weight>ve[k])
                    ve[k]=ve[j]+p->weight ;
            }
        }// 计算每个事件的最早发生时间 ve 值
        for ( j=0; j<G->vexnum; j++)
            vl[j]=ve[j];// 事件最晚发生时间初始化
        for (m=G->vexnum-1; m>=0, m--)
        {
            j=topol[m] ;
            p=G->adjlist[i].firstarc;
            for (; pl=NULL; p=p->nextarc)
            {
                k=p->adjvex ;
                if (vl[k]-p->weight<vl[j])
                    vl[i]=$v_i$[k]-p->weight ;
            }
        }// 计算每个事件的最晚发生时间 vl 值
        for (m=0 , m<G->vexnum; m++)
        {
            p=G->adjlist[m].firstarc ;
            for(; p!=NULL; p=p->nextarc )
            {
                k=p->adjvex;
                if ( (ve[m]+p->weight)==l[k])
                    printf("<%d, %d>, m, j");
            }
        }// 输出所有的关键活动
    }//end of else
}

# 算法分析

设 AOE 网有 n 个事件,e 个活动,则算法的主要执行是:

  • 进行拓扑排序:时间复杂度是O(n+e)O(n+e)

  • 求每个事件的 ve 值和 vl 值:时间复杂度是O(n+e)O(n+e)

  • 根据 ve 值和 vl 值找关键活动:时间复杂度是O(n+e)O(n+e)

因此,整个算法的时间复杂度是O(n+e)O(n+e)

\ No newline at end of file +关键路径问题 - 数据结构与算法 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# AOV: Activity On Vertex

略(不考)

# AOE: Activity On Edge

与 AOV 网相对应的是 AOE (Activity On Edge) ,是边表示活动的有向无环图,如图所示。图中顶点表示事件 (Event),每个事件表示在其前的所有活动已经完成,其后的活动可以开始;弧表示活动,弧上的权值表示相应活动所需的时间或费用

与 AOE 有关的研究问题

  • 完成整个工程至少需要多少时间?
  • 哪些活动是影响工程进度 (费用) 的关键?

工程完成最短时间:从起点到终点的最长路径长度 (路径上各活动持续时间之和)

长度最长的路径称为关键路径,关键路径上的活动称为关键活动。 关键活动是影响整个工程的关键。

# 求 AOE 中关键路径和关键活动

v0v_0 是起点,从v0v_0viv_i 的最长路径长度称为事件viv_i 的最早发生时间,即是 以viv_i 为尾的所有活动的最早发生时间。

若活动aia_i 是弧<j,k><j,k>,持续时间是dut(<j,k>)dut(<j,k>), 设:

e(i)e(i): 表示活动aia_i 的最早开始时间;

l(i)l(i): 在不影响进度的前提下,表示活动aia_i 的最晚开始时间;

l(i)e(i)l(i)-e(i) 表示活动aia_i 的时间余量,若l(i)e(i)=0l(i)-e(i)=0,表示活动aia_i 是关键活动

ve(i)v_e(i): 表示事件viv_i 的最早发生时间,即从起点到顶点viv_i 的最长路径长度

vl(i)v_l(i): 表示事件viv_i 的最晚发生时间

则有以下关系:

e(i)=ve(j)l(i)=vl(k)dut(<j,k>)\begin{aligned} e(i) &= v_e(j)\\ l(i) &= v_l(k)-dut(<j,k>) \end{aligned}

并且:

ve(j)={0Max{ve(i)+dut(<i,j>)<vi,vj>是网中的弧}j=0,表示vj是起点j0\begin{aligned} v_e(j) = \left\{ \begin{aligned} &0\\ &Max\{ve(i)+dut(<i, j>)|<v_i, v_j>是网中的弧\} \end{aligned} \begin{aligned} j=0,表示vj是起点\\ j\neq 0 \end{aligned} \right. \end{aligned}

含义是:源点事件的最早发生时间设为 0; 除源点外,只有进入顶点vjv_j 的所有弧所代表的活 动全部结束后,事件vjv_j 才能发生。即只有vjv_j 的所有前驱事件viv_i 的最早发生时间ve(i)v_e(i) 计算出来 后,才能计算ve(j)v_e(j)

方法是:对所有事件进行拓扑排序,然后依次按拓扑顺序计算每个事件的最早发生时间。

vl(j)={ve(n1)Min{vl(k)dut(<j,k>)<vj,vk>是网中的弧}j=n1,表示vj是终点jn1\begin{aligned} v_l(j) = \left\{ \begin{aligned} &v_e(n-1) \\ &Min\{v_l(k)-dut(<j, k>)|<v_j, v_k>是网中的弧\} \end{aligned} \begin{aligned} j=n-1,表示v_j是终点\\ j\neq n-1 \end{aligned} \right. \end{aligned}

含义是:只有vjv_j 的所有后继事件vkv_k 的最晚发生时间vl(k)v_l(k) 计算出来后,才能计算vl(j)v_l(j)

方法是:按拓扑排序的逆顺序,依次计算每个事件的最晚发生时间。

# 算法思想

  1. 利用拓扑排序求出 AOE 网的一个拓扑序列;

  2. 从拓扑排序的序列的第一个顶点 (源点) 开始,按拓扑顺序依次计算每个事件的最早发生时间ve(i)v_e(i);

  3. 从拓扑排序的序列的最后一个顶点 (汇点) 开始,按逆拓扑顺序依次计算每个事件的最晚发生时间vl(i)v_l(i);

# 代码实现

c++
void critical_path(ALGraph *G) //Adjacency List Graph
{
    int j, k, m ; LinkNode *p ;
    if (Topologic_Sort(G)==-1)
        printf("\nAOE网中存在回路,错误!!\n\n");
    else   
    {
        for (j=0; j<G->vexnum; j++)
            ve[j]=0; // 事件最早发生时间初始化 
        for (m=0 ; m<G->vexnum; m++)
        {
            j=topol[m] ;
            p=G->adjlist[i].firstarc ;
            for(; pl=NULL; p=p->nextarc )
            {
                k=p->adjvex;
                if (ve[j]+p->weight>ve[k])
                    ve[k]=ve[j]+p->weight ;
            }
        }// 计算每个事件的最早发生时间 ve 值
        for ( j=0; j<G->vexnum; j++)
            vl[j]=ve[j];// 事件最晚发生时间初始化
        for (m=G->vexnum-1; m>=0, m--)
        {
            j=topol[m] ;
            p=G->adjlist[i].firstarc;
            for (; pl=NULL; p=p->nextarc)
            {
                k=p->adjvex ;
                if (vl[k]-p->weight<vl[j])
                    vl[i]=$v_i$[k]-p->weight ;
            }
        }// 计算每个事件的最晚发生时间 vl 值
        for (m=0 , m<G->vexnum; m++)
        {
            p=G->adjlist[m].firstarc ;
            for(; p!=NULL; p=p->nextarc )
            {
                k=p->adjvex;
                if ( (ve[m]+p->weight)==l[k])
                    printf("<%d, %d>, m, j");
            }
        }// 输出所有的关键活动
    }//end of else
}

# 算法分析

设 AOE 网有 n 个事件,e 个活动,则算法的主要执行是:

  • 进行拓扑排序:时间复杂度是O(n+e)O(n+e)

  • 求每个事件的 ve 值和 vl 值:时间复杂度是O(n+e)O(n+e)

  • 根据 ve 值和 vl 值找关键活动:时间复杂度是O(n+e)O(n+e)

因此,整个算法的时间复杂度是O(n+e)O(n+e)

\ No newline at end of file diff --git a/cs/data-structure-and-algorithm/graph/index.html b/cs/data-structure-and-algorithm/graph/index.html index b139a11d..f44bb359 100644 --- a/cs/data-structure-and-algorithm/graph/index.html +++ b/cs/data-structure-and-algorithm/graph/index.html @@ -1 +1 @@ -图 - 数据结构与算法 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 图的存储结构:

  1. AM: Adjacent Matrix 邻接矩阵
  2. AL: Adjacent List 邻接表
  3. RAL: Reverse Adjacent List 逆邻接表
  4. TL: Triple List 三元组顺序表 (往往是行逻辑链接的,性能更好)
  5. CL: Cross List 十字链表

# 图按存储结构分为:

  1. AMGraph: Adjacent Matrix Graph
  2. ALGraph: Adjacent List Graph
  3. TLGraph: Triple List Graph
  4. RALGraph: Reverse Adjacent List Graph
  5. CLGraph: Cross/Orthogonal List Graph

# 图的遍历

# BFS

时间复杂度取决于图的存储结构:

  • 邻接矩阵:O(n2)O(n^2)
  • 邻接表:O(n+e)O(n+e)

# DFS

时间复杂度取决于图的存储结构:

  • 邻接矩阵:O(n2)O(n^2)
  • 邻接表:O(n+e)O(n+e)

# 有向图的拓扑排序

一个图可拓扑排序的充要条件是它无环,即它是有向无环图 (DirectedAcyclic Graph,DAG)

# 算法实现

采用正邻接链作为 AOV 网的存储结构;

设立堆栈 (或队列),用来暂存入度为 0 的顶点;

伪代码
while(堆栈/队列不为空){
    删除顶点以它为尾的弧:弧头顶点的入度减1,度数为0则入堆栈(或队列)
}

# 算法分析

设 AOV 网有 n 个顶点,e 条边,则算法的主要执行是:

  • 统计各顶点的入度:时间复杂度是O(n+e)O(n+e);

  • 入度为 0 的顶点入栈:时间复杂度是O(n)O(n);

  • 排序过程:顶点入栈和出栈操作执行 n 次,入度减 1 的操作共执行 e
    次,时间复杂度是O(n+e)O(n+e);

因此,整个算法的时间复杂度是O(n+e)O(n+e)

# 无向图的生成树

dfs 稍作修改即可得到生成树算法

保证每个节点只访问一次就可以避免环

# 无向图的生成森林

在生成树的基础上,加上并查集

# 有向图的强连通分量

  1. 对有向图 G 进行 dfs 生成森林 T
  2. 按中序遍历顺序编号
  3. 从编号最大的节点开始再 dfs 遍历
  4. 按 (2) 中标出的顶点编号,从编号最大的顶点开始对 G’进行深度优先搜索,得到一棵深度优先生成树。若一次完整的搜索过程没有遍历 G’的所有顶点,则从未访问的顶点中选择一个编号最大的顶点,由它开始再进行深度优先搜索,并得到另一棵深度优先生成树。在该步中,每一次深度优先搜索所得到的生成树中的顶点就是 G 的一个强连通分量的所有顶点。
  5. 重复步骤 (4),直到 G’中的所有顶点都被访问。如下图是求一棵有向树的强连通分量过程。
\ No newline at end of file +图 - 数据结构与算法 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 图的存储结构:

  1. AM: Adjacent Matrix 邻接矩阵
  2. AL: Adjacent List 邻接表
  3. RAL: Reverse Adjacent List 逆邻接表
  4. TL: Triple List 三元组顺序表 (往往是行逻辑链接的,性能更好)
  5. CL: Cross List 十字链表

# 图按存储结构分为:

  1. AMGraph: Adjacent Matrix Graph
  2. ALGraph: Adjacent List Graph
  3. TLGraph: Triple List Graph
  4. RALGraph: Reverse Adjacent List Graph
  5. CLGraph: Cross/Orthogonal List Graph

# 图的遍历

# BFS

时间复杂度取决于图的存储结构:

  • 邻接矩阵:O(n2)O(n^2)
  • 邻接表:O(n+e)O(n+e)

# DFS

时间复杂度取决于图的存储结构:

  • 邻接矩阵:O(n2)O(n^2)
  • 邻接表:O(n+e)O(n+e)

# 有向图的拓扑排序

一个图可拓扑排序的充要条件是它无环,即它是有向无环图 (DirectedAcyclic Graph,DAG)

# 算法实现

采用正邻接链作为 AOV 网的存储结构;

设立堆栈 (或队列),用来暂存入度为 0 的顶点;

伪代码
while(堆栈/队列不为空){
    删除顶点以它为尾的弧:弧头顶点的入度减1,度数为0则入堆栈(或队列)
}

# 算法分析

设 AOV 网有 n 个顶点,e 条边,则算法的主要执行是:

  • 统计各顶点的入度:时间复杂度是O(n+e)O(n+e);

  • 入度为 0 的顶点入栈:时间复杂度是O(n)O(n);

  • 排序过程:顶点入栈和出栈操作执行 n 次,入度减 1 的操作共执行 e
    次,时间复杂度是O(n+e)O(n+e);

因此,整个算法的时间复杂度是O(n+e)O(n+e)

# 无向图的生成树

dfs 稍作修改即可得到生成树算法

保证每个节点只访问一次就可以避免环

# 无向图的生成森林

在生成树的基础上,加上并查集

# 有向图的强连通分量

  1. 对有向图 G 进行 dfs 生成森林 T
  2. 按中序遍历顺序编号
  3. 从编号最大的节点开始再 dfs 遍历
  4. 按 (2) 中标出的顶点编号,从编号最大的顶点开始对 G’进行深度优先搜索,得到一棵深度优先生成树。若一次完整的搜索过程没有遍历 G’的所有顶点,则从未访问的顶点中选择一个编号最大的顶点,由它开始再进行深度优先搜索,并得到另一棵深度优先生成树。在该步中,每一次深度优先搜索所得到的生成树中的顶点就是 G 的一个强连通分量的所有顶点。
  5. 重复步骤 (4),直到 G’中的所有顶点都被访问。如下图是求一棵有向树的强连通分量过程。
\ No newline at end of file diff --git a/cs/data-structure-and-algorithm/hash/index.html b/cs/data-structure-and-algorithm/hash/index.html index 6619ad35..6fc06790 100644 --- a/cs/data-structure-and-algorithm/hash/index.html +++ b/cs/data-structure-and-algorithm/hash/index.html @@ -1 +1 @@ -哈希表 - 数据结构与算法 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 哈希表 / 散列表

应用哈希函数,由记录的关键字确定记录在表中的地址,并将记录放入此地址,这样构成的表叫哈希表

# 哈希查找 / 散列查找

利用哈希函数进行查找的过程叫哈希查找

# 哈希映射函数 / 散列函数

在记录的关键字与记录的存储地址之间建立的一种对应关系叫哈希函数

# 原始 hash 函数

简单一点的 hash 算法就是直接取模 (除留余数法)。

高级一点的 hash 算法会模乘以一个大素数来将源数据的分布规律变得不那么显著,也就是说,不管输入的是一串分布很紧凑的数字序列还是很稀疏的数字序列,生成的结果都是非常分散的数字序列。

linux 内核代码里面的这个 hash 要更高一级,包含 2 个特征:
最接近 32 位或者者 64 位上限黄金分割点的素数,
只要要最少的移位和求和就能生成。
这个素数定义如下:

c
/* 2^31 + 2^29 - 2^25 + 2^22 - 2^19 - 2^16 + 1 */
#define GOLDEN_RATIO_PRIME_32 0x9e370001UL

前者确保即便是 1,2 这样的小数也会被乘溢出,被轻易打散。素数非常大还可以使无论输入如何,生成的哈希值的高位都是足够随机的,有助于改善生成哈希值高位总是相近的问题。

后者确保任何一个整数乘这个大素数的时候都可以通过最少的移位和求和就可得到乘积,不用傻傻的真的相乘。

# 直接定址法

取关键字或关键字的某个线性函数作哈希地址,即H(key)=keyH(key)=keyH(key)=akey+bH(key)=a·key+b (a,b 为常数)

特点:直接定址法所得地址集合与关键字集合大小相等,不会发生冲突,但实际中很少使用。

# 数字分析法

对关键字进行分析,取关键字的若干位或组合作为哈希地址。

适用于关键字位数比哈希地址位数大,且可能出现的关键字事先知道的情况。

# 平方取中法

将关键字平方后取中间几位作为哈希地址。一个数平方后中间几位和数的每一位都有关,则由随机分布的关键字得到的散列地址也是随机的。散列函数所取的位数由散列表的长度决定。

适于不知道全部关键字情况,是一种较为常用的方法

# 折叠法

将关键字分割成位数相同的几部分 (最后一部分可以不同),然后取这几部分的叠加和作为哈希地址。

数位叠加有移位叠加和间界叠加两种:

  • 移位叠加:将分割后的几部分低位对齐相加。
  • 间界叠加:从一端到另一端沿分割界来回折迭,然后对齐相加。

适于关键字位数很多,且每一位上数字分布大致均匀情况。

# 除留余数法

取关键字被某个不大于哈希表表长 m 的数 p 除后所得余数作哈希地址,即:
H(key)=key%p(pm)H(key)=key\ \% \ p\ (p\leq m)
是一种简单、常用的哈希函数构造方法。

利用这种方法的关键是 p 的选取,p 选的不好,容易产生同义词。p 的选取的分析:

  • 选取p=2i(pm)p=2^i\ (p\leq m): 运算便于用移位来实现,但等于将关键字的高位忽略而仅留下低位二进制数。高位不同而低位相同的 关键字是同义词。
  • 选取p=q×f(qf都是质因数,pm)p=q\times f\ (q、f 都是质因数,p\leq m): 则所有含有 q 或 f 因子的关键字的散列地址均是 q 或 f 的倍数。
  • 选取pp 为素数或p=q×f(qf是质数且均大于20pm)p=q\times f\ (q、f是质数且均大于20,p\leq m): 常用的选取方法,能减少冲突出现的可能性。

# 随机数法

取关键字的随机函数值作哈希地址,即H(key)=random(key)H(key) = random(key)

当散列表中关键字长度不等时,该方法比较合适。

# 冲突处理

# 开放定址法

当冲突发生时,形成某个探测序列;按此序列逐个探测散列表中的其他地址,直到找到给定的关键字或一个空地址 (开放的地址) 为止,将发生冲突的记录放到该地址中。散列地址的计算公式是:

Hi(key)=(H(key)+di)%m,i=1,2,...,k(km1)H_i(key)=(H(key)+d_i) \% m, i=1, 2, ..., k (k \leq m-1)

其中:
H(key)H(key):哈希函数;
mm:散列表长度;
did_i:第 i 次探测时的增量序列;
Hi(key)H_i(key):经第 i 次探测后得到的散列地址。

核心在于探测序列did_i,即如何形成探测序列。

# 线性探测法

将散列表T[0...m1]T[0 ...m-1] 看成循环向量。当发生冲突时,从初次发生冲突的 位置依次向后探测其他的地址。

增量序列为:di=1,2,3,...,m1d_i=1, 2, 3, ..., m-1

设初次发生冲突的地址是 h,则依次探测 T[h+1],T[h+2]...,T[h+1],T[h+2]..., 直到T[m1]T[m-1] 之后又循环到表头,再次探测T[0]T[1]...T[0],T[1]...,直到 T [h-1]$。探测过程终止的情况是:

  • 探测到的地址为空:表中没有记录。
    • 若是查找则失败;
    • 若是插入则将记录写入到该地址;
  • 探测到的地址有给定的关键字:
    • 若是查找则成功;
    • 若是插入则失败;
  • 直到T[h1]T[h-1] 之后回到T[h]T[h]:
    • 仍未探测到空地址或给定的关键字,散列表满。

优点:只要空间未满,总能找到空闲的位置存放新插入的数据,能充分利用整个表的空间。

问题:例如原本有两个 cluster 数据,随着哈希表不断扩充,两个 cluster 会逐渐聚集为一个更大的 cluster,产生数据聚集的问题。

循环上限did_iii 最大为nn.

# 二次探测法 (平方探测法) (变体很多,需要看题)

原始did_idi=i2d_i = i^2

原始序列:di=12,22,32...d_i = 1^2, 2^2, 3^2 ...

改进did_idi=(1)i1i+122d_i = (-1)^{i-1}\cdot\left\lfloor\frac{i+1}{2}\right\rfloor^2

改进序列:di=12,12,22,22,32,32...di = 1^2, -1^2, 2^2, -2^2, 3^2, -3^2 ...

循环上限:did_iii 最大为nn,有时可以是\frac{n}

二次探测针对线性探测法的 “聚集” 问题进行了改进,避免了 “聚集” 现象产生。

原始did_i 在不断扩充哈希表时会导致一半的空间用不上,改进的did_i 针对这一问题进行了改进。

优点:探测序列跳跃式地散列到整个表中,不易产生 “冲突聚集” 现象。

问题:不能保证探测到散列表的所有地址,不能充分利用整个表的空间。(“表满不了”)

# 伪随机探测法

增量序列使用一个伪随机函数来生成一个落在闭区间 [1,m-1] 的随机序列。

# 再哈希法

这种方法是同时构造多个不同的哈希函数:

Hi=RHikey),i=12,3,nH_i=RH_i(key),i=1,2,3,…,n

RHiRH_i:一组不同的哈希函数,第 1 次发生冲突时用RH1RH_1 计算,第 2 次发生冲突时用RH2RH_2 计算,以此类推直到某个HiH_i 不再发生冲突为止。

优点:不易产生聚集

问题:增加了计算时间

# 链定址法 (拉链法)

将所有关键字为同义词 (散列地址相同) 的记录存储在一个单链表中,并用一维数组存放链表的头指针

设散列表长为 m,定义一个一维指针数组: RecNode *linkhash[m] ,其中 RecNode 是结点类型,每个分量的初值为空。

凡是散列地址为 k 的记录都插入到以 linkhash[k] 为头指针的链表中,插入位置可以在表头或表尾或按关键字排序插入。

注意:若某一位置已存储的冲突元素有 4 个,查找失败需要比较 5 次,包括最后一次空指针。

# 建立公共溢出区

这种方法的基本思想是:将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表.(注意:在这个方法里面是把元素分开两个表来存储)

# 哈希表的删除操作

不能抹除该位置的元素,而是需要一个特殊字符 "special key" 取代原来的位置,代表这里原本有元素但是被删除了。

# 哈希表查找分析

由于 “冲突” 的存在,哈希表效率的评价仍然需要 ASL。

哈希表的 填满因子 / 装载因子 λ\lambda ( 或α\alpha ) 定义:

λ=已经插入的元素数哈希表长度\lambda=\frac{已经插入的元素数}{哈希表长度}

The expected number U(2)U(2) of probes in an unsuccessful search is:

U(λ)=k=1kλk1(1λ)=11λU(\lambda)=\sum_{k=1}^{\infty}k\lambda^{k-1}(1-\lambda)=\frac{1}{1-\lambda}

So the expected number of probes for successful searches (AVL) is:

S(λ)=1λ0λU(λ)dx=1λln11λS(\lambda)=\frac{1}{\lambda}\int_{0}^{\lambda}{U(\lambda)dx}=\frac{1}{\lambda}ln\frac{1}{1-\lambda}

线性探测法的平均查找长度是:

Snl成功12×(1+11λ)Snl失败12×(1+1(1λ)2)S_{nl成功}≈\frac{1}{2}\times(1+\frac{1}{1-\lambda})\\ S_{nl失败}≈\frac{1}{2}\times(1+\frac{1}{(1-\lambda)^2})

二次 / 平方探测法的平均查找长度是:

Snl成功1λ×ln(1λ)Snl失败1λS_{nl成功}≈-\frac{1}{\lambda}\times ln(1-\lambda)\\ S_{nl失败}≈\frac{1}{\lambda}

链地址法解决冲突的平均查找长度是:

Snl成功1+λ2Snl失败λ+eλS_{nl成功}≈1+\frac{\lambda}{2}\\ S_{nl失败}≈\lambda+e^{-\lambda}

# 代码例题

假设构建哈希表使用线性探查法解决冲突,试计算每次查找的关键字比较次数。

  1. 可能的关键字为正整数;
  2. 使用哈希函数 h (k,M)= k % M, M 为哈希表的长度;
  3. 因为 0 不是关键字,所以,假定用 0 表示空单元;
  4. 为了区分空单元和删除后的 “空单元”,给每个单元添加一个布尔型标识,表示该单元是否空;空单元设置为 true,非空设置为 false;
  5. 假定删除关键字时,只将标识置为 true, 关键字域不变。
c++
#include <iostream>
#include <vector>
using namespace std;
typedef int Key;
typedef pair<Key, bool>  Cell;
//a cell consists of a key and a flag of bool. If the cell is empty, the second component is set to true, otherwise false.
typedef vector<Cell> Table; //type of a hash table
//hash function, where M should be the hash table size.
size_t h(Key k, size_t M = 11){
    return k % M;
}
// 它返回线性探查法解决冲突查找是否成功、查找终止的下标以及关键字的比较次数
pair<pair<bool, size_t>, int> lookup(const Table& t, const Key k){
    size_t M=t.size();
    size_t hi=h(k,M),j,i;
    int count = 0;
    for(j=0;j<M;++j){
        i=(hi+j)%M;
        ++count;
        if(t[i].first==0)break;
        else if(t[i].first==k&&!t[i].second)return make_pair(make_pair(1,i),count);
    }
    return make_pair(make_pair(0,i),count);
}
\ No newline at end of file +哈希表 - 数据结构与算法 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 哈希表 / 散列表

应用哈希函数,由记录的关键字确定记录在表中的地址,并将记录放入此地址,这样构成的表叫哈希表

# 哈希查找 / 散列查找

利用哈希函数进行查找的过程叫哈希查找

# 哈希映射函数 / 散列函数

在记录的关键字与记录的存储地址之间建立的一种对应关系叫哈希函数

# 原始 hash 函数

简单一点的 hash 算法就是直接取模 (除留余数法)。

高级一点的 hash 算法会模乘以一个大素数来将源数据的分布规律变得不那么显著,也就是说,不管输入的是一串分布很紧凑的数字序列还是很稀疏的数字序列,生成的结果都是非常分散的数字序列。

linux 内核代码里面的这个 hash 要更高一级,包含 2 个特征:
最接近 32 位或者者 64 位上限黄金分割点的素数,
只要要最少的移位和求和就能生成。
这个素数定义如下:

c
/* 2^31 + 2^29 - 2^25 + 2^22 - 2^19 - 2^16 + 1 */
#define GOLDEN_RATIO_PRIME_32 0x9e370001UL

前者确保即便是 1,2 这样的小数也会被乘溢出,被轻易打散。素数非常大还可以使无论输入如何,生成的哈希值的高位都是足够随机的,有助于改善生成哈希值高位总是相近的问题。

后者确保任何一个整数乘这个大素数的时候都可以通过最少的移位和求和就可得到乘积,不用傻傻的真的相乘。

# 直接定址法

取关键字或关键字的某个线性函数作哈希地址,即H(key)=keyH(key)=keyH(key)=akey+bH(key)=a·key+b (a,b 为常数)

特点:直接定址法所得地址集合与关键字集合大小相等,不会发生冲突,但实际中很少使用。

# 数字分析法

对关键字进行分析,取关键字的若干位或组合作为哈希地址。

适用于关键字位数比哈希地址位数大,且可能出现的关键字事先知道的情况。

# 平方取中法

将关键字平方后取中间几位作为哈希地址。一个数平方后中间几位和数的每一位都有关,则由随机分布的关键字得到的散列地址也是随机的。散列函数所取的位数由散列表的长度决定。

适于不知道全部关键字情况,是一种较为常用的方法

# 折叠法

将关键字分割成位数相同的几部分 (最后一部分可以不同),然后取这几部分的叠加和作为哈希地址。

数位叠加有移位叠加和间界叠加两种:

  • 移位叠加:将分割后的几部分低位对齐相加。
  • 间界叠加:从一端到另一端沿分割界来回折迭,然后对齐相加。

适于关键字位数很多,且每一位上数字分布大致均匀情况。

# 除留余数法

取关键字被某个不大于哈希表表长 m 的数 p 除后所得余数作哈希地址,即:
H(key)=key%p(pm)H(key)=key\ \% \ p\ (p\leq m)
是一种简单、常用的哈希函数构造方法。

利用这种方法的关键是 p 的选取,p 选的不好,容易产生同义词。p 的选取的分析:

  • 选取p=2i(pm)p=2^i\ (p\leq m): 运算便于用移位来实现,但等于将关键字的高位忽略而仅留下低位二进制数。高位不同而低位相同的 关键字是同义词。
  • 选取p=q×f(qf都是质因数,pm)p=q\times f\ (q、f 都是质因数,p\leq m): 则所有含有 q 或 f 因子的关键字的散列地址均是 q 或 f 的倍数。
  • 选取pp 为素数或p=q×f(qf是质数且均大于20pm)p=q\times f\ (q、f是质数且均大于20,p\leq m): 常用的选取方法,能减少冲突出现的可能性。

# 随机数法

取关键字的随机函数值作哈希地址,即H(key)=random(key)H(key) = random(key)

当散列表中关键字长度不等时,该方法比较合适。

# 冲突处理

# 开放定址法

当冲突发生时,形成某个探测序列;按此序列逐个探测散列表中的其他地址,直到找到给定的关键字或一个空地址 (开放的地址) 为止,将发生冲突的记录放到该地址中。散列地址的计算公式是:

Hi(key)=(H(key)+di)%m,i=1,2,...,k(km1)H_i(key)=(H(key)+d_i) \% m, i=1, 2, ..., k (k \leq m-1)

其中:
H(key)H(key):哈希函数;
mm:散列表长度;
did_i:第 i 次探测时的增量序列;
Hi(key)H_i(key):经第 i 次探测后得到的散列地址。

核心在于探测序列did_i,即如何形成探测序列。

# 线性探测法

将散列表T[0...m1]T[0 ...m-1] 看成循环向量。当发生冲突时,从初次发生冲突的 位置依次向后探测其他的地址。

增量序列为:di=1,2,3,...,m1d_i=1, 2, 3, ..., m-1

设初次发生冲突的地址是 h,则依次探测 T[h+1],T[h+2]...,T[h+1],T[h+2]..., 直到T[m1]T[m-1] 之后又循环到表头,再次探测T[0]T[1]...T[0],T[1]...,直到 T [h-1]$。探测过程终止的情况是:

  • 探测到的地址为空:表中没有记录。
    • 若是查找则失败;
    • 若是插入则将记录写入到该地址;
  • 探测到的地址有给定的关键字:
    • 若是查找则成功;
    • 若是插入则失败;
  • 直到T[h1]T[h-1] 之后回到T[h]T[h]:
    • 仍未探测到空地址或给定的关键字,散列表满。

优点:只要空间未满,总能找到空闲的位置存放新插入的数据,能充分利用整个表的空间。

问题:例如原本有两个 cluster 数据,随着哈希表不断扩充,两个 cluster 会逐渐聚集为一个更大的 cluster,产生数据聚集的问题。

循环上限did_iii 最大为nn.

# 二次探测法 (平方探测法) (变体很多,需要看题)

原始did_idi=i2d_i = i^2

原始序列:di=12,22,32...d_i = 1^2, 2^2, 3^2 ...

改进did_idi=(1)i1i+122d_i = (-1)^{i-1}\cdot\left\lfloor\frac{i+1}{2}\right\rfloor^2

改进序列:di=12,12,22,22,32,32...di = 1^2, -1^2, 2^2, -2^2, 3^2, -3^2 ...

循环上限:did_iii 最大为nn,有时可以是\frac{n}

二次探测针对线性探测法的 “聚集” 问题进行了改进,避免了 “聚集” 现象产生。

原始did_i 在不断扩充哈希表时会导致一半的空间用不上,改进的did_i 针对这一问题进行了改进。

优点:探测序列跳跃式地散列到整个表中,不易产生 “冲突聚集” 现象。

问题:不能保证探测到散列表的所有地址,不能充分利用整个表的空间。(“表满不了”)

# 伪随机探测法

增量序列使用一个伪随机函数来生成一个落在闭区间 [1,m-1] 的随机序列。

# 再哈希法

这种方法是同时构造多个不同的哈希函数:

Hi=RHikey),i=12,3,nH_i=RH_i(key),i=1,2,3,…,n

RHiRH_i:一组不同的哈希函数,第 1 次发生冲突时用RH1RH_1 计算,第 2 次发生冲突时用RH2RH_2 计算,以此类推直到某个HiH_i 不再发生冲突为止。

优点:不易产生聚集

问题:增加了计算时间

# 链定址法 (拉链法)

将所有关键字为同义词 (散列地址相同) 的记录存储在一个单链表中,并用一维数组存放链表的头指针

设散列表长为 m,定义一个一维指针数组: RecNode *linkhash[m] ,其中 RecNode 是结点类型,每个分量的初值为空。

凡是散列地址为 k 的记录都插入到以 linkhash[k] 为头指针的链表中,插入位置可以在表头或表尾或按关键字排序插入。

注意:若某一位置已存储的冲突元素有 4 个,查找失败需要比较 5 次,包括最后一次空指针。

# 建立公共溢出区

这种方法的基本思想是:将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表.(注意:在这个方法里面是把元素分开两个表来存储)

# 哈希表的删除操作

不能抹除该位置的元素,而是需要一个特殊字符 "special key" 取代原来的位置,代表这里原本有元素但是被删除了。

# 哈希表查找分析

由于 “冲突” 的存在,哈希表效率的评价仍然需要 ASL。

哈希表的 填满因子 / 装载因子 λ\lambda ( 或α\alpha ) 定义:

λ=已经插入的元素数哈希表长度\lambda=\frac{已经插入的元素数}{哈希表长度}

The expected number U(2)U(2) of probes in an unsuccessful search is:

U(λ)=k=1kλk1(1λ)=11λU(\lambda)=\sum_{k=1}^{\infty}k\lambda^{k-1}(1-\lambda)=\frac{1}{1-\lambda}

So the expected number of probes for successful searches (AVL) is:

S(λ)=1λ0λU(λ)dx=1λln11λS(\lambda)=\frac{1}{\lambda}\int_{0}^{\lambda}{U(\lambda)dx}=\frac{1}{\lambda}ln\frac{1}{1-\lambda}

线性探测法的平均查找长度是:

Snl成功12×(1+11λ)Snl失败12×(1+1(1λ)2)S_{nl成功}≈\frac{1}{2}\times(1+\frac{1}{1-\lambda})\\ S_{nl失败}≈\frac{1}{2}\times(1+\frac{1}{(1-\lambda)^2})

二次 / 平方探测法的平均查找长度是:

Snl成功1λ×ln(1λ)Snl失败1λS_{nl成功}≈-\frac{1}{\lambda}\times ln(1-\lambda)\\ S_{nl失败}≈\frac{1}{\lambda}

链地址法解决冲突的平均查找长度是:

Snl成功1+λ2Snl失败λ+eλS_{nl成功}≈1+\frac{\lambda}{2}\\ S_{nl失败}≈\lambda+e^{-\lambda}

# 代码例题

假设构建哈希表使用线性探查法解决冲突,试计算每次查找的关键字比较次数。

  1. 可能的关键字为正整数;
  2. 使用哈希函数 h (k,M)= k % M, M 为哈希表的长度;
  3. 因为 0 不是关键字,所以,假定用 0 表示空单元;
  4. 为了区分空单元和删除后的 “空单元”,给每个单元添加一个布尔型标识,表示该单元是否空;空单元设置为 true,非空设置为 false;
  5. 假定删除关键字时,只将标识置为 true, 关键字域不变。
c++
#include <iostream>
#include <vector>
using namespace std;
typedef int Key;
typedef pair<Key, bool>  Cell;
//a cell consists of a key and a flag of bool. If the cell is empty, the second component is set to true, otherwise false.
typedef vector<Cell> Table; //type of a hash table
//hash function, where M should be the hash table size.
size_t h(Key k, size_t M = 11){
    return k % M;
}
// 它返回线性探查法解决冲突查找是否成功、查找终止的下标以及关键字的比较次数
pair<pair<bool, size_t>, int> lookup(const Table& t, const Key k){
    size_t M=t.size();
    size_t hi=h(k,M),j,i;
    int count = 0;
    for(j=0;j<M;++j){
        i=(hi+j)%M;
        ++count;
        if(t[i].first==0)break;
        else if(t[i].first==k&&!t[i].second)return make_pair(make_pair(1,i),count);
    }
    return make_pair(make_pair(0,i),count);
}
\ No newline at end of file diff --git a/cs/data-structure-and-algorithm/heap-sort/index.html b/cs/data-structure-and-algorithm/heap-sort/index.html index dd397106..96c83c63 100644 --- a/cs/data-structure-and-algorithm/heap-sort/index.html +++ b/cs/data-structure-and-algorithm/heap-sort/index.html @@ -1 +1 @@ -堆排序 - 数据结构与算法 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

区分:堆排序的堆不是堆栈的堆

# 原理

  • 堆排序可以视为一种聪明的选择排序。
  • 堆排序适合数组这样的数据结构。
  • 选择排序需要不断在未排序部分找最大 / 小值然后放在已排序部分后面,堆排序只是将 “找最值” 的部分用 “调整堆” 代替,调整好的堆的堆顶就是我们想要的最值。
  • 堆排序基于二叉树结构,堆是一种按一定规律存储数据的二叉树。利用堆最值位于堆顶的特点,不断将堆顶的最值和堆最后一个元素交换(堆最后一个元素后面都是已排序部分),然后重新调整未排序部分使其再变回一个堆。

# 最大堆 / 小根堆 / 小顶堆

  • 最大值在根节点 / 堆顶
  • 结点的键值都小于等于其父结点的键值
  • 排降序建最大堆

# 最小堆 / 大根堆 / 大顶堆

  • 最小值在根节点 / 堆顶
  • 结点的键值都大于等于其父结点的键值
  • 排升序建最小堆

# 递归函数实现

该递归是尾部递归,可以改为循环实现

c++
template <class Record>
void Sortable_list< Record>:: heap_sort ()
/* Post: The entries of the Sortable_list have been rearranged so that their keys are sorted into nondecreasing order.
Uses: The contiguous List implementation of Chapter 6, build_heap, and in- sert _heap. */
{
    Record current;//temporary storage for moving entries
    int last_unsorted; //Entries beyond last _unsorted have been sorted.
    build_heap(); //First phase: Turn the list into a heap.
    for (last_unsorted = count - 1; last unsorted > 0; last_unsorted--) {
        current = entry [last unsorted]; //Extract last entry from list.
        entry [last_unsorted] = entry [0]; //Move top of heap to the end.
        insert_heap(current, O, last _unsorted -1); // Restore the heap.
    }
}

# 插入堆:

c++
template <class Record>
void Sortable_list< Record>::insert_heap(const Record &current, int low, int high)
/* Pre: The entries of the Sortable_list between indices low + 1and high,inclusive, form a heap. The entry in position low wil be discarded.
Post: The entry current has been inserted into the Sortable list and theentries rearranged so that the entries between indices low and high,inclusive, form a heap.
Uses: The class Record, and the contiguous List implementation of Chapter 6.*/
{
    int large; // position of child of entry [low] with the larger key
    large = 2 * low + 1; // large is now the left child of low.
    while (large =< high) {
        if (large < high & entry [large] < entry [large + 1])large ++; //large+1 refers to right child of low, large is now the child of low with the largest key.
        if(current>=entry[large])break; //current belongs ni position low.
        else { //Promote entry [large ] and move down the tree.
            entry [low] = entry [large]; //The larger one is promoted, low becomes the new vacancy and large is the left child.
            low = large;
            large=2*low +1;
        }
    }
    entry [low] = current;
}

# 建堆:

c++
template <class Record>
void Sortable_Jist< Record> :: build_heap()
/* Post:The entries of the Sortable_list have been rearranged so that it becomes a heap.
Uses: The contiguous List implementation of Chapter 6, and insert_heap. */
{
    int low; // All entries beyond the position low form a heap.
    for (low = count/2 - 1; low >= 0; --low ){
        Record current = entry [low];
        insert heap(current,low, count一1);
    }
}

# 非递归实现

利用数组实现,常用下标 0 作为根节点,此时孩子节点和父亲节点的计算:

left_child = parent*2+1

right_child = parent*2+2

child-1 = parent*2+0/1

parent = (child-1)>>1

# 向上调整

插入一个节点到堆的末尾

c++
void AdjustUp(HPDataType* a, size_t child){
	size_t parent;
	while (child > 0){
        parent = (child - 1) / 2;
		if (a[child] > a[parent]){ // 大堆
			swap(&a[child], &a[parent]);
			child = parent;
		}
		else{
			break;
		}
	}
}

向上调整建堆

c++
// 从数组第 2 个数直到最后一个数重复进行向上调整算法
for(int i=1;i<n;i++){
    AdjustUp(a,i);
}

向上调整法建堆时间复杂度: O(nlogn)O(nlogn)

# 向下调整

c++
void AdjustDown(HPDataType* a, size_t size, int parent){
	size_t child = parent * 2 + 1;
	while (child < size){
		if (child + 1 < size && a[child + 1] > a[child]){ // 比较左右孩子
			++child;
		}
		if (a[child] > a[parent]){ // 大堆
			swap(&a[parent], &a[child]);
			parent = child;
            size_t child = parent * 2 + 1;
		}
		else{
			break;
		}
	}
}
c++
// 从最后一个叶子的父亲开始,不断 --,直到第一个节点 (包括第一个节点),重复进行向下调整算法
// 最后一个叶子节点的数组下标是 n-1,最后一个叶子节点的父亲的数组下标为 (n-1-1)/2 = n/2-1
for(int i=n/2-1;i>=0;i--){
    AdjustDown(a,n,i);
}

向下调整法建堆时间复杂度: O(n)O(n)

参考:
https://blog.csdn.net/zhang_si_hang/article/details/124018889

# 性能

  • 与快排相比,堆排序的常数部分差一点,比较次数多一些,赋值次数少一些

  • 堆排序是不稳定排序

# 堆的应用

堆是一种常用的可以对排序、最值查找…… 优化的数据结构、技巧。

# 优先级队列

基于堆实现,c++ 里为 priority_queue

# 前 k 个最大 / 小的数

  • 经典面试题

    • 题面:给定一个有 N 个 entry 的 list ,设计一个算法, 从 N 个 entry 中找出最大的 k 个。假定 N 很大且 k 很小 (例如 N = 100 亿,k = 30)。

    • 题解:用堆排序,建堆需要时间复杂度:kl˙og2kk\dot log_{2}k;调整需要时间复杂度:Nl˙og2kN\dot log_{2}k;总共为:O((N+k)log2k)O((N+k)log_{2}k)

# 第 k 个最大 / 小的数

  • 对顶堆
    基于堆维持最大值 / 最小值的特点,用于维持第 k 大 / 第 k 小的数据
\ No newline at end of file +堆排序 - 数据结构与算法 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

区分:堆排序的堆不是堆栈的堆

# 原理

  • 堆排序可以视为一种聪明的选择排序。
  • 堆排序适合数组这样的数据结构。
  • 选择排序需要不断在未排序部分找最大 / 小值然后放在已排序部分后面,堆排序只是将 “找最值” 的部分用 “调整堆” 代替,调整好的堆的堆顶就是我们想要的最值。
  • 堆排序基于二叉树结构,堆是一种按一定规律存储数据的二叉树。利用堆最值位于堆顶的特点,不断将堆顶的最值和堆最后一个元素交换(堆最后一个元素后面都是已排序部分),然后重新调整未排序部分使其再变回一个堆。

# 最大堆 / 小根堆 / 小顶堆

  • 最大值在根节点 / 堆顶
  • 结点的键值都小于等于其父结点的键值
  • 排降序建最大堆

# 最小堆 / 大根堆 / 大顶堆

  • 最小值在根节点 / 堆顶
  • 结点的键值都大于等于其父结点的键值
  • 排升序建最小堆

# 递归函数实现

该递归是尾部递归,可以改为循环实现

c++
template <class Record>
void Sortable_list< Record>:: heap_sort ()
/* Post: The entries of the Sortable_list have been rearranged so that their keys are sorted into nondecreasing order.
Uses: The contiguous List implementation of Chapter 6, build_heap, and in- sert _heap. */
{
    Record current;//temporary storage for moving entries
    int last_unsorted; //Entries beyond last _unsorted have been sorted.
    build_heap(); //First phase: Turn the list into a heap.
    for (last_unsorted = count - 1; last unsorted > 0; last_unsorted--) {
        current = entry [last unsorted]; //Extract last entry from list.
        entry [last_unsorted] = entry [0]; //Move top of heap to the end.
        insert_heap(current, O, last _unsorted -1); // Restore the heap.
    }
}

# 插入堆:

c++
template <class Record>
void Sortable_list< Record>::insert_heap(const Record &current, int low, int high)
/* Pre: The entries of the Sortable_list between indices low + 1and high,inclusive, form a heap. The entry in position low wil be discarded.
Post: The entry current has been inserted into the Sortable list and theentries rearranged so that the entries between indices low and high,inclusive, form a heap.
Uses: The class Record, and the contiguous List implementation of Chapter 6.*/
{
    int large; // position of child of entry [low] with the larger key
    large = 2 * low + 1; // large is now the left child of low.
    while (large =< high) {
        if (large < high & entry [large] < entry [large + 1])large ++; //large+1 refers to right child of low, large is now the child of low with the largest key.
        if(current>=entry[large])break; //current belongs ni position low.
        else { //Promote entry [large ] and move down the tree.
            entry [low] = entry [large]; //The larger one is promoted, low becomes the new vacancy and large is the left child.
            low = large;
            large=2*low +1;
        }
    }
    entry [low] = current;
}

# 建堆:

c++
template <class Record>
void Sortable_Jist< Record> :: build_heap()
/* Post:The entries of the Sortable_list have been rearranged so that it becomes a heap.
Uses: The contiguous List implementation of Chapter 6, and insert_heap. */
{
    int low; // All entries beyond the position low form a heap.
    for (low = count/2 - 1; low >= 0; --low ){
        Record current = entry [low];
        insert heap(current,low, count一1);
    }
}

# 非递归实现

利用数组实现,常用下标 0 作为根节点,此时孩子节点和父亲节点的计算:

left_child = parent*2+1

right_child = parent*2+2

child-1 = parent*2+0/1

parent = (child-1)>>1

# 向上调整

插入一个节点到堆的末尾

c++
void AdjustUp(HPDataType* a, size_t child){
	size_t parent;
	while (child > 0){
        parent = (child - 1) / 2;
		if (a[child] > a[parent]){ // 大堆
			swap(&a[child], &a[parent]);
			child = parent;
		}
		else{
			break;
		}
	}
}

向上调整建堆

c++
// 从数组第 2 个数直到最后一个数重复进行向上调整算法
for(int i=1;i<n;i++){
    AdjustUp(a,i);
}

向上调整法建堆时间复杂度: O(nlogn)O(nlogn)

# 向下调整

c++
void AdjustDown(HPDataType* a, size_t size, int parent){
	size_t child = parent * 2 + 1;
	while (child < size){
		if (child + 1 < size && a[child + 1] > a[child]){ // 比较左右孩子
			++child;
		}
		if (a[child] > a[parent]){ // 大堆
			swap(&a[parent], &a[child]);
			parent = child;
            size_t child = parent * 2 + 1;
		}
		else{
			break;
		}
	}
}
c++
// 从最后一个叶子的父亲开始,不断 --,直到第一个节点 (包括第一个节点),重复进行向下调整算法
// 最后一个叶子节点的数组下标是 n-1,最后一个叶子节点的父亲的数组下标为 (n-1-1)/2 = n/2-1
for(int i=n/2-1;i>=0;i--){
    AdjustDown(a,n,i);
}

向下调整法建堆时间复杂度: O(n)O(n)

参考:
https://blog.csdn.net/zhang_si_hang/article/details/124018889

# 性能

  • 与快排相比,堆排序的常数部分差一点,比较次数多一些,赋值次数少一些

  • 堆排序是不稳定排序

# 堆的应用

堆是一种常用的可以对排序、最值查找…… 优化的数据结构、技巧。

# 优先级队列

基于堆实现,c++ 里为 priority_queue

# 前 k 个最大 / 小的数

  • 经典面试题

    • 题面:给定一个有 N 个 entry 的 list ,设计一个算法, 从 N 个 entry 中找出最大的 k 个。假定 N 很大且 k 很小 (例如 N = 100 亿,k = 30)。

    • 题解:用堆排序,建堆需要时间复杂度:kl˙og2kk\dot log_{2}k;调整需要时间复杂度:Nl˙og2kN\dot log_{2}k;总共为:O((N+k)log2k)O((N+k)log_{2}k)

# 第 k 个最大 / 小的数

  • 对顶堆
    基于堆维持最大值 / 最小值的特点,用于维持第 k 大 / 第 k 小的数据
\ No newline at end of file diff --git a/cs/data-structure-and-algorithm/minimum-spanning-tree/index.html b/cs/data-structure-and-algorithm/minimum-spanning-tree/index.html index f1597c1b..dff12cf1 100644 --- a/cs/data-structure-and-algorithm/minimum-spanning-tree/index.html +++ b/cs/data-structure-and-algorithm/minimum-spanning-tree/index.html @@ -1 +1 @@ -最小生成树 - 数据结构与算法 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 定义

最小生成树 Minimum Spanning Tree 问题

等价问题:寻找一个带权无向图中某一点到另一个点的最短路径 / 权最小的路径

注意:当各边有相同权值时,由于选择的随意性,产生的生成树可能不唯一。

# Kruskal (克鲁斯卡尔) 算法

为主导,利用最小堆并查集

对所有边按权值从小到大排序,逐个添加不形成回路的边,直到包含所有的顶点。

# Prim (普里姆) 算法

  • 为主导
  • 贪心思想,不断选最小权值的边
  1. 从某一顶点出发,选择与它关联的具有最小权值的边,将其顶点加入到生成树顶点集合 U1U_1 中,剩余顶点集合为 U2U_2
  2. 以后每一步从:
    • 一个顶点在 U1U_1 中,
    • 另一个顶点在 U2U_2 中,
      的所有边中权值最小的边,将 U2U_2 中该顶点加入到 U1U_1
  3. 重复步骤 2 继续 n1n-1 次直到 U2U_2 为空
c++
//lowcost 存放生成树顶点集合内顶点到生成树外各顶点的各边上 的当前最小权值
//nearvex 记录生成树顶点集合外各顶点距离集合内哪个顶点最近 (即权值最小)
void Prim(Graph<string>& G, MinSpanTree&T) {
    int i, j, n = G.NumberOfVertices( );// 顶点数
    float * lowcost = new float[n];
    int * nearvex = new int[n];
    for(i=1;i<n;i++){
        lowcost[i] = G.GetWeight(0, i); // 顶点 0 到各边代价
        nearvex[i] = 0; // 及最短带权路径
    }
    nearvex[0] = -1;// 加到生成树顶点集合
    MSTEdgeNode e;// 最小生成树结点单元
    for ( i = 1; i < n; i++ ) {// 循环 n-1 次,加入 n-1 条边
        float min = MaxValue;
        int v = 0;
        for ( j = 0; j < n; j++ ){
            if ( nearvex[j] != -1 && lowcost[j] < min ) {
                v=j;
                min=lowcost[j];
            }
        }
        // 求生成树外顶点到生成树内顶点具有最小权值的边,v 是当前具最小权值的边
        if ( v ) { //v=0 表示再也找不到要求顶点
            e.tail = nearvex[v];
            e.head = v;
            e.cost = lowcost[v];
            T.Insert (e); // 选出的边加入生成树 // 若是计算 MST 总权值则是加该边的权值
            nearvex[v]=-1; // 该边加入生成树标记
            for ( j = 1; j < n; j++ ){
                if ( nearvex[j] != -1 && G.GetWeight(v, j) < lowcost[j] ) {
                    lowcost[j] = G.GetWeight(v, j);
                    nearvex[j] = v;
                }
            }
        }
    }
    free loecodt; free nearex;
}

# 两种算法比较

分析普里姆算法,设连通网络有 n 个顶点,则该算法的时间复杂度为O(n2)O(n^2),它适用于边稠密的网络,与边的数目无关。
克鲁斯卡尔算法主要针对边展开,边数少时效率会很高,所以对于边稀疏的图有优势。

\ No newline at end of file +最小生成树 - 数据结构与算法 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 定义

最小生成树 Minimum Spanning Tree 问题

等价问题:寻找一个带权无向图中某一点到另一个点的最短路径 / 权最小的路径

注意:当各边有相同权值时,由于选择的随意性,产生的生成树可能不唯一。

# Kruskal (克鲁斯卡尔) 算法

为主导,利用最小堆并查集

对所有边按权值从小到大排序,逐个添加不形成回路的边,直到包含所有的顶点。

# Prim (普里姆) 算法

  • 为主导
  • 贪心思想,不断选最小权值的边
  1. 从某一顶点出发,选择与它关联的具有最小权值的边,将其顶点加入到生成树顶点集合 U1U_1 中,剩余顶点集合为 U2U_2
  2. 以后每一步从:
    • 一个顶点在 U1U_1 中,
    • 另一个顶点在 U2U_2 中,
      的所有边中权值最小的边,将 U2U_2 中该顶点加入到 U1U_1
  3. 重复步骤 2 继续 n1n-1 次直到 U2U_2 为空
c++
//lowcost 存放生成树顶点集合内顶点到生成树外各顶点的各边上 的当前最小权值
//nearvex 记录生成树顶点集合外各顶点距离集合内哪个顶点最近 (即权值最小)
void Prim(Graph<string>& G, MinSpanTree&T) {
    int i, j, n = G.NumberOfVertices( );// 顶点数
    float * lowcost = new float[n];
    int * nearvex = new int[n];
    for(i=1;i<n;i++){
        lowcost[i] = G.GetWeight(0, i); // 顶点 0 到各边代价
        nearvex[i] = 0; // 及最短带权路径
    }
    nearvex[0] = -1;// 加到生成树顶点集合
    MSTEdgeNode e;// 最小生成树结点单元
    for ( i = 1; i < n; i++ ) {// 循环 n-1 次,加入 n-1 条边
        float min = MaxValue;
        int v = 0;
        for ( j = 0; j < n; j++ ){
            if ( nearvex[j] != -1 && lowcost[j] < min ) {
                v=j;
                min=lowcost[j];
            }
        }
        // 求生成树外顶点到生成树内顶点具有最小权值的边,v 是当前具最小权值的边
        if ( v ) { //v=0 表示再也找不到要求顶点
            e.tail = nearvex[v];
            e.head = v;
            e.cost = lowcost[v];
            T.Insert (e); // 选出的边加入生成树 // 若是计算 MST 总权值则是加该边的权值
            nearvex[v]=-1; // 该边加入生成树标记
            for ( j = 1; j < n; j++ ){
                if ( nearvex[j] != -1 && G.GetWeight(v, j) < lowcost[j] ) {
                    lowcost[j] = G.GetWeight(v, j);
                    nearvex[j] = v;
                }
            }
        }
    }
    free loecodt; free nearex;
}

# 两种算法比较

分析普里姆算法,设连通网络有 n 个顶点,则该算法的时间复杂度为O(n2)O(n^2),它适用于边稠密的网络,与边的数目无关。
克鲁斯卡尔算法主要针对边展开,边数少时效率会很高,所以对于边稀疏的图有优势。

\ No newline at end of file diff --git a/cs/data-structure-and-algorithm/pre-in-post-index/index.html b/cs/data-structure-and-algorithm/pre-in-post-index/index.html index 8611e044..8cd684bf 100644 --- a/cs/data-structure-and-algorithm/pre-in-post-index/index.html +++ b/cs/data-structure-and-algorithm/pre-in-post-index/index.html @@ -1 +1 @@ -前缀、中缀、后缀表达式 - 数据结构与算法 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 三种表达式

  • 前缀表达式 / Prefix Notation

    • 波兰式 / Polish Notation
  • 中缀表达式 / Infix Notation (中缀表达式才需要有括号)

  • 后缀表达式 / Postfix Notation

    • 逆波兰式 / Reverse Polish Notation

# 三种表达式的相互转化

# 括号法

通用方法,略

# 表达式树法

通用方法,略

# 栈方法

专用于: 中缀 -> 前缀 / 后缀

很像,注意区别,对照记忆

# 中缀 -> 后缀

  • 扫描
  • 打印
  • 遇到操作数:直接打印
  • 遇到操作符:
    1. 优先级小于等于栈顶:栈顶出栈并打印,继续与下一个栈顶操作符比较
    2. 优先级大于栈顶:入栈
    3. 栈顶为括号 (一定是左括号):入栈
  • 遇到括号:
    1. 左括号:直接入栈
    2. 右括号:不断出栈并打印,直到出栈一个左括号为止

# 中缀 -> 前缀

  • 扫描
  • 打印
  • 遇到操作数:直接打印
  • 遇到操作符:
    1. 优先级小于栈顶:栈顶出栈并打印,继续与下一个栈顶操作符比较
    2. 优先级大于等于栈顶:入栈
    3. 栈顶为括号 (一定是右括号):入栈
  • 遇到括号:
    1. 左括号:不断出栈并打印,直到出栈一个右括号为止
    2. 右括号:直接入栈
\ No newline at end of file +前缀、中缀、后缀表达式 - 数据结构与算法 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 三种表达式

  • 前缀表达式 / Prefix Notation

    • 波兰式 / Polish Notation
  • 中缀表达式 / Infix Notation (中缀表达式才需要有括号)

  • 后缀表达式 / Postfix Notation

    • 逆波兰式 / Reverse Polish Notation

# 三种表达式的相互转化

# 括号法

通用方法,略

# 表达式树法

通用方法,略

# 栈方法

专用于: 中缀 -> 前缀 / 后缀

很像,注意区别,对照记忆

# 中缀 -> 后缀

  • 扫描
  • 打印
  • 遇到操作数:直接打印
  • 遇到操作符:
    1. 优先级小于等于栈顶:栈顶出栈并打印,继续与下一个栈顶操作符比较
    2. 优先级大于栈顶:入栈
    3. 栈顶为括号 (一定是左括号):入栈
  • 遇到括号:
    1. 左括号:直接入栈
    2. 右括号:不断出栈并打印,直到出栈一个左括号为止

# 中缀 -> 前缀

  • 扫描
  • 打印
  • 遇到操作数:直接打印
  • 遇到操作符:
    1. 优先级小于栈顶:栈顶出栈并打印,继续与下一个栈顶操作符比较
    2. 优先级大于等于栈顶:入栈
    3. 栈顶为括号 (一定是右括号):入栈
  • 遇到括号:
    1. 左括号:不断出栈并打印,直到出栈一个右括号为止
    2. 右括号:直接入栈
\ No newline at end of file diff --git a/cs/data-structure-and-algorithm/radix-sort/index.html b/cs/data-structure-and-algorithm/radix-sort/index.html index 8a58bdf0..321b17b9 100644 --- a/cs/data-structure-and-algorithm/radix-sort/index.html +++ b/cs/data-structure-and-algorithm/radix-sort/index.html @@ -1 +1 @@ -基排序 - 数据结构与算法 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

基排序 / 桶排序 / 数字排序

# 原理

需要频繁进行分组重排,(类似于归并)适用于链表

可分为两种:

  • MSD,最高位优先 (Most Significant Digit first)

  • LSD,最低位优先 (Least Significant Digit first)

# 代码

c++
//Definition for singly-linked list.
struct ListNode {
    int val;
    ListNode *next;
    ListNode() : val(0), next(nullptr) {}
    ListNode(int x) : val(x), next(nullptr) {}
    ListNode(int x, ListNode *next) : val(x), next(next) {}
};
c++
class Solution {
public:
    ListNode* sortList(ListNode* head)
    {
        ListNode* dummyhead=new ListNode(0,head);
        ListNode* p=dummyhead;
        while(p->next!=nullptr)
        {
            p->next->val+=100000;
            p=p->next;
        }
        vector<queue<ListNode*>>vec(10); // 按 0~9 分组
        for(int i=1;i<=100000;i*=10) // 这里是 6 位数,共 6 趟
        {
            int flag=0;
            while(dummyhead->next!=nullptr)
            {
                if(dummyhead->next->val/(i*10)!=0)
                    flag=1;
                vec[dummyhead->next->val/i%10].push(dummyhead->next);
                dummyhead->next=dummyhead->next->next;
            }
            ListNode* p=dummyhead;
            for(int j=0;j<10;++j) // 将每个组节点连接起来
            {
                while(!vec[j].empty())
                {
                    vec[j].front()->next=p->next;
                    p->next=vec[j].front();
                    p=p->next;
                    vec[j].pop();
                }
            }
            if(flag==0)
                break;
        }
        p=dummyhead;
        while(p->next!=nullptr)
        {
            p->next->val-=100000;
            p=p->next;
        }
        ListNode* ret=dummyhead->next;
        delete dummyhead;
        return ret;
    }
};

# 复杂度

设有nn 个待排序记录,关键字位数为dd,每位有rr 种取值。则排序的趟数是dd; 在每一趟中:

  • 链表初始化的时间复杂度:O(r)O(r);
  • 分配的时间复杂度:O(n)O(n);
  • 分配后收集的时间复杂度:O(r)O(r);

则链式基数排序的时间复杂度为: O(d(n+r))O(d\cdot (n+r))

在排序过程中使用的辅助空间是:2r2r 个链表指针,nn 个指针域空间,
实际应用中rr 远小于nn,可以得到时间复杂度为:O(dn)O(dn)

则空间复杂度为:O(n+r)O(n+r)

  • 当 n 很大,d 比较小小,基数排序可以比归并、快排性能更好

  • 基排序是稳定排序。

\ No newline at end of file +基排序 - 数据结构与算法 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

基排序 / 桶排序 / 数字排序

# 原理

需要频繁进行分组重排,(类似于归并)适用于链表

可分为两种:

  • MSD,最高位优先 (Most Significant Digit first)

  • LSD,最低位优先 (Least Significant Digit first)

# 代码

c++
//Definition for singly-linked list.
struct ListNode {
    int val;
    ListNode *next;
    ListNode() : val(0), next(nullptr) {}
    ListNode(int x) : val(x), next(nullptr) {}
    ListNode(int x, ListNode *next) : val(x), next(next) {}
};
c++
class Solution {
public:
    ListNode* sortList(ListNode* head)
    {
        ListNode* dummyhead=new ListNode(0,head);
        ListNode* p=dummyhead;
        while(p->next!=nullptr)
        {
            p->next->val+=100000;
            p=p->next;
        }
        vector<queue<ListNode*>>vec(10); // 按 0~9 分组
        for(int i=1;i<=100000;i*=10) // 这里是 6 位数,共 6 趟
        {
            int flag=0;
            while(dummyhead->next!=nullptr)
            {
                if(dummyhead->next->val/(i*10)!=0)
                    flag=1;
                vec[dummyhead->next->val/i%10].push(dummyhead->next);
                dummyhead->next=dummyhead->next->next;
            }
            ListNode* p=dummyhead;
            for(int j=0;j<10;++j) // 将每个组节点连接起来
            {
                while(!vec[j].empty())
                {
                    vec[j].front()->next=p->next;
                    p->next=vec[j].front();
                    p=p->next;
                    vec[j].pop();
                }
            }
            if(flag==0)
                break;
        }
        p=dummyhead;
        while(p->next!=nullptr)
        {
            p->next->val-=100000;
            p=p->next;
        }
        ListNode* ret=dummyhead->next;
        delete dummyhead;
        return ret;
    }
};

# 复杂度

设有nn 个待排序记录,关键字位数为dd,每位有rr 种取值。则排序的趟数是dd; 在每一趟中:

  • 链表初始化的时间复杂度:O(r)O(r);
  • 分配的时间复杂度:O(n)O(n);
  • 分配后收集的时间复杂度:O(r)O(r);

则链式基数排序的时间复杂度为: O(d(n+r))O(d\cdot (n+r))

在排序过程中使用的辅助空间是:2r2r 个链表指针,nn 个指针域空间,
实际应用中rr 远小于nn,可以得到时间复杂度为:O(dn)O(dn)

则空间复杂度为:O(n+r)O(n+r)

  • 当 n 很大,d 比较小小,基数排序可以比归并、快排性能更好

  • 基排序是稳定排序。

\ No newline at end of file diff --git a/cs/data-structure-and-algorithm/shortest-path/index.html b/cs/data-structure-and-algorithm/shortest-path/index.html index 3e9849b0..3bab5dc1 100644 --- a/cs/data-structure-and-algorithm/shortest-path/index.html +++ b/cs/data-structure-and-algorithm/shortest-path/index.html @@ -1 +1 @@ -最短路径问题 - 数据结构与算法 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 定义

寻找一个带权有向图中某一点到另一个点的最短路径 / 权最小的路径

当然以下算法也适用于无向图

# Floyd (弗洛伊德) 算法

  • 可以算出所有点之间的最短距离
c++
//dist 初始化为邻接矩阵,若 i 没有指向 j 的边,则应有 dist [i][j]=MAX_INT (表示无穷大的数)
void floyd(){
    for(int k = 0; k < n; k ++){   // 作为循环中间点的 k 必须放在最外一层循环 
        for(int i = 0; i < n; i ++){
            for(int j = 0; j < n; j ++){
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]); 
            }    
        }    
    }    
}
//dist [i][j] 得出的是 i 到 j 的最短路径
  • 时间复杂度为:O(n3)O(n^{3})

# Warshall 算法

和 Floyd (弗洛伊德) 算法很像,二者常常一起统称为 Warshall-Floyd 算法 ,三重循环一样,只是循环最内层执行的赋值不一样

  • 用于由邻接矩阵计算可达矩阵

    • 由关系矩阵计算传递闭包矩阵

    • 关系矩阵即为邻接矩阵,对应的传递闭包矩阵即为可达矩阵

c++
//dist 初始化为邻接矩阵,若存在 i 指向 j 的边,则应有 dist [i][j]=1
void floyd(){
    for(int k = 0; k < n; k ++){   // 作为循环中间点的 k 必须放在最外一层循环 
        for(int i = 0; i < n; i ++){
            for(int j = 0; j < n; j ++){
                dist[i][j] = dist[i][j] | (dist[i][k] && dist[k][j]); 
            }    
        }    
    }
}
//dist [i][j] 得出的可达矩阵

或者:

c++
void floyd(){
    for(int i = 0;i < n;i++){  // 先列
		for(int j = 0;j < n;j++){  // 后行
			if(matrix[j][i] == 1){	//	第 j 行与第 i 行进行或操作,并最终赋值到第 j 行 
				for(int k = 0;k < n;k++){
					matrix[j][k] = matrix[j][k] | matrix[i][k];
				} 
			}		
		}	
	}
}

初始化邻接矩阵对角线元素d[i][i]d[i][i] 为 0,得到的可达矩阵若d[i][i]=1d[i][i]=1 则存在包含点 i 的环,从而可以判断图是否有环和找环

  • 时间复杂度为:O(n3)O(n^{3})

# Dijkstra (迪杰斯特拉) 算法

可以算出某一个点到其他所有点之间的最短距离,即单源点最短路径

对 Prim 算法略加改动就成了 Dijkstra 算法,
将 Prim 算法中求每个顶点VkV_k 的 lowcost 值用 dist [k] 代替即可。

与 Prim 算法一样用了贪心思想,只有在每条边权值非负的情况下才能保证结果正确

  • dist [i] 是点 s 出发到 i 的最短路径长度,长度为 n
  • 初始需要 dist [i] 赋值为 s 出发的边指向的各个点的权
  • 剩余不相邻的点全部为 MAX_INT (表示无穷大的数)
  • shortest [i] 是标记 s 到点 i 的距离 dist [i] 是否确定为最短路径,长度为 n
c++
void dijkstra(int s){
    memset(shortest, false, sizeof(shortest));
    shortest[s] = true;
    for(int i = 0; i < n; i ++){
        dist[i] = graph[s][i]; //graph [s][i] 为 s 到 i 的有向边的权
        // 初始化 dist [i] 赋值为 s 出发的边指向的各个点的权
    }
    int index;
    for(int i = 1; i < n; i ++){ // 一共 n-1 轮后 s 到其余所有点到距离都是最短距离
        int mincost = MAX_INT; // 表示无穷大的数
        for(int j = 0; j < n; j ++){
            if(!shortest[j] && dist[j] < mincost){
                mincost = dist[j];
                index = j;
            }    
        } // 此处可以改用堆,存储 dist 中未被确定为最短距离的元素和下标,维护最小值
        shortest[index] = true; // 第 i 轮确定 i 到 index 的距离为最短距离 
        for(int j = 0; j < n; j ++){
            if(!shortest[j] && dist[j] > dist[index] + graph[index][j]){
                dist[j] = dist[index] + graph[index][j];
            }    
        }    
    }
}
  • 时间复杂度为:O(n2)O(n^{2})
\ No newline at end of file +最短路径问题 - 数据结构与算法 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 定义

寻找一个带权有向图中某一点到另一个点的最短路径 / 权最小的路径

当然以下算法也适用于无向图

# Floyd (弗洛伊德) 算法

  • 可以算出所有点之间的最短距离
c++
//dist 初始化为邻接矩阵,若 i 没有指向 j 的边,则应有 dist [i][j]=MAX_INT (表示无穷大的数)
void floyd(){
    for(int k = 0; k < n; k ++){   // 作为循环中间点的 k 必须放在最外一层循环 
        for(int i = 0; i < n; i ++){
            for(int j = 0; j < n; j ++){
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]); 
            }    
        }    
    }    
}
//dist [i][j] 得出的是 i 到 j 的最短路径
  • 时间复杂度为:O(n3)O(n^{3})

# Warshall 算法

和 Floyd (弗洛伊德) 算法很像,二者常常一起统称为 Warshall-Floyd 算法 ,三重循环一样,只是循环最内层执行的赋值不一样

  • 用于由邻接矩阵计算可达矩阵

    • 由关系矩阵计算传递闭包矩阵

    • 关系矩阵即为邻接矩阵,对应的传递闭包矩阵即为可达矩阵

c++
//dist 初始化为邻接矩阵,若存在 i 指向 j 的边,则应有 dist [i][j]=1
void floyd(){
    for(int k = 0; k < n; k ++){   // 作为循环中间点的 k 必须放在最外一层循环 
        for(int i = 0; i < n; i ++){
            for(int j = 0; j < n; j ++){
                dist[i][j] = dist[i][j] | (dist[i][k] && dist[k][j]); 
            }    
        }    
    }
}
//dist [i][j] 得出的可达矩阵

或者:

c++
void floyd(){
    for(int i = 0;i < n;i++){  // 先列
		for(int j = 0;j < n;j++){  // 后行
			if(matrix[j][i] == 1){	//	第 j 行与第 i 行进行或操作,并最终赋值到第 j 行 
				for(int k = 0;k < n;k++){
					matrix[j][k] = matrix[j][k] | matrix[i][k];
				} 
			}		
		}	
	}
}

初始化邻接矩阵对角线元素d[i][i]d[i][i] 为 0,得到的可达矩阵若d[i][i]=1d[i][i]=1 则存在包含点 i 的环,从而可以判断图是否有环和找环

  • 时间复杂度为:O(n3)O(n^{3})

# Dijkstra (迪杰斯特拉) 算法

可以算出某一个点到其他所有点之间的最短距离,即单源点最短路径

对 Prim 算法略加改动就成了 Dijkstra 算法,
将 Prim 算法中求每个顶点VkV_k 的 lowcost 值用 dist [k] 代替即可。

与 Prim 算法一样用了贪心思想,只有在每条边权值非负的情况下才能保证结果正确

  • dist [i] 是点 s 出发到 i 的最短路径长度,长度为 n
  • 初始需要 dist [i] 赋值为 s 出发的边指向的各个点的权
  • 剩余不相邻的点全部为 MAX_INT (表示无穷大的数)
  • shortest [i] 是标记 s 到点 i 的距离 dist [i] 是否确定为最短路径,长度为 n
c++
void dijkstra(int s){
    memset(shortest, false, sizeof(shortest));
    shortest[s] = true;
    for(int i = 0; i < n; i ++){
        dist[i] = graph[s][i]; //graph [s][i] 为 s 到 i 的有向边的权
        // 初始化 dist [i] 赋值为 s 出发的边指向的各个点的权
    }
    int index;
    for(int i = 1; i < n; i ++){ // 一共 n-1 轮后 s 到其余所有点到距离都是最短距离
        int mincost = MAX_INT; // 表示无穷大的数
        for(int j = 0; j < n; j ++){
            if(!shortest[j] && dist[j] < mincost){
                mincost = dist[j];
                index = j;
            }    
        } // 此处可以改用堆,存储 dist 中未被确定为最短距离的元素和下标,维护最小值
        shortest[index] = true; // 第 i 轮确定 i 到 index 的距离为最短距离 
        for(int j = 0; j < n; j ++){
            if(!shortest[j] && dist[j] > dist[index] + graph[index][j]){
                dist[j] = dist[index] + graph[index][j];
            }    
        }    
    }
}
  • 时间复杂度为:O(n2)O(n^{2})
\ No newline at end of file diff --git a/cs/data-structure-and-algorithm/stack-queue/index.html b/cs/data-structure-and-algorithm/stack-queue/index.html index e49f568b..55a84e2e 100644 --- a/cs/data-structure-and-algorithm/stack-queue/index.html +++ b/cs/data-structure-and-algorithm/stack-queue/index.html @@ -1 +1 @@ -栈与队列 - 数据结构与算法 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 循环队列

  • 对于一个容量为 mm 的循环队列

  • 实际存储空间为 m+1m+1

  • 初始状态 / 判空条件: rear==frontrear == front

  • 判满条件:(rear+1)%m==front(rear+1)\%m==front

  • 入队操作:

伪代码
新元素加入队尾;
队尾指针 + 1;
  • 出队操作:
伪代码
访问队头元素;
队头指针 + 1;
  • 任意时刻队列内包含的元素数量为: (m+rearfront)%m(m+rear-front)\%m

# 共享栈

  • 对于一个容量为mm 的共享栈

  • 初始状态 / 判空条件: top0==1top1==mtop_0==-1\ \land\ top_1==m

  • 判满条件:top1top0==1top_1-top_0==1

  • 入栈操作:

伪代码
top0 先 + 1 再赋值;
top1 先 - 1 再赋值;
  • 出栈操作:
伪代码
top0-1;
top1+1;
  • 任意时刻队列内包含的元素数量为: ...
\ No newline at end of file +栈与队列 - 数据结构与算法 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 循环队列

  • 对于一个容量为 mm 的循环队列

  • 实际存储空间为 m+1m+1

  • 初始状态 / 判空条件: rear==frontrear == front

  • 判满条件:(rear+1)%m==front(rear+1)\%m==front

  • 入队操作:

伪代码
新元素加入队尾;
队尾指针 + 1;
  • 出队操作:
伪代码
访问队头元素;
队头指针 + 1;
  • 任意时刻队列内包含的元素数量为: (m+rearfront)%m(m+rear-front)\%m

# 共享栈

  • 对于一个容量为mm 的共享栈

  • 初始状态 / 判空条件: top0==1top1==mtop_0==-1\ \land\ top_1==m

  • 判满条件:top1top0==1top_1-top_0==1

  • 入栈操作:

伪代码
top0 先 + 1 再赋值;
top1 先 - 1 再赋值;
  • 出栈操作:
伪代码
top0-1;
top1+1;
  • 任意时刻队列内包含的元素数量为: ...
\ No newline at end of file diff --git a/cs/devops/acme/index.html b/cs/devops/acme/index.html index a1646185..82beb303 100644 --- a/cs/devops/acme/index.html +++ b/cs/devops/acme/index.html @@ -1 +1 @@ -acme.sh 插件 - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 证书相关文件格式

  • 证书 (Certificate) - .cer.crt
  • 私钥 (Private Key) - .key
  • 证书签名请求 (Certificate signing request) - .csr
  • 证书吊销列表 (Certificate Revocation List) - .crl

以上除了 .crl 均可以使用这两种编码方式,从而有这样的后缀:

  • base64 编码 - .pem
  • 二进制编码 (少见) - .der

为了给我们的网页应用使用 https 协议,我们需要得到有效的第三方认证证书以及对应的私钥

CA,certificate authority。证书局,用于制作、认证证书的第三方机构

# 安装

安装 acme.shhttps://github.com/acmesh-official/acme.sh

shell
curl https://get.acme.sh | sh -s email=username@example.com

但是需要🪜,所以国内等效的做法是:

shell
git clone --depth 1 https://github.com/acmesh-official/acme.sh.git
cd acme.sh
./acme.sh --install -m username@example.com

替换 username@example.com 为自己的邮箱,用来接收上游证书的邮件通知

目前探索了三种方法,最推荐第三种方法,直接接入运营商的 API ,需要 issue 时只需要一行指令实现,非常方便。

# 方法一

请求注册,并将返回结果写到 acme-dns.challenges

shell
curl -s -X POST https://auth.acme-dns.io/register | python3 -m json.tool > acme-dns.challenges;cat acme-dns.challenges

acme-dns注册用户

导出用户名、密码、子域名等结果

shell
export ACMEDNS_USERNAME="$(cat acme-dns.challenges | awk -F"\"" '/username/{print $4}')"
export ACMEDNS_PASSWORD="$(cat acme-dns.challenges | awk -F"\"" '/password/{print $4}')"
export ACMEDNS_SUBDOMAIN="$(cat acme-dns.challenges | awk -F"\"" '/subdomain/{print $4}')"
echo "FULLDOMAIN = $(cat acme-dns.challenges | awk -F"\"" '/fulldomain/{print $4}')"

同时增加 cname 记录来完成挑战:

cname

申请 ssl 证书:

shell
~/.acme.sh/acme.sh --issue --dns dns_acmedns -d vm.fuusen.space --dnssleep 300

结果:

shell
root@proxmox:~# ~/.acme.sh/acme.sh --issue --dns dns_acmedns -d vm.fuusen.space --dnssleep 300
[Sun Mar 10 12:19:48 PM CST 2024] Using CA: https://acme-v02.api.letsencrypt.org/directory
[Sun Mar 10 12:19:48 PM CST 2024] Creating domain key
[Sun Mar 10 12:19:48 PM CST 2024] The domain key is here: /root/.acme.sh/vm.fuusen.space_ecc/vm.fuusen.space.key
[Sun Mar 10 12:19:48 PM CST 2024] Single domain='vm.fuusen.space'
[Sun Mar 10 12:19:51 PM CST 2024] Getting webroot for domain='vm.fuusen.space'
[Sun Mar 10 12:19:51 PM CST 2024] Adding txt value: JE6AGlpWVR5S192edUoStf3_OXAG9UR_cwnKIGGIL9U for domain:  _acme-challenge.vm.fuusen.space
[Sun Mar 10 12:19:51 PM CST 2024] Using acme-dns
[Sun Mar 10 12:19:52 PM CST 2024] The txt record is added: Success.
[Sun Mar 10 12:19:52 PM CST 2024] Sleep 300 seconds for the txt records to take effect
[Sun Mar 10 12:24:53 PM CST 2024] Verifying: vm.fuusen.space
[Sun Mar 10 12:24:54 PM CST 2024] Pending, The CA is processing your order, please just wait. (1/30)
[Sun Mar 10 12:24:58 PM CST 2024] Success
[Sun Mar 10 12:24:58 PM CST 2024] Removing DNS records.
[Sun Mar 10 12:24:58 PM CST 2024] Removing txt: JE6AGlpWVR5S192edUoStf3_OXAG9UR_cwnKIGGIL9U for domain: _acme-challenge.vm.fuusen.space
[Sun Mar 10 12:24:58 PM CST 2024] Using acme-dns
[Sun Mar 10 12:24:58 PM CST 2024] Removed: Success
[Sun Mar 10 12:24:58 PM CST 2024] Verify finished, start to sign.
[Sun Mar 10 12:24:58 PM CST 2024] Lets finalize the order.
[Sun Mar 10 12:24:58 PM CST 2024] Le_OrderFinalize='https://acme-v02.api.letsencrypt.org/acme/finalize/1610913557/251061640687'
[Sun Mar 10 12:24:59 PM CST 2024] Downloading cert.
[Sun Mar 10 12:24:59 PM CST 2024] Le_LinkCert='https://acme-v02.api.letsencrypt.org/acme/cert/03567f6bc53bd6e36d65f5b8f094bfb91eaa'
[Sun Mar 10 12:25:00 PM CST 2024] Cert success.
-----BEGIN CERTIFICATE-----
MIIEHzCCAwegAwIBAgISA1Z/a8U71uNtZfW48JS/uR6qMA0GCSqGSIb3DQEBCwUA
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
EwJSMzAeFw0yNDAzMTAwMzI0NTlaFw0yNDA2MDgwMzI0NThaMBoxGDAWBgNVBAMT
D3ZtLmZ1dXNlbi5zcGFjZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABEbT5BcQ
x14Rc9EqGps5dTQ9Jl5ywvrWAVJmQFtmbIBAileSa+/KYuYeSmjuDAyjj99to2KM
R9fVK6j4fYDycCOjggIQMIICDDAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0lBBYwFAYI
KwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFBo67Zs5
olZHLkCkGTQK/ZFVQJwvMB8GA1UdIwQYMBaAFBQusxe3WFbLrlAJQOYfr52LFMLG
MFUGCCsGAQUFBwEBBEkwRzAhBggrBgEFBQcwAYYVaHR0cDovL3IzLm8ubGVuY3Iu
b3JnMCIGCCsGAQUFBzAChhZodHRwOi8vcjMuaS5sZW5jci5vcmcvMBoGA1UdEQQT
MBGCD3ZtLmZ1dXNlbi5zcGFjZTATBgNVHSAEDDAKMAgGBmeBDAECATCCAQMGCisG
AQQB1nkCBAIEgfQEgfEA7wB1ADtTd3U+LbmAToswWwb+QDtn2E/D9Me9AA0tcm/h
+tQXAAABjiabW4kAAAQDAEYwRAIgehF+9/VI/MC8IvkLbFTpa82IP1zXOpZFvW1U
D77cdCYCIAy+z2hwinQtpc4up40bhNx4+h1JujS7DDgyNwsfdGaCAHYA7s3QZNXb
Gs7FXLedtM0TojKHRny87N7DUUhZRnEftZsAAAGOJptbiQAABAMARzBFAiAy8u5B
ZN0V23ZzMJ1dViQ4bfXWJyxs42W93GIpmJRkPAIhAOfoZmJpDW02uZV667vTZWqF
zmGJfM3njf+XQnnARF3dMA0GCSqGSIb3DQEBCwUAA4IBAQAxiO0OOA/tVqDfoQne
JrlX1wB+aYmTHeqwfxBE+Q0Mu0irGtX9K4XyhQR06edLKw1fXY2dH+iYKvscsE91
iGhs0nSrAqKIi3VLLgvEFrTEW7C8Pftgt4Hbx89LvION7MgXXHe62L4JvrTkQ/Y4
sRa6vt48bDkDspQ1BQrT589SiXMUsNOE947mbaViR3cbg2oQd+XxLJaAb1ZoSNd0
Lvs/j5u67r30C5QnSEGxChR/6c9V9+aw07yttoD6M8iA7LA736pPjWAM8hvQ+cQa
wAWyDU1Ub89KJx5Pv+nvbNCRT1TjoqmhPxYSxsDTYAjUTV9sBbxvcUdG7w+6tUwX
6b9m
-----END CERTIFICATE-----
[Sun Mar 10 12:25:00 PM CST 2024] Your cert is in: /root/.acme.sh/vm.fuusen.space_ecc/vm.fuusen.space.cer
[Sun Mar 10 12:25:00 PM CST 2024] Your cert key is in: /root/.acme.sh/vm.fuusen.space_ecc/vm.fuusen.space.key
[Sun Mar 10 12:25:00 PM CST 2024] The intermediate CA cert is in: /root/.acme.sh/vm.fuusen.space_ecc/ca.cer
[Sun Mar 10 12:25:00 PM CST 2024] And the full chain certs is there: /root/.acme.sh/vm.fuusen.space_ecc/fullchain.cer

# 方法二

推荐使用 Let's Encrypt 作为上游 CA :

shell
acme.sh --set-default-ca --server letsencrypt

使用 Nginx ,在 /etc/nginx/conf.d/ 中新建一个配置文件 letsencrypt.conf (名字随意),内容如下:

letsencrypt.conf
server {
	listen 80;
	listen [::]:80;
	server_name example1.com;
	server_name example2.com;
	location /.well-known/acme-challenge {
		root /var/www/letsencrypt;
	}
	location / {
		rewrite	^/(.*)$ https://$host/$1 permanent;
	}
}

运行:

shell
acme.sh --issue -d md.fuusen.space -d tex.fuusen.space -w /var/www/letsencrypt --debug

reference:

  • https://u.sb/acme-sh-ssl/

# 方法三

用运营商的 API ,自动添加 txt 记录完成挑战。参考:https://github.com/acmesh-official/acme.sh/wiki/dnsapi2

首先第一次需要设置 API ,具体需要看不同的运营商。

shell
export ...=...

然后 issue 之后会自动保存所设置的 API 。

执行指令:

shell
acme.sh --issue --dns [dns_your_server] -d example.com

似乎也可以一次性批量 issue 多个 cert ,但是我实际测试却只得到了同时 issue 时的第一个域名的证书,可能是还存在 bug 。

这样方法得到的证书文件在 ~/.acme.sh/example.com_ecc/ 如下:

shell
├── ca.cer
├── fullchain.cer
├── example.com.cer
├── example.com.conf
├── example.com.csr
├── example.com.csr.conf
└── example.com.key

其中:

  • fullchain.cer 是对应的证书文件
  • example.com.key 是对应的密钥文件

Nginx 配置:

xxx.conf
server {
		......
		ssl_certificate  /home/lsy/.acme.sh/example.com_ecc/fullchain.cer;
        ssl_certificate_key  /home/lsy/.acme.sh/example.com_ecc/example.com.key;
        ......
}

⚠️ 注意如果 curl 网页时出现如下报错:

shell
curl: (35) OpenSSL/3.0.13: error:0A00010B:SSL routines::wrong version number

说明 http /https 的协议配置有问题,出现了本来该用 https 却用了 http ,或反之的情况。

Edited on Views times
\ No newline at end of file +acme.sh 插件 - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 证书相关文件格式

  • 证书 (Certificate) - .cer.crt
  • 私钥 (Private Key) - .key
  • 证书签名请求 (Certificate signing request) - .csr
  • 证书吊销列表 (Certificate Revocation List) - .crl

以上除了 .crl 均可以使用这两种编码方式,从而有这样的后缀:

  • base64 编码 - .pem
  • 二进制编码 (少见) - .der

为了给我们的网页应用使用 https 协议,我们需要得到有效的第三方认证证书以及对应的私钥

CA,certificate authority。证书局,用于制作、认证证书的第三方机构

# 安装

安装 acme.shhttps://github.com/acmesh-official/acme.sh

shell
curl https://get.acme.sh | sh -s email=username@example.com

但是需要🪜,所以国内等效的做法是:

shell
git clone --depth 1 https://github.com/acmesh-official/acme.sh.git
cd acme.sh
./acme.sh --install -m username@example.com

替换 username@example.com 为自己的邮箱,用来接收上游证书的邮件通知

目前探索了三种方法,最推荐第三种方法,直接接入运营商的 API ,需要 issue 时只需要一行指令实现,非常方便。

# 方法一

请求注册,并将返回结果写到 acme-dns.challenges

shell
curl -s -X POST https://auth.acme-dns.io/register | python3 -m json.tool > acme-dns.challenges;cat acme-dns.challenges

acme-dns注册用户

导出用户名、密码、子域名等结果

shell
export ACMEDNS_USERNAME="$(cat acme-dns.challenges | awk -F"\"" '/username/{print $4}')"
export ACMEDNS_PASSWORD="$(cat acme-dns.challenges | awk -F"\"" '/password/{print $4}')"
export ACMEDNS_SUBDOMAIN="$(cat acme-dns.challenges | awk -F"\"" '/subdomain/{print $4}')"
echo "FULLDOMAIN = $(cat acme-dns.challenges | awk -F"\"" '/fulldomain/{print $4}')"

同时增加 cname 记录来完成挑战:

cname

申请 ssl 证书:

shell
~/.acme.sh/acme.sh --issue --dns dns_acmedns -d vm.fuusen.space --dnssleep 300

结果:

shell
root@proxmox:~# ~/.acme.sh/acme.sh --issue --dns dns_acmedns -d vm.fuusen.space --dnssleep 300
[Sun Mar 10 12:19:48 PM CST 2024] Using CA: https://acme-v02.api.letsencrypt.org/directory
[Sun Mar 10 12:19:48 PM CST 2024] Creating domain key
[Sun Mar 10 12:19:48 PM CST 2024] The domain key is here: /root/.acme.sh/vm.fuusen.space_ecc/vm.fuusen.space.key
[Sun Mar 10 12:19:48 PM CST 2024] Single domain='vm.fuusen.space'
[Sun Mar 10 12:19:51 PM CST 2024] Getting webroot for domain='vm.fuusen.space'
[Sun Mar 10 12:19:51 PM CST 2024] Adding txt value: JE6AGlpWVR5S192edUoStf3_OXAG9UR_cwnKIGGIL9U for domain:  _acme-challenge.vm.fuusen.space
[Sun Mar 10 12:19:51 PM CST 2024] Using acme-dns
[Sun Mar 10 12:19:52 PM CST 2024] The txt record is added: Success.
[Sun Mar 10 12:19:52 PM CST 2024] Sleep 300 seconds for the txt records to take effect
[Sun Mar 10 12:24:53 PM CST 2024] Verifying: vm.fuusen.space
[Sun Mar 10 12:24:54 PM CST 2024] Pending, The CA is processing your order, please just wait. (1/30)
[Sun Mar 10 12:24:58 PM CST 2024] Success
[Sun Mar 10 12:24:58 PM CST 2024] Removing DNS records.
[Sun Mar 10 12:24:58 PM CST 2024] Removing txt: JE6AGlpWVR5S192edUoStf3_OXAG9UR_cwnKIGGIL9U for domain: _acme-challenge.vm.fuusen.space
[Sun Mar 10 12:24:58 PM CST 2024] Using acme-dns
[Sun Mar 10 12:24:58 PM CST 2024] Removed: Success
[Sun Mar 10 12:24:58 PM CST 2024] Verify finished, start to sign.
[Sun Mar 10 12:24:58 PM CST 2024] Lets finalize the order.
[Sun Mar 10 12:24:58 PM CST 2024] Le_OrderFinalize='https://acme-v02.api.letsencrypt.org/acme/finalize/1610913557/251061640687'
[Sun Mar 10 12:24:59 PM CST 2024] Downloading cert.
[Sun Mar 10 12:24:59 PM CST 2024] Le_LinkCert='https://acme-v02.api.letsencrypt.org/acme/cert/03567f6bc53bd6e36d65f5b8f094bfb91eaa'
[Sun Mar 10 12:25:00 PM CST 2024] Cert success.
-----BEGIN CERTIFICATE-----
MIIEHzCCAwegAwIBAgISA1Z/a8U71uNtZfW48JS/uR6qMA0GCSqGSIb3DQEBCwUA
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
EwJSMzAeFw0yNDAzMTAwMzI0NTlaFw0yNDA2MDgwMzI0NThaMBoxGDAWBgNVBAMT
D3ZtLmZ1dXNlbi5zcGFjZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABEbT5BcQ
x14Rc9EqGps5dTQ9Jl5ywvrWAVJmQFtmbIBAileSa+/KYuYeSmjuDAyjj99to2KM
R9fVK6j4fYDycCOjggIQMIICDDAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0lBBYwFAYI
KwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFBo67Zs5
olZHLkCkGTQK/ZFVQJwvMB8GA1UdIwQYMBaAFBQusxe3WFbLrlAJQOYfr52LFMLG
MFUGCCsGAQUFBwEBBEkwRzAhBggrBgEFBQcwAYYVaHR0cDovL3IzLm8ubGVuY3Iu
b3JnMCIGCCsGAQUFBzAChhZodHRwOi8vcjMuaS5sZW5jci5vcmcvMBoGA1UdEQQT
MBGCD3ZtLmZ1dXNlbi5zcGFjZTATBgNVHSAEDDAKMAgGBmeBDAECATCCAQMGCisG
AQQB1nkCBAIEgfQEgfEA7wB1ADtTd3U+LbmAToswWwb+QDtn2E/D9Me9AA0tcm/h
+tQXAAABjiabW4kAAAQDAEYwRAIgehF+9/VI/MC8IvkLbFTpa82IP1zXOpZFvW1U
D77cdCYCIAy+z2hwinQtpc4up40bhNx4+h1JujS7DDgyNwsfdGaCAHYA7s3QZNXb
Gs7FXLedtM0TojKHRny87N7DUUhZRnEftZsAAAGOJptbiQAABAMARzBFAiAy8u5B
ZN0V23ZzMJ1dViQ4bfXWJyxs42W93GIpmJRkPAIhAOfoZmJpDW02uZV667vTZWqF
zmGJfM3njf+XQnnARF3dMA0GCSqGSIb3DQEBCwUAA4IBAQAxiO0OOA/tVqDfoQne
JrlX1wB+aYmTHeqwfxBE+Q0Mu0irGtX9K4XyhQR06edLKw1fXY2dH+iYKvscsE91
iGhs0nSrAqKIi3VLLgvEFrTEW7C8Pftgt4Hbx89LvION7MgXXHe62L4JvrTkQ/Y4
sRa6vt48bDkDspQ1BQrT589SiXMUsNOE947mbaViR3cbg2oQd+XxLJaAb1ZoSNd0
Lvs/j5u67r30C5QnSEGxChR/6c9V9+aw07yttoD6M8iA7LA736pPjWAM8hvQ+cQa
wAWyDU1Ub89KJx5Pv+nvbNCRT1TjoqmhPxYSxsDTYAjUTV9sBbxvcUdG7w+6tUwX
6b9m
-----END CERTIFICATE-----
[Sun Mar 10 12:25:00 PM CST 2024] Your cert is in: /root/.acme.sh/vm.fuusen.space_ecc/vm.fuusen.space.cer
[Sun Mar 10 12:25:00 PM CST 2024] Your cert key is in: /root/.acme.sh/vm.fuusen.space_ecc/vm.fuusen.space.key
[Sun Mar 10 12:25:00 PM CST 2024] The intermediate CA cert is in: /root/.acme.sh/vm.fuusen.space_ecc/ca.cer
[Sun Mar 10 12:25:00 PM CST 2024] And the full chain certs is there: /root/.acme.sh/vm.fuusen.space_ecc/fullchain.cer

# 方法二

推荐使用 Let's Encrypt 作为上游 CA :

shell
acme.sh --set-default-ca --server letsencrypt

使用 Nginx ,在 /etc/nginx/conf.d/ 中新建一个配置文件 letsencrypt.conf (名字随意),内容如下:

letsencrypt.conf
server {
	listen 80;
	listen [::]:80;
	server_name example1.com;
	server_name example2.com;
	location /.well-known/acme-challenge {
		root /var/www/letsencrypt;
	}
	location / {
		rewrite	^/(.*)$ https://$host/$1 permanent;
	}
}

运行:

shell
acme.sh --issue -d md.fuusen.space -d tex.fuusen.space -w /var/www/letsencrypt --debug

reference:

  • https://u.sb/acme-sh-ssl/

# 方法三

用运营商的 API ,自动添加 txt 记录完成挑战。参考:https://github.com/acmesh-official/acme.sh/wiki/dnsapi2

首先第一次需要设置 API ,具体需要看不同的运营商。

shell
export ...=...

然后 issue 之后会自动保存所设置的 API 。

执行指令:

shell
acme.sh --issue --dns [dns_your_server] -d example.com

似乎也可以一次性批量 issue 多个 cert ,但是我实际测试却只得到了同时 issue 时的第一个域名的证书,可能是还存在 bug 。

这样方法得到的证书文件在 ~/.acme.sh/example.com_ecc/ 如下:

shell
├── ca.cer
├── fullchain.cer
├── example.com.cer
├── example.com.conf
├── example.com.csr
├── example.com.csr.conf
└── example.com.key

其中:

  • fullchain.cer 是对应的证书文件
  • example.com.key 是对应的密钥文件

Nginx 配置:

xxx.conf
server {
		......
		ssl_certificate  /home/lsy/.acme.sh/example.com_ecc/fullchain.cer;
        ssl_certificate_key  /home/lsy/.acme.sh/example.com_ecc/example.com.key;
        ......
}

⚠️ 注意如果 curl 网页时出现如下报错:

shell
curl: (35) OpenSSL/3.0.13: error:0A00010B:SSL routines::wrong version number

说明 http /https 的协议配置有问题,出现了本来该用 https 却用了 http ,或反之的情况。

Edited on Views times
\ No newline at end of file diff --git a/cs/devops/bash/index.html b/cs/devops/bash/index.html index 49b211ac..6742c37d 100644 --- a/cs/devops/bash/index.html +++ b/cs/devops/bash/index.html @@ -1 +1 @@ -Linux 的 shell 配置原理 - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 环境变量文件的加载顺序

在登录 Linux 系统并启动一个 bash shell 时,默认情况下 bash 会在若干个文件中查找环境变量的设置。这些文件统称为系统环境文件。bash 检查的环境变量文件的顺序情况取决于系统运行的 shell 方式。系统运行 shell 方式一般为 4 种:

是否交互式是否登陆式哪些情况
通过系统用户登录默认运行的 shell
非登录交互式运行 shell
执行脚本运行非交互式 shell

shell-config

# bash 命令启动 shell

命令 bash 启动 shell 时,可以通过选项改变其行为

shell
bash [长选项] [选项] [脚本]
选项含义
-ishell 在交互模式下运行
-lshell 作为登陆 shell
-r启动受限 shell
--选项结束标志,后面的内容当做文件名或参数,即使他们以 - 开头
--login-l
--noprofile阻止读取初始化文件 /etc/profile~/.bash_profile , ~/.bash_login , ~/profile
--norc在交互式 shell,阻止读取初始化文件 ~/.bashrc 。如果 shell 以 sh 调用的话,该选项默认是打开的。
--recfile file在交互式 shell,指定初始化文件是 file 而不是 ~/.bashrc
--version版本信息

# 检查当前 shell 状态

# 查看当前是否登录式

shell
shopt login_shell
# 结果为 on 则是登陆式
login_shell    	on
# 结果为 off 不是登陆式
login_shell    	off

# 查看当前是否交互式

shell
echo $PS1
# 结果非空则是交互式
shell
echo $-
# 结果包含 i 则是交互式

References:

  • Reference1
  • Reference2
Edited on Views times
\ No newline at end of file +Linux 的 shell 配置原理 - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 环境变量文件的加载顺序

在登录 Linux 系统并启动一个 bash shell 时,默认情况下 bash 会在若干个文件中查找环境变量的设置。这些文件统称为系统环境文件。bash 检查的环境变量文件的顺序情况取决于系统运行的 shell 方式。系统运行 shell 方式一般为 4 种:

是否交互式是否登陆式哪些情况
通过系统用户登录默认运行的 shell
非登录交互式运行 shell
执行脚本运行非交互式 shell

shell-config

# bash 命令启动 shell

命令 bash 启动 shell 时,可以通过选项改变其行为

shell
bash [长选项] [选项] [脚本]
选项含义
-ishell 在交互模式下运行
-lshell 作为登陆 shell
-r启动受限 shell
--选项结束标志,后面的内容当做文件名或参数,即使他们以 - 开头
--login-l
--noprofile阻止读取初始化文件 /etc/profile~/.bash_profile , ~/.bash_login , ~/profile
--norc在交互式 shell,阻止读取初始化文件 ~/.bashrc 。如果 shell 以 sh 调用的话,该选项默认是打开的。
--recfile file在交互式 shell,指定初始化文件是 file 而不是 ~/.bashrc
--version版本信息

# 检查当前 shell 状态

# 查看当前是否登录式

shell
shopt login_shell
# 结果为 on 则是登陆式
login_shell    	on
# 结果为 off 不是登陆式
login_shell    	off

# 查看当前是否交互式

shell
echo $PS1
# 结果非空则是交互式
shell
echo $-
# 结果包含 i 则是交互式

References:

  • Reference1
  • Reference2
Edited on Views times
\ No newline at end of file diff --git a/cs/devops/clone-vm/index.html b/cs/devops/clone-vm/index.html index 68e1a1ed..fdd254a1 100644 --- a/cs/devops/clone-vm/index.html +++ b/cs/devops/clone-vm/index.html @@ -1 +1 @@ -VM 迁移与克隆 - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# VMware 或 VirtualBox 导出虚拟机

导出之前可以参考以下几个因素,避免后续麻烦:

  • 虚拟机由 VMware 或 VirtualBox 导出,磁盘镜像有可能是 vmdk 格式,如果从 KVM 管理器导出,可能是 qcow2 格式。最流行的虚拟机导出格式是 OVF 标准,但实际上由于 OVF 标准本身不完善,以及虚拟机管理器导出的众多非标准扩展信息,跨管理器使用 OVF 往往受很多限制。
  • 除了格式不兼容之外,如果虚拟机管理器之间的虚拟硬件设备差别太大,也可能导致虚拟机镜像导入失败。特别是 Windows 虚拟机,对于硬件变化特别敏感。为解决这一问题,可以在导出 Windows 虚拟机之前安装 MergeIDE.zip,并在导入后启动前将虚拟磁盘改为 IDE 类型。
  • 最后还需要考虑半虚拟化驱动因素。半虚拟化驱动能够改善虚拟硬件性能,但往往针对特定虚拟机管理器。GNU/Linux 和其他开源 Unix 类操作系统默认已经安装所有必要的半虚拟化驱动,可以在导入虚拟机后直接改用半虚拟化驱动。对于 Windows 虚拟机,还需要自行安装 Windows 版本的半虚拟化驱动软件。

GNU/Linux 和其他开源 Unix 虚拟机通常可以直接导入。但由于以上提到的因素,不能保证所有 Windows 虚拟机均能够顺利导入成功。

以 VMware 导出举例,点击: 文件 / File -> 导出为OVF / Export as OVF

vmware

# 导入虚拟机到 PVE

执行以下命令可以创建新虚拟机,虚拟机的 CPU、内存和名称沿用 OVF 配置文件中的设置,磁盘镜像将导入存储。网络配置可以手工完成。

shell
qm importovf 999 myvm.ovf local-lvm

其中 999 是虚拟机 id , local-lvm 表示磁盘镜像将导入该节点的 local-lvm 存储

# 克隆 PVE 虚拟机

# Full Clone

可以从 VM 或者 VM 模版 Full Clone 一个 VM ,这样会完全复制一台虚拟机,占用和原来虚拟机一样的磁盘,克隆需要的时间久一点。

# Linked Clone

首先需要将一台已有的 VM 关机后转化为模版:

convert-to-template

此后该虚拟机无法再被启动,被锁定作为一个共享的模版。希望从该模版创建虚拟机,则右击该 VM 模版选择克隆 / Clone ,此时可以选择 Linked Clone,这样得到的虚拟机会和该模版虚拟机共享磁盘,创建速度更快,而且占用磁盘更少。

Edited on Views times
\ No newline at end of file +VM 迁移与克隆 - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# VMware 或 VirtualBox 导出虚拟机

导出之前可以参考以下几个因素,避免后续麻烦:

  • 虚拟机由 VMware 或 VirtualBox 导出,磁盘镜像有可能是 vmdk 格式,如果从 KVM 管理器导出,可能是 qcow2 格式。最流行的虚拟机导出格式是 OVF 标准,但实际上由于 OVF 标准本身不完善,以及虚拟机管理器导出的众多非标准扩展信息,跨管理器使用 OVF 往往受很多限制。
  • 除了格式不兼容之外,如果虚拟机管理器之间的虚拟硬件设备差别太大,也可能导致虚拟机镜像导入失败。特别是 Windows 虚拟机,对于硬件变化特别敏感。为解决这一问题,可以在导出 Windows 虚拟机之前安装 MergeIDE.zip,并在导入后启动前将虚拟磁盘改为 IDE 类型。
  • 最后还需要考虑半虚拟化驱动因素。半虚拟化驱动能够改善虚拟硬件性能,但往往针对特定虚拟机管理器。GNU/Linux 和其他开源 Unix 类操作系统默认已经安装所有必要的半虚拟化驱动,可以在导入虚拟机后直接改用半虚拟化驱动。对于 Windows 虚拟机,还需要自行安装 Windows 版本的半虚拟化驱动软件。

GNU/Linux 和其他开源 Unix 虚拟机通常可以直接导入。但由于以上提到的因素,不能保证所有 Windows 虚拟机均能够顺利导入成功。

以 VMware 导出举例,点击: 文件 / File -> 导出为OVF / Export as OVF

vmware

# 导入虚拟机到 PVE

执行以下命令可以创建新虚拟机,虚拟机的 CPU、内存和名称沿用 OVF 配置文件中的设置,磁盘镜像将导入存储。网络配置可以手工完成。

shell
qm importovf 999 myvm.ovf local-lvm

其中 999 是虚拟机 id , local-lvm 表示磁盘镜像将导入该节点的 local-lvm 存储

# 克隆 PVE 虚拟机

# Full Clone

可以从 VM 或者 VM 模版 Full Clone 一个 VM ,这样会完全复制一台虚拟机,占用和原来虚拟机一样的磁盘,克隆需要的时间久一点。

# Linked Clone

首先需要将一台已有的 VM 关机后转化为模版:

convert-to-template

此后该虚拟机无法再被启动,被锁定作为一个共享的模版。希望从该模版创建虚拟机,则右击该 VM 模版选择克隆 / Clone ,此时可以选择 Linked Clone,这样得到的虚拟机会和该模版虚拟机共享磁盘,创建速度更快,而且占用磁盘更少。

Edited on Views times
\ No newline at end of file diff --git a/cs/devops/haproxy-ssh/index.html b/cs/devops/haproxy-ssh/index.html index 48c9a895..3cedca92 100644 --- a/cs/devops/haproxy-ssh/index.html +++ b/cs/devops/haproxy-ssh/index.html @@ -1 +1 @@ -HAProxy 代理 SSH - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 宿主与虚拟机之间的网络问题

我们的两台宿主居然都 ping 不到虚拟机,导致后续 haproxy 代理转发后出现所有虚拟机 server 都是 down 状态

原因应该是宿主只有一个校园网网段的 ip,但是虚拟机只有实验室局域网网段的 ip

这个问题需要配置宿主节点的网络,可以在 PVE 控制面板修改 网络 / Network:

network

实际上就是编辑该节点的: /etc/network/interfaces 配置文件

应该需要配置虚拟网卡才能解决,但是我们的一台服务器有两张网卡(图中 eno1 eno2) 所以我们最后的解决方案给服务器插了多一条网线,配置该网卡 ip 为实验室局域网的 ip,从而该服务器连接上了虚拟机

# 安装 HAProxy

shell
apt isntall haproxy

或者源码编译安装

可快速上手学习、搜索问题的官网资料

# 配置 haproxy.cfg

编辑 /etc/haproxy/haproxy.cfg 配置文件,所需要的基本指令如下:

检查并重载配置文件

shell
haproxy -f /etc/haproxy/haproxy.cfg

仅检查:

shell
haproxy -f /etc/haproxy/haproxy.cfg -c

⚠️ 注意,文件最后需要有换行符结尾,否则会有报错:

shell
Missing LF on last line, file might have been truncated at position xx

重启 haproxy 服务

shell
service haproxy restart
# or
systemctl restart haproxy

配置由 5 部分组成,当然并不都是必须的: globaldefaultsfrontendbackendlisten (可能还有更多)

我们的 SSH 代理转发需求只需配置 frontendbackend 即可,我们的配置如下:

raw
frontend fe_ssh
   bind *:2222 ssl crt /etc/pve/nodes/proxmox2/pveproxy-ssl.pem
   mode tcp
   log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq dst:%[var(sess.dst)] "
   tcp-request content set-var(sess.dst) ssl_fc_sni
   use_backend %[ssl_fc_sni]
backend server1
   mode tcp
   server s1 192.168.134.247:22 check
backend server2
   mode tcp
   server s2 192.168.134.30:22 check
backend server3
   mode tcp
   server s2 172.18.198.204:22 check
  • 其中 frontend 后面的 fe_sshbackend 后面的 server1 等都是自定义的名字;
  • 端口 bind *:2222 所指定的端口也是自定义的;跟在其后面的 ssl crt /etc/pve/nodes/proxmox2/pveproxy-ssl.pem 是指定 ssl 证书,该路径是 PVE 的通过上传的或用其提供插件自动申请的 ssl 证书所在路径。
    • haproxy 似乎只认定一个 xxx.pem 证书文件的对应 key 文件是 xxx.pem.key ,所以 key 文件需要以这个形式命名放在 pem 相同路径上

# SSH 连接

shell
ssh -o ProxyCommand="openssl s_client -quiet -connect [服务器ip]:2222 -servername [servername]" -l [登陆虚拟机用的用户名] [虚拟机主机名]

其中:

  • [服务器 ip] 即一般使用 ssh 登陆时的 @ 后面的 ip,或者主机名

  • [登陆虚拟机用的用户名] 即一般使用 ssh 登陆时的 @ 前面的用户名

  • [servername] 是 backend 指定的对应服务器名字,例如我们配置文件中的 server1 、 server2 、 server3

  • [虚拟机主机名] 可以自定义,但是最后和虚拟机主机名一致,否则以后连接会出现这样的报错:

    shell
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    @    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
    Someone could be eavesdropping on you right now (man-in-the-middle attack)!
    It is also possible that a host key has just been changed.
    The fingerprint for the ED25519 key sent by the remote host is
    SHA256:fDBSRwFB552ZiUUmekpCWrbuSdh186h4c12JdrAQxTM.
    Please contact your system administrator.
    Add correct host key in /Users/xxx/.ssh/known_hosts to get rid of this message.
    Offending ED25519 key in /Users/minamoto/.ssh/known_hosts:xx
    Host key for xxx has changed and you have requested strict checking.
    Host key verification failed.

    即连接不同的虚拟机总是需要指定不同的主机名才不会产生冲突

# Dashboard

raw
frontend stats
    mode http
    bind *:9000
    stats enable
    stats uri /stats
    stats refresh 10s
    # stats uri /stats # choose a subpath for the dashboard
    # stats admin if localhost   # enable to restrict to localhost
    # stats admin if 10.0.0.0/8  # enable to restrict to 10.x.x.x network sources
    # stats admin auth <username:password> # enable to setup basic http auth

目前发现每次修改配置文件后 dashboard 没有同步更新,除非修改 dashboard 配置的端口号,在新端口号才有同步更新了的数据

配置好后可以打开 http://node_ip:9000/stats

若想要 https 访问,则需要在 bind *:9000 后面加上 ssl 证书文件路径,否则只能 http 访问

raw
bind *:9000 ssl crt /etc/pve/nodes/proxmox2/pveproxy-ssl.pem

最终效果(图中用的是 9002 端口):

dashboard

  • reference1
  • reference2
Edited on Views times
\ No newline at end of file +HAProxy 代理 SSH - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 宿主与虚拟机之间的网络问题

我们的两台宿主居然都 ping 不到虚拟机,导致后续 haproxy 代理转发后出现所有虚拟机 server 都是 down 状态

原因应该是宿主只有一个校园网网段的 ip,但是虚拟机只有实验室局域网网段的 ip

这个问题需要配置宿主节点的网络,可以在 PVE 控制面板修改 网络 / Network:

network

实际上就是编辑该节点的: /etc/network/interfaces 配置文件

应该需要配置虚拟网卡才能解决,但是我们的一台服务器有两张网卡(图中 eno1 eno2) 所以我们最后的解决方案给服务器插了多一条网线,配置该网卡 ip 为实验室局域网的 ip,从而该服务器连接上了虚拟机

# 安装 HAProxy

shell
apt isntall haproxy

或者源码编译安装

可快速上手学习、搜索问题的官网资料

# 配置 haproxy.cfg

编辑 /etc/haproxy/haproxy.cfg 配置文件,所需要的基本指令如下:

检查并重载配置文件

shell
haproxy -f /etc/haproxy/haproxy.cfg

仅检查:

shell
haproxy -f /etc/haproxy/haproxy.cfg -c

⚠️ 注意,文件最后需要有换行符结尾,否则会有报错:

shell
Missing LF on last line, file might have been truncated at position xx

重启 haproxy 服务

shell
service haproxy restart
# or
systemctl restart haproxy

配置由 5 部分组成,当然并不都是必须的: globaldefaultsfrontendbackendlisten (可能还有更多)

我们的 SSH 代理转发需求只需配置 frontendbackend 即可,我们的配置如下:

raw
frontend fe_ssh
   bind *:2222 ssl crt /etc/pve/nodes/proxmox2/pveproxy-ssl.pem
   mode tcp
   log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq dst:%[var(sess.dst)] "
   tcp-request content set-var(sess.dst) ssl_fc_sni
   use_backend %[ssl_fc_sni]
backend server1
   mode tcp
   server s1 192.168.134.247:22 check
backend server2
   mode tcp
   server s2 192.168.134.30:22 check
backend server3
   mode tcp
   server s2 172.18.198.204:22 check
  • 其中 frontend 后面的 fe_sshbackend 后面的 server1 等都是自定义的名字;
  • 端口 bind *:2222 所指定的端口也是自定义的;跟在其后面的 ssl crt /etc/pve/nodes/proxmox2/pveproxy-ssl.pem 是指定 ssl 证书,该路径是 PVE 的通过上传的或用其提供插件自动申请的 ssl 证书所在路径。
    • haproxy 似乎只认定一个 xxx.pem 证书文件的对应 key 文件是 xxx.pem.key ,所以 key 文件需要以这个形式命名放在 pem 相同路径上

# SSH 连接

shell
ssh -o ProxyCommand="openssl s_client -quiet -connect [服务器ip]:2222 -servername [servername]" -l [登陆虚拟机用的用户名] [虚拟机主机名]

其中:

  • [服务器 ip] 即一般使用 ssh 登陆时的 @ 后面的 ip,或者主机名

  • [登陆虚拟机用的用户名] 即一般使用 ssh 登陆时的 @ 前面的用户名

  • [servername] 是 backend 指定的对应服务器名字,例如我们配置文件中的 server1 、 server2 、 server3

  • [虚拟机主机名] 可以自定义,但是最后和虚拟机主机名一致,否则以后连接会出现这样的报错:

    shell
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    @    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
    Someone could be eavesdropping on you right now (man-in-the-middle attack)!
    It is also possible that a host key has just been changed.
    The fingerprint for the ED25519 key sent by the remote host is
    SHA256:fDBSRwFB552ZiUUmekpCWrbuSdh186h4c12JdrAQxTM.
    Please contact your system administrator.
    Add correct host key in /Users/xxx/.ssh/known_hosts to get rid of this message.
    Offending ED25519 key in /Users/minamoto/.ssh/known_hosts:xx
    Host key for xxx has changed and you have requested strict checking.
    Host key verification failed.

    即连接不同的虚拟机总是需要指定不同的主机名才不会产生冲突

# Dashboard

raw
frontend stats
    mode http
    bind *:9000
    stats enable
    stats uri /stats
    stats refresh 10s
    # stats uri /stats # choose a subpath for the dashboard
    # stats admin if localhost   # enable to restrict to localhost
    # stats admin if 10.0.0.0/8  # enable to restrict to 10.x.x.x network sources
    # stats admin auth <username:password> # enable to setup basic http auth

目前发现每次修改配置文件后 dashboard 没有同步更新,除非修改 dashboard 配置的端口号,在新端口号才有同步更新了的数据

配置好后可以打开 http://node_ip:9000/stats

若想要 https 访问,则需要在 bind *:9000 后面加上 ssl 证书文件路径,否则只能 http 访问

raw
bind *:9000 ssl crt /etc/pve/nodes/proxmox2/pveproxy-ssl.pem

最终效果(图中用的是 9002 端口):

dashboard

  • reference1
  • reference2
Edited on Views times
\ No newline at end of file diff --git a/cs/devops/nat-traversal/index.html b/cs/devops/nat-traversal/index.html index 8d06d738..0de77fd3 100644 --- a/cs/devops/nat-traversal/index.html +++ b/cs/devops/nat-traversal/index.html @@ -1 +1 @@ -内网穿透 - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# frp

# Tailscale

# Ngrok

# 绑定自己的域名(要充钱)

Ngrok uses the Host header sent by the browser to determine how to redirect your traffic you will need to "reserve" the domain you want to use in the Ngrok dashboard. Note that doing this requires a paid Ngrok plan. After reserving your domain you will be given a CNAME record to point it to.

生成 reserverd 域名,获取 cname-target ,然后将域名 DNS 解析添加 CNAME 记录目标到 cname-target

# Tunnelmole

支持类似 frp 自己搭建内网穿透,同时官方也提供类似 Ngrok 的服务

\ No newline at end of file +内网穿透 - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# frp

# Tailscale

# Ngrok

# 绑定自己的域名(要充钱)

Ngrok uses the Host header sent by the browser to determine how to redirect your traffic you will need to "reserve" the domain you want to use in the Ngrok dashboard. Note that doing this requires a paid Ngrok plan. After reserving your domain you will be given a CNAME record to point it to.

生成 reserverd 域名,获取 cname-target ,然后将域名 DNS 解析添加 CNAME 记录目标到 cname-target

# Tunnelmole

支持类似 frp 自己搭建内网穿透,同时官方也提供类似 Ngrok 的服务

\ No newline at end of file diff --git a/cs/devops/nginx/index.html b/cs/devops/nginx/index.html index e3d31c23..be63ac7a 100644 --- a/cs/devops/nginx/index.html +++ b/cs/devops/nginx/index.html @@ -1 +1 @@ -Nginx - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

查看 niginx 进程:

ps -ef|grep nginx

进程:

  • master
  • worker

查看 nginx 的:版本、安装目录 (--prefix)、编译参数

nginx -V

重新加载配置文件:

shell
nginx -s reload

查看配置文件 nginx.config 所在目录,验证默认配置文件,常用于检查配置文件有没有写对:

nginx -t

常见目录有:

/etc/nginx/conf
/usr/local/etc/nginx
/opt/homebrew/etc/nginx

停止 nginx 服务:

nginx -s quit		 	//优雅停止
nginx -s stop			//立即停止
nginx -s reload		//重载配置文件
nginx -s reopen		//重新打开日志文件

配置文件 nginx.config

  • 全局块
  • events 块
  • http 块
    • include mime.types
    • server 块 // 代表一个虚拟主机,可以放在 server 目录下的 local.config
      • location 块
    • include servers/*

使用 openssl 生成证书

  • 生成私钥文件(private key)

    openssl genrsa -out private.key 2048
  • 根据私钥生成证书签名请求文件(Certificate Signing Request, 简称 CSR 文件)

    openssl req-new -key private.key -out cert.cr
  • 使用私钥对证书申请进行签名从而生成证书文件(pem 文件)

    openssl x509 -req-in cert.cr -out cacert.pem -signkey private.key
Edited on Views times
\ No newline at end of file +Nginx - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

查看 niginx 进程:

ps -ef|grep nginx

进程:

  • master
  • worker

查看 nginx 的:版本、安装目录 (--prefix)、编译参数

nginx -V

重新加载配置文件:

shell
nginx -s reload

查看配置文件 nginx.config 所在目录,验证默认配置文件,常用于检查配置文件有没有写对:

nginx -t

常见目录有:

/etc/nginx/conf
/usr/local/etc/nginx
/opt/homebrew/etc/nginx

停止 nginx 服务:

nginx -s quit		 	//优雅停止
nginx -s stop			//立即停止
nginx -s reload		//重载配置文件
nginx -s reopen		//重新打开日志文件

配置文件 nginx.config

  • 全局块
  • events 块
  • http 块
    • include mime.types
    • server 块 // 代表一个虚拟主机,可以放在 server 目录下的 local.config
      • location 块
    • include servers/*

使用 openssl 生成证书

  • 生成私钥文件(private key)

    openssl genrsa -out private.key 2048
  • 根据私钥生成证书签名请求文件(Certificate Signing Request, 简称 CSR 文件)

    openssl req-new -key private.key -out cert.cr
  • 使用私钥对证书申请进行签名从而生成证书文件(pem 文件)

    openssl x509 -req-in cert.cr -out cacert.pem -signkey private.key
Edited on Views times
\ No newline at end of file diff --git a/cs/devops/overleaf/index.html b/cs/devops/overleaf/index.html index c1c530f2..ab955ffd 100644 --- a/cs/devops/overleaf/index.html +++ b/cs/devops/overleaf/index.html @@ -1 +1 @@ -OverLeaf - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

部署了一个 overleaf 玩,目的需求是做一个共享文档,作为腾讯文档、知识库的替代品

注册管理员账号的时候,出现了报错:

alert
Session error. Please check you have cookies enabled. If the problem persists, try clearing your cache and cookies.

查阅这个 issue 后,得到了解决方案,将 config/variables.env 这里注释掉:

variables.env
# SHARELATEX_BEHIND_PROXY=true
# SHARELATEX_SECURE_COOKIE=true

无论这里是 true 还是 false 都需要注释掉

每次 bin/up 都会这样的结果:

shell
lsy@lsy:~/data/overleaf-toolkit$ bin/up
Initiating Mongo replica set...
WARN[0000] /home/lsy/data/overleaf-toolkit/lib/docker-compose.base.yml: `version` is obsolete
WARN[0000] /home/lsy/data/overleaf-toolkit/lib/docker-compose.vars.yml: `version` is obsolete
WARN[0000] /home/lsy/data/overleaf-toolkit/lib/docker-compose.redis.yml: `version` is obsolete
WARN[0000] /home/lsy/data/overleaf-toolkit/lib/docker-compose.mongo.yml: `version` is obsolete
WARN[0000] /home/lsy/data/overleaf-toolkit/lib/docker-compose.nginx.yml: `version` is obsolete
[+] Running 1/0
 ✔ Container mongo  Running                                                                                                               0.0s
WARN[0000] /home/lsy/data/overleaf-toolkit/lib/docker-compose.base.yml: `version` is obsolete
WARN[0000] /home/lsy/data/overleaf-toolkit/lib/docker-compose.vars.yml: `version` is obsolete
WARN[0000] /home/lsy/data/overleaf-toolkit/lib/docker-compose.redis.yml: `version` is obsolete
WARN[0000] /home/lsy/data/overleaf-toolkit/lib/docker-compose.mongo.yml: `version` is obsolete
WARN[0000] /home/lsy/data/overleaf-toolkit/lib/docker-compose.nginx.yml: `version` is obsolete
[+] Running 4/4
 ✔ Container mongo       Running                                                                                                          0.0s
 ✔ Container redis       Running                                                                                                          0.0s
 ✔ Container sharelatex  Recreated                                                                                                       60.5s
 ✔ Container nginx       Recreated                                                                                                        0.1s
Attaching to mongo, nginx, redis, sharelatex
sharelatex  | *** Running /etc/my_init.d/000_check_for_old_bind_mounts_5.sh...
sharelatex  | *** Running /etc/my_init.d/000_check_for_old_env_vars_5.sh...
sharelatex  | *** Running /etc/my_init.d/00_regen_ssh_host_keys.sh...
sharelatex  | *** Running /etc/my_init.d/100_generate_secrets.sh...
sharelatex  | generating random secrets
sharelatex  | *** Running /etc/my_init.d/100_make_overleaf_data_dirs.sh...
......

显然这个项目使用的是一个需要 nohup 的脚本。

使用这样的脚本模版方便管理:

shell
.
├── running.log
├── running.pid
├── start.sh
└── stop.sh
start.sh :
run=bin/up # 启动脚本的指令
DIR="$( cd "$( dirname "$0"  )" && pwd  )"
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$DIR/lib
nohup $DIR/$run > $DIR/running.log 2>&1& echo $! > $DIR/running.pid
stop.sh :
kill `cat running.pid`

使用 logrotate 定期清理日志。在 /etc/logrotate.conf 配置文件中增加:

/etc/logrotate.conf
/home/lsy/data/overleaf-toolkit/running.log {
        size 1k
        create 700 lsy lsy
        rotate 4
}

当然这里 /home/lsy/data/overleaf-toolkit/ 换成自己对应的 running.log 存放的目录

重新加载 logrotate 的配置文件:

shell
sudo logrotate /etc/logrotate.conf

后续出现的问题

没办法使用 markdown 插件,不符合需求,转而寻找支持 typst 、 markdown 的更紧跟时代潮流的方案

Edited on Views times
\ No newline at end of file +OverLeaf - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

部署了一个 overleaf 玩,目的需求是做一个共享文档,作为腾讯文档、知识库的替代品

注册管理员账号的时候,出现了报错:

alert
Session error. Please check you have cookies enabled. If the problem persists, try clearing your cache and cookies.

查阅这个 issue 后,得到了解决方案,将 config/variables.env 这里注释掉:

variables.env
# SHARELATEX_BEHIND_PROXY=true
# SHARELATEX_SECURE_COOKIE=true

无论这里是 true 还是 false 都需要注释掉

每次 bin/up 都会这样的结果:

shell
lsy@lsy:~/data/overleaf-toolkit$ bin/up
Initiating Mongo replica set...
WARN[0000] /home/lsy/data/overleaf-toolkit/lib/docker-compose.base.yml: `version` is obsolete
WARN[0000] /home/lsy/data/overleaf-toolkit/lib/docker-compose.vars.yml: `version` is obsolete
WARN[0000] /home/lsy/data/overleaf-toolkit/lib/docker-compose.redis.yml: `version` is obsolete
WARN[0000] /home/lsy/data/overleaf-toolkit/lib/docker-compose.mongo.yml: `version` is obsolete
WARN[0000] /home/lsy/data/overleaf-toolkit/lib/docker-compose.nginx.yml: `version` is obsolete
[+] Running 1/0
 ✔ Container mongo  Running                                                                                                               0.0s
WARN[0000] /home/lsy/data/overleaf-toolkit/lib/docker-compose.base.yml: `version` is obsolete
WARN[0000] /home/lsy/data/overleaf-toolkit/lib/docker-compose.vars.yml: `version` is obsolete
WARN[0000] /home/lsy/data/overleaf-toolkit/lib/docker-compose.redis.yml: `version` is obsolete
WARN[0000] /home/lsy/data/overleaf-toolkit/lib/docker-compose.mongo.yml: `version` is obsolete
WARN[0000] /home/lsy/data/overleaf-toolkit/lib/docker-compose.nginx.yml: `version` is obsolete
[+] Running 4/4
 ✔ Container mongo       Running                                                                                                          0.0s
 ✔ Container redis       Running                                                                                                          0.0s
 ✔ Container sharelatex  Recreated                                                                                                       60.5s
 ✔ Container nginx       Recreated                                                                                                        0.1s
Attaching to mongo, nginx, redis, sharelatex
sharelatex  | *** Running /etc/my_init.d/000_check_for_old_bind_mounts_5.sh...
sharelatex  | *** Running /etc/my_init.d/000_check_for_old_env_vars_5.sh...
sharelatex  | *** Running /etc/my_init.d/00_regen_ssh_host_keys.sh...
sharelatex  | *** Running /etc/my_init.d/100_generate_secrets.sh...
sharelatex  | generating random secrets
sharelatex  | *** Running /etc/my_init.d/100_make_overleaf_data_dirs.sh...
......

显然这个项目使用的是一个需要 nohup 的脚本。

使用这样的脚本模版方便管理:

shell
.
├── running.log
├── running.pid
├── start.sh
└── stop.sh
start.sh :
run=bin/up # 启动脚本的指令
DIR="$( cd "$( dirname "$0"  )" && pwd  )"
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$DIR/lib
nohup $DIR/$run > $DIR/running.log 2>&1& echo $! > $DIR/running.pid
stop.sh :
kill `cat running.pid`

使用 logrotate 定期清理日志。在 /etc/logrotate.conf 配置文件中增加:

/etc/logrotate.conf
/home/lsy/data/overleaf-toolkit/running.log {
        size 1k
        create 700 lsy lsy
        rotate 4
}

当然这里 /home/lsy/data/overleaf-toolkit/ 换成自己对应的 running.log 存放的目录

重新加载 logrotate 的配置文件:

shell
sudo logrotate /etc/logrotate.conf

后续出现的问题

没办法使用 markdown 插件,不符合需求,转而寻找支持 typst 、 markdown 的更紧跟时代潮流的方案

Edited on Views times
\ No newline at end of file diff --git a/cs/devops/pve-passthrough-gpu/index.html b/cs/devops/pve-passthrough-gpu/index.html index ef459b94..e38a54eb 100644 --- a/cs/devops/pve-passthrough-gpu/index.html +++ b/cs/devops/pve-passthrough-gpu/index.html @@ -1 +1 @@ -PVE 直通显卡 - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

PVE 版本:8.1.4 ,显卡:NVIDIA GTX 745

# 宿主机配置

# IOMMU

shell
nano /etc/default/grub

GRUB_CMDLINE_LINUX_DEFAULT="..." 中的内容修改为如下:

shell
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt video=efifb:off"

准确来说是在 "..." 原来的内容后面增加这些内容,其中:

  • quiet 一般是原来就有的
  • intel_iommu=oniommu=pt 是必须的
  • video=efifb:off 如果你是给 Windows VM 直通显卡串流玩游戏的话是需要的

然后更新配置文件:

shell
update-grub

检查 IOMMU 是否启动:

shell
dmesg | grep -e DMAR -e IOMMU

看到有 DMAR 或 IOMMU 输出就行,例如我们就只看到了 DMAR 的输出。

# 配置显卡

找到自己的显卡的相关信息:

shell
lspci -knn | grep VGA

我们需要如下内容:

shell
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation GM107 [GeForce GTX 745] [10de:1382] (rev a2)
        Subsystem: NVIDIA Corporation GM107 [GeForce GTX 745] [10de:1065] # these ids
        Kernel modules: nvidiafb, nouveau # these modules
  • [10de:1065]<vendor id>:<device id> 形式的厂商 id 和设备 id
  • nvidiafbnouveau 是我们的显卡所使用的驱动模块

将厂商 id 和设备 id 组合添加到 vfio 配置文件中:

shell
nano /etc/modprobe.d/vfio.conf

增加如下内容:

shell
options vfio-pci ids=10de:1382 disable_vga=1

如果你有多张显卡需要直通,那么不同显卡对应的 <vendor id>:<device id> 就以逗号分隔加在 ids= 后面即可,例如:

shell
options vfio-pci ids=1145:1400,1919:1800 disable_vga=1

屏蔽显卡驱动模块:

shell
echo "blacklist <some-module>" >> /etc/modprobe.d/blacklist.conf

对每一个模块都需要加单独一行,例如我们是 nvidiafbnouveau ,则需要:

shell
echo "blacklist nvidiafb" >> /etc/modprobe.d/blacklist.conf
echo "blacklist nouveau" >> /etc/modprobe.d/blacklist.conf

有一些教程说是修改配置文件 /etc/modprobe.d/pve-blacklist.conf ,但是官方文档(目前)说的是 /etc/modprobe.d/blacklist.conf ,两者不知道有没有区别

# vfio

shell
nano /etc/modules

增加如下几行:

shell
vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd #not needed if on kernel 6.2 or newer

最后执行如下指令,并且重启:

shell
update-initramfs -u -k all

最后使用如下指令检查配置是否成功:

shell
lspci -k

预期是得到对应的显卡部分有如下输出结果:

shell
01:00.0 VGA compatible controller: NVIDIA Corporation GP108 [GeForce GT 1030] (rev a1)
        Subsystem: Micro-Star International Co., Ltd. [MSI] GP108 [GeForce GT 1030]
        Kernel driver in use: <some-module> # 预期是 vfio
        Kernel modules: <some-module>

# 问题

执行最后一句指令时,我们却遇到了这个输出:

shell
...
Re-executing '/etc/kernel/postinst.d/zz-proxmox-boot' in new private mount namespace..
No /etc/kernel/proxmox-boot-uuids found, skipping ESP sync.

然后 lspci -k 检查也没有预期的输出,虚拟机添加显卡设备后无法开机。

我尝试了官方文档中 Host Device Passthrough 部分的方法:

For both methods you need to update the initramfs again and reboot after that.

Should this not work, you might need to set a soft dependency to load the gpu modules before loading vfio-pci. This can be done with the softdep flag, see also the manpages on modprobe.d for more information.

For example, if you are using drivers named <some-module> :

shell
# echo "softdep <some-module> pre: vfio-pci" >> /etc/modprobe.d/<some-module>.conf

但仍然没有效果。

所幸,似乎有不少人也遇到了这个问题,我找到了这个帖子,似乎说是因为没有同步连接 ESP 导致的,接下来我按照里面一个解决方案走:

然后我先尝试了重新挂载 /boot/efi ,首先 lsblk -o +FSTYPE 查看 /boot/efi 挂载的磁盘分区,例如我这里是 sda2 ,然后重新挂载一下:

shell
umount /boot/efi
proxmox-boot-tool init /dev/sda2

然后先前类似 No /etc/kernel/proxmox-boot-uuids found, skipping ESP sync. 的输出就没有了,最后成功了。

# VM 配置

选中 VM ,在 == 硬件(Hardware)== 部分中,== 机型(Machine)== 应该(尽量)选择 q35 类型,如果不是的话可以在关机状态下修改。

然后还是在硬件(Hardware)部分,点击添加(add),选择 PCI 设备,找到自己的显卡添加设备。

或者 CLI 版本操作:

shell
qm set VMID -hostpci0 00:02.0
# or add these to vm config file:
# hostpci0: 00:02.0

启动虚拟机,一切无误的话就能够正常启动,然后在虚拟机中就可以当作真实物理机插着显卡进一步安装驱动操作啦

\ No newline at end of file +PVE 直通显卡 - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

PVE 版本:8.1.4 ,显卡:NVIDIA GTX 745

# 宿主机配置

# IOMMU

shell
nano /etc/default/grub

GRUB_CMDLINE_LINUX_DEFAULT="..." 中的内容修改为如下:

shell
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt video=efifb:off"

准确来说是在 "..." 原来的内容后面增加这些内容,其中:

  • quiet 一般是原来就有的
  • intel_iommu=oniommu=pt 是必须的
  • video=efifb:off 如果你是给 Windows VM 直通显卡串流玩游戏的话是需要的

然后更新配置文件:

shell
update-grub

检查 IOMMU 是否启动:

shell
dmesg | grep -e DMAR -e IOMMU

看到有 DMAR 或 IOMMU 输出就行,例如我们就只看到了 DMAR 的输出。

# 配置显卡

找到自己的显卡的相关信息:

shell
lspci -knn | grep VGA

我们需要如下内容:

shell
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation GM107 [GeForce GTX 745] [10de:1382] (rev a2)
        Subsystem: NVIDIA Corporation GM107 [GeForce GTX 745] [10de:1065] # these ids
        Kernel modules: nvidiafb, nouveau # these modules
  • [10de:1065]<vendor id>:<device id> 形式的厂商 id 和设备 id
  • nvidiafbnouveau 是我们的显卡所使用的驱动模块

将厂商 id 和设备 id 组合添加到 vfio 配置文件中:

shell
nano /etc/modprobe.d/vfio.conf

增加如下内容:

shell
options vfio-pci ids=10de:1382 disable_vga=1

如果你有多张显卡需要直通,那么不同显卡对应的 <vendor id>:<device id> 就以逗号分隔加在 ids= 后面即可,例如:

shell
options vfio-pci ids=1145:1400,1919:1800 disable_vga=1

屏蔽显卡驱动模块:

shell
echo "blacklist <some-module>" >> /etc/modprobe.d/blacklist.conf

对每一个模块都需要加单独一行,例如我们是 nvidiafbnouveau ,则需要:

shell
echo "blacklist nvidiafb" >> /etc/modprobe.d/blacklist.conf
echo "blacklist nouveau" >> /etc/modprobe.d/blacklist.conf

有一些教程说是修改配置文件 /etc/modprobe.d/pve-blacklist.conf ,但是官方文档(目前)说的是 /etc/modprobe.d/blacklist.conf ,两者不知道有没有区别

# vfio

shell
nano /etc/modules

增加如下几行:

shell
vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd #not needed if on kernel 6.2 or newer

最后执行如下指令,并且重启:

shell
update-initramfs -u -k all

最后使用如下指令检查配置是否成功:

shell
lspci -k

预期是得到对应的显卡部分有如下输出结果:

shell
01:00.0 VGA compatible controller: NVIDIA Corporation GP108 [GeForce GT 1030] (rev a1)
        Subsystem: Micro-Star International Co., Ltd. [MSI] GP108 [GeForce GT 1030]
        Kernel driver in use: <some-module> # 预期是 vfio
        Kernel modules: <some-module>

# 问题

执行最后一句指令时,我们却遇到了这个输出:

shell
...
Re-executing '/etc/kernel/postinst.d/zz-proxmox-boot' in new private mount namespace..
No /etc/kernel/proxmox-boot-uuids found, skipping ESP sync.

然后 lspci -k 检查也没有预期的输出,虚拟机添加显卡设备后无法开机。

我尝试了官方文档中 Host Device Passthrough 部分的方法:

For both methods you need to update the initramfs again and reboot after that.

Should this not work, you might need to set a soft dependency to load the gpu modules before loading vfio-pci. This can be done with the softdep flag, see also the manpages on modprobe.d for more information.

For example, if you are using drivers named <some-module> :

shell
# echo "softdep <some-module> pre: vfio-pci" >> /etc/modprobe.d/<some-module>.conf

但仍然没有效果。

所幸,似乎有不少人也遇到了这个问题,我找到了这个帖子,似乎说是因为没有同步连接 ESP 导致的,接下来我按照里面一个解决方案走:

然后我先尝试了重新挂载 /boot/efi ,首先 lsblk -o +FSTYPE 查看 /boot/efi 挂载的磁盘分区,例如我这里是 sda2 ,然后重新挂载一下:

shell
umount /boot/efi
proxmox-boot-tool init /dev/sda2

然后先前类似 No /etc/kernel/proxmox-boot-uuids found, skipping ESP sync. 的输出就没有了,最后成功了。

# VM 配置

选中 VM ,在 == 硬件(Hardware)== 部分中,== 机型(Machine)== 应该(尽量)选择 q35 类型,如果不是的话可以在关机状态下修改。

然后还是在硬件(Hardware)部分,点击添加(add),选择 PCI 设备,找到自己的显卡添加设备。

或者 CLI 版本操作:

shell
qm set VMID -hostpci0 00:02.0
# or add these to vm config file:
# hostpci0: 00:02.0

启动虚拟机,一切无误的话就能够正常启动,然后在虚拟机中就可以当作真实物理机插着显卡进一步安装驱动操作啦

\ No newline at end of file diff --git a/cs/devops/pve-switch-sysdisk/index.html b/cs/devops/pve-switch-sysdisk/index.html index 2e1b6af9..15c586b3 100644 --- a/cs/devops/pve-switch-sysdisk/index.html +++ b/cs/devops/pve-switch-sysdisk/index.html @@ -1 +1 @@ -PVE 更换系统盘时的一个问题 - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

考完期末考这天修了一晚上 PVE 上的虚拟机启动不了的问题。起因是更换了系统盘,将原来的机械硬盘换成了一个 SSD,重装了 PVE,发现虚拟机无法开机。这期间查询了大量论坛,尝试了各种各样的方法,最后终于以非常简单的方式解决,决定写一写记录一下,避免以后再遇到,因为这个问题单纯看 PVE 的报错竟然是完全和问题原因不沾边的!

更换系统盘前,将虚拟机 vm1 迁移到了另一个节点上,更换系统盘重装系统后,将 vm1 迁移回了这台物理机上,启动虚拟机,得到了如下报错:

shell
TASK ERROR: KVM virtualisation configured, but not available. Either disable in VM configuration or enable in BIOS.

按照报错的指引,进入 BIOS 查看了设置,设置是正确的,有启用虚拟化支持。

然后在网络上查询了大量资料、论坛讨论记录,均无法解决。这个过程尝试了包括:

  • apt upgrade 升级

  • 开新虚拟机

  • 重装系统(PVE)

  • 在虚拟机 Option 中取消 KVM hardware Virtualization 的启用,这样就没有使用 KVM 技术,虚拟机性能是会更差的。但是启动 vm1 发现虚拟机一直重启,对新虚拟机是有如下报错:

    shell
    Error: Unknown device type.
    can't create interface fwln306i0 - command '/sbin/ip link add name fwln306i0 mtu 1500 type veth peer name fwpr306p0 mtu 1500' failed: exit code 2
    kvm: -netdev type=tap,id=net0,ifname=tap306i0,script=/var/lib/qemu-server/pve-bridge,downscript=/var/lib/qemu-server/pve-bridgedown: network script /var/lib/qemu-server/pve-bridge failed with status 512
    TASK ERROR: start failed: QEMU exited with code 1

上述方法都没有解决问题。

真正发现问题原因是我在查看 BIOS 和重装系统后,发现每次开机启动 PVE 都有这样的报错:

PVE开机报错

经过询问大佬,才知道,我们更换系统盘后,由于仍想利用旧的机械硬盘,机械盘仍然插在物理机上。拔掉旧的盘之后问题就解决了。

PVE 采用 LVM,产生了逻辑卷冲突,导致了上图的报错,至于为什么会有什么关于虚拟化的报错,我们就不太清楚了,但是因为这个奇怪的报错我们浪费了两三个小时......

\ No newline at end of file +PVE 更换系统盘时的一个问题 - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

考完期末考这天修了一晚上 PVE 上的虚拟机启动不了的问题。起因是更换了系统盘,将原来的机械硬盘换成了一个 SSD,重装了 PVE,发现虚拟机无法开机。这期间查询了大量论坛,尝试了各种各样的方法,最后终于以非常简单的方式解决,决定写一写记录一下,避免以后再遇到,因为这个问题单纯看 PVE 的报错竟然是完全和问题原因不沾边的!

更换系统盘前,将虚拟机 vm1 迁移到了另一个节点上,更换系统盘重装系统后,将 vm1 迁移回了这台物理机上,启动虚拟机,得到了如下报错:

shell
TASK ERROR: KVM virtualisation configured, but not available. Either disable in VM configuration or enable in BIOS.

按照报错的指引,进入 BIOS 查看了设置,设置是正确的,有启用虚拟化支持。

然后在网络上查询了大量资料、论坛讨论记录,均无法解决。这个过程尝试了包括:

  • apt upgrade 升级

  • 开新虚拟机

  • 重装系统(PVE)

  • 在虚拟机 Option 中取消 KVM hardware Virtualization 的启用,这样就没有使用 KVM 技术,虚拟机性能是会更差的。但是启动 vm1 发现虚拟机一直重启,对新虚拟机是有如下报错:

    shell
    Error: Unknown device type.
    can't create interface fwln306i0 - command '/sbin/ip link add name fwln306i0 mtu 1500 type veth peer name fwpr306p0 mtu 1500' failed: exit code 2
    kvm: -netdev type=tap,id=net0,ifname=tap306i0,script=/var/lib/qemu-server/pve-bridge,downscript=/var/lib/qemu-server/pve-bridgedown: network script /var/lib/qemu-server/pve-bridge failed with status 512
    TASK ERROR: start failed: QEMU exited with code 1

上述方法都没有解决问题。

真正发现问题原因是我在查看 BIOS 和重装系统后,发现每次开机启动 PVE 都有这样的报错:

PVE开机报错

经过询问大佬,才知道,我们更换系统盘后,由于仍想利用旧的机械硬盘,机械盘仍然插在物理机上。拔掉旧的盘之后问题就解决了。

PVE 采用 LVM,产生了逻辑卷冲突,导致了上图的报错,至于为什么会有什么关于虚拟化的报错,我们就不太清楚了,但是因为这个奇怪的报错我们浪费了两三个小时......

\ No newline at end of file diff --git a/cs/devops/pve/index.html b/cs/devops/pve/index.html index 2eaa1adf..c0da7446 100644 --- a/cs/devops/pve/index.html +++ b/cs/devops/pve/index.html @@ -1,2 +1,2 @@ -PVE 搭建小集群 - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 前言

在 Matrix 实验室用电子垃圾搭了一个小集群。

起因是 jygg 拿了一台被淘汰的存储型服务器给 cjl 玩,(据说是以前买来发现性能太差了,于是就把里面的 64T 的硬盘全部拿走了装到别的服务器上了,这台就废弃了),cjl 整了个 500g 的机械硬盘给服务器装上了,同时把不知为啥留在这里的一个台式 PC 给我玩,然后索性就装上了 PVE,在 jygg 的帮助下非常顺利搭了一个两台物理机组成的集群。

# 安装 PVE

官网下载 PVE,这是一个只有 1G 大小左右的基于 debian 的装好了 proxmox 相关软件、服务的镜像,然后用 U 盘给物理机安装。

安装过程可以用 proxmox 提供的图形化安装页面,当然安装好的 debian 本身不会有 GUI。会需要用到键盘,以及鼠标 (除非键盘技巧特别好)。

安装过程有一些需要额外注意:

  • hostname 会设置采取 FQDN 域名,但是实际上 proxmox 只会检查输入的是不是默认的 .invalid 结尾,只需改掉这个即可
    • jygg 说这个域名最好不要填可以被解析到的域名
  • 不需要设置登陆 debian 的用户名,web 控制台登陆用的超级管理员用户名即 root 即可
  • 安装过程设置的 ip 地址后面改起来也比较麻烦(尤其是组建集群时)最好提前确定好
    • jygg 的帮助下我们安装时就给 2 个物理机设置了校园网内可供访问的 ip(Matrix 从校园网络中心租的网段)
  • DNS Server 在这个界面里只能设置一个,可以安装完后再加
  • 安装结束,及时拔掉 U 盘,然后重启即可
  • 此后不再需要显示器键盘鼠标等外设,物理机插着电源和网线即可

重启后,用浏览器可以直接访问 https://ip:8006https://域名:8006 ,登陆 proxmox 的控制台,需要注意 PVE 强制只能使用 https 协议

按照先前 jygg 说的安装过程最好不使用可被解析的域名,此时应该没法使用域名访问,用 ip 访问即可

此外还需记得配置 dns 服务器:

dns

# ssl 证书

这里介绍两种方法,都可以通过 PVE 控制台操作实现。需要注意,两种方法最后节点网页使用的 ssl 证书的路径在该节点 /etc/pve/nodes/节点名/ 目录下,名字默认是:

  • pveproxy-ssl.pem
  • pveproxy-ssl.key

证书位置

# 插件自动申请 ssl 证书

为了 https 访问能够不被浏览器阻挡,也为了安全,还需给自己的域名申请 ssl 证书,此后就用 https://域名:8006 对此 PVE 提供了基于 acme.sh 的自动化脚本,根据不同运营商给 proxmox 安装对应的插件,就可以实现自动申请 ssl 证书

ssl

# 注册 ACM 账号

数据中心 -> ACME -> 账户

注册ACM账号

# 添加 ACME 插件

数据中心 -> ACME -> 质询插件,或者指令 pvenode acme plugin add

ACME 插件的配置存放在 /etc/pve/priv/acme/plugins.cfg 中 ,一个插件可供整个集群使用

我们当然没有公网 ip,只能选择 dns 挑战。按照我们购买域名的运营商选择对应 api 接口,在运营商网页 API 相关部分获取对应的接口所需数据,填入数据,然后创建 acme 插件即可。

acme-plugin

如图是以 Porkbun 运营商为例创建 acme 插件

# 添加节点域名

每一个物理机节点都可以设置一个节点域名(node domain),但实际上一个集群只需要一台机器的 ip 绑定对应域名即可。选择这个 “主节点”:

机器 -> Certificate / 凭证 -> ACME -> Add / 添加

选择刚刚创建好的 acme 插件,填入你想要绑定的域名即可:

节点域名

最后点击 Order Certificate Now / 立即预约凭证 ,api 填写无误将顺利完成任务得到 OK 状态,后续不再需要手动申请证书,PVE 将利用 acme 插件定期自动申请凭证。

# 手动上传 ssl 证书

另一种方式是使用自己申请的 ssl 证书:

自己上传ssl证书

如图上传对应的 pemkey 文件即可。当然这种方式需要记得 ssl 过期前重新申请并上传文件。

# 更换 apt 软件源

PVE 实际上是一个 Debian ,按照 debian 换源方式操作即可。

需要注意的是 PVE 内置了一个 enterprise 软件源,但是这个软件源必须向 Proxmox 订阅(充钱)才能使用。我们当然只想白嫖,也不是商业用途,所以我们要把 /etc/apt/sources.list.d/pve-enterprise.list 里的这个软件源注释掉(当然删掉这个文件也是可以的):

javascript
deb https://enterprise.proxmox.com/debian/pve buster pve-enterprise

或者可以在 web 控制台操作禁用这些包含 enterprise 字眼的软件源

最后还需创建一个 /etc/apt/sources.list.d/pve-no-subscription.list 文件,(当然其实文件名只是给人看的,名字自定义即可)然后在文件内添加无需订阅的 PVE 软件源:

javascript
# PVE pve-no-subscription repository provided by proxmox.com,
# NOT recommended for production use
deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription

注意其中 bookworm 是我们的 debian12 版本名,如果你的版本不一样还需换成对应的名字

最后结果:

apt

# 动态配置网络

默认在 PVE 里更改宿主机的网络配置是需要重启才能生效的,此时所有虚拟机业务都会中断。所以我们需要让 PVE 支持 Reload 网络配置,方法很简单:

apt install ifupdown2
-

如果安装时提示说需要卸载 proxmox-ve,请确保已经加入了 pve-no-subscription 这个软件源并 apt update

# 配置防火墙

PVE 的防火墙层级比较复杂,分为三个部分:

  • 集群
  • 主机
  • VM

每个部分都由各自的开关,并且在每个虚拟机网卡上也有开关。

** 首先要打开集群(Cluster)的防火墙开关。** 然后你可以配置整个集群的防火墙规则,比如限制对主机的 22 端口访问。

但是你会发现没有起作用。这是因为主机(Host)的防火墙开关没开。所以还需要开一下主机(Host)的防火墙开关

此时主机的防火墙规则应当已经工作,如果还没有工作,请检查网卡的防火墙开关是否开启

Please however check that you:

  • Enabled firewalling on Data Centre options

  • Enabled firewalling on Node(s)

  • Enabled firewalling on VM

  • Set individual VM network interfaces to firewall

https://forum.proxmox.com/threads/pve-firewall-doesnt-have-any-effect.47393/

为了搭建 Kubernetes 节点,下一步需要创建对应的 VM 节点。但手动创建 VM 节点、安装系统也是痛苦的,所以应该使用 Terraform 来简化这个过程,并自始至终保持可管理性。

# 参考资料

参考了 Matrix 的知识库。官方文档是全英文的,非常详细,但是英文不太适合快速上手,可以考虑参考中文翻译版本,这个翻译不一定及时更新到最新 proxmox 版本

Edited on Views times
\ No newline at end of file +PVE 搭建小集群 - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 前言

在 Matrix 实验室用电子垃圾搭了一个小集群。

起因是 jygg 拿了一台被淘汰的存储型服务器给 cjl 玩,(据说是以前买来发现性能太差了,于是就把里面的 64T 的硬盘全部拿走了装到别的服务器上了,这台就废弃了),cjl 整了个 500g 的机械硬盘给服务器装上了,同时把不知为啥留在这里的一个台式 PC 给我玩,然后索性就装上了 PVE,在 jygg 的帮助下非常顺利搭了一个两台物理机组成的集群。

# 安装 PVE

官网下载 PVE,这是一个只有 1G 大小左右的基于 debian 的装好了 proxmox 相关软件、服务的镜像,然后用 U 盘给物理机安装。

安装过程可以用 proxmox 提供的图形化安装页面,当然安装好的 debian 本身不会有 GUI。会需要用到键盘,以及鼠标 (除非键盘技巧特别好)。

安装过程有一些需要额外注意:

  • hostname 会设置采取 FQDN 域名,但是实际上 proxmox 只会检查输入的是不是默认的 .invalid 结尾,只需改掉这个即可
    • jygg 说这个域名最好不要填可以被解析到的域名
  • 不需要设置登陆 debian 的用户名,web 控制台登陆用的超级管理员用户名即 root 即可
  • 安装过程设置的 ip 地址后面改起来也比较麻烦(尤其是组建集群时)最好提前确定好
    • jygg 的帮助下我们安装时就给 2 个物理机设置了校园网内可供访问的 ip(Matrix 从校园网络中心租的网段)
  • DNS Server 在这个界面里只能设置一个,可以安装完后再加
  • 安装结束,及时拔掉 U 盘,然后重启即可
  • 此后不再需要显示器键盘鼠标等外设,物理机插着电源和网线即可

重启后,用浏览器可以直接访问 https://ip:8006https://域名:8006 ,登陆 proxmox 的控制台,需要注意 PVE 强制只能使用 https 协议

按照先前 jygg 说的安装过程最好不使用可被解析的域名,此时应该没法使用域名访问,用 ip 访问即可

此外还需记得配置 dns 服务器:

dns

# ssl 证书

这里介绍两种方法,都可以通过 PVE 控制台操作实现。需要注意,两种方法最后节点网页使用的 ssl 证书的路径在该节点 /etc/pve/nodes/节点名/ 目录下,名字默认是:

  • pveproxy-ssl.pem
  • pveproxy-ssl.key

证书位置

# 插件自动申请 ssl 证书

为了 https 访问能够不被浏览器阻挡,也为了安全,还需给自己的域名申请 ssl 证书,此后就用 https://域名:8006 对此 PVE 提供了基于 acme.sh 的自动化脚本,根据不同运营商给 proxmox 安装对应的插件,就可以实现自动申请 ssl 证书

ssl

# 注册 ACM 账号

数据中心 -> ACME -> 账户

注册ACM账号

# 添加 ACME 插件

数据中心 -> ACME -> 质询插件,或者指令 pvenode acme plugin add

ACME 插件的配置存放在 /etc/pve/priv/acme/plugins.cfg 中 ,一个插件可供整个集群使用

我们当然没有公网 ip,只能选择 dns 挑战。按照我们购买域名的运营商选择对应 api 接口,在运营商网页 API 相关部分获取对应的接口所需数据,填入数据,然后创建 acme 插件即可。

acme-plugin

如图是以 Porkbun 运营商为例创建 acme 插件

# 添加节点域名

每一个物理机节点都可以设置一个节点域名(node domain),但实际上一个集群只需要一台机器的 ip 绑定对应域名即可。选择这个 “主节点”:

机器 -> Certificate / 凭证 -> ACME -> Add / 添加

选择刚刚创建好的 acme 插件,填入你想要绑定的域名即可:

节点域名

最后点击 Order Certificate Now / 立即预约凭证 ,api 填写无误将顺利完成任务得到 OK 状态,后续不再需要手动申请证书,PVE 将利用 acme 插件定期自动申请凭证。

# 手动上传 ssl 证书

另一种方式是使用自己申请的 ssl 证书:

自己上传ssl证书

如图上传对应的 pemkey 文件即可。当然这种方式需要记得 ssl 过期前重新申请并上传文件。

# 更换 apt 软件源

PVE 实际上是一个 Debian ,按照 debian 换源方式操作即可。

需要注意的是 PVE 内置了一个 enterprise 软件源,但是这个软件源必须向 Proxmox 订阅(充钱)才能使用。我们当然只想白嫖,也不是商业用途,所以我们要把 /etc/apt/sources.list.d/pve-enterprise.list 里的这个软件源注释掉(当然删掉这个文件也是可以的):

javascript
deb https://enterprise.proxmox.com/debian/pve buster pve-enterprise

或者可以在 web 控制台操作禁用这些包含 enterprise 字眼的软件源

最后还需创建一个 /etc/apt/sources.list.d/pve-no-subscription.list 文件,(当然其实文件名只是给人看的,名字自定义即可)然后在文件内添加无需订阅的 PVE 软件源:

javascript
# PVE pve-no-subscription repository provided by proxmox.com,
# NOT recommended for production use
deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription

注意其中 bookworm 是我们的 debian12 版本名,如果你的版本不一样还需换成对应的名字

最后结果:

apt

# 动态配置网络

默认在 PVE 里更改宿主机的网络配置是需要重启才能生效的,此时所有虚拟机业务都会中断。所以我们需要让 PVE 支持 Reload 网络配置,方法很简单:

apt install ifupdown2
+

如果安装时提示说需要卸载 proxmox-ve,请确保已经加入了 pve-no-subscription 这个软件源并 apt update

# 配置防火墙

PVE 的防火墙层级比较复杂,分为三个部分:

  • 集群
  • 主机
  • VM

每个部分都由各自的开关,并且在每个虚拟机网卡上也有开关。

** 首先要打开集群(Cluster)的防火墙开关。** 然后你可以配置整个集群的防火墙规则,比如限制对主机的 22 端口访问。

但是你会发现没有起作用。这是因为主机(Host)的防火墙开关没开。所以还需要开一下主机(Host)的防火墙开关

此时主机的防火墙规则应当已经工作,如果还没有工作,请检查网卡的防火墙开关是否开启

Please however check that you:

  • Enabled firewalling on Data Centre options

  • Enabled firewalling on Node(s)

  • Enabled firewalling on VM

  • Set individual VM network interfaces to firewall

https://forum.proxmox.com/threads/pve-firewall-doesnt-have-any-effect.47393/

为了搭建 Kubernetes 节点,下一步需要创建对应的 VM 节点。但手动创建 VM 节点、安装系统也是痛苦的,所以应该使用 Terraform 来简化这个过程,并自始至终保持可管理性。

# 参考资料

参考了 Matrix 的知识库。官方文档是全英文的,非常详细,但是英文不太适合快速上手,可以考虑参考中文翻译版本,这个翻译不一定及时更新到最新 proxmox 版本

Edited on Views times
\ No newline at end of file diff --git a/cs/devops/sql/index.html b/cs/devops/sql/index.html index 0bf0a59c..ed5d0de6 100644 --- a/cs/devops/sql/index.html +++ b/cs/devops/sql/index.html @@ -1 +1 @@ -SQL 基础 - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# DBMS

数据库管理系统 DBMS 的分类:

關聯式資料庫(SQL)非關聯式資料庫 - (nosQL /not just SQL)
• MySQL• MogoDB
• Oracle• Redis
• PostgreSQL• DynamoDB
• SQL Server• Elaticsearch
關聯式資料庫管理系統 (RDBMS)非關聯式資料庫管理系統 (NRDBMS)

SQL - Structured Query Language - 结构性询问语言

Edited on Views times
\ No newline at end of file +SQL 基础 - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# DBMS

数据库管理系统 DBMS 的分类:

關聯式資料庫(SQL)非關聯式資料庫 - (nosQL /not just SQL)
• MySQL• MogoDB
• Oracle• Redis
• PostgreSQL• DynamoDB
• SQL Server• Elaticsearch
關聯式資料庫管理系統 (RDBMS)非關聯式資料庫管理系統 (NRDBMS)

SQL - Structured Query Language - 结构性询问语言

Edited on Views times
\ No newline at end of file diff --git a/cs/devops/sync-pve-cluster/index.html b/cs/devops/sync-pve-cluster/index.html index 21e281b6..2ba2e578 100644 --- a/cs/devops/sync-pve-cluster/index.html +++ b/cs/devops/sync-pve-cluster/index.html @@ -1 +1 @@ -PVE 更改节点主机名与集群同步 - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 更改主机名

更改主机名的操作和 Debian 基本一致,但是 PVE 中会产生新的问题:

  • 配置文件需要手动迁移
  • 如果该节点已加入了集群,集群同步会出问题:
    • 集群配置文件需要手动更新
    • 节点之间 ssh 通信问题
  • Cepth 我在这次还没有配置 Cepth,所以情况未知

和 Debian 一样的操作:

bash
#!/bin/bash
# 获取旧主机名字
old_hostname=$(hostname)
# 输入新主机名
echo "请输入新的主机名:"
read new_hostname
sudo sed -i "s/$old_hostname/$new_hostname/g" /etc/hosts /etc/hostname /etc/postfix/main.cf

然后需要重启让新主机名生效。重启会可能会同时看到新节点和旧节点,新节点上看不到原来的虚拟机、容器,旧节点上看得到,因为虽然重启创建了 /etc/pve/nodes/$new_hostname/ 目录,但是旧节点的配置文件还在 /etc/pve/nodes/$old_hostname/ 中。

其中 /etc/pve/nodes/$old_hostname/qemu-server/ 比较特殊, mv 指令无法将它们直接移动,需要借助 “中转” 移动过去。

bash
#!/bin/bash
# 输入新主机名
read old_hostname
# 获取旧主机名
new_hostname=$(hostname)
cp -r /etc/pve/nodes/$old_hostname/* /etc/pve/nodes/$new_hostname/
# 中转
mkdir /root/temp
mv /etc/pve/nodes/$old_hostname/qemu-server/* /root/temp/
cp /root/temp/* /etc/pve/nodes/$new_hostname/qemu-server/
rm -rf /etc/pve/nodes/$old_hostname /root/temp /root/t.sh

每一个更改主机名的节点,都要单独对其执行如上操作。

# 集群同步

# 集群配置文件

按照官方文档,在每一个节点上编辑集群配置文件 /etc/pve/corosync.conf/etc/corosync/corosync.conf (一般重启 corosync 会自动和前者同步),可以修改不同节点主机名、IP、集群 id 等:

bash
cp /etc/pve/corosync.conf /etc/pve/corosync.conf.new
cp /etc/pve/corosync.conf /etc/pve/corosync.conf.bak
nano /etc/pve/corosync.conf.new
mv /etc/pve/corosync.conf.new /etc/pve/corosync.conf
systemctl restart corosync

如果修改节点 id,一定注意它是从 1 开始而不是 0 开始的!

这里因为权限问题不能直接编辑,而是创建新文件覆盖的方式编辑。原因如下:

shell
root@node3:~# ls -lah /etc/pve/corosync.conf
-rw-r----- 1 root www-data 638 Aug 13 14:36 /etc/pve/corosync.conf

还有另一种方式可以编辑这样的文件,通过切换文件系统的方式。如果上述方法操作失误或编辑出错了,可以通过如下方法挽救:

shell
systemctl stop pve-cluster
systemctl stop corosync
pmxcfs -l
# 现在可以编辑任意文件了
nano /etc/pve/corosync.conf
# 恢复
killall pmxcfs
systemctl start pve-cluster
systemctl start corosync

此外,若修改了节点的 id,还需要在重启 corosync 前受影响节点上删除旧的 id 信息:

shell
rm -rf /var/lib/corosync/*

编辑好配置文件之后,预期将在面板的 数据中心->概要; Datacenter(Cluster)->Summary 看到预期的节点情况。

这个过程由于我参考了官方文档 “从删除集群删除节点” 的内容,我曾误删过 /etc/corosync/authkey 和 ,导致了 systemctl start corosync 失败,查看日志看到 no such file or directory 这样的的报错,可以从其他节点 tcp 等方式拷贝过去解决。

# ssh 通信

修改主机名后还会导致节点之间的 ssh 通信出问题,登录某一节点 ip 的面板无法访问另一个节点的信息。

修改 /etc/hosts 增加这些节点和 ip,仍没有解决。

在每一个节点上对每一个其他节点 nodeX (x.x.x.x) 执行 /usr/bin/ssh -e none -o 'HostKeyAlias=nodeX' root@x.x.x.x /bin/true ,仍没有解决。

最终解决:

在每一个节点 nodeX (x.x.x.x) 上,查看 /etc/ssh/ssh_host_rsa_key.pub 得到该节点为 PVE 使用的 rsa 公钥 (pub)xxx... ,然后在集群共享文件 /etc/pve/priv/known_hosts 中编辑确保有且仅有如下信息,删去旧的不正确的信息:

known_hosts
x.x.x.x ssh-rsa (pub)xxx...
nodeX ssh-rsa (pub)xxx...
x.x.x.x ssh-rsa (pub)xxx...
nodeX ssh-rsa (pub)xxx...
......

在每一个节点上,建立软链接:

shell
ln -s /etc/pve/priv/known_hosts /etc/ssh/ssh_known_hosts

最后重启 pveproxy 服务:

shell
systemctl restart pveproxy
\ No newline at end of file +PVE 更改节点主机名与集群同步 - DevOps - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 更改主机名

更改主机名的操作和 Debian 基本一致,但是 PVE 中会产生新的问题:

  • 配置文件需要手动迁移
  • 如果该节点已加入了集群,集群同步会出问题:
    • 集群配置文件需要手动更新
    • 节点之间 ssh 通信问题
  • Cepth 我在这次还没有配置 Cepth,所以情况未知

和 Debian 一样的操作:

bash
#!/bin/bash
# 获取旧主机名字
old_hostname=$(hostname)
# 输入新主机名
echo "请输入新的主机名:"
read new_hostname
sudo sed -i "s/$old_hostname/$new_hostname/g" /etc/hosts /etc/hostname /etc/postfix/main.cf

然后需要重启让新主机名生效。重启会可能会同时看到新节点和旧节点,新节点上看不到原来的虚拟机、容器,旧节点上看得到,因为虽然重启创建了 /etc/pve/nodes/$new_hostname/ 目录,但是旧节点的配置文件还在 /etc/pve/nodes/$old_hostname/ 中。

其中 /etc/pve/nodes/$old_hostname/qemu-server/ 比较特殊, mv 指令无法将它们直接移动,需要借助 “中转” 移动过去。

bash
#!/bin/bash
# 输入新主机名
read old_hostname
# 获取旧主机名
new_hostname=$(hostname)
cp -r /etc/pve/nodes/$old_hostname/* /etc/pve/nodes/$new_hostname/
# 中转
mkdir /root/temp
mv /etc/pve/nodes/$old_hostname/qemu-server/* /root/temp/
cp /root/temp/* /etc/pve/nodes/$new_hostname/qemu-server/
rm -rf /etc/pve/nodes/$old_hostname /root/temp /root/t.sh

每一个更改主机名的节点,都要单独对其执行如上操作。

# 集群同步

# 集群配置文件

按照官方文档,在每一个节点上编辑集群配置文件 /etc/pve/corosync.conf/etc/corosync/corosync.conf (一般重启 corosync 会自动和前者同步),可以修改不同节点主机名、IP、集群 id 等:

bash
cp /etc/pve/corosync.conf /etc/pve/corosync.conf.new
cp /etc/pve/corosync.conf /etc/pve/corosync.conf.bak
nano /etc/pve/corosync.conf.new
mv /etc/pve/corosync.conf.new /etc/pve/corosync.conf
systemctl restart corosync

如果修改节点 id,一定注意它是从 1 开始而不是 0 开始的!

这里因为权限问题不能直接编辑,而是创建新文件覆盖的方式编辑。原因如下:

shell
root@node3:~# ls -lah /etc/pve/corosync.conf
-rw-r----- 1 root www-data 638 Aug 13 14:36 /etc/pve/corosync.conf

还有另一种方式可以编辑这样的文件,通过切换文件系统的方式。如果上述方法操作失误或编辑出错了,可以通过如下方法挽救:

shell
systemctl stop pve-cluster
systemctl stop corosync
pmxcfs -l
# 现在可以编辑任意文件了
nano /etc/pve/corosync.conf
# 恢复
killall pmxcfs
systemctl start pve-cluster
systemctl start corosync

此外,若修改了节点的 id,还需要在重启 corosync 前受影响节点上删除旧的 id 信息:

shell
rm -rf /var/lib/corosync/*

编辑好配置文件之后,预期将在面板的 数据中心->概要; Datacenter(Cluster)->Summary 看到预期的节点情况。

这个过程由于我参考了官方文档 “从删除集群删除节点” 的内容,我曾误删过 /etc/corosync/authkey 和 ,导致了 systemctl start corosync 失败,查看日志看到 no such file or directory 这样的的报错,可以从其他节点 tcp 等方式拷贝过去解决。

# ssh 通信

修改主机名后还会导致节点之间的 ssh 通信出问题,登录某一节点 ip 的面板无法访问另一个节点的信息。

修改 /etc/hosts 增加这些节点和 ip,仍没有解决。

在每一个节点上对每一个其他节点 nodeX (x.x.x.x) 执行 /usr/bin/ssh -e none -o 'HostKeyAlias=nodeX' root@x.x.x.x /bin/true ,仍没有解决。

最终解决:

在每一个节点 nodeX (x.x.x.x) 上,查看 /etc/ssh/ssh_host_rsa_key.pub 得到该节点为 PVE 使用的 rsa 公钥 (pub)xxx... ,然后在集群共享文件 /etc/pve/priv/known_hosts 中编辑确保有且仅有如下信息,删去旧的不正确的信息:

known_hosts
x.x.x.x ssh-rsa (pub)xxx...
nodeX ssh-rsa (pub)xxx...
x.x.x.x ssh-rsa (pub)xxx...
nodeX ssh-rsa (pub)xxx...
......

在每一个节点上,建立软链接:

shell
ln -s /etc/pve/priv/known_hosts /etc/ssh/ssh_known_hosts

最后重启 pveproxy 服务:

shell
systemctl restart pveproxy
\ No newline at end of file diff --git a/cs/fronet-end/hexo/index.html b/cs/fronet-end/hexo/index.html index 8b30f35b..57202ce4 100644 --- a/cs/fronet-end/hexo/index.html +++ b/cs/fronet-end/hexo/index.html @@ -1,3 +1,3 @@ -Hexo - 前端 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

Hexo 是一个基于 Node 框架的博客框架

pnpm install hexo-cli -g		//安装
hexo init blog						//初始化
cd blog; npm install			//安装依赖

blog 目录下生成静态文件(到 public 目录下,用于发布)

hexo g						//缩略
hexo generate			//一样

blog 目录下清除已生成的静态文件和 cache( 到 public 目录下)

hexo clean

blog 目录下本地运行 hexo 服务

hexo s						//缩略
hexo server				//一样

在 blog 目录下将 public 目录下的静态文件复制到 nginx 的对应目录,从而使用 nginx 服务部署:

sudo cp -r public/* /var/www/html/

一键部署,参考: https://hexo.io/docs/one-command-deployment

hexo d					//缩略
+Hexo - 前端 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

Hexo 是一个基于 Node 框架的博客框架

pnpm install hexo-cli -g		//安装
hexo init blog						//初始化
cd blog; npm install			//安装依赖

blog 目录下生成静态文件(到 public 目录下,用于发布)

hexo g						//缩略
hexo generate			//一样

blog 目录下清除已生成的静态文件和 cache( 到 public 目录下)

hexo clean

blog 目录下本地运行 hexo 服务

hexo s						//缩略
hexo server				//一样

在 blog 目录下将 public 目录下的静态文件复制到 nginx 的对应目录,从而使用 nginx 服务部署:

sudo cp -r public/* /var/www/html/

一键部署,参考: https://hexo.io/docs/one-command-deployment

hexo d					//缩略
 hexo deploy			//一样
-
Edited on Views times
\ No newline at end of file +
Edited on Views times
\ No newline at end of file diff --git a/cs/fronet-end/nodejs/index.html b/cs/fronet-end/nodejs/index.html index f93da288..fa53ede2 100644 --- a/cs/fronet-end/nodejs/index.html +++ b/cs/fronet-end/nodejs/index.html @@ -1,5 +1,5 @@ -Node.js - 前端 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# require

require 是 Node.js 中用于加载模块的函数。它的主要作用是将外部模块引入到当前的 JavaScript 文件中,以便在代码中使用被引入的模块的功能、变量或对象。

require 函数的基本语法是:

require(moduleName);

其中, moduleName 是要引入的模块的名称或路径。

require 函数的工作原理如下:

  1. 首先,Node.js 会检查 moduleName 是否是一个核心模块(Node.js 内置的模块)。如果是核心模块,Node.js 会直接加载并返回该模块的导出内容。
  2. 如果 moduleName 不是核心模块,Node.js 会尝试在当前目录下查找指定名称的文件或文件夹。
    • 如果指定名称是一个文件,Node.js 将尝试加载该文件,并返回文件中导出的内容。
    • 如果指定名称是一个文件夹,Node.js 将尝试查找该文件夹下的 package.json 文件。如果找到了 package.json 文件,并且文件中包含一个 "main" 属性,Node.js 将加载该属性指定的文件,并返回文件中导出的内容。
    • 如果以上两种情况都不满足,Node.js 将尝试查找指定名称的文件夹下的 index.js 文件,并返回文件中导出的内容。
  3. 如果在当前目录下找不到指定的文件或文件夹,Node.js 会递归地向上查找,直到找到指定的模块或到达文件系统的根目录为止。如果在任何一个父级目录中找到了指定的模块,Node.js 将加载该模块并返回导出的内容。
  4. 如果在所有的搜索路径中都找不到指定的模块,Node.js 将抛出一个 Error

需要注意的是, require 函数是同步的,并且模块在第一次被引入后会被缓存,所以多次调用 require 函数引入同一个模块不会导致模块被重复加载,而是直接返回缓存的内容。如果想要重新加载一个模块,可以使用 delete require.cache[moduleName] 来删除缓存。

# HTTP 请求

在现代的 Node.js 环境中,进行 HTTP 请求最广泛使用且比较前沿的模块是 node-fetchaxios 。它们都支持 TypeScript,并提供了简洁的 API 来发送 HTTP 请求。

  1. node-fetchnode-fetch 是一个基于 Fetch API 标准的轻量级 HTTP 客户端。它提供了类似于浏览器中 fetch 函数的接口,可以发送 HTTP 请求并处理响应。 node-fetch 在 Node.js 环境中非常流行,因为它支持 Promise,并且使用起来非常简洁。你可以使用以下命令安装 node-fetch 模块:

    npm install node-fetch
    +Node.js - 前端 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

    # require

    require 是 Node.js 中用于加载模块的函数。它的主要作用是将外部模块引入到当前的 JavaScript 文件中,以便在代码中使用被引入的模块的功能、变量或对象。

    require 函数的基本语法是:

    require(moduleName);

    其中, moduleName 是要引入的模块的名称或路径。

    require 函数的工作原理如下:

    1. 首先,Node.js 会检查 moduleName 是否是一个核心模块(Node.js 内置的模块)。如果是核心模块,Node.js 会直接加载并返回该模块的导出内容。
    2. 如果 moduleName 不是核心模块,Node.js 会尝试在当前目录下查找指定名称的文件或文件夹。
      • 如果指定名称是一个文件,Node.js 将尝试加载该文件,并返回文件中导出的内容。
      • 如果指定名称是一个文件夹,Node.js 将尝试查找该文件夹下的 package.json 文件。如果找到了 package.json 文件,并且文件中包含一个 "main" 属性,Node.js 将加载该属性指定的文件,并返回文件中导出的内容。
      • 如果以上两种情况都不满足,Node.js 将尝试查找指定名称的文件夹下的 index.js 文件,并返回文件中导出的内容。
    3. 如果在当前目录下找不到指定的文件或文件夹,Node.js 会递归地向上查找,直到找到指定的模块或到达文件系统的根目录为止。如果在任何一个父级目录中找到了指定的模块,Node.js 将加载该模块并返回导出的内容。
    4. 如果在所有的搜索路径中都找不到指定的模块,Node.js 将抛出一个 Error

    需要注意的是, require 函数是同步的,并且模块在第一次被引入后会被缓存,所以多次调用 require 函数引入同一个模块不会导致模块被重复加载,而是直接返回缓存的内容。如果想要重新加载一个模块,可以使用 delete require.cache[moduleName] 来删除缓存。

    # HTTP 请求

    在现代的 Node.js 环境中,进行 HTTP 请求最广泛使用且比较前沿的模块是 node-fetchaxios 。它们都支持 TypeScript,并提供了简洁的 API 来发送 HTTP 请求。

    1. node-fetchnode-fetch 是一个基于 Fetch API 标准的轻量级 HTTP 客户端。它提供了类似于浏览器中 fetch 函数的接口,可以发送 HTTP 请求并处理响应。 node-fetch 在 Node.js 环境中非常流行,因为它支持 Promise,并且使用起来非常简洁。你可以使用以下命令安装 node-fetch 模块:

      npm install node-fetch
       

      或者使用 yarn:

      yarn add node-fetch
       

      安装完成后,你可以在 TypeScript 代码中引入并使用 node-fetch 模块来发送 HTTP 请求。

    2. axiosaxios 是一个流行的基于 Promise 的 HTTP 客户端,可以在 Node.js 环境和浏览器中使用。它提供了简洁的 API 和许多功能,如请求拦截器、响应拦截器、取消请求等。 axios 在 Node.js 环境中也非常受欢迎,并且有广泛的社区支持。你可以使用以下命令安装 axios 模块:

      npm install axios
       

      或者使用 yarn:

      yarn add axios
      -

      安装完成后,你可以在 TypeScript 代码中引入并使用 axios 模块来发送 HTTP 请求。

    这两个模块都非常流行和可靠,具体使用哪个取决于你的个人偏好和项目要求。它们都提供了良好的文档和示例,以帮助你开始使用它们进行 HTTP 请求。

    Edited on Views times
    \ No newline at end of file +

    安装完成后,你可以在 TypeScript 代码中引入并使用 axios 模块来发送 HTTP 请求。

这两个模块都非常流行和可靠,具体使用哪个取决于你的个人偏好和项目要求。它们都提供了良好的文档和示例,以帮助你开始使用它们进行 HTTP 请求。

Edited on Views times
\ No newline at end of file diff --git a/cs/languages/js/index.html b/cs/languages/js/index.html index ea75ea5d..f82bebfa 100644 --- a/cs/languages/js/index.html +++ b/cs/languages/js/index.html @@ -1 +1 @@ -JavaScript 基础 - 编程语言 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# JSON.stringify()

JSON.stringify() 是 JavaScript 中的一个方法,用于将 JavaScript 对象或值转换为 JSON 字符串。

具体作用如下:

  • 序列化: JSON.stringify() 方法将 JavaScript 对象或值序列化为一个 JSON 字符串。序列化是指将对象的结构和数据转换为字符串的过程,使其可以在网络传输或存储中进行传递和持久化。
  • JSON 格式:JSON(JavaScript Object Notation)是一种常用的数据交换格式,具有简洁、易读和跨语言的特性。 JSON.stringify() 将 JavaScript 对象或值转换为符合 JSON 格式的字符串,方便与其他系统或服务进行数据交互。

语法:

JSON.stringify(value[, replacer[, space]])
  • value :要被序列化为 JSON 字符串的 JavaScript 对象或值。
  • replacer (可选):一个函数或数组,用于控制序列化过程中的属性过滤和转换。可以传递一个函数作为 replacer,该函数将被应用于对象的每个属性,并在序列化时对属性值进行转换。也可以传递一个数组,包含要序列化的属性名列表,仅包含在该列表中的属性将被序列化。
  • space (可选):用于美化输出的空格数。如果是一个数字,则表示使用相应数量的空格进行缩进;如果是一个字符串,则使用该字符串作为缩进符号。

下面是一个简单的示例:

const obj = {
  name: 'Alice',
  age: 30,
  isActive: true
};
const jsonString = JSON.stringify(obj);
console.log(jsonString);
// 输出: '{"name":"Alice","age":30,"isActive":true}'

在上面的示例中, obj 对象通过 JSON.stringify() 方法被序列化为一个 JSON 字符串。 jsonString 的值为 {"name":"Alice","age":30,"isActive":true} 。该字符串符合 JSON 格式,可以在传输或存储中使用。

JSON.stringify() 方法用于将 JavaScript 对象或值转换为 JSON 字符串,方便数据的传输和持久化。

# JSON.parse()

JSON.parse() 是一个 JavaScript 内置函数,用于将符合 JSON 格式的字符串转换为对应的 JavaScript 对象。

JSON.parse() 的基本语法如下:

JSON.parse(jsonString);

其中, jsonString 是一个符合 JSON 格式的字符串。

JSON.parse() 函数的工作原理如下:

  1. 首先,它会接收一个 JSON 格式的字符串作为输入。
  2. 然后,它会解析这个字符串,并将其转换为对应的 JavaScript 对象。
  3. 如果解析成功,它将返回转换后的 JavaScript 对象;如果解析失败,它将抛出一个 SyntaxError

在将字符串转换为 JavaScript 对象时, JSON.parse() 支持的 JSON 数据类型有:

  • 字符串(字符串需要使用双引号)
  • 数字(整数或浮点数)
  • 布尔值( truefalse
  • null
  • 数组(用方括号 [] 表示)
  • 对象(用花括号 {} 表示)

以下是一些示例,展示了 JSON.parse() 函数的用法:

const jsonString = '{"name": "John", "age": 30, "isStudent": true, "hobbies": ["reading", "swimming"]}';
const obj = JSON.parse(jsonString);
console.log(obj.name); // 输出: John
console.log(obj.age); // 输出: 30
console.log(obj.isStudent); // 输出: true
console.log(obj.hobbies[0]); // 输出: reading
console.log(obj.hobbies[1]); // 输出: swimming

在这个示例中,我们有一个符合 JSON 格式的字符串 jsonString ,然后我们使用 JSON.parse() 将其转换为了一个 JavaScript 对象 obj 。接下来,我们可以通过访问 obj 的属性来获取和操作 JSON 数据。

需要注意的是, JSON.parse() 只能解析合法的 JSON 字符串,因此如果提供给它的字符串不符合 JSON 语法,就会导致解析失败并抛出 SyntaxError 。另外, JSON.parse() 不支持解析带有函数、日期或正则表达式等特殊类型的 JSON 数据。

# JSON.parse(JSON.stringify( ))

JSON.parse(JSON.stringify()) 函数组合用法可以将一个 JavaScript 对象进行深度克隆,从而创建一个与原对象完全相同的新对象。这个过程可以确保输入和输出是不变的。

JSON.stringify() 函数将 JavaScript 对象转换为 JSON 字符串,而 JSON.parse() 函数将 JSON 字符串解析为 JavaScript 对象。通过将一个对象先使用 JSON.stringify() 转换为字符串,然后再使用 JSON.parse() 解析回对象,可以创建一个新的对象,该对象与原对象在值上是相等的,但是在引用上是不同的。

这个过程的效果是创建了原对象的一个深度副本(deep copy),而不是对原对象进行引用传递。这在需要确保对原对象的修改不会影响到副本时非常有用。

需要注意的是,这种深度克隆方法只适用于可以被 JSON 序列化和反序列化的数据类型,例如对象、数组、字符串、数字、布尔值等。对于无法被 JSON 序列化的数据类型,比如函数、正则表达式、 undefined 等,这种方法将无法克隆它们。

下面是一个示例,展示了 JSON.parse(JSON.stringify()) 函数组合的效果:

const obj = { a: 1, b: { c: 2 } };
const clone = JSON.parse(JSON.stringify(obj));
console.log(obj);   // { a: 1, b: { c: 2 } }
console.log(clone); // { a: 1, b: { c: 2 } }
console.log(obj === clone);                  // false
console.log(obj.b === clone.b);              // false
console.log(obj.b.c === clone.b.c);          // true

在上述示例中, obj 对象被克隆为 clone 对象,它们的值是相等的,但是它们是两个不同的对象,因此对其中一个对象的修改不会影响到另一个对象。

# Promise

Promise 是 JavaScript 中处理异步操作的一种机制,它代表了一个异步操作的最终完成或失败,并可以返回结果或错误。

在传统的 JavaScript 中,处理异步操作通常使用回调函数。但是,回调函数的嵌套会导致代码变得难以理解和维护,形成所谓的 "回调地狱"。为了解决这个问题,Promise 被引入作为一种更优雅和可读性更高的异步编程模式。

一个 Promise 对象代表了一个异步操作,它有三种状态:

  1. Pending(进行中):初始状态,表示异步操作还未完成,仍处于进行中的状态。

  2. Fulfilled(已成功):表示异步操作已经成功完成,并返回了一个值。在这种状态下,Promise 对象会调用 then 方法注册的回调函数,并将异步操作的结果传递给这些回调函数。

  3. Rejected(已失败):表示异步操作发生了错误或失败。在这种状态下,Promise 对象会调用 catch 方法注册的回调函数,并将错误信息传递给这些回调函数。

Promise 对象具有以下特点:

  • Promise 对象是不可变的,一旦进入了 Fulfilled 或 Rejected 状态,就不会再发生状态的改变。
  • 通过调用 then 方法可以注册成功回调函数,通过调用 catch 方法可以注册失败回调函数。
  • Promise 对象可以被链式调用,通过返回新的 Promise 对象来实现链式操作。
  • Promise 提供了一些静态方法,如 Promise.allPromise.race 等,用于处理多个 Promise 对象。

在现代的 JavaScript 中,Promise 已经成为了标准的异步操作处理方式,被广泛应用于各种场景,如网络请求、文件操作等。它提供了一种更直观、可靠和易于使用的方式来处理异步操作,避免了回调地狱问题,提高了代码的可读性和可维护性。

# 网络请求处理

# handler(req, res)

async function handler(req, res) 是一个异步函数,通常用作处理 HTTP 请求的处理程序。这个函数接受两个参数 reqres ,分别代表请求对象和响应对象。

具体的函数实现和参数可能会根据具体的需求和开发框架而有所不同。在某些情况下, reqres 参数可能会被命名为其他名称,而函数的实现也可能会有其他逻辑。

以下是一个示例,展示了一个类似的函数实现,用于处理 HTTP POST 请求,返回一个 JSON 响应:

// handler.js
export default async function handler(req, res) {
  try {
    const { body } = req;
    
    // 处理请求逻辑
    const result = await processRequest(body);
    
    // 返回 JSON 响应
    res.status(200).json({ success: true, data: result });
  } catch (error) {
    console.error(error);
    res.status(500).json({ success: false, error: "Internal Server Error" });
  }
}

在上述示例中, handler 函数是一个异步函数,它接受 reqres 作为参数。函数内部可以根据具体需求进行逻辑处理,例如从请求体中获取数据、调用其他函数进行处理,并最终返回一个 JSON 响应。

# axios

# axios.post

await axios.post 是使用 axios 发送 POST 请求并等待其响应的语法。使用 await 关键字可以让 JavaScript 在发送请求后暂停执行,直到获得响应为止。

下面是一个使用 await axios.post 发送 POST 请求的示例:

import axios from 'axios';
async function postData() {
  try {
    const response = await axios.post('https://api.example.com/data', {
      name: 'John',
      age: 30
    });
    console.log(response.data);
  } catch (error) {
    console.error(error);
  }
}
postData();

在这个示例中,我们定义了一个名为 postData 的异步函数。在该函数内部,我们使用 await axios.post 发送 POST 请求到指定的 URL,并传递一个包含数据的 JavaScript 对象作为请求体。

当发送请求时,JavaScript 会等待 axios 返回响应。一旦收到响应,它会将响应存储在 response 变量中。我们可以使用 response.data 来访问响应数据。

如果请求成功,我们打印出响应数据。如果请求失败,则会捕获错误并打印错误信息。

需要注意的是,在使用 await 关键字之前,必须将其包裹在 async 函数内部。这是因为 await 只能在异步函数中使用。

在使用 await 时,必须将其放在 async 函数内部。这样才能正确地使用 await axios.post 并处理响应。

axios.post 是一个用于发送 HTTP POST 请求的方法,它返回一个 Promise 对象。这个 Promise 对象在请求完成后会被解析,提供了请求的响应数据和其他相关信息。

await axios.post 的返回值是一个 Promise,它解析为 axios 的响应对象。响应对象具有许多属性,其中最常用的是 data 属性,它包含服务器返回的数据。具体地说, axios.post 方法返回的 Promise 对象具有以下结构:

interface AxiosResponse<T = any> {
  data: T;
  status: number;
  statusText: string;
  headers: any;
  config: AxiosRequestConfig;
  request?: any;
}
interface AxiosError<T = any> extends Error {
  config: AxiosRequestConfig;
  code?: string;
  request?: any;
  response?: AxiosResponse<T>;
  isAxiosError: boolean;
}
interface AxiosPromise<T = any> extends Promise<AxiosResponse<T>> {}
  • AxiosResponse 是成功响应的类型,它包含以下属性:

    • data :响应的数据,类型为泛型 T 所指定的类型。
    • status :HTTP 响应状态码。
    • statusText :HTTP 响应状态文本。
    • headers :响应的 HTTP 头信息。
    • config :发起请求时的配置对象。
    • request :发起的请求实例。
  • AxiosError 是请求错误时的类型,它继承自 Error 对象,包含以下属性:

    • config :发起请求时的配置对象。
    • code :请求错误的错误码。
    • request :发起的请求实例。
    • response :包含错误响应的 AxiosResponse 对象。
    • isAxiosError :标识是否为 Axios 错误。
  • AxiosPromiseaxios.post 方法返回的 Promise 对象的类型,它是一个泛型类型,泛型 T 表示响应数据的类型。

通过对返回的 Promise 对象调用 .then 方法,您可以注册成功回调函数来处理响应数据。如果请求失败,则可以通过 .catch 方法注册错误回调函数进行错误处理。

示例代码:

axios.post(url, data)
  .then((response: AxiosResponse) => {
    // 处理成功响应
    console.log(response.data);
  })
  .catch((error: AxiosError) => {
    // 处理错误
    console.error(error.message);
  });

请注意, axios.post 返回的 Promise 对象根据请求结果可能会被解析为成功响应或错误响应。因此,在处理响应时,建议使用 .then.catch 方法来适当地处理成功和错误的情况。

# 网络请求

# fetch( )

使用 JavaScript 内置的 Fetch API 进行网络请求:

  1. 构建请求参数:创建一个包含请求方法、请求头、请求体等信息的配置对象。

  2. 发起网络请求:使用 fetch() 函数发送请求,并将配置对象作为参数传递给它。 fetch() 函数返回一个 Promise 对象,代表异步操作的结果。

  3. 处理响应:通过 Promise 的解决来获取服务器返回的响应。可以使用响应对象的方法和属性来读取响应的状态、头部和主体数据。

  4. 解析响应数据:根据服务器返回的数据类型,使用合适的方法将响应的主体数据解析为可用的格式,例如 JSON、文本或二进制数据。

下面是一个使用 Fetch API 进行 GET 请求的示例:

fetch('https://api.example.com/data')
  .then(response => {
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    return response.json();
  })
  .then(data => {
    console.log(data); // 处理响应数据
  })
  .catch(error => {
    console.error('Error:', error);
  });

上述示例展示了一个简单的 GET 请求,其中:

  • 使用 fetch() 函数发送了一个 GET 请求到 'https://api.example.com/data'
  • fetch() 函数返回的 Promise 对象通过 .then() 方法进行链式处理。在第一个 .then() 中,我们检查响应的状态码是否为成功状态( ok ),如果不是,则抛出一个错误。
  • 如果响应状态码正常,我们使用 response.json() 方法将响应的主体数据解析为 JSON 格式。
  • 最后一个 .then() 用于处理解析后的数据。
  • 如果在请求过程中发生错误,或任何一个 .then() 中抛出了错误,将进入 .catch() ,在控制台输出错误信息。

类似地,你可以使用 fetch() 函数进行 POST 请求,只需在配置对象中设置请求方法为 'POST' ,并通过 body 属性提供请求体数据。

请注意,Fetch API 默认不会将错误状态(如 404 或 500)视为网络错误。它会将这些状态码视为请求成功,并通过 response.ok 属性进行判断。如果你希望将这些状态码也视为网络错误,可以在第一个 .then() 中进行额外的检查或自定义处理逻辑。

这是使用 JavaScript 内置的 Fetch API 进行网络请求的基本流程。根据具体的需求和场景,你可以进一步使用其他方法和属性来扩展和定制请求和响应的处理。

Edited on Views times
\ No newline at end of file +JavaScript 基础 - 编程语言 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# JSON.stringify()

JSON.stringify() 是 JavaScript 中的一个方法,用于将 JavaScript 对象或值转换为 JSON 字符串。

具体作用如下:

  • 序列化: JSON.stringify() 方法将 JavaScript 对象或值序列化为一个 JSON 字符串。序列化是指将对象的结构和数据转换为字符串的过程,使其可以在网络传输或存储中进行传递和持久化。
  • JSON 格式:JSON(JavaScript Object Notation)是一种常用的数据交换格式,具有简洁、易读和跨语言的特性。 JSON.stringify() 将 JavaScript 对象或值转换为符合 JSON 格式的字符串,方便与其他系统或服务进行数据交互。

语法:

JSON.stringify(value[, replacer[, space]])
  • value :要被序列化为 JSON 字符串的 JavaScript 对象或值。
  • replacer (可选):一个函数或数组,用于控制序列化过程中的属性过滤和转换。可以传递一个函数作为 replacer,该函数将被应用于对象的每个属性,并在序列化时对属性值进行转换。也可以传递一个数组,包含要序列化的属性名列表,仅包含在该列表中的属性将被序列化。
  • space (可选):用于美化输出的空格数。如果是一个数字,则表示使用相应数量的空格进行缩进;如果是一个字符串,则使用该字符串作为缩进符号。

下面是一个简单的示例:

const obj = {
  name: 'Alice',
  age: 30,
  isActive: true
};
const jsonString = JSON.stringify(obj);
console.log(jsonString);
// 输出: '{"name":"Alice","age":30,"isActive":true}'

在上面的示例中, obj 对象通过 JSON.stringify() 方法被序列化为一个 JSON 字符串。 jsonString 的值为 {"name":"Alice","age":30,"isActive":true} 。该字符串符合 JSON 格式,可以在传输或存储中使用。

JSON.stringify() 方法用于将 JavaScript 对象或值转换为 JSON 字符串,方便数据的传输和持久化。

# JSON.parse()

JSON.parse() 是一个 JavaScript 内置函数,用于将符合 JSON 格式的字符串转换为对应的 JavaScript 对象。

JSON.parse() 的基本语法如下:

JSON.parse(jsonString);

其中, jsonString 是一个符合 JSON 格式的字符串。

JSON.parse() 函数的工作原理如下:

  1. 首先,它会接收一个 JSON 格式的字符串作为输入。
  2. 然后,它会解析这个字符串,并将其转换为对应的 JavaScript 对象。
  3. 如果解析成功,它将返回转换后的 JavaScript 对象;如果解析失败,它将抛出一个 SyntaxError

在将字符串转换为 JavaScript 对象时, JSON.parse() 支持的 JSON 数据类型有:

  • 字符串(字符串需要使用双引号)
  • 数字(整数或浮点数)
  • 布尔值( truefalse
  • null
  • 数组(用方括号 [] 表示)
  • 对象(用花括号 {} 表示)

以下是一些示例,展示了 JSON.parse() 函数的用法:

const jsonString = '{"name": "John", "age": 30, "isStudent": true, "hobbies": ["reading", "swimming"]}';
const obj = JSON.parse(jsonString);
console.log(obj.name); // 输出: John
console.log(obj.age); // 输出: 30
console.log(obj.isStudent); // 输出: true
console.log(obj.hobbies[0]); // 输出: reading
console.log(obj.hobbies[1]); // 输出: swimming

在这个示例中,我们有一个符合 JSON 格式的字符串 jsonString ,然后我们使用 JSON.parse() 将其转换为了一个 JavaScript 对象 obj 。接下来,我们可以通过访问 obj 的属性来获取和操作 JSON 数据。

需要注意的是, JSON.parse() 只能解析合法的 JSON 字符串,因此如果提供给它的字符串不符合 JSON 语法,就会导致解析失败并抛出 SyntaxError 。另外, JSON.parse() 不支持解析带有函数、日期或正则表达式等特殊类型的 JSON 数据。

# JSON.parse(JSON.stringify( ))

JSON.parse(JSON.stringify()) 函数组合用法可以将一个 JavaScript 对象进行深度克隆,从而创建一个与原对象完全相同的新对象。这个过程可以确保输入和输出是不变的。

JSON.stringify() 函数将 JavaScript 对象转换为 JSON 字符串,而 JSON.parse() 函数将 JSON 字符串解析为 JavaScript 对象。通过将一个对象先使用 JSON.stringify() 转换为字符串,然后再使用 JSON.parse() 解析回对象,可以创建一个新的对象,该对象与原对象在值上是相等的,但是在引用上是不同的。

这个过程的效果是创建了原对象的一个深度副本(deep copy),而不是对原对象进行引用传递。这在需要确保对原对象的修改不会影响到副本时非常有用。

需要注意的是,这种深度克隆方法只适用于可以被 JSON 序列化和反序列化的数据类型,例如对象、数组、字符串、数字、布尔值等。对于无法被 JSON 序列化的数据类型,比如函数、正则表达式、 undefined 等,这种方法将无法克隆它们。

下面是一个示例,展示了 JSON.parse(JSON.stringify()) 函数组合的效果:

const obj = { a: 1, b: { c: 2 } };
const clone = JSON.parse(JSON.stringify(obj));
console.log(obj);   // { a: 1, b: { c: 2 } }
console.log(clone); // { a: 1, b: { c: 2 } }
console.log(obj === clone);                  // false
console.log(obj.b === clone.b);              // false
console.log(obj.b.c === clone.b.c);          // true

在上述示例中, obj 对象被克隆为 clone 对象,它们的值是相等的,但是它们是两个不同的对象,因此对其中一个对象的修改不会影响到另一个对象。

# Promise

Promise 是 JavaScript 中处理异步操作的一种机制,它代表了一个异步操作的最终完成或失败,并可以返回结果或错误。

在传统的 JavaScript 中,处理异步操作通常使用回调函数。但是,回调函数的嵌套会导致代码变得难以理解和维护,形成所谓的 "回调地狱"。为了解决这个问题,Promise 被引入作为一种更优雅和可读性更高的异步编程模式。

一个 Promise 对象代表了一个异步操作,它有三种状态:

  1. Pending(进行中):初始状态,表示异步操作还未完成,仍处于进行中的状态。

  2. Fulfilled(已成功):表示异步操作已经成功完成,并返回了一个值。在这种状态下,Promise 对象会调用 then 方法注册的回调函数,并将异步操作的结果传递给这些回调函数。

  3. Rejected(已失败):表示异步操作发生了错误或失败。在这种状态下,Promise 对象会调用 catch 方法注册的回调函数,并将错误信息传递给这些回调函数。

Promise 对象具有以下特点:

  • Promise 对象是不可变的,一旦进入了 Fulfilled 或 Rejected 状态,就不会再发生状态的改变。
  • 通过调用 then 方法可以注册成功回调函数,通过调用 catch 方法可以注册失败回调函数。
  • Promise 对象可以被链式调用,通过返回新的 Promise 对象来实现链式操作。
  • Promise 提供了一些静态方法,如 Promise.allPromise.race 等,用于处理多个 Promise 对象。

在现代的 JavaScript 中,Promise 已经成为了标准的异步操作处理方式,被广泛应用于各种场景,如网络请求、文件操作等。它提供了一种更直观、可靠和易于使用的方式来处理异步操作,避免了回调地狱问题,提高了代码的可读性和可维护性。

# 网络请求处理

# handler(req, res)

async function handler(req, res) 是一个异步函数,通常用作处理 HTTP 请求的处理程序。这个函数接受两个参数 reqres ,分别代表请求对象和响应对象。

具体的函数实现和参数可能会根据具体的需求和开发框架而有所不同。在某些情况下, reqres 参数可能会被命名为其他名称,而函数的实现也可能会有其他逻辑。

以下是一个示例,展示了一个类似的函数实现,用于处理 HTTP POST 请求,返回一个 JSON 响应:

// handler.js
export default async function handler(req, res) {
  try {
    const { body } = req;
    
    // 处理请求逻辑
    const result = await processRequest(body);
    
    // 返回 JSON 响应
    res.status(200).json({ success: true, data: result });
  } catch (error) {
    console.error(error);
    res.status(500).json({ success: false, error: "Internal Server Error" });
  }
}

在上述示例中, handler 函数是一个异步函数,它接受 reqres 作为参数。函数内部可以根据具体需求进行逻辑处理,例如从请求体中获取数据、调用其他函数进行处理,并最终返回一个 JSON 响应。

# axios

# axios.post

await axios.post 是使用 axios 发送 POST 请求并等待其响应的语法。使用 await 关键字可以让 JavaScript 在发送请求后暂停执行,直到获得响应为止。

下面是一个使用 await axios.post 发送 POST 请求的示例:

import axios from 'axios';
async function postData() {
  try {
    const response = await axios.post('https://api.example.com/data', {
      name: 'John',
      age: 30
    });
    console.log(response.data);
  } catch (error) {
    console.error(error);
  }
}
postData();

在这个示例中,我们定义了一个名为 postData 的异步函数。在该函数内部,我们使用 await axios.post 发送 POST 请求到指定的 URL,并传递一个包含数据的 JavaScript 对象作为请求体。

当发送请求时,JavaScript 会等待 axios 返回响应。一旦收到响应,它会将响应存储在 response 变量中。我们可以使用 response.data 来访问响应数据。

如果请求成功,我们打印出响应数据。如果请求失败,则会捕获错误并打印错误信息。

需要注意的是,在使用 await 关键字之前,必须将其包裹在 async 函数内部。这是因为 await 只能在异步函数中使用。

在使用 await 时,必须将其放在 async 函数内部。这样才能正确地使用 await axios.post 并处理响应。

axios.post 是一个用于发送 HTTP POST 请求的方法,它返回一个 Promise 对象。这个 Promise 对象在请求完成后会被解析,提供了请求的响应数据和其他相关信息。

await axios.post 的返回值是一个 Promise,它解析为 axios 的响应对象。响应对象具有许多属性,其中最常用的是 data 属性,它包含服务器返回的数据。具体地说, axios.post 方法返回的 Promise 对象具有以下结构:

interface AxiosResponse<T = any> {
  data: T;
  status: number;
  statusText: string;
  headers: any;
  config: AxiosRequestConfig;
  request?: any;
}
interface AxiosError<T = any> extends Error {
  config: AxiosRequestConfig;
  code?: string;
  request?: any;
  response?: AxiosResponse<T>;
  isAxiosError: boolean;
}
interface AxiosPromise<T = any> extends Promise<AxiosResponse<T>> {}
  • AxiosResponse 是成功响应的类型,它包含以下属性:

    • data :响应的数据,类型为泛型 T 所指定的类型。
    • status :HTTP 响应状态码。
    • statusText :HTTP 响应状态文本。
    • headers :响应的 HTTP 头信息。
    • config :发起请求时的配置对象。
    • request :发起的请求实例。
  • AxiosError 是请求错误时的类型,它继承自 Error 对象,包含以下属性:

    • config :发起请求时的配置对象。
    • code :请求错误的错误码。
    • request :发起的请求实例。
    • response :包含错误响应的 AxiosResponse 对象。
    • isAxiosError :标识是否为 Axios 错误。
  • AxiosPromiseaxios.post 方法返回的 Promise 对象的类型,它是一个泛型类型,泛型 T 表示响应数据的类型。

通过对返回的 Promise 对象调用 .then 方法,您可以注册成功回调函数来处理响应数据。如果请求失败,则可以通过 .catch 方法注册错误回调函数进行错误处理。

示例代码:

axios.post(url, data)
  .then((response: AxiosResponse) => {
    // 处理成功响应
    console.log(response.data);
  })
  .catch((error: AxiosError) => {
    // 处理错误
    console.error(error.message);
  });

请注意, axios.post 返回的 Promise 对象根据请求结果可能会被解析为成功响应或错误响应。因此,在处理响应时,建议使用 .then.catch 方法来适当地处理成功和错误的情况。

# 网络请求

# fetch( )

使用 JavaScript 内置的 Fetch API 进行网络请求:

  1. 构建请求参数:创建一个包含请求方法、请求头、请求体等信息的配置对象。

  2. 发起网络请求:使用 fetch() 函数发送请求,并将配置对象作为参数传递给它。 fetch() 函数返回一个 Promise 对象,代表异步操作的结果。

  3. 处理响应:通过 Promise 的解决来获取服务器返回的响应。可以使用响应对象的方法和属性来读取响应的状态、头部和主体数据。

  4. 解析响应数据:根据服务器返回的数据类型,使用合适的方法将响应的主体数据解析为可用的格式,例如 JSON、文本或二进制数据。

下面是一个使用 Fetch API 进行 GET 请求的示例:

fetch('https://api.example.com/data')
  .then(response => {
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    return response.json();
  })
  .then(data => {
    console.log(data); // 处理响应数据
  })
  .catch(error => {
    console.error('Error:', error);
  });

上述示例展示了一个简单的 GET 请求,其中:

  • 使用 fetch() 函数发送了一个 GET 请求到 'https://api.example.com/data'
  • fetch() 函数返回的 Promise 对象通过 .then() 方法进行链式处理。在第一个 .then() 中,我们检查响应的状态码是否为成功状态( ok ),如果不是,则抛出一个错误。
  • 如果响应状态码正常,我们使用 response.json() 方法将响应的主体数据解析为 JSON 格式。
  • 最后一个 .then() 用于处理解析后的数据。
  • 如果在请求过程中发生错误,或任何一个 .then() 中抛出了错误,将进入 .catch() ,在控制台输出错误信息。

类似地,你可以使用 fetch() 函数进行 POST 请求,只需在配置对象中设置请求方法为 'POST' ,并通过 body 属性提供请求体数据。

请注意,Fetch API 默认不会将错误状态(如 404 或 500)视为网络错误。它会将这些状态码视为请求成功,并通过 response.ok 属性进行判断。如果你希望将这些状态码也视为网络错误,可以在第一个 .then() 中进行额外的检查或自定义处理逻辑。

这是使用 JavaScript 内置的 Fetch API 进行网络请求的基本流程。根据具体的需求和场景,你可以进一步使用其他方法和属性来扩展和定制请求和响应的处理。

Edited on Views times
\ No newline at end of file diff --git a/cs/languages/rust/index.html b/cs/languages/rust/index.html index 3d2e133e..6a11242d 100644 --- a/cs/languages/rust/index.html +++ b/cs/languages/rust/index.html @@ -1 +1 @@ -Rust 基础 - 编程语言 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 参考资料

  • Rust 语言圣经 (自称)
    • 锈书
  • 官网

# 环境配置

更新 Rust

bash
rustup update

卸载 Rust

bash
rustup self uninstall

查看版本

bash
rustc --version
## 显示格式
rustc.x.y.z([commit hash] [commit date])

安装 Rust 同时还会安装文档,查看本地文档

bash
rustup doc

# Rust 工具

# 编译器

# rustc

只适合单文件编译

shell
rustc xxx.rs <output>

# cargo

Cargo 是 Rust 的构建系统和包管理工具,适用于较大型项目编译、链接

  • 构建代码
  • 下载依赖的库
  • 构建这些库

创建项目,会创建一个新目录 project 并且初始化一个 git 项目

shell
cargo new project

创建好的项目结构

shell
.
├── .git
├── .gitignore
├── Cargo.toml
└── src
    └── main.rs

检查代码能否通过编译,并不会编译项目,很常用

shell
cargo check

构建项目

shell
cargo build           # 默认为调试模式即 --debug
cargo build --debug   # 同上
cargo build --release # 发布模式,编译出的程序性能更高

运行项目

shell
cargo run           # 默认为调试模式即 --debug
cargo run --debug   # 同上
cargo run --release # 发布模式,编译出的程序性能更高

# 安装依赖库换源

目前 cargo search 无法使用镜像

  • 字节镜像源参考
  • 华科镜像源参考

# 方法一

$HOME/.cargo/config.toml 文件 (没有则创建一个) 添加如下内容:

l toml
# 华科镜像源
[registries]
ustc = { index = "https://mirrors.ustc.edu.cn/crates.io-index/" } 
# 或者
[registries.ustc]
index = "https://mirrors.ustc.edu.cn/crates.io-index/"

或者稀疏索引的方式,要求 cargo >= 1.68 :

toml
[source.ustc-sparse]
registry = "sparse+https://mirrors.ustc.edu.cn/crates.io-index/"

同时需要在项目 cargo.toml 使用注册方式引入依赖库:

toml
[dependencies]
<要引入的包> = { registry = "ustc" }
<要引入的包> = { registry = "rsproxy" }

# 方法二

不需要对项目 cargo.toml 添加配置,只需要 $HOME/.cargo/config.toml 文件 (没有则创建一个) 添加如下内容:

toml
[source.crates-io]
replace-with = 'rsproxy' # 字节跳动镜像源
[source.rsproxy]
registry = "https://rsproxy.cn/crates.io-index" # 镜像源 url

稀疏索引,要求 cargo >= 1.68 :

toml
[source.rsproxy-sparse]
registry = "sparse+https://rsproxy.cn/index/"
[registries.rsproxy]
index = "https://rsproxy.cn/crates.io-index"
[net]
git-fetch-with-cli = true

# 项目结构

# 项目结构要求

  • Cargo.toml 在项目顶层下
  • 源代码都应该在 src 目录下
  • 顶层目录可以放置:README、许可信息、配置文件和其它与程序源码无关的文件

如果创建项目时没有使用 cargo,也可以把项目转化为使用 cargo:

  • 把源代码文件移动到 src 下
  • 创建 Cargo.toml 并填写相应的配置

# Cargo.toml

eg:

toml
[package]
name = "my-project"
version = "0.1.0"
authors = ["fuuzen <fuuzen.github.io>"]
edition = "2024"
[dependencies]
...

# [package]

  • name
  • version
  • authors
  • edition

# [dependencies]

  • crate 包
  • ...

三种描述:

  • 基于 Rust 官方仓库 crates.io ,通过版本说明来描述
  • 基于项目源代码的 git 仓库地址,通过 URL 来描述
  • 基于本地项目的绝对路径或者相对路径,通过类 Unix 模式的路径来描述

eg :

l toml
[dependencies]
rand = "0.3"
hammer = { version = "0.5.0"}
color = { git = "https://github.com/bjz/color-rs" }
geometry = { path = "crates/geometry" }

# 变量和常量

# 变量

# let 变量绑定 (binding)

rust 中 let 表达式的类似其他语言赋值的作用,实际上不是赋值,而叫做 绑定,这与 rust 所有权 这一核心概念有关

默认绑定变量类型为 immutable 不可变的,需要可变则须加上 mut 显式声明

rust
// 使用 let 来声明变量,进行绑定,a 是不可变的
// 此处没有指定 a 的类型,编译器会默认根据 a 的值为 a 推断类型:i32,有符号 32 位整数
// 语句的末尾必须以分号结尾
let a = 10;
// 主动指定 b 的类型为 i32
let b: i32 = 20;
// 这里有两点值得注意:
// 1. 可以在数值中带上类型:30i32 表示数值是 30,类型是 i32
// 2. c 是可变的,mut 是 mutable 的缩写
let mut c = 30i32;
// 还能在数值和类型中间添加一个下划线,让可读性更好
let d = 30_i32;
// 跟其它语言一样,可以使用一个函数的返回值来作为另一个函数的参数
let e = add(add(a, b), add(c, d));

# _ 编译器忽略未使用变量

告诉编译器不要警告未使用的变量,为此可以用下划线作为变量名的开头

rsut
let _a = 5

# let 变量解构

从一个复杂的变量中匹配出部分内容

rust
let (a, mut b): (bool,bool) = (true, false);
//a = true, 不可变;b = false,可变
println!("a = {:?}, b = {:?}", a, b);
b = true;
assert_eq!(a, b);

# 解构式赋值

Rust 1.59 版本后可以在赋值语句的左式中使用元组、切片和结构体模式,不需要 let

struct Struct {
    e: i32
}
fn main() {
    let (a, b, c, d, e);
    (a, b) = (1, 2);
    //_ 代表匹配一个值,但是我们不关心具体的值是什么,因此没有使用一个变量名而是使用了 _
    [c, .., d, _] = [1, 2, 3, 4, 5];
    Struct { e, .. } = Struct { e: 5 };
    assert_eq!([1, 2, 1, 4, 5], [a, b, c, d, e]);
}

这种使用方式跟之前的 let 保持了一致性,但是 let 会重新绑定,而这里仅仅是对之前绑定的变量进行再赋值。

使用 += 的赋值语句还不支持解构式赋值

# 变量遮蔽 (shadowing)

Rust 允许声明相同的变量名,在后面声明的变量会遮蔽掉前面声明的。

变量遮蔽的用处在于,如果你在某个作用域内无需再使用之前的变量(在被遮蔽后,无法再访问到之前的同名变量),就可以重复的使用变量名字,而不用绞尽脑汁去想更多的名字。

  • 可以使用相同的名字声明新的变量,新的变量就会 shadow(隐藏)之前声明的同名变量

  • 在后续的代码中这个变量名代表的就是新的变量

shadow 和把变量标记为 mut 是不一样的:

  • 如果不使用 let 关键字,那么重新给非 mut 的变量赋值会导致编译时错误
  • 而使用 let 声明的同名新变量,也是不可变的
  • 使用 let 声明的同名新变量,它的类型可以与之前不同

# 常量

常量也是绑定到一个常量名且不允许更改的值

# 常量和变量之间的差异

  • 常量不允许使用 mut常量不仅仅默认不可变,而且自始至终不可变,因为常量在编译完成后,已经确定它的值。
  • 常量使用 const 关键字而不是 let 关键字来声明,并且值的类型必须标注

# Rust 常量的命名约定

  • 全部字母都使用大写
  • 使用下划线分隔单词,另外对数字字面量可插入下划线以提高可读性

# 基本类型 (标量)

# 原始类型

# 整数类型

类型定义的形式统一为: 有无符号 + 类型大小(位数)

长度有符号类型无符号类型
8 位i8u8
16 位i16u16
32 位i32u32
64 位i64u64
128 位i128u128
视架构而定isizeusize

# isizeusize 类型

isizeusize 类型的位数由程序运行的计算机的架构所决定:

  • 如果是 64 位计算机,那就是 64 位的
  • 如果是 32 位计算机,那就是 32 位的
  • ...

# 整数字面值

rust 有以下 5 种整数字面类型:

Number literalsExample
Decimal98_222
Hex0xff
Octal0o77
Binary0b1111_0000
Byte (u8 only)b'A'
  • 除了 Byte 类型外,所有的数值字面值都允许使用类型后缀。

    • 例如 57u8
  • 如果不太清楚应该使用那种类型,可以使用 Rust 相应的默认类型

    • 整数的默认类型就是 i32 ,其速度整体上是较快的,即使是在 64 位操作系统中

# 整数溢出

  • 调试模式 (--debug) 下编译:Rust 会检查整数溢出,如果发生溢出,程序在运行时就会 panic

  • 发布模式下(--release)编译:Rust 不会检查可能导致 panic 的整数溢出

    • 如果溢出发生:Rust 会执行 “环绕” 操作:(取模)

      • 例如: u8 的范围是 0-255,如果把一个 u8 变量的值设为 256,那么 Rust 会将 256 变成 0,257 变成 1 ⋯
    • 但程序不会 panic

# 浮点类型

Rust 有两种基础的浮点类型,也就是含有小数部分的类型:

  • f32 ,32 位,单精度
  • f64 ,64 位,双精度

Rust 的浮点类型使用了 IEEE-754 标准来表述

f64默认类型,因为在现代 CPU 上 f64f32 的速度差不多,而且精度更高。

# 布尔类型

  • 符号是 bool
  • Rust 的布尔类型也有两个值:
    • true
    • false
  • 占一个字节大小

Rust 不允许其他类型直接当作布尔类型使用,和其他语言不太一样!

# 字符类型

  • 符号是 char
  • Rust 语言中 char 类型被用来描述语言中最基础的单个字符。
  • 字符类型的字面值使用单引号
  • 占用 4 字节大小
  • 是 Unicode 标量值,可以表示比 ASCII 多得多的字符内容,包括:拼音、中日韩文、零长度空白字符、emoji 表情等。

Unicode 中并没有 “字符” 的概念,所以直觉上认为的字符也许与 Rust 中的概念并不相符

# 基本类型转换

# 隐式

  1. 整数类型之间的转换:Rust 允许在整数类型之间进行隐式转换,只要目标类型的表示范围足够容纳源类型的值。例如,可以将 u8 转换为 u16i32 转换为 u64 等。
  2. 浮点数类型之间的转换:Rust 允许在浮点数类型之间进行隐式转换,只要目标类型能够表示源类型的精度和范围。例如,可以将 f32 转换为 f64
  3. 整数类型到浮点数类型的转换:Rust 允许将整数类型隐式转换为相应的浮点数类型。例如,可以将 i32 转换为 f64
  4. 字面量的隐式转换:在字面量的使用中,Rust 会根据上下文自动进行隐式类型转换。例如,可以将整数字面量 42 隐式转换为 u8i32 或其他整数类型,或将浮点数字面量 3.14 隐式转换为 f32f64

# 显式

Rust 鼓励显式的类型转换,并提供了一些安全的类型转换方法,以确保程序在类型转换时保持安全和可预测。Rust 有三种变量类型显式转换的方法:

  • as 关键字
  • frominto 这些 trait 进行转换
  • 字符串类型可以使用 parse 方法转换到数字类型

# as & as_<T>()

as 运算符转换示例:

t rust
let x: i32 = 5;
let y: u32 = x as u32;

as 运算符还有一个安全版本 as_<T>() ,它会在溢出时返回一个 Option 值。

eg:

rust
fn main() {
    let num: u32 = 42;
    
    // 将 u32 类型转换为 i16 类型
    let converted: Option<i16> = num.as_();
    
    match converted {
        Some(value) => println!("Converted value: {}", value),
        None => println!("Conversion failed"),
    }
}

# From & Into

在 Rust 中, FromInto 是用于自定义类型转换的 trait。通过实现这些 trait,可以定义自定义类型之间的转换规则。

From trait 定义了一个类型转换的关联函数 from() ,用于将其他类型转换为当前类型。

Into trait 则定义了一个类型转换的方法 into() ,用于将当前类型转换为其他类型。

eg:

rust
// 定义一个自定义类型
struct MyType(u32);
// 实现 From trait,将 u32 类型转换为 MyType
impl From<u32> for MyType {
    fn from(value: u32) -> Self {
        MyType(value)
    }
}
// 实现 Into trait,将 MyType 转换为 u32 类型
impl Into<u32> for MyType {
    fn into(self) -> u32 {
        self.0
    }
}
fn main() {
    let num: u32 = 42;
    
    // 使用 From trait 进行转换
    let my_type: MyType = MyType::from(num);
    
    // 使用 Into trait 进行转换
    let back_to_num: u32 = my_type.into();
    println!("MyType: {:?}", my_type);
    println!("Back to u32: {}", back_to_num);
}

# parse

使用 parse 方法将字符串类型转换为数字类型,如整数或浮点数。 parse 方法是定义在 str 类型上的一个函数,它返回一个 Result 枚举类型,表示解析操作的结果。

eg:

rust
fn main() {
    let num_str = "42";
    
    // 将字符串转换为整数类型
    let num: Result<i32, _> = num_str.parse();
    
    match num {
        Ok(n) => println!("Parsed number: {}", n),
        Err(e) => println!("Error: {}", e),
    }
}

# 复合类型

  • 复合类型可以将多个值放在一个类型里。
  • Rust 提供了两种基础的复合类型:元组(Tuple)、数组

# Tuple

  • Tuple 可以将多个类型的多个值放在一个类型里
  • Tuple 的长度是固定的:一旦声明就无法改变
  • Tuple 中的每个位置都对应一个类型, Tuple 中各元素的类型不必相同

# 创建 Tuple

在小括号里,将值用逗号分开

rust
let tup: (132, f64, 48) = (500, 6.4, 1);

# 获取 Tuple 的元素值

可以使用模式匹配来解构(destructure)一个 Tuple 来取元素的值

rust
let (x, y, z) = tup;

# 访问 Tuple 的元素

在 tuple 变量使用点标记法,后接元素的索引号

rust
println!("{} {} {}", tup.O, tup.1, tup.2);

# 数组

  • 数组也可以将多个值放在一个类型里
  • 数组中每个元素的类型必须相同
  • 数组的长度也是固定的

数组没有 Vector 灵活,如果想让你的数据存放在 stack(栈)上而不是 heap(堆)上,或者想保证有固定数量的元素,这时使用数组更有好处

# 数组的类型

数组的类型以这种形式表示: [类型;长度]

# 声明一个数组

两种方法:

  • 在中括号里,各值用逗号分开
  • 如果数组的每个元素值都相同,那么可以定义为: [初始值;长度]
rust
let a = [1, 2, 3, 4, 51];
let a =3;5]
// 它就相当于:let a= [3, 3, 3, 3, 3];

# 访问数组的元素

可以使用索引来访问数组的元素。

如果访问的索引超出了数组的范围,那么:

  • 索引是字面量等,编译器能检查出来,编译不通过
  • 编译器没能检查出来,编译通过
    • 运行会报错(runtime 时会 panic)
    • Rust 不会允许其继续访问相应地址的内存

# 枚举类型

enum 关键字表示枚举类型

# 定义枚举

例如 IP 地址:IPV4、IPv6

rust
enum IpAddrKind {
  V4,
  V6,
}

标准库中的 IpAddr

rust
struct Ipv4Addr {
  // --snip--
struct Ipv6Addr {
  // --snip--
}
enum IpAddr {
  V4(Ipv4Addr),
  V6(Ipv6Addr),
}

# 变体、标识符、枚举值

  • 变体是枚举类型的不同选项或可能的值之一
  • 标识符是用于表示枚举类型的变体的名称
  • 枚举值是通过选择枚举类型的一个变体来实例化的具体值

枚举的变体都位于标识符的命名空间下,使用两个冒号 :: 进行分隔

rust
let four = IpAddrKind::V4;
let six = IpAddrKind::V6;

# 将数据附加到枚举的变体中

rust
enum IpAddr {
  V4(String),
  V6(String),
}
// 每个变体可以拥有不同的类型以及关联的数据量
enum IpAddr {
  V4(u8, u8, u8, u8),
  V6(String),
}
  • 优点:
    • 不需要额外使用 struct
    • 每个变体可以拥有不同的类型以及关联的数据量

# 枚举方法

struct 类似,也使用 impl 关键字

# Option 枚举

  • 定义于标准库中
  • 在 Prelude(预导入模块)中
  • 描述了:某个值可能存在(某种类型)或不存在的情况
# Option<T>

Rust 没有 Null。其它语言中,Null 是一个值,它表示 “没有值”,一个变量可以处于两种状态:空值(nuI)、非空。

Null 引用: Billion Dollar Mistake

Null 的问题在于:当你尝试像使用非 Null 值那样使用 NuIl 值的时候,就会引起某种错误

Null 的概念还是有用的:因某种原因而变无效或缺失的值

Rust 中类似 Null 概念的枚举 Option<T> ,定义如下:

rust
enum Option<T>{
  Some(T),
  None,
}

T 是一个类型参数,代表值的类型。这里出现三个类型都定义在标准库中:

  • Option<T>
  • Some (T)Some 表示存在一个值,并将该值包装在 Some
  • None

Option<T>T 是不同的类型,不可以把 Option<T> 直接当成 T ,例如以下代码会报错:

rust
let x:i8 =5;
let y: Option<i8> = Some(5);
let sum = x + y; // 编译报错:error [E0277]: cannot add `Option<i8>` to `i8`

若想使用 Option<T> 中的 T ,必须将它转换为 T

# 基础控制流

# 选择分支

# if else

rust
if ... {
  ...
} else if ... {
  ...
} else {
  ...
}

如下代码在 rust 编译器环境下会产生报错:

rust
let number = if condition { 5 } else { "6" }

因为返回给 number 的结果类型不确定!

# match

允许一个值与一系列模式进行匹配,并执行匹配的模式对应的代码,模式可以是字面值、变量名、通配符...

match 匹配必须穷举所有的可能,否则会产生报错:

bash
error [E0004]: non-exhaustive patterns:...
  • _ 通配符:替代其余没列出的值
rust
match ... {
  a => (...),
  b => (...),
  _ => (...),
}

# if let

语法的一般形式如下:

rust
if let pattern = expression {
  // 匹配成功的处理逻辑
} else if let pattern = expression {
  // 匹配成功的处理逻辑
} else {
  // 匹配失败的处理逻辑
}

在上述语法中, pattern 是要匹配的模式, expression 是要进行匹配的表达式。如果表达式与模式匹配成功,则执行匹配成功的处理逻辑。如果匹配失败,则执行匹配失败的处理逻辑。

下面是一个示例,展示了如何使用 if let 处理 Option 类型:

rust
fn main() {
    let some_value: Option<i32> = Some(5);
    if let Some(x) = some_value {
        println!("Got value: {}", x);
    } else {
        println!("Value is None");
    }
}

在上述示例中, some_value 是一个 Option<i32> 类型的变量,被赋值为 Some(5) 。通过使用 if let Some(x) = some_value ,我们尝试将 some_value 解构为 Some 并提取其中的值。如果匹配成功,将会执行 println!("Got value: {}", x) ,打印提取到的值。如果匹配失败(即 some_valueNone ),则执行 println!("Value is None")

使用 if let 处理只关心一种匹配而忽略其它匹配的情况,可以使代码更简洁、清晰地处理特定模式的匹配,减少了手动编写 match 表达式的工作量,

可以把 iflet 看作是 match 的语法糖

# 循环

# loop

  • 没有条件判断
  • 使用 break 跳出循环
  • loop 有返回值,为 break 后面的表达式
rust
let result = loop {
  ...
  if ... {
    break (expression) ;
  }
}

# while

rust
while ... {
  ...
}

和其他语言差别不大

# for

loopwhile 更适合遍历容器,更安全、高效

rust
// eg:
let a = [10, 20, 30, 40, 50];
for element in a.iter() {
  println! ("the value is: {}", element);
}

# 所有权 Ownership

# 什么是所有权

Rust 的核心特性就是所有权

所有程序在运行时都必须管理它们使用的计算机内存

  • 有些语言有垃圾收集机制 (GC),在程序运行时,它们会不断地寻找不再使用的内存
  • 还有一些语言,程序员必须显式地分配和释放内存 (eg: C)
  • Rust 采用了第三种方式:
    • 内存是通过一个所有权系统来管理的,其中包含一组编译器在编译时检查的规则
    • 当程序运行时,所有权特性不会减慢程序的运行速度,因为 Rust 的所有权系统将将内存的管理提前到了编译阶段

在像 Rust 这样的系统级编程语言里,一个值是在 stack 上还是在 heap 上对语言的行和你为什么要做某些决定是有更大的影响的。管理 heap 数据就是所有权存在的原因。

# Stack vs Heap

在代码运行的时候,Stack 和 Heap 都是你可用的内存,但他们的结构很不相同:

  • Stack

    • Stack 按值的接收顺序来存储,按相反的顺序将它们移除(后进先出,LIFO)

      • 添加数据叫做压入栈 push
      • 移除数据叫做弹出栈 pop
    • 所有存储在 Stack 上的数据必须拥有已知的固定的大小

      • 因为指针是已知固定大小的,可以把指针存放在 stack 上。但如果想要实际数据,你必须使用指针来定位,然后访问 heap
    • 把数据压到 stack 上要比在 heap 上分配快得多,因为操作系统不需要寻找用来存储新数据的空间,那个位置永远都在 stack 的顶端

    • 如果数据存放的距离比较近,那么处理器的处理速度就会更快一些

  • Heap

    • 当你把数据放入 heap 时,你会请求一定数量的空间,这个过程叫做在 heap 上进行分配,有时仅仅称 “分配”。在 heap 上分配空间需要做更多的工作

      • 操作系统在 heap 里找到一块足够大的空间
      • 然后要做好记录方便下次分配,把它标记为在用
      • 并返回一个指针,也就是这个空间的地址
    • 编译时大小未知的数据或运行时大小可能发生变化的数据必须存放在 heap 上

    • 如果数据之间的距离比较远,那么处理速度就会慢一些

所有权解决的问题:

  • 跟踪代码的哪些部分正在使用 heap 的哪些数据
  • 最小化 heap 上的重复数据量
  • 清理 heap 上未使用的数据以避免空间不足。

掌握了所有权,那么就不需要经常去想 stack 或 heap 了

# 所有权规则

# 三条规则

  • 每个值都有一个变量,这个变量是该值的所有者
  • 每个值同时只能有一个所有者
  • 当所有者超出作用域(scope)时
    • 它拥有它的值的所有权,就会被 drop 函数清理 (heap 上的数据)
    • 它没有它的值的所有权,不会清理

# 返回值与作用域

函数在返回值的过程中同样也会发生所有权的转移,返回表达式的值的所有权将转移到函数结果所赋值的变量上

# 复制 Copy trait

用于像整数这样完全存放在 stack 上面不包含 heap 上的简单数据类型(标量)

  • 如果一个类型实现了 Copy 这个 trait ,那么旧的变量在赋值后仍然可用
  • 如果一个类型或者该类型的一部分实现了 Drop trait ,那么 Rust 不允许让它再去实现 Copy trait
rust
let x = 5;
let y = x;
//x 和 y 都是有效的
println! ("{} {}", x, y);

# 移动 Move

多个变量可以与同一个数据使用一种独特的方式 Move 来交互

String 类型为例

rust
let s1 = String::from ("hello"); 
let s2 = s1;

当把 s1 赋给 s2String 在 stack 上的数据被复制了一份,heap 内容不变

string-move

s1s2 离开作用域时,它们都会尝试释放相同的内存,就会导致二次释放 (double free) bug 。为了避免这个问题,Rust 会让原来的 s1 失效 ,此后当 s1・离开作用域的时候,Rust 不需要释放任何东西。

s1 此后处于 moved 状态,即失效。

  • 浅拷贝(shallow copy)
    • 只拷贝 stack 上的数据,有可能产生二次释放 (double free) bug
  • 深拷贝(deep copy)
    • 同时拷贝 stack 和 heap 上的数据

Rust 中采用的是第三种 “拷贝”,也就是 ** 移动 Move **,在浅拷贝的基础上让原来的 stack 数据失效。

这体现了 Rust 隐含的一个设计原则:Rust 不会自动创建数据的深拷贝。就运行时性能而言,任何自动赋值的操作都是廉价的。

# 克隆 CLone

针对包含 heap 数据的矢量数据类型,相当于深拷贝

rust
let s1 = String::from("Hello");
let s2 = s1.clone();

string-clone

# 引用 Reference

& 符号就表示引用,允许引用该值而不取得其所有权;

对应的解引用符号是 *

和 C/C++ 一样,Rust 引用是符号是 & ,解引用符号是 *

string-reference

Rust 中的引用在任何给定的时刻,引用必须一直有效 (非悬空引用),只能满足下列条件之一:

  • 一个可变的引用
  • 任意数量不可变的引用

# 可变引用 Mutable Reference

Rust 支持可变引用 ,用 &mut 符号代替 & 即为可变引用。

但是可变引用有以下几个限制:

  • 在特定作用域内,对于某一块数据,只能有一个可变引用
  • 不可以同时拥有可变引用和不可变引用
  • (多个不变的引用是可以的)

第一个限制的好处是可在编译时防止数据竞争。违反将出现如下报错:

bash
error[E0499]: cannot borrow 'xxx' as mutable more than once at a time

第二个限制避免了可变引用对不可变引用的影响。违反将出现如下报错:

bash
error[E0502]: cannot borrow 'xxx' as mutable because it is also borrowed as immutable

::: infromation

以下三种行为下会发生数据竞争:

  • 两个或多个指针同时访问同一个数据
  • 至少有一个指针用于写入数据
  • 没有使用任何机制来同步对数据的访问

数据竞争在运行时是很难发现的(C/C++ 里经常出现),所以 Rust 从根本上避免了这种问题来保证运行时的安全性

:::

可以通过创建新的作用域,来允许非同时的创建多个可变引用

rust
fn main () {
  let mut s = String:: from "Hello");
	{
	  let s1 = &mut s;
	}
  let s2 = &mut s;
}

# 悬空引用 Dangling Reference

也叫悬垂引用,在 Rust 里,编译器可保证引用永远都不是悬空引用。如果你引用了某些数据,编译器将保证在引用离开作用域之前数据不会离开作用域。对于任何出现的悬空引用, Rust 在编译阶段就会报错:

bash
error[E0106]: missing lifetime specifier

悬空指针(Dangling Pointer):一个指针引用了内存中的某个地址,而这块内存可能已经释放并分配给其它人使用了。

# 借用 Borrow

引用作为函数参数这个行为叫做借用 ,本质上就是引用。

rust
fn main () {
  let mut s1 = String::from("Hello");
  let len = calculate_length(&mut s1);
  println!("The length of '{}' is {}.", s1, len);
}
fn calculate_length(s: &mut String) -> usize {
  s.push_str(", world");
  s.len()
}

# 切片类型 slice

Rust 的另外一种不持有所有权的数据类型

# 字符串切片

字符串切片是指向字符串中一部分内容的引用

形式: [开始索引..结束索引]

  • 开始索引就是切片起始位置的索引值,若不写则默认为 0
  • 结束索引是切片终止位置的下一个索引值,若不写则默认为 String 的 Capacity
rust
fn main(){
  let s = String::from("Hello world");
  let hello = &s[0..5]; // 左闭右开
  let world = &s[6..11];// 左闭右开
}

string-slice

字符串切片的范围索引必须发生在有效的 UTF-8 字符边界内

如果尝试从一个多字节的字符中创建字符串切片,程序会报错并退出

字符串字面值实际上就是字符串切片 String slice

rust
//s 的类型是 &str
let s = "Hello, World!"

⭐️ 将字符串切片作参数传递

rust
fn first_words:(&String) -> &str {}

对于这样接受字符串作为参数的函数,有经验的 Rust 开发者会采用 &str 作为参数类型,因这样就可以同时接收 String
和 &str 类型的参数了:

rust
fn first_words:(&str) -> &str {}
  • 使用字符串切片,直接作为参数调用该函数 first_words(mystr)
  • 使用 String,可以创建一个完整的 String 切片作为参数来调用该函数 firstwords(&mystr[..])

定义函数时使用字符串切片来代替字符串引用会使我们的 API 更加通用,且不会损失任何功能。

# 数组切片

rust
let a = [1, 2, 3, 4, 5];
let slice = &a[1..3];

# 矢量变量

# String 类型

字符串字面值是程序里手写的那些字符串值,它们是不可变的、硬编码的。

Rust 还有第二种字符串类型: Sting

String 比那些基础标量数据类型更复杂,在 heap 上分配。能够存储在编译时未知数量的文本。

# 数据结构

一个 String 由 stack 上的 3 部分组成:

  • 一个指向存放字符串内容的内存的指针
  • 长度 len,就是存放字符串内容所需的字节数
  • 容量 capacity ,是 String 从操作系统总共获得内存的总字节数

存放字符串内容的部分在 heap 上

string"hello"

# 创建 String 类型的值

可以使用 from 函数从字符串字面值创建出 String 类型

rust
let s = String::from("hello");

:: 表示 fromString 类型下的函数

这类字符串是可以被修改的

# Vector 类型

# struct

# struct 基础操作

# 定义 struct

  • 使用 struct 关键字,并內整个 struct 命名
  • 在花括号内,为所有字段(Field)定义名称和类型
rust
struct User {
  username: String,
  email: String,
  sign_in_count: u64,
  active: bool,
}

# 实例化 struct

想要使用 struct ,需要创建 struct 的实例:

  • 每个字段指定具体值
  • 无需按声明的顺序进行指定
rust
let user1 = User {
  email: String::from("someone@example.com"),
  username: String::from("someusername123"),
  active: true,
  sign_in_count: 1,
}

一旦 struct 的实例是可变的,那么实例中所有的字段都是可变的

# 取得 struct 里面的某个值

使用点标记法:

rust
user1.email = String::from("anotheremail@example.com");

# 字段初始化简写

字段名与字段值对应变量名相同时,就可以使用字段初始化简写的方式:

rust
fn build_user(email: String, username: String) -> User {
  User {
    email,
    username,
    active: true,
    sign_in_count: 1,
  }
}

# struct 更新语法

当你想基于某个 struct 实例来创建一个新实例的时候,可以使用 struct 更新语法:

rust
// 不使用 struct 更新语法
let user2 = User {
  email: String::from("another@example.com"),
  username: String::from("anotherusername567"),
  active: user1.active,
  sign_in_count: user1.sign_in_count,
}
// 使用 struct 更新语法
let user2 = User {
  email: String::from("another@example.com"),
  username: String: from ("anotherusername567"),
  ..user1
};

# debug 阶段打印 struct

rust
#[derive(Debug)] // 添加注解,表示派生自 Debug 这个 trait
...
println!("{:?}", mystruct);// 输出为一行,不够清晰直观
println!("{:#?}", mystruct);// 输出结构化信息,更清晰直观

# struct 数据的所有权

rust
struct User {
  username: String,
  email: String,
  sign_in_count: u64,
  active: bool,
}

这里的字段使用了 String 而不是 &str:

  • struct 实例拥有其所有的数据
  • 只要 struct 实例是有效的,那么里面的字段数据也是有效的
  • struct 里也可以存放引用,但这需要使用生命周期

# struct 的方法

Rust 是一个多范式的语言,也支持面向对象编程

使用 impl 关键字:

rust
impl mystruct {
  fn ... (&self, ...){
    
  }
  ...
}

Rust 方法与函数不同之处:

  • 方法是在 struct (或 enumtrait 对象)的上下文中定义
  • 第一个参数是 self ,表示方法被调用的 struct 实例

# struct 扩展定义

# tuple struct

Rust 可定义类似 tuplestruct ,叫做 tuple struct

Tuple struct 整体有个名字,但里面的元素没有名字

适用于想给整个 tuple 起名,并让它不同于其它 tuple ,而且又不需要给每个元素起名

# 定义 tuple struct

使用 struct 关键字,后边是名字,以及里面元素的类型

rust
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
//black 和 origin 是不同的类型,是不同 tuple struct 的实例

# Unit-Like Struct

可以定义没有任何字段的 struct,叫做 Unit-Like struct(因为与空元组 () 也就是单元类型类似)

适用于需要在某个类型上实现某个 trait,但是在里面又没有想要存储的数据

# Package, Crate, Module

Rust 的模块系统:

  • Package(包):Cargo 的特性,让你构建、测试、共享 crate
  • Crate(单元包):一个模块树,它可产生一个 library 或可执行文件
  • Module(模块): use :让你控制代码的组织、作用域、私有路径
  • Path(路径):为 structfunctionmodule 等项命名的方式

# Package

一个 Package 包含:

  • 1 个 Cargo.toml ,它描述了如何构建这些 Crates
  • 必须至少包含一个 crate (library 或 binary)
    • 只能包含 0-1 个 library crate
    • 可以包含任意数量的 binary crate

# Package 项目结构

这些是 Cargo 的惯例

  • 一个 Package 包含一个 binary crate src/main.rssrc/lib.rs

    • src/main.rs 即为唯一的 binary crate
      • binary crate 的 crate root
  • 一个 Package 可以包含多个 binary crate

    • src/bin 下每个文件是单独的 binary crate
  • 一个 Package 包含 0 或 1 个 library crate

    • src/lib.rs 存在则包含 1 个 library crate ,否则不包含
    • library crate 的 crate root

crate 名与 package 名 ( name ) 相同

Cargo 把 crate root 文件交给 rustc 来构建 library 或 binary

# Crate

Crate 的作用:将相关功能组合到一个作用域内,便于在项目间进行共享,防止冲突

Crate 的类型有两类:

  • binary
  • library

Crate Root 是源代码文件,Rust 编译器从这里开始,组成 Crate 的根 Module

src/main.rssrc/lib.rs 叫做 crate roots

# Module

其作用在于:

  • 在一个 crate 内,将代码进行分组
  • 增加可读性,易于复用
  • 控制项目(item)的私有性(public、private)

# 建立 module

使用 mod 关键字

  • 可嵌套
  • 可包含其它项( structenum 、常量、 trait 、函数等)的定义

# 私有边界(privacy boundary)

模块不仅可以组织代码,还可以定义私有边界。如果想把 函数 或 struct 等设为私有,可以将它放到某个模块中。只要是在 mod 里,Rust 中所有的条目(函数,方法, structenum ,模块,常量)默认是私有的。

:::

这里的条目包括:函数,方法, structenum ,模块,常量等所有可以被引用、调用的东西

:::

  • 父级模块无法访问子模块中的私有条目
  • 子模块里可以使用所有祖先模块中的条目
  • 文件的根级无论是私有还是公共的都可以互相调用

# pub 关键字

使用 pub 关键字来将某些条目标记为公共的

rust
mod front_of_house {
  pub mod hosting {
    pub fn add_to_waitlist() {}
  }
}
pub fn eat_at_restaurant() {
  crate::front_of_house::hosting::add_to_waitlist(); // 绝对路径调用
  front_of_house::hosting::add_to_waitlist(); // 相对路径调用
}

pubstruct 使用, struct 内所有成员仍然默认是私有的!

pubenum 使用, enum 内所有成员就都是公共的!

# Path

为了在 Rust 的模块中找到某个条目,需要使用路径。路径有两种形式:

  • 绝对路径:从 crate root 开始,使用 crate 名 或字面值 crate
  • 相对路径:从当前模块开始,使用 selfsuper 或当前模块的标识符

路径至少由一个标识符组成,标识符之间使用 ::

# super 关键字

类似文件系统中的 .. 表示上一级目录, super 表示用来访问父级模块路径中的内容。

rust
fn serve_order() {}
mod back_of__house {
  fn fix_incorrect_order {
    cook_order();
    super::serve_order();
  }
  fn cook_order() {}
}

# use 关键字

use 关键字将路径导入到作用域内,仍遵循私有性原则,即只有公共部分才能使用

rust
mod front_of_house {
  pub mod hosting {
    pub fn add_to_waitlist() {}
  }
}
// 绝对路径:
use crate::front_of_house::hosting; 
// 相对路径:
use front_of_house::hosting; 
// 默认导入到当前文件 (crate) 作用域内
// 此后 hosting 等效于如下效果:
mod hosting() {}

Rust 惯用做法:并不直接 use 导入函数本身,而是导入函数的父模块,通过父模块调用函数,以此来表示这个函数不是本地定义的,而是从其他地方导入的。

但对于 struct , enum 则是直接导入它们本身,除非出现同名条目,则只好导入它们的父级模块来区分它们,或者用 as 关键字为他们取别名。

# pub use 重导出

use 导入的是在本文件作用域内的私有的模块

该用 pub use 关键字则外部代码导入本 文件时也能使用这些模块

# 外部包和标准库

外部包以及标准库 ( std ) 的使用需要:

  1. Cargo.tomldependencies 添加依赖的包;标准库 ( std ) 也被当做外部包但不需要这一步
  2. use 将特定条目引入作用域,外部包和标准库都需要。

# 嵌套路径

如果使用同一个包或模块下的多个条目,可以使用嵌套路径清理大量的 use 语句

rust
use 路径相同的部分::{self, 到包1路径差异的部分, 到包2 路径差异的部分, ...}
// 当需要导入路径相同部分所指向的包本身时可以用 self

eg :

rust
use std::io;
use std::io::Write;
// 上面代码等效于下面
use std::io::{self, Write}

# 通配符 *

使用 * 可以把路径中所有的公共条目都引入到作用域。 但注意要谨慎使用。

应用场景:

  • 测试,将所有被测试代码引入到 tests 模块
  • 有时被用于预导入(prelude)模块

# 将模块内容移动到其它文件

模块定义时,如果模块名后边是 ; ,而不是代码块:

  • Rust 会从与模块同名的文件中加载内容
  • 模块树的结构不会变化

这里我详细解释我讲不清楚,也懒得写了🤯

# 常用集合

# Vec<T>

# 创建

Vec::new() 函数

vec!

# 更新

push 方法,注意是可变引用

# 删除

与任何其它 struct v 一样,当 Vec 离开作用域后

  • 它就被清理掉了
  • 它所有的元素也被清理掉了

# 读取

下标索引

get 方法 ,返回 Option<T> 类型,与 match 搭配

# 遍历

rust
for element in my_vector {
  ...element...
}
for element in &my_vector {
  ...*element...
}
for element in &mut my_vector {
  ...*element...
}

# String

Rust 开发者经常会被字符串困扰的原因

  • Rust 倾向于暴露可能的错误
  • 字符串数据结构复杂
  • UTF-8

Rust 选择将正确处理 String 数据作所有 Rust 程序的默认行为

  • 缺点:程序员必须在处理 UTF-8 数据之前投入更多的精力

  • 优点:可防止在开发后期处理涉及非 ASCII 字符的错误

# 区分字符串和 String

字符串是什么

  • Rust 的核心语言层面,只有一个字符串类型:字符串切片 str(或 &str)
  • 字符串切片:对存储在其它地方、UTF-8 编码的字符串的引用
    • 字符串字面值:存储在二进制文件中,也是字符串切片

String 类型是什么

  • 来自 标准库 而不是 核心语言
  • 可增长、可修改、可拥有

二者都采用 UTF-8 編码。

Rust 的标准库还包含了很多其它的字符串类型,例如: OsStringOsStrGStrngCStr ... 它们可能使用了不同的编码。通常 String 结尾的是可获得所有权的; Str 结尾的是可借用的。

String 的本质是对 Vec<u8> 的包装,很多 Vec<T> 的操作都可用于 String

# 创建

String::new() 函数

to_string() 方法,可用于实现了 Display trait 的类型,包括字符串字面值

String::from() 函数

# 更新

push_str( xxx : &str ) 方法,把一个字符串切片附加到 String 后面,注意是可变引用,传入的参数是不获取所有权的借用

push( x : char ) 方法,把单个字符附加到 String 后面,注意是可变引用,传入的参数是不获取所有权的借用

+ 运算符,连接两个字符串 ,注意必须满足: String = String + &strString = String + &String会取得 + 左边字符串的所有权

这里 + 运算符使用了类似这个签名的方法 fn add(self, s:&str)-> String{..}

标准库中的 add 方法使用了泛型 ;本来只能 String = String + &str ,但这里出现了解引用强制转換(deref coercion),从而可以 String = String + &String

format! 宏,连接多个字符串,不会取得任何参数的所有权

rust
let s3 = s1 + "-" + &s2 + "_" + &s3;
// 等效于
let s3 = format!("{}-{}-{}", s1, s2, s3);

# 读取

Rust 的字符串不支持索引语法访问,原因在于采用的是 UTF-8 编码,很多语言的字符并不能只通过一个字节表示,这些字符专业术语叫 Unicode 标量值,例如汉字需要 3 个字节。

Rust 的字符串不支持索引语法访问的另外一个原因在于索引操作应消耗一个常量时间 O(1) ,而 String 无法保证:需要遍历所有内容,来确定有多少个合法的字符。

len() 方法,返回字符串长度

# 删除

[..] 切片,由于上述 UTF-8 编码的原因,虽然编译通过,但对于很多语言的字符,如果切割时跨越了字符边界就会 出现 panic

# 遍历

Rust 有三种看待字符串的方式:

  • Bytes, 字节,可以用 bytes 方法返回迭代器遍历
  • Scalar Values, 标量值,可以用 chars 方法返回迭代器遍历
  • Grapheme Clusters, 字形簇(最接近所谓的 “字母”),比较复杂,标准库未提供

# HashMap<K,V>

HashMap 用的较少,不在 Prelude 中,所以要使用它就需要 use std::collections::HashMap ; 标准库对其支持较少,没有内置的宏来创建 HashMap

注意 HashMap 数据存储在 heap 上。

HashMap 时同构的,即一个 HashMap 中:

  • 所有的 K 必须是同一种类型
  • 所有的 V 必须是同一种类型

# 创建

HashMap::new() 函数

collect() 方法, collect() 方法可以把数据整合成很多种集合类型,包括 HashMap ,返回值需要显式指明类型

  • 在元素类型 Vec<Tuple> 上使用 collect() 方法,可以组建一个 HashMap ,要求有两个 Tuple :一个作为 K ,一个作为 V

  • eg :

  • rust
    use std::collections::HashMap;
    fn main () {
      let teams = vec![String::from("Blue"), String::from("Yellow")];
      let intial_scores = vec! [10, 50];
    	let scores: HashMap<_, _> = teams.iter().zip(intial_scores.iter()).collect();
    }

# 更新

insert() 方法

  • 替换现有的 V

    • 如果向 HashMap 插入一对 KV ,然后再插入同样的 K ,但是不同的 V ,那么原来的 V 会被替换掉
  • 只在 K 不对应任何值的情况下,才插入 V

    • entry() 方法:检查指定的 K 是否对应一个 V
      • 参数为 K`
      • 返回 enum Entry :代表值是否存在
    • or_insert() 方法:
      • 当返回 enum Entry 代表值不存在,即 EntryVacantEntry 变体,将方法参数作为 K 的新值插进去,返回到这个值的可变引用
      • 否则返回到对应的 V 的一个可变引用
rust
scores.entry(String::from("Blue")).or_insert(50);

# 所有权

  • 对于实现了 Copy trait 的类型(例如 i32 ),值会被复制到 HashMap
  • 对于拥有所有权的值(例如 String ),值会被移动,所有权会转移给 HashMap
  • 如果将值的引用插入到 HashMap ,值本身不会移动,在 HashMap 有效的期间,被引 用的值必须保持有效
rust
use std:: collections:: HashMap;
fn main() {
  let field_name = String::from("Favorite color");
  let field_value = String::from("Blue");
  let mut map = HashMap::new();
  map.insert(&field_name, &field_value);
	println!("{}: {}", field_name, field_value);// 这一句可以通过编译
	map.insert(field_name, field_value);
	println!("{}: {}", field_name, field_value);// 这一句无法通过编译

# 读取

get() 方法,借用一个参数 K ;返回类型为 Option<&V>

rust
match scores.get(&String::from("Blue")) {
  Some(s) => println!("{}", s),
  None => println!("team not exist"),
}

# 遍历

for 循环 + 模式匹配

rust
for (k, v) in &scores {
  printin! ("{}: {}", k, v);
}

# Hash 函数

默认情况下, HashMap 使用加密功能强大的 Hash 函数,可以抵抗拒绝服务(DoS)攻击。它具有如下特点:

  • 不是可用的最快的 Hash 算法
  • 但具有更好安全性。

可以指定不同的 hasher 来切换到另一个函数。

  • hasher 是实现 BuildHasher trait 的类型

# 错误处理

错误处理体现了 Rust 的可靠性,大部分情况下在编译时提示错误并处理。

Rust 没有类似异常的机制。

错误的分类:

  • 可恢复错误:文件未找到,可再次尝试
    • 返回 Result<T , E>
  • 不可恢复错误,bug,例如访问的索引超出范围
    • 调用 panic!

# 不可恢复错误

panic! 宏执行:

  • 程序会打印一个错误信息,可自定义,即传递给 panic!&str 类型字符串
    • 调试 (默认 --debug ) 模式下才会打印
    • --release 模式下不会打印
  • 执行以下两个操作之一
    • (默认) 程序展开调用栈(工作量大)
      • Rust 沿着调用栈往回走
      • 清理每个遇到的函数
    • 立即中止调用栈
      • 不进行清理,直接停止程序
      • 内存需要 OS 进行清理
  • 退出程序

想让二进制文件更小,把设置从 “展开” 改为 “中止”,只需在 Cargo.toml 文件下增加:

toml
[profile.release]
panic = 'abort'

将环境变量 RUST_BACKTRACE 设置为

  • 0 ,使 panic! 报错指出源代码出错的地方,即开发者所写的代码中
  • 1 ,使 panic! 报错指出真正出错的地方,即依赖的代码中,它将回溯,打印出包含错误点的所有调用函数的列表
  • full ,比 1 更加详细

# 可恢复错误

rust
enum Result<T, E> {
  Ok(T),
  Err(E),
}
  • T :操作成功情况下, Ok 变体里返回的数据的类型
  • E :操作失败情况下, Err 变体里返回的错误的类型

match 表达式处理

Option 枚举一样,Result 及其变体也是由 prelude 带入作用域

rust
use std::fs::File;
// simple demo
fn main() {
  let f = File::open("hello.txt");
  let f = match f {
    Ok(file) => file,
    Err(error) => {
      panic!("Error opening file {:?}", error);
    }
  };
}
// complex demo
fn main() {
  let f = File::open( "hello.txt");
  let f = match f {
    Ok(file) => file,
    Err(error) => match error.kind() {
      ErrorKind::NotFound => match File::create("hello.txt") {
        Ok(fc) => fc,
        Err(e) => panic!("Error creating file: {:?}", e),
      }
      other_error => panic!("Error opening the file: {:?}", other_error),
    },
  };
}

闭包处理

rust
let f = File::open ("hello.txt").unwrap_or_else(|error| {
  if error.kind() == ErrorKind::NotFound {
    File::create( "hello.txt").unwrap_or_else(|error| {
      panic!("Error creating file: {:?}", error);
    })
  } else {
    panic! ("Error opening file: {:?}", error);
  }
});

unwrap() 方法,是 match 方法处理 Result<T, E> 的快捷方式,但是无法自定义错误信息

rust
let f = File::open("hello.txt");
let f = match f {
  Ok(file) => file,
  Err(error) => {
    panic!("Error opening file {:?}", error);
  }
};
// 等价于
let f = File::open("hello.txt").unwrap();

expect() 方法,在 unwrap 的基础上,支持 自定义错误信息

# 传播错误

? 用于快捷地传播错误

  • 如果 Result<T, E>Ok : Ok 中的值就是表达式的结果,然后继续执行程序
  • 如果 Result<T, E>Err : Err 本身 就是整个函数的返回值,就像使用了 return
rust
fn read username_from_file() -> Result<String, io::Error> {
  let f = File::open("hello.txt");
  let mut f = match f {
    Ok(file) => file,
    Err(e) => return Err(e),
  };
  let mut s = String::new();
  match f.read_to_string(&mut s) {
    Ok(_) => Ok(s),
    Err(e) => Err(e)
// 相当于 Err (e) => return Err (e),
  }
}
// 等价于
fn read username_from_file() -> Result<String, io::Error> {
  let f = File::open("hello.txt")?;
  let mut s = String::new();
  f.read_to_string(&mut s)?;
  Ok(s)
}
// 链式调用优化
fn read username_from_file() -> Result<String, io::Error> {
  let mut s = String::new();
  File::open("hello. txt")?.read_to_string(&mut s)?;
  Ok(s)
}

?from 函数

trait std::convert::From 上的 from 函数用于错误之间的转换

  • ? 所应用的错误,会隐式的被 from 函数处理
  • ? 调用 from 函数时它所接收的错误类型会被转化为当前函数返回类型所定义的错误类型

适用于要求针对不同错误原因,返回同一种错误类型,需要 每个错误类型实现了转换为所返回的错误类型的 from 函数

? 运算符与 main 函数

? 返回类型只能是 Result<T, E>Option<T> 或任何实现了的 Try 类型

main 函数返回类型是: () ,不能直接返回 ? 运算符的结果

main 函数的返回类型也可以是:Result<T,E> ,可以定义其返回 Box<dyn Error> ,这是 trait 对象,简单理解:“任何可能的错误类型”

rust
use std::fs::File;
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
  let f = File::open ("hello.txt")?;
  Ok(())
}

# 数据类型有效性检查

panic! 的主要应用场景之一,自定义结构体方法(以下 demo 是 new )来处理数据是否有效

t rust
pub struct Guess {
  value: i32,
}
impl Guess {
  pub fn new(value: i32) -> Guess {
    if value <1 || value > 100 {
      panic!("Guess value must be between 1 and 100, got {}", value);
    }
    Guess { value }
  }
  pub fn value(&self) -> i32 {
    self.value
  }
}

getter :返回字段数据

# 抽象化

# 泛型

泛型类似 C++ 的模版可以提高代码复用能力,处理重复代码的问题

泛型是具体类型或其它属性的抽象代替,你编写的代码不是最终的代码,而是一种模板,里面有一些 “占位符”,编译器在编译时将 “占位符” 替换具体的类型。

占位符的声明:

  • 定义函数时,在 fn 函数名 的后面用 <T, K, ...> 尖括号声明

  • 定义结构体时,在 struct 结构体名 的后面用 <T, K, ...> 尖括号声明

  • 定义枚举类型时,在 enum 枚举类型名 的后面用 <T, K, ...> 尖括号声明

  • 定义方法时,若结构体 / 枚举类型是用泛型定义的,则也需要声明占位符或类型

    • rust
      impl<T> Point<T> { // 在类型 T 上实现方法
        fn x(&self) -> &T {
          &self.x
        }
      }
    • rust
      impl Point<i32> { // 只针对具体类型实现方法
        fn x1(&self) -> i32 {
          &self. X
        }
      }
    • struct 里的泛型类型参数可以和方法的泛型类型参数不同

例如: fn largest<T>(list:&T) -> T{...}T 就是一个泛型占位符

当出现需要太多类型参数,代码往往 需要重组为多个更小的单元

单态化(monomorphization)

Rust 在编译时将泛型替换具体类型,这一过程叫单态化,使泛型代码性能与非泛型代码无异

# trait

Rust 中的 trait 是抽象的定义共享行为,与其它语言的接口 (interface) 类似,但有些区别,它告诉 Rust 编译器某种类型具有哪些并且可以与其它类型共享的功能

trait bounds (约束):泛型类型参数指定为实现了特定行为的类型

# 定义 trait

trait 的定义:把方法签名放在一起,来定义实现某种目的所必需的一组行为。

  • 关键字: trait
  • 只有方法签名,没有具体实现
  • trait 可以有多个方法:每个方法签名占一行,以 ; 结尾
  • 实现该 trait 的类型必须提供具体的方法实现
rust
pub trait MyTrait {
  fn my_trait_function(&self) -> ... ;
}

# 实现 trait

在类型上实现 trait 与为类型实现方法类似。格式:

rust
impl MyTrait for MyStruct1 {
  fn my_trait_function(&self) -> ... {
    ...
  }
}
impl MyTrait for MyStruct2 {
  fn my_trait_function(&self) -> ... {
    ...
  }
}

这样的实现实际上叫做重写实现

# 约束

可以在某个类型上实现某个 trait 的前提条件是:这个类型或这个 trait 是在本地 crate 里定义的。

也就是无法外部类型来实现外部的 trait ,这个限制是程序属性的一部分(也就是一致性)。

更具体地说是孤儿规则:之所以这样命名是因为父类型不存在。

此规则的目的和原因:

  • 确保其他人的代码不能破坏您的代码,反之亦然。
  • 如果没有这个规则,两个 crate 可以为同一类型实现同一个 trait ,Rust 就不知道应该使用哪个实现了

# 默认实现

在定义 trait 的时候,不再只是函数签名,而是直接实现该函数,那么这个实现就是所有类型可以调用(虽然不一定正确)的默认实现

注意:

  • 默认实现的方法可以调用 trait 中其它的方法,即使这些方法没有默认实现
  • 无法从方法的重写实现里面调用默认的实现

# 项目结构惯例

trait 的定义和实现常放在 src/lib.rs ,并加上 pub 关键字 ,在其他文件通过 use package_name::trait_name 导入

# trait 作为参数

# impl trait

适用于简单情况,实际上 impl trait 语法是 trait bound 的语法糖

rust
pub fn notify(item: impl MyTrait) {
  //notify 这个函数将只能使用实现了 MyTrait 的类型作为参数 item
}

# trait bound

可用于复杂情况

rust
pub fn notify<T: MyTrait>(item1: T, item2: T, ... ) {
  //notify 这个函数将只能使用实现了 MyTrait 的类型作为参数 item1,item2...
}

# 实用包、crate

# std::env

args 函数收集传入程序的参数

collect 方法可以将参数按空格分割转化为 Vec<String>

rust
use std::env;
fn main () {
  let args: Vec<String> = env::args().collect();
  //env::args_os () //OsString 迭代器
  println! ("{:?}", args);
}

# std::fs

file system 缩写,显然是处理文件相关的模块

read_to_string(filename) 函数读取 filename 路径的文件

Edited on Views times
\ No newline at end of file +Rust 基础 - 编程语言 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 参考资料

  • Rust 语言圣经 (自称)
    • 锈书
  • 官网

# 环境配置

更新 Rust

bash
rustup update

卸载 Rust

bash
rustup self uninstall

查看版本

bash
rustc --version
## 显示格式
rustc.x.y.z([commit hash] [commit date])

安装 Rust 同时还会安装文档,查看本地文档

bash
rustup doc

# Rust 工具

# 编译器

# rustc

只适合单文件编译

shell
rustc xxx.rs <output>

# cargo

Cargo 是 Rust 的构建系统和包管理工具,适用于较大型项目编译、链接

  • 构建代码
  • 下载依赖的库
  • 构建这些库

创建项目,会创建一个新目录 project 并且初始化一个 git 项目

shell
cargo new project

创建好的项目结构

shell
.
├── .git
├── .gitignore
├── Cargo.toml
└── src
    └── main.rs

检查代码能否通过编译,并不会编译项目,很常用

shell
cargo check

构建项目

shell
cargo build           # 默认为调试模式即 --debug
cargo build --debug   # 同上
cargo build --release # 发布模式,编译出的程序性能更高

运行项目

shell
cargo run           # 默认为调试模式即 --debug
cargo run --debug   # 同上
cargo run --release # 发布模式,编译出的程序性能更高

# 安装依赖库换源

目前 cargo search 无法使用镜像

  • 字节镜像源参考
  • 华科镜像源参考

# 方法一

$HOME/.cargo/config.toml 文件 (没有则创建一个) 添加如下内容:

l toml
# 华科镜像源
[registries]
ustc = { index = "https://mirrors.ustc.edu.cn/crates.io-index/" } 
# 或者
[registries.ustc]
index = "https://mirrors.ustc.edu.cn/crates.io-index/"

或者稀疏索引的方式,要求 cargo >= 1.68 :

toml
[source.ustc-sparse]
registry = "sparse+https://mirrors.ustc.edu.cn/crates.io-index/"

同时需要在项目 cargo.toml 使用注册方式引入依赖库:

toml
[dependencies]
<要引入的包> = { registry = "ustc" }
<要引入的包> = { registry = "rsproxy" }

# 方法二

不需要对项目 cargo.toml 添加配置,只需要 $HOME/.cargo/config.toml 文件 (没有则创建一个) 添加如下内容:

toml
[source.crates-io]
replace-with = 'rsproxy' # 字节跳动镜像源
[source.rsproxy]
registry = "https://rsproxy.cn/crates.io-index" # 镜像源 url

稀疏索引,要求 cargo >= 1.68 :

toml
[source.rsproxy-sparse]
registry = "sparse+https://rsproxy.cn/index/"
[registries.rsproxy]
index = "https://rsproxy.cn/crates.io-index"
[net]
git-fetch-with-cli = true

# 项目结构

# 项目结构要求

  • Cargo.toml 在项目顶层下
  • 源代码都应该在 src 目录下
  • 顶层目录可以放置:README、许可信息、配置文件和其它与程序源码无关的文件

如果创建项目时没有使用 cargo,也可以把项目转化为使用 cargo:

  • 把源代码文件移动到 src 下
  • 创建 Cargo.toml 并填写相应的配置

# Cargo.toml

eg:

toml
[package]
name = "my-project"
version = "0.1.0"
authors = ["fuuzen <fuuzen.github.io>"]
edition = "2024"
[dependencies]
...

# [package]

  • name
  • version
  • authors
  • edition

# [dependencies]

  • crate 包
  • ...

三种描述:

  • 基于 Rust 官方仓库 crates.io ,通过版本说明来描述
  • 基于项目源代码的 git 仓库地址,通过 URL 来描述
  • 基于本地项目的绝对路径或者相对路径,通过类 Unix 模式的路径来描述

eg :

l toml
[dependencies]
rand = "0.3"
hammer = { version = "0.5.0"}
color = { git = "https://github.com/bjz/color-rs" }
geometry = { path = "crates/geometry" }

# 变量和常量

# 变量

# let 变量绑定 (binding)

rust 中 let 表达式的类似其他语言赋值的作用,实际上不是赋值,而叫做 绑定,这与 rust 所有权 这一核心概念有关

默认绑定变量类型为 immutable 不可变的,需要可变则须加上 mut 显式声明

rust
// 使用 let 来声明变量,进行绑定,a 是不可变的
// 此处没有指定 a 的类型,编译器会默认根据 a 的值为 a 推断类型:i32,有符号 32 位整数
// 语句的末尾必须以分号结尾
let a = 10;
// 主动指定 b 的类型为 i32
let b: i32 = 20;
// 这里有两点值得注意:
// 1. 可以在数值中带上类型:30i32 表示数值是 30,类型是 i32
// 2. c 是可变的,mut 是 mutable 的缩写
let mut c = 30i32;
// 还能在数值和类型中间添加一个下划线,让可读性更好
let d = 30_i32;
// 跟其它语言一样,可以使用一个函数的返回值来作为另一个函数的参数
let e = add(add(a, b), add(c, d));

# _ 编译器忽略未使用变量

告诉编译器不要警告未使用的变量,为此可以用下划线作为变量名的开头

rsut
let _a = 5

# let 变量解构

从一个复杂的变量中匹配出部分内容

rust
let (a, mut b): (bool,bool) = (true, false);
//a = true, 不可变;b = false,可变
println!("a = {:?}, b = {:?}", a, b);
b = true;
assert_eq!(a, b);

# 解构式赋值

Rust 1.59 版本后可以在赋值语句的左式中使用元组、切片和结构体模式,不需要 let

struct Struct {
    e: i32
}
fn main() {
    let (a, b, c, d, e);
    (a, b) = (1, 2);
    //_ 代表匹配一个值,但是我们不关心具体的值是什么,因此没有使用一个变量名而是使用了 _
    [c, .., d, _] = [1, 2, 3, 4, 5];
    Struct { e, .. } = Struct { e: 5 };
    assert_eq!([1, 2, 1, 4, 5], [a, b, c, d, e]);
}

这种使用方式跟之前的 let 保持了一致性,但是 let 会重新绑定,而这里仅仅是对之前绑定的变量进行再赋值。

使用 += 的赋值语句还不支持解构式赋值

# 变量遮蔽 (shadowing)

Rust 允许声明相同的变量名,在后面声明的变量会遮蔽掉前面声明的。

变量遮蔽的用处在于,如果你在某个作用域内无需再使用之前的变量(在被遮蔽后,无法再访问到之前的同名变量),就可以重复的使用变量名字,而不用绞尽脑汁去想更多的名字。

  • 可以使用相同的名字声明新的变量,新的变量就会 shadow(隐藏)之前声明的同名变量

  • 在后续的代码中这个变量名代表的就是新的变量

shadow 和把变量标记为 mut 是不一样的:

  • 如果不使用 let 关键字,那么重新给非 mut 的变量赋值会导致编译时错误
  • 而使用 let 声明的同名新变量,也是不可变的
  • 使用 let 声明的同名新变量,它的类型可以与之前不同

# 常量

常量也是绑定到一个常量名且不允许更改的值

# 常量和变量之间的差异

  • 常量不允许使用 mut常量不仅仅默认不可变,而且自始至终不可变,因为常量在编译完成后,已经确定它的值。
  • 常量使用 const 关键字而不是 let 关键字来声明,并且值的类型必须标注

# Rust 常量的命名约定

  • 全部字母都使用大写
  • 使用下划线分隔单词,另外对数字字面量可插入下划线以提高可读性

# 基本类型 (标量)

# 原始类型

# 整数类型

类型定义的形式统一为: 有无符号 + 类型大小(位数)

长度有符号类型无符号类型
8 位i8u8
16 位i16u16
32 位i32u32
64 位i64u64
128 位i128u128
视架构而定isizeusize

# isizeusize 类型

isizeusize 类型的位数由程序运行的计算机的架构所决定:

  • 如果是 64 位计算机,那就是 64 位的
  • 如果是 32 位计算机,那就是 32 位的
  • ...

# 整数字面值

rust 有以下 5 种整数字面类型:

Number literalsExample
Decimal98_222
Hex0xff
Octal0o77
Binary0b1111_0000
Byte (u8 only)b'A'
  • 除了 Byte 类型外,所有的数值字面值都允许使用类型后缀。

    • 例如 57u8
  • 如果不太清楚应该使用那种类型,可以使用 Rust 相应的默认类型

    • 整数的默认类型就是 i32 ,其速度整体上是较快的,即使是在 64 位操作系统中

# 整数溢出

  • 调试模式 (--debug) 下编译:Rust 会检查整数溢出,如果发生溢出,程序在运行时就会 panic

  • 发布模式下(--release)编译:Rust 不会检查可能导致 panic 的整数溢出

    • 如果溢出发生:Rust 会执行 “环绕” 操作:(取模)

      • 例如: u8 的范围是 0-255,如果把一个 u8 变量的值设为 256,那么 Rust 会将 256 变成 0,257 变成 1 ⋯
    • 但程序不会 panic

# 浮点类型

Rust 有两种基础的浮点类型,也就是含有小数部分的类型:

  • f32 ,32 位,单精度
  • f64 ,64 位,双精度

Rust 的浮点类型使用了 IEEE-754 标准来表述

f64默认类型,因为在现代 CPU 上 f64f32 的速度差不多,而且精度更高。

# 布尔类型

  • 符号是 bool
  • Rust 的布尔类型也有两个值:
    • true
    • false
  • 占一个字节大小

Rust 不允许其他类型直接当作布尔类型使用,和其他语言不太一样!

# 字符类型

  • 符号是 char
  • Rust 语言中 char 类型被用来描述语言中最基础的单个字符。
  • 字符类型的字面值使用单引号
  • 占用 4 字节大小
  • 是 Unicode 标量值,可以表示比 ASCII 多得多的字符内容,包括:拼音、中日韩文、零长度空白字符、emoji 表情等。

Unicode 中并没有 “字符” 的概念,所以直觉上认为的字符也许与 Rust 中的概念并不相符

# 基本类型转换

# 隐式

  1. 整数类型之间的转换:Rust 允许在整数类型之间进行隐式转换,只要目标类型的表示范围足够容纳源类型的值。例如,可以将 u8 转换为 u16i32 转换为 u64 等。
  2. 浮点数类型之间的转换:Rust 允许在浮点数类型之间进行隐式转换,只要目标类型能够表示源类型的精度和范围。例如,可以将 f32 转换为 f64
  3. 整数类型到浮点数类型的转换:Rust 允许将整数类型隐式转换为相应的浮点数类型。例如,可以将 i32 转换为 f64
  4. 字面量的隐式转换:在字面量的使用中,Rust 会根据上下文自动进行隐式类型转换。例如,可以将整数字面量 42 隐式转换为 u8i32 或其他整数类型,或将浮点数字面量 3.14 隐式转换为 f32f64

# 显式

Rust 鼓励显式的类型转换,并提供了一些安全的类型转换方法,以确保程序在类型转换时保持安全和可预测。Rust 有三种变量类型显式转换的方法:

  • as 关键字
  • frominto 这些 trait 进行转换
  • 字符串类型可以使用 parse 方法转换到数字类型

# as & as_<T>()

as 运算符转换示例:

t rust
let x: i32 = 5;
let y: u32 = x as u32;

as 运算符还有一个安全版本 as_<T>() ,它会在溢出时返回一个 Option 值。

eg:

rust
fn main() {
    let num: u32 = 42;
    
    // 将 u32 类型转换为 i16 类型
    let converted: Option<i16> = num.as_();
    
    match converted {
        Some(value) => println!("Converted value: {}", value),
        None => println!("Conversion failed"),
    }
}

# From & Into

在 Rust 中, FromInto 是用于自定义类型转换的 trait。通过实现这些 trait,可以定义自定义类型之间的转换规则。

From trait 定义了一个类型转换的关联函数 from() ,用于将其他类型转换为当前类型。

Into trait 则定义了一个类型转换的方法 into() ,用于将当前类型转换为其他类型。

eg:

rust
// 定义一个自定义类型
struct MyType(u32);
// 实现 From trait,将 u32 类型转换为 MyType
impl From<u32> for MyType {
    fn from(value: u32) -> Self {
        MyType(value)
    }
}
// 实现 Into trait,将 MyType 转换为 u32 类型
impl Into<u32> for MyType {
    fn into(self) -> u32 {
        self.0
    }
}
fn main() {
    let num: u32 = 42;
    
    // 使用 From trait 进行转换
    let my_type: MyType = MyType::from(num);
    
    // 使用 Into trait 进行转换
    let back_to_num: u32 = my_type.into();
    println!("MyType: {:?}", my_type);
    println!("Back to u32: {}", back_to_num);
}

# parse

使用 parse 方法将字符串类型转换为数字类型,如整数或浮点数。 parse 方法是定义在 str 类型上的一个函数,它返回一个 Result 枚举类型,表示解析操作的结果。

eg:

rust
fn main() {
    let num_str = "42";
    
    // 将字符串转换为整数类型
    let num: Result<i32, _> = num_str.parse();
    
    match num {
        Ok(n) => println!("Parsed number: {}", n),
        Err(e) => println!("Error: {}", e),
    }
}

# 复合类型

  • 复合类型可以将多个值放在一个类型里。
  • Rust 提供了两种基础的复合类型:元组(Tuple)、数组

# Tuple

  • Tuple 可以将多个类型的多个值放在一个类型里
  • Tuple 的长度是固定的:一旦声明就无法改变
  • Tuple 中的每个位置都对应一个类型, Tuple 中各元素的类型不必相同

# 创建 Tuple

在小括号里,将值用逗号分开

rust
let tup: (132, f64, 48) = (500, 6.4, 1);

# 获取 Tuple 的元素值

可以使用模式匹配来解构(destructure)一个 Tuple 来取元素的值

rust
let (x, y, z) = tup;

# 访问 Tuple 的元素

在 tuple 变量使用点标记法,后接元素的索引号

rust
println!("{} {} {}", tup.O, tup.1, tup.2);

# 数组

  • 数组也可以将多个值放在一个类型里
  • 数组中每个元素的类型必须相同
  • 数组的长度也是固定的

数组没有 Vector 灵活,如果想让你的数据存放在 stack(栈)上而不是 heap(堆)上,或者想保证有固定数量的元素,这时使用数组更有好处

# 数组的类型

数组的类型以这种形式表示: [类型;长度]

# 声明一个数组

两种方法:

  • 在中括号里,各值用逗号分开
  • 如果数组的每个元素值都相同,那么可以定义为: [初始值;长度]
rust
let a = [1, 2, 3, 4, 51];
let a =3;5]
// 它就相当于:let a= [3, 3, 3, 3, 3];

# 访问数组的元素

可以使用索引来访问数组的元素。

如果访问的索引超出了数组的范围,那么:

  • 索引是字面量等,编译器能检查出来,编译不通过
  • 编译器没能检查出来,编译通过
    • 运行会报错(runtime 时会 panic)
    • Rust 不会允许其继续访问相应地址的内存

# 枚举类型

enum 关键字表示枚举类型

# 定义枚举

例如 IP 地址:IPV4、IPv6

rust
enum IpAddrKind {
  V4,
  V6,
}

标准库中的 IpAddr

rust
struct Ipv4Addr {
  // --snip--
struct Ipv6Addr {
  // --snip--
}
enum IpAddr {
  V4(Ipv4Addr),
  V6(Ipv6Addr),
}

# 变体、标识符、枚举值

  • 变体是枚举类型的不同选项或可能的值之一
  • 标识符是用于表示枚举类型的变体的名称
  • 枚举值是通过选择枚举类型的一个变体来实例化的具体值

枚举的变体都位于标识符的命名空间下,使用两个冒号 :: 进行分隔

rust
let four = IpAddrKind::V4;
let six = IpAddrKind::V6;

# 将数据附加到枚举的变体中

rust
enum IpAddr {
  V4(String),
  V6(String),
}
// 每个变体可以拥有不同的类型以及关联的数据量
enum IpAddr {
  V4(u8, u8, u8, u8),
  V6(String),
}
  • 优点:
    • 不需要额外使用 struct
    • 每个变体可以拥有不同的类型以及关联的数据量

# 枚举方法

struct 类似,也使用 impl 关键字

# Option 枚举

  • 定义于标准库中
  • 在 Prelude(预导入模块)中
  • 描述了:某个值可能存在(某种类型)或不存在的情况
# Option<T>

Rust 没有 Null。其它语言中,Null 是一个值,它表示 “没有值”,一个变量可以处于两种状态:空值(nuI)、非空。

Null 引用: Billion Dollar Mistake

Null 的问题在于:当你尝试像使用非 Null 值那样使用 NuIl 值的时候,就会引起某种错误

Null 的概念还是有用的:因某种原因而变无效或缺失的值

Rust 中类似 Null 概念的枚举 Option<T> ,定义如下:

rust
enum Option<T>{
  Some(T),
  None,
}

T 是一个类型参数,代表值的类型。这里出现三个类型都定义在标准库中:

  • Option<T>
  • Some (T)Some 表示存在一个值,并将该值包装在 Some
  • None

Option<T>T 是不同的类型,不可以把 Option<T> 直接当成 T ,例如以下代码会报错:

rust
let x:i8 =5;
let y: Option<i8> = Some(5);
let sum = x + y; // 编译报错:error [E0277]: cannot add `Option<i8>` to `i8`

若想使用 Option<T> 中的 T ,必须将它转换为 T

# 基础控制流

# 选择分支

# if else

rust
if ... {
  ...
} else if ... {
  ...
} else {
  ...
}

如下代码在 rust 编译器环境下会产生报错:

rust
let number = if condition { 5 } else { "6" }

因为返回给 number 的结果类型不确定!

# match

允许一个值与一系列模式进行匹配,并执行匹配的模式对应的代码,模式可以是字面值、变量名、通配符...

match 匹配必须穷举所有的可能,否则会产生报错:

bash
error [E0004]: non-exhaustive patterns:...
  • _ 通配符:替代其余没列出的值
rust
match ... {
  a => (...),
  b => (...),
  _ => (...),
}

# if let

语法的一般形式如下:

rust
if let pattern = expression {
  // 匹配成功的处理逻辑
} else if let pattern = expression {
  // 匹配成功的处理逻辑
} else {
  // 匹配失败的处理逻辑
}

在上述语法中, pattern 是要匹配的模式, expression 是要进行匹配的表达式。如果表达式与模式匹配成功,则执行匹配成功的处理逻辑。如果匹配失败,则执行匹配失败的处理逻辑。

下面是一个示例,展示了如何使用 if let 处理 Option 类型:

rust
fn main() {
    let some_value: Option<i32> = Some(5);
    if let Some(x) = some_value {
        println!("Got value: {}", x);
    } else {
        println!("Value is None");
    }
}

在上述示例中, some_value 是一个 Option<i32> 类型的变量,被赋值为 Some(5) 。通过使用 if let Some(x) = some_value ,我们尝试将 some_value 解构为 Some 并提取其中的值。如果匹配成功,将会执行 println!("Got value: {}", x) ,打印提取到的值。如果匹配失败(即 some_valueNone ),则执行 println!("Value is None")

使用 if let 处理只关心一种匹配而忽略其它匹配的情况,可以使代码更简洁、清晰地处理特定模式的匹配,减少了手动编写 match 表达式的工作量,

可以把 iflet 看作是 match 的语法糖

# 循环

# loop

  • 没有条件判断
  • 使用 break 跳出循环
  • loop 有返回值,为 break 后面的表达式
rust
let result = loop {
  ...
  if ... {
    break (expression) ;
  }
}

# while

rust
while ... {
  ...
}

和其他语言差别不大

# for

loopwhile 更适合遍历容器,更安全、高效

rust
// eg:
let a = [10, 20, 30, 40, 50];
for element in a.iter() {
  println! ("the value is: {}", element);
}

# 所有权 Ownership

# 什么是所有权

Rust 的核心特性就是所有权

所有程序在运行时都必须管理它们使用的计算机内存

  • 有些语言有垃圾收集机制 (GC),在程序运行时,它们会不断地寻找不再使用的内存
  • 还有一些语言,程序员必须显式地分配和释放内存 (eg: C)
  • Rust 采用了第三种方式:
    • 内存是通过一个所有权系统来管理的,其中包含一组编译器在编译时检查的规则
    • 当程序运行时,所有权特性不会减慢程序的运行速度,因为 Rust 的所有权系统将将内存的管理提前到了编译阶段

在像 Rust 这样的系统级编程语言里,一个值是在 stack 上还是在 heap 上对语言的行和你为什么要做某些决定是有更大的影响的。管理 heap 数据就是所有权存在的原因。

# Stack vs Heap

在代码运行的时候,Stack 和 Heap 都是你可用的内存,但他们的结构很不相同:

  • Stack

    • Stack 按值的接收顺序来存储,按相反的顺序将它们移除(后进先出,LIFO)

      • 添加数据叫做压入栈 push
      • 移除数据叫做弹出栈 pop
    • 所有存储在 Stack 上的数据必须拥有已知的固定的大小

      • 因为指针是已知固定大小的,可以把指针存放在 stack 上。但如果想要实际数据,你必须使用指针来定位,然后访问 heap
    • 把数据压到 stack 上要比在 heap 上分配快得多,因为操作系统不需要寻找用来存储新数据的空间,那个位置永远都在 stack 的顶端

    • 如果数据存放的距离比较近,那么处理器的处理速度就会更快一些

  • Heap

    • 当你把数据放入 heap 时,你会请求一定数量的空间,这个过程叫做在 heap 上进行分配,有时仅仅称 “分配”。在 heap 上分配空间需要做更多的工作

      • 操作系统在 heap 里找到一块足够大的空间
      • 然后要做好记录方便下次分配,把它标记为在用
      • 并返回一个指针,也就是这个空间的地址
    • 编译时大小未知的数据或运行时大小可能发生变化的数据必须存放在 heap 上

    • 如果数据之间的距离比较远,那么处理速度就会慢一些

所有权解决的问题:

  • 跟踪代码的哪些部分正在使用 heap 的哪些数据
  • 最小化 heap 上的重复数据量
  • 清理 heap 上未使用的数据以避免空间不足。

掌握了所有权,那么就不需要经常去想 stack 或 heap 了

# 所有权规则

# 三条规则

  • 每个值都有一个变量,这个变量是该值的所有者
  • 每个值同时只能有一个所有者
  • 当所有者超出作用域(scope)时
    • 它拥有它的值的所有权,就会被 drop 函数清理 (heap 上的数据)
    • 它没有它的值的所有权,不会清理

# 返回值与作用域

函数在返回值的过程中同样也会发生所有权的转移,返回表达式的值的所有权将转移到函数结果所赋值的变量上

# 复制 Copy trait

用于像整数这样完全存放在 stack 上面不包含 heap 上的简单数据类型(标量)

  • 如果一个类型实现了 Copy 这个 trait ,那么旧的变量在赋值后仍然可用
  • 如果一个类型或者该类型的一部分实现了 Drop trait ,那么 Rust 不允许让它再去实现 Copy trait
rust
let x = 5;
let y = x;
//x 和 y 都是有效的
println! ("{} {}", x, y);

# 移动 Move

多个变量可以与同一个数据使用一种独特的方式 Move 来交互

String 类型为例

rust
let s1 = String::from ("hello"); 
let s2 = s1;

当把 s1 赋给 s2String 在 stack 上的数据被复制了一份,heap 内容不变

string-move

s1s2 离开作用域时,它们都会尝试释放相同的内存,就会导致二次释放 (double free) bug 。为了避免这个问题,Rust 会让原来的 s1 失效 ,此后当 s1・离开作用域的时候,Rust 不需要释放任何东西。

s1 此后处于 moved 状态,即失效。

  • 浅拷贝(shallow copy)
    • 只拷贝 stack 上的数据,有可能产生二次释放 (double free) bug
  • 深拷贝(deep copy)
    • 同时拷贝 stack 和 heap 上的数据

Rust 中采用的是第三种 “拷贝”,也就是 ** 移动 Move **,在浅拷贝的基础上让原来的 stack 数据失效。

这体现了 Rust 隐含的一个设计原则:Rust 不会自动创建数据的深拷贝。就运行时性能而言,任何自动赋值的操作都是廉价的。

# 克隆 CLone

针对包含 heap 数据的矢量数据类型,相当于深拷贝

rust
let s1 = String::from("Hello");
let s2 = s1.clone();

string-clone

# 引用 Reference

& 符号就表示引用,允许引用该值而不取得其所有权;

对应的解引用符号是 *

和 C/C++ 一样,Rust 引用是符号是 & ,解引用符号是 *

string-reference

Rust 中的引用在任何给定的时刻,引用必须一直有效 (非悬空引用),只能满足下列条件之一:

  • 一个可变的引用
  • 任意数量不可变的引用

# 可变引用 Mutable Reference

Rust 支持可变引用 ,用 &mut 符号代替 & 即为可变引用。

但是可变引用有以下几个限制:

  • 在特定作用域内,对于某一块数据,只能有一个可变引用
  • 不可以同时拥有可变引用和不可变引用
  • (多个不变的引用是可以的)

第一个限制的好处是可在编译时防止数据竞争。违反将出现如下报错:

bash
error[E0499]: cannot borrow 'xxx' as mutable more than once at a time

第二个限制避免了可变引用对不可变引用的影响。违反将出现如下报错:

bash
error[E0502]: cannot borrow 'xxx' as mutable because it is also borrowed as immutable

::: infromation

以下三种行为下会发生数据竞争:

  • 两个或多个指针同时访问同一个数据
  • 至少有一个指针用于写入数据
  • 没有使用任何机制来同步对数据的访问

数据竞争在运行时是很难发现的(C/C++ 里经常出现),所以 Rust 从根本上避免了这种问题来保证运行时的安全性

:::

可以通过创建新的作用域,来允许非同时的创建多个可变引用

rust
fn main () {
  let mut s = String:: from "Hello");
	{
	  let s1 = &mut s;
	}
  let s2 = &mut s;
}

# 悬空引用 Dangling Reference

也叫悬垂引用,在 Rust 里,编译器可保证引用永远都不是悬空引用。如果你引用了某些数据,编译器将保证在引用离开作用域之前数据不会离开作用域。对于任何出现的悬空引用, Rust 在编译阶段就会报错:

bash
error[E0106]: missing lifetime specifier

悬空指针(Dangling Pointer):一个指针引用了内存中的某个地址,而这块内存可能已经释放并分配给其它人使用了。

# 借用 Borrow

引用作为函数参数这个行为叫做借用 ,本质上就是引用。

rust
fn main () {
  let mut s1 = String::from("Hello");
  let len = calculate_length(&mut s1);
  println!("The length of '{}' is {}.", s1, len);
}
fn calculate_length(s: &mut String) -> usize {
  s.push_str(", world");
  s.len()
}

# 切片类型 slice

Rust 的另外一种不持有所有权的数据类型

# 字符串切片

字符串切片是指向字符串中一部分内容的引用

形式: [开始索引..结束索引]

  • 开始索引就是切片起始位置的索引值,若不写则默认为 0
  • 结束索引是切片终止位置的下一个索引值,若不写则默认为 String 的 Capacity
rust
fn main(){
  let s = String::from("Hello world");
  let hello = &s[0..5]; // 左闭右开
  let world = &s[6..11];// 左闭右开
}

string-slice

字符串切片的范围索引必须发生在有效的 UTF-8 字符边界内

如果尝试从一个多字节的字符中创建字符串切片,程序会报错并退出

字符串字面值实际上就是字符串切片 String slice

rust
//s 的类型是 &str
let s = "Hello, World!"

⭐️ 将字符串切片作参数传递

rust
fn first_words:(&String) -> &str {}

对于这样接受字符串作为参数的函数,有经验的 Rust 开发者会采用 &str 作为参数类型,因这样就可以同时接收 String
和 &str 类型的参数了:

rust
fn first_words:(&str) -> &str {}
  • 使用字符串切片,直接作为参数调用该函数 first_words(mystr)
  • 使用 String,可以创建一个完整的 String 切片作为参数来调用该函数 firstwords(&mystr[..])

定义函数时使用字符串切片来代替字符串引用会使我们的 API 更加通用,且不会损失任何功能。

# 数组切片

rust
let a = [1, 2, 3, 4, 5];
let slice = &a[1..3];

# 矢量变量

# String 类型

字符串字面值是程序里手写的那些字符串值,它们是不可变的、硬编码的。

Rust 还有第二种字符串类型: Sting

String 比那些基础标量数据类型更复杂,在 heap 上分配。能够存储在编译时未知数量的文本。

# 数据结构

一个 String 由 stack 上的 3 部分组成:

  • 一个指向存放字符串内容的内存的指针
  • 长度 len,就是存放字符串内容所需的字节数
  • 容量 capacity ,是 String 从操作系统总共获得内存的总字节数

存放字符串内容的部分在 heap 上

string"hello"

# 创建 String 类型的值

可以使用 from 函数从字符串字面值创建出 String 类型

rust
let s = String::from("hello");

:: 表示 fromString 类型下的函数

这类字符串是可以被修改的

# Vector 类型

# struct

# struct 基础操作

# 定义 struct

  • 使用 struct 关键字,并內整个 struct 命名
  • 在花括号内,为所有字段(Field)定义名称和类型
rust
struct User {
  username: String,
  email: String,
  sign_in_count: u64,
  active: bool,
}

# 实例化 struct

想要使用 struct ,需要创建 struct 的实例:

  • 每个字段指定具体值
  • 无需按声明的顺序进行指定
rust
let user1 = User {
  email: String::from("someone@example.com"),
  username: String::from("someusername123"),
  active: true,
  sign_in_count: 1,
}

一旦 struct 的实例是可变的,那么实例中所有的字段都是可变的

# 取得 struct 里面的某个值

使用点标记法:

rust
user1.email = String::from("anotheremail@example.com");

# 字段初始化简写

字段名与字段值对应变量名相同时,就可以使用字段初始化简写的方式:

rust
fn build_user(email: String, username: String) -> User {
  User {
    email,
    username,
    active: true,
    sign_in_count: 1,
  }
}

# struct 更新语法

当你想基于某个 struct 实例来创建一个新实例的时候,可以使用 struct 更新语法:

rust
// 不使用 struct 更新语法
let user2 = User {
  email: String::from("another@example.com"),
  username: String::from("anotherusername567"),
  active: user1.active,
  sign_in_count: user1.sign_in_count,
}
// 使用 struct 更新语法
let user2 = User {
  email: String::from("another@example.com"),
  username: String: from ("anotherusername567"),
  ..user1
};

# debug 阶段打印 struct

rust
#[derive(Debug)] // 添加注解,表示派生自 Debug 这个 trait
...
println!("{:?}", mystruct);// 输出为一行,不够清晰直观
println!("{:#?}", mystruct);// 输出结构化信息,更清晰直观

# struct 数据的所有权

rust
struct User {
  username: String,
  email: String,
  sign_in_count: u64,
  active: bool,
}

这里的字段使用了 String 而不是 &str:

  • struct 实例拥有其所有的数据
  • 只要 struct 实例是有效的,那么里面的字段数据也是有效的
  • struct 里也可以存放引用,但这需要使用生命周期

# struct 的方法

Rust 是一个多范式的语言,也支持面向对象编程

使用 impl 关键字:

rust
impl mystruct {
  fn ... (&self, ...){
    
  }
  ...
}

Rust 方法与函数不同之处:

  • 方法是在 struct (或 enumtrait 对象)的上下文中定义
  • 第一个参数是 self ,表示方法被调用的 struct 实例

# struct 扩展定义

# tuple struct

Rust 可定义类似 tuplestruct ,叫做 tuple struct

Tuple struct 整体有个名字,但里面的元素没有名字

适用于想给整个 tuple 起名,并让它不同于其它 tuple ,而且又不需要给每个元素起名

# 定义 tuple struct

使用 struct 关键字,后边是名字,以及里面元素的类型

rust
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
//black 和 origin 是不同的类型,是不同 tuple struct 的实例

# Unit-Like Struct

可以定义没有任何字段的 struct,叫做 Unit-Like struct(因为与空元组 () 也就是单元类型类似)

适用于需要在某个类型上实现某个 trait,但是在里面又没有想要存储的数据

# Package, Crate, Module

Rust 的模块系统:

  • Package(包):Cargo 的特性,让你构建、测试、共享 crate
  • Crate(单元包):一个模块树,它可产生一个 library 或可执行文件
  • Module(模块): use :让你控制代码的组织、作用域、私有路径
  • Path(路径):为 structfunctionmodule 等项命名的方式

# Package

一个 Package 包含:

  • 1 个 Cargo.toml ,它描述了如何构建这些 Crates
  • 必须至少包含一个 crate (library 或 binary)
    • 只能包含 0-1 个 library crate
    • 可以包含任意数量的 binary crate

# Package 项目结构

这些是 Cargo 的惯例

  • 一个 Package 包含一个 binary crate src/main.rssrc/lib.rs

    • src/main.rs 即为唯一的 binary crate
      • binary crate 的 crate root
  • 一个 Package 可以包含多个 binary crate

    • src/bin 下每个文件是单独的 binary crate
  • 一个 Package 包含 0 或 1 个 library crate

    • src/lib.rs 存在则包含 1 个 library crate ,否则不包含
    • library crate 的 crate root

crate 名与 package 名 ( name ) 相同

Cargo 把 crate root 文件交给 rustc 来构建 library 或 binary

# Crate

Crate 的作用:将相关功能组合到一个作用域内,便于在项目间进行共享,防止冲突

Crate 的类型有两类:

  • binary
  • library

Crate Root 是源代码文件,Rust 编译器从这里开始,组成 Crate 的根 Module

src/main.rssrc/lib.rs 叫做 crate roots

# Module

其作用在于:

  • 在一个 crate 内,将代码进行分组
  • 增加可读性,易于复用
  • 控制项目(item)的私有性(public、private)

# 建立 module

使用 mod 关键字

  • 可嵌套
  • 可包含其它项( structenum 、常量、 trait 、函数等)的定义

# 私有边界(privacy boundary)

模块不仅可以组织代码,还可以定义私有边界。如果想把 函数 或 struct 等设为私有,可以将它放到某个模块中。只要是在 mod 里,Rust 中所有的条目(函数,方法, structenum ,模块,常量)默认是私有的。

:::

这里的条目包括:函数,方法, structenum ,模块,常量等所有可以被引用、调用的东西

:::

  • 父级模块无法访问子模块中的私有条目
  • 子模块里可以使用所有祖先模块中的条目
  • 文件的根级无论是私有还是公共的都可以互相调用

# pub 关键字

使用 pub 关键字来将某些条目标记为公共的

rust
mod front_of_house {
  pub mod hosting {
    pub fn add_to_waitlist() {}
  }
}
pub fn eat_at_restaurant() {
  crate::front_of_house::hosting::add_to_waitlist(); // 绝对路径调用
  front_of_house::hosting::add_to_waitlist(); // 相对路径调用
}

pubstruct 使用, struct 内所有成员仍然默认是私有的!

pubenum 使用, enum 内所有成员就都是公共的!

# Path

为了在 Rust 的模块中找到某个条目,需要使用路径。路径有两种形式:

  • 绝对路径:从 crate root 开始,使用 crate 名 或字面值 crate
  • 相对路径:从当前模块开始,使用 selfsuper 或当前模块的标识符

路径至少由一个标识符组成,标识符之间使用 ::

# super 关键字

类似文件系统中的 .. 表示上一级目录, super 表示用来访问父级模块路径中的内容。

rust
fn serve_order() {}
mod back_of__house {
  fn fix_incorrect_order {
    cook_order();
    super::serve_order();
  }
  fn cook_order() {}
}

# use 关键字

use 关键字将路径导入到作用域内,仍遵循私有性原则,即只有公共部分才能使用

rust
mod front_of_house {
  pub mod hosting {
    pub fn add_to_waitlist() {}
  }
}
// 绝对路径:
use crate::front_of_house::hosting; 
// 相对路径:
use front_of_house::hosting; 
// 默认导入到当前文件 (crate) 作用域内
// 此后 hosting 等效于如下效果:
mod hosting() {}

Rust 惯用做法:并不直接 use 导入函数本身,而是导入函数的父模块,通过父模块调用函数,以此来表示这个函数不是本地定义的,而是从其他地方导入的。

但对于 struct , enum 则是直接导入它们本身,除非出现同名条目,则只好导入它们的父级模块来区分它们,或者用 as 关键字为他们取别名。

# pub use 重导出

use 导入的是在本文件作用域内的私有的模块

该用 pub use 关键字则外部代码导入本 文件时也能使用这些模块

# 外部包和标准库

外部包以及标准库 ( std ) 的使用需要:

  1. Cargo.tomldependencies 添加依赖的包;标准库 ( std ) 也被当做外部包但不需要这一步
  2. use 将特定条目引入作用域,外部包和标准库都需要。

# 嵌套路径

如果使用同一个包或模块下的多个条目,可以使用嵌套路径清理大量的 use 语句

rust
use 路径相同的部分::{self, 到包1路径差异的部分, 到包2 路径差异的部分, ...}
// 当需要导入路径相同部分所指向的包本身时可以用 self

eg :

rust
use std::io;
use std::io::Write;
// 上面代码等效于下面
use std::io::{self, Write}

# 通配符 *

使用 * 可以把路径中所有的公共条目都引入到作用域。 但注意要谨慎使用。

应用场景:

  • 测试,将所有被测试代码引入到 tests 模块
  • 有时被用于预导入(prelude)模块

# 将模块内容移动到其它文件

模块定义时,如果模块名后边是 ; ,而不是代码块:

  • Rust 会从与模块同名的文件中加载内容
  • 模块树的结构不会变化

这里我详细解释我讲不清楚,也懒得写了🤯

# 常用集合

# Vec<T>

# 创建

Vec::new() 函数

vec!

# 更新

push 方法,注意是可变引用

# 删除

与任何其它 struct v 一样,当 Vec 离开作用域后

  • 它就被清理掉了
  • 它所有的元素也被清理掉了

# 读取

下标索引

get 方法 ,返回 Option<T> 类型,与 match 搭配

# 遍历

rust
for element in my_vector {
  ...element...
}
for element in &my_vector {
  ...*element...
}
for element in &mut my_vector {
  ...*element...
}

# String

Rust 开发者经常会被字符串困扰的原因

  • Rust 倾向于暴露可能的错误
  • 字符串数据结构复杂
  • UTF-8

Rust 选择将正确处理 String 数据作所有 Rust 程序的默认行为

  • 缺点:程序员必须在处理 UTF-8 数据之前投入更多的精力

  • 优点:可防止在开发后期处理涉及非 ASCII 字符的错误

# 区分字符串和 String

字符串是什么

  • Rust 的核心语言层面,只有一个字符串类型:字符串切片 str(或 &str)
  • 字符串切片:对存储在其它地方、UTF-8 编码的字符串的引用
    • 字符串字面值:存储在二进制文件中,也是字符串切片

String 类型是什么

  • 来自 标准库 而不是 核心语言
  • 可增长、可修改、可拥有

二者都采用 UTF-8 編码。

Rust 的标准库还包含了很多其它的字符串类型,例如: OsStringOsStrGStrngCStr ... 它们可能使用了不同的编码。通常 String 结尾的是可获得所有权的; Str 结尾的是可借用的。

String 的本质是对 Vec<u8> 的包装,很多 Vec<T> 的操作都可用于 String

# 创建

String::new() 函数

to_string() 方法,可用于实现了 Display trait 的类型,包括字符串字面值

String::from() 函数

# 更新

push_str( xxx : &str ) 方法,把一个字符串切片附加到 String 后面,注意是可变引用,传入的参数是不获取所有权的借用

push( x : char ) 方法,把单个字符附加到 String 后面,注意是可变引用,传入的参数是不获取所有权的借用

+ 运算符,连接两个字符串 ,注意必须满足: String = String + &strString = String + &String会取得 + 左边字符串的所有权

这里 + 运算符使用了类似这个签名的方法 fn add(self, s:&str)-> String{..}

标准库中的 add 方法使用了泛型 ;本来只能 String = String + &str ,但这里出现了解引用强制转換(deref coercion),从而可以 String = String + &String

format! 宏,连接多个字符串,不会取得任何参数的所有权

rust
let s3 = s1 + "-" + &s2 + "_" + &s3;
// 等效于
let s3 = format!("{}-{}-{}", s1, s2, s3);

# 读取

Rust 的字符串不支持索引语法访问,原因在于采用的是 UTF-8 编码,很多语言的字符并不能只通过一个字节表示,这些字符专业术语叫 Unicode 标量值,例如汉字需要 3 个字节。

Rust 的字符串不支持索引语法访问的另外一个原因在于索引操作应消耗一个常量时间 O(1) ,而 String 无法保证:需要遍历所有内容,来确定有多少个合法的字符。

len() 方法,返回字符串长度

# 删除

[..] 切片,由于上述 UTF-8 编码的原因,虽然编译通过,但对于很多语言的字符,如果切割时跨越了字符边界就会 出现 panic

# 遍历

Rust 有三种看待字符串的方式:

  • Bytes, 字节,可以用 bytes 方法返回迭代器遍历
  • Scalar Values, 标量值,可以用 chars 方法返回迭代器遍历
  • Grapheme Clusters, 字形簇(最接近所谓的 “字母”),比较复杂,标准库未提供

# HashMap<K,V>

HashMap 用的较少,不在 Prelude 中,所以要使用它就需要 use std::collections::HashMap ; 标准库对其支持较少,没有内置的宏来创建 HashMap

注意 HashMap 数据存储在 heap 上。

HashMap 时同构的,即一个 HashMap 中:

  • 所有的 K 必须是同一种类型
  • 所有的 V 必须是同一种类型

# 创建

HashMap::new() 函数

collect() 方法, collect() 方法可以把数据整合成很多种集合类型,包括 HashMap ,返回值需要显式指明类型

  • 在元素类型 Vec<Tuple> 上使用 collect() 方法,可以组建一个 HashMap ,要求有两个 Tuple :一个作为 K ,一个作为 V

  • eg :

  • rust
    use std::collections::HashMap;
    fn main () {
      let teams = vec![String::from("Blue"), String::from("Yellow")];
      let intial_scores = vec! [10, 50];
    	let scores: HashMap<_, _> = teams.iter().zip(intial_scores.iter()).collect();
    }

# 更新

insert() 方法

  • 替换现有的 V

    • 如果向 HashMap 插入一对 KV ,然后再插入同样的 K ,但是不同的 V ,那么原来的 V 会被替换掉
  • 只在 K 不对应任何值的情况下,才插入 V

    • entry() 方法:检查指定的 K 是否对应一个 V
      • 参数为 K`
      • 返回 enum Entry :代表值是否存在
    • or_insert() 方法:
      • 当返回 enum Entry 代表值不存在,即 EntryVacantEntry 变体,将方法参数作为 K 的新值插进去,返回到这个值的可变引用
      • 否则返回到对应的 V 的一个可变引用
rust
scores.entry(String::from("Blue")).or_insert(50);

# 所有权

  • 对于实现了 Copy trait 的类型(例如 i32 ),值会被复制到 HashMap
  • 对于拥有所有权的值(例如 String ),值会被移动,所有权会转移给 HashMap
  • 如果将值的引用插入到 HashMap ,值本身不会移动,在 HashMap 有效的期间,被引 用的值必须保持有效
rust
use std:: collections:: HashMap;
fn main() {
  let field_name = String::from("Favorite color");
  let field_value = String::from("Blue");
  let mut map = HashMap::new();
  map.insert(&field_name, &field_value);
	println!("{}: {}", field_name, field_value);// 这一句可以通过编译
	map.insert(field_name, field_value);
	println!("{}: {}", field_name, field_value);// 这一句无法通过编译

# 读取

get() 方法,借用一个参数 K ;返回类型为 Option<&V>

rust
match scores.get(&String::from("Blue")) {
  Some(s) => println!("{}", s),
  None => println!("team not exist"),
}

# 遍历

for 循环 + 模式匹配

rust
for (k, v) in &scores {
  printin! ("{}: {}", k, v);
}

# Hash 函数

默认情况下, HashMap 使用加密功能强大的 Hash 函数,可以抵抗拒绝服务(DoS)攻击。它具有如下特点:

  • 不是可用的最快的 Hash 算法
  • 但具有更好安全性。

可以指定不同的 hasher 来切换到另一个函数。

  • hasher 是实现 BuildHasher trait 的类型

# 错误处理

错误处理体现了 Rust 的可靠性,大部分情况下在编译时提示错误并处理。

Rust 没有类似异常的机制。

错误的分类:

  • 可恢复错误:文件未找到,可再次尝试
    • 返回 Result<T , E>
  • 不可恢复错误,bug,例如访问的索引超出范围
    • 调用 panic!

# 不可恢复错误

panic! 宏执行:

  • 程序会打印一个错误信息,可自定义,即传递给 panic!&str 类型字符串
    • 调试 (默认 --debug ) 模式下才会打印
    • --release 模式下不会打印
  • 执行以下两个操作之一
    • (默认) 程序展开调用栈(工作量大)
      • Rust 沿着调用栈往回走
      • 清理每个遇到的函数
    • 立即中止调用栈
      • 不进行清理,直接停止程序
      • 内存需要 OS 进行清理
  • 退出程序

想让二进制文件更小,把设置从 “展开” 改为 “中止”,只需在 Cargo.toml 文件下增加:

toml
[profile.release]
panic = 'abort'

将环境变量 RUST_BACKTRACE 设置为

  • 0 ,使 panic! 报错指出源代码出错的地方,即开发者所写的代码中
  • 1 ,使 panic! 报错指出真正出错的地方,即依赖的代码中,它将回溯,打印出包含错误点的所有调用函数的列表
  • full ,比 1 更加详细

# 可恢复错误

rust
enum Result<T, E> {
  Ok(T),
  Err(E),
}
  • T :操作成功情况下, Ok 变体里返回的数据的类型
  • E :操作失败情况下, Err 变体里返回的错误的类型

match 表达式处理

Option 枚举一样,Result 及其变体也是由 prelude 带入作用域

rust
use std::fs::File;
// simple demo
fn main() {
  let f = File::open("hello.txt");
  let f = match f {
    Ok(file) => file,
    Err(error) => {
      panic!("Error opening file {:?}", error);
    }
  };
}
// complex demo
fn main() {
  let f = File::open( "hello.txt");
  let f = match f {
    Ok(file) => file,
    Err(error) => match error.kind() {
      ErrorKind::NotFound => match File::create("hello.txt") {
        Ok(fc) => fc,
        Err(e) => panic!("Error creating file: {:?}", e),
      }
      other_error => panic!("Error opening the file: {:?}", other_error),
    },
  };
}

闭包处理

rust
let f = File::open ("hello.txt").unwrap_or_else(|error| {
  if error.kind() == ErrorKind::NotFound {
    File::create( "hello.txt").unwrap_or_else(|error| {
      panic!("Error creating file: {:?}", error);
    })
  } else {
    panic! ("Error opening file: {:?}", error);
  }
});

unwrap() 方法,是 match 方法处理 Result<T, E> 的快捷方式,但是无法自定义错误信息

rust
let f = File::open("hello.txt");
let f = match f {
  Ok(file) => file,
  Err(error) => {
    panic!("Error opening file {:?}", error);
  }
};
// 等价于
let f = File::open("hello.txt").unwrap();

expect() 方法,在 unwrap 的基础上,支持 自定义错误信息

# 传播错误

? 用于快捷地传播错误

  • 如果 Result<T, E>Ok : Ok 中的值就是表达式的结果,然后继续执行程序
  • 如果 Result<T, E>Err : Err 本身 就是整个函数的返回值,就像使用了 return
rust
fn read username_from_file() -> Result<String, io::Error> {
  let f = File::open("hello.txt");
  let mut f = match f {
    Ok(file) => file,
    Err(e) => return Err(e),
  };
  let mut s = String::new();
  match f.read_to_string(&mut s) {
    Ok(_) => Ok(s),
    Err(e) => Err(e)
// 相当于 Err (e) => return Err (e),
  }
}
// 等价于
fn read username_from_file() -> Result<String, io::Error> {
  let f = File::open("hello.txt")?;
  let mut s = String::new();
  f.read_to_string(&mut s)?;
  Ok(s)
}
// 链式调用优化
fn read username_from_file() -> Result<String, io::Error> {
  let mut s = String::new();
  File::open("hello. txt")?.read_to_string(&mut s)?;
  Ok(s)
}

?from 函数

trait std::convert::From 上的 from 函数用于错误之间的转换

  • ? 所应用的错误,会隐式的被 from 函数处理
  • ? 调用 from 函数时它所接收的错误类型会被转化为当前函数返回类型所定义的错误类型

适用于要求针对不同错误原因,返回同一种错误类型,需要 每个错误类型实现了转换为所返回的错误类型的 from 函数

? 运算符与 main 函数

? 返回类型只能是 Result<T, E>Option<T> 或任何实现了的 Try 类型

main 函数返回类型是: () ,不能直接返回 ? 运算符的结果

main 函数的返回类型也可以是:Result<T,E> ,可以定义其返回 Box<dyn Error> ,这是 trait 对象,简单理解:“任何可能的错误类型”

rust
use std::fs::File;
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
  let f = File::open ("hello.txt")?;
  Ok(())
}

# 数据类型有效性检查

panic! 的主要应用场景之一,自定义结构体方法(以下 demo 是 new )来处理数据是否有效

t rust
pub struct Guess {
  value: i32,
}
impl Guess {
  pub fn new(value: i32) -> Guess {
    if value <1 || value > 100 {
      panic!("Guess value must be between 1 and 100, got {}", value);
    }
    Guess { value }
  }
  pub fn value(&self) -> i32 {
    self.value
  }
}

getter :返回字段数据

# 抽象化

# 泛型

泛型类似 C++ 的模版可以提高代码复用能力,处理重复代码的问题

泛型是具体类型或其它属性的抽象代替,你编写的代码不是最终的代码,而是一种模板,里面有一些 “占位符”,编译器在编译时将 “占位符” 替换具体的类型。

占位符的声明:

  • 定义函数时,在 fn 函数名 的后面用 <T, K, ...> 尖括号声明

  • 定义结构体时,在 struct 结构体名 的后面用 <T, K, ...> 尖括号声明

  • 定义枚举类型时,在 enum 枚举类型名 的后面用 <T, K, ...> 尖括号声明

  • 定义方法时,若结构体 / 枚举类型是用泛型定义的,则也需要声明占位符或类型

    • rust
      impl<T> Point<T> { // 在类型 T 上实现方法
        fn x(&self) -> &T {
          &self.x
        }
      }
    • rust
      impl Point<i32> { // 只针对具体类型实现方法
        fn x1(&self) -> i32 {
          &self. X
        }
      }
    • struct 里的泛型类型参数可以和方法的泛型类型参数不同

例如: fn largest<T>(list:&T) -> T{...}T 就是一个泛型占位符

当出现需要太多类型参数,代码往往 需要重组为多个更小的单元

单态化(monomorphization)

Rust 在编译时将泛型替换具体类型,这一过程叫单态化,使泛型代码性能与非泛型代码无异

# trait

Rust 中的 trait 是抽象的定义共享行为,与其它语言的接口 (interface) 类似,但有些区别,它告诉 Rust 编译器某种类型具有哪些并且可以与其它类型共享的功能

trait bounds (约束):泛型类型参数指定为实现了特定行为的类型

# 定义 trait

trait 的定义:把方法签名放在一起,来定义实现某种目的所必需的一组行为。

  • 关键字: trait
  • 只有方法签名,没有具体实现
  • trait 可以有多个方法:每个方法签名占一行,以 ; 结尾
  • 实现该 trait 的类型必须提供具体的方法实现
rust
pub trait MyTrait {
  fn my_trait_function(&self) -> ... ;
}

# 实现 trait

在类型上实现 trait 与为类型实现方法类似。格式:

rust
impl MyTrait for MyStruct1 {
  fn my_trait_function(&self) -> ... {
    ...
  }
}
impl MyTrait for MyStruct2 {
  fn my_trait_function(&self) -> ... {
    ...
  }
}

这样的实现实际上叫做重写实现

# 约束

可以在某个类型上实现某个 trait 的前提条件是:这个类型或这个 trait 是在本地 crate 里定义的。

也就是无法外部类型来实现外部的 trait ,这个限制是程序属性的一部分(也就是一致性)。

更具体地说是孤儿规则:之所以这样命名是因为父类型不存在。

此规则的目的和原因:

  • 确保其他人的代码不能破坏您的代码,反之亦然。
  • 如果没有这个规则,两个 crate 可以为同一类型实现同一个 trait ,Rust 就不知道应该使用哪个实现了

# 默认实现

在定义 trait 的时候,不再只是函数签名,而是直接实现该函数,那么这个实现就是所有类型可以调用(虽然不一定正确)的默认实现

注意:

  • 默认实现的方法可以调用 trait 中其它的方法,即使这些方法没有默认实现
  • 无法从方法的重写实现里面调用默认的实现

# 项目结构惯例

trait 的定义和实现常放在 src/lib.rs ,并加上 pub 关键字 ,在其他文件通过 use package_name::trait_name 导入

# trait 作为参数

# impl trait

适用于简单情况,实际上 impl trait 语法是 trait bound 的语法糖

rust
pub fn notify(item: impl MyTrait) {
  //notify 这个函数将只能使用实现了 MyTrait 的类型作为参数 item
}

# trait bound

可用于复杂情况

rust
pub fn notify<T: MyTrait>(item1: T, item2: T, ... ) {
  //notify 这个函数将只能使用实现了 MyTrait 的类型作为参数 item1,item2...
}

# 实用包、crate

# std::env

args 函数收集传入程序的参数

collect 方法可以将参数按空格分割转化为 Vec<String>

rust
use std::env;
fn main () {
  let args: Vec<String> = env::args().collect();
  //env::args_os () //OsString 迭代器
  println! ("{:?}", args);
}

# std::fs

file system 缩写,显然是处理文件相关的模块

read_to_string(filename) 函数读取 filename 路径的文件

Edited on Views times
\ No newline at end of file diff --git a/cs/os/concepts/index.html b/cs/os/concepts/index.html index 7cc442cb..cd53008c 100644 --- a/cs/os/concepts/index.html +++ b/cs/os/concepts/index.html @@ -1 +1 @@ -操作系统绪论 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 操作系统的定义

实际上操作系统没有普遍接受的定义

操作系统 (Operating System,OS)是指控制管理整个计算机系统的硬件和软件资源,并合理地组织调度计算机的工作资源分配;以提供给用户其他软件方便的接口环境;它是计算机系统中最基本的系统软件

# 操作系统的功能和目标

# 作为系统资源的管理者

# 提供的功能

  • 处理机管理

  • 存储器管理

  • 文件管理

  • 设备管理

# 目标

安全、高效

# 向上层提供方便易用的服务

# GUI

(Graphical User Interface) 图形化用户接口

# CLI

(Command Line Interface) 命令行接口

  • 联机命令接口 = 交互式命令接口
  • 脱机命令接口 = 批处理命令接口

# 程序接口

可以在程序中进行系统调用来使用程序接口。普通用户不能直接使用程序接口,只能通过程序代码间接使用。

软件和程序员才能使用程序接口

封装思想:操作系统把一些丑陋的硬件功能封装成简单易用的服务,使用户能更方便地使用计算机,用户无需关心底层硬件的原理,只需要对操作系统发出命令即可

# 作为最接近硬件的层次

目标:实现对硬件机器的拓展

没有任何软件支持的计算机称为裸机。在裸机上安装的操作系统,可以提供资源管理功能和方便用户的服务功能,将裸机改造成功能更强、使用更方便的机器

通常把覆盖了软件的机器成为扩充机器,又称之虚拟机

# 操作系统的特征

# 并发

并发:指两个或多个事件在同一时间间隔内发生。这些事件宏观上是同时发生的,但微观上是交替发生的

操作系统的并发性:计算机系统中 “同时” 运行着多个程序,这些程序宏观上看是同时运行着的,而微观上看是交替运行的。

操作系统就是伴随着 “多道程序技术” 而出现的。因此,操作系统和程序并发是一起诞生的。

注意(重要考点):单核 CPU 同一时刻只能执行一个程序,各个程序只能并发地执行多核 CPU 同一时刻可以同时执行多个程序,多个程序可以并行地执行

# 共享

共享即资源共享,是指系统中的资源可供内存中多个并发执行的进程共同使用。

# 互斥共享方式

系统中的某些资源,虽然可以提供给多个进程使用,但一个时间段内只允许一个进程访问该资源

# 同时共享方式

系统中的某些资源,允许一个时间段内由多个进程 “同时” 对它们进行访问

所谓的 “同时” 往往是宏观上的,而在微观上,这些进程可能是交替地对该资源进行访问的(即分时共享)

并发共享 的关系是相互依存,不可分割

如果失去并发性,则系统中只有一个程序正在运行,则共享性失去存在的意义;

如果失去共享性,则不同的程序不能同时访问硬盘资源,就无法实现同时发送文件,也就无法并发

# 虚拟

虚拟是指把一个物理上的实体变为若干个逻辑上的对应物。物理实体(前者)是实际存在的,而逻辑上对应物(后者)是用户感受到的。

# 空分复用技术

如虚拟存储器技术

# 时分复用技术

如虚拟处理器

并发共享 的关系是相互依存,不可分割

如果失去了并发性,则一个时间段内系统中只需运行一道程序,那么就失去了实现虚拟性的意义了。因此,没有并发性,就谈不上虚拟性

# 异步

异步指,在多道程序环境下,允许多个程序并发执行,但由于资源有限,进程的执行不是一贯到底的,而是走走停停,以不可预知的速度向前推进,这就是进程的异步性。

# 操作系统的发展和分类

# 手工操作阶段

主要缺点:

用户独占全机、人机速度矛盾导致资源利用率极低

# 批处理阶段

引入脱机输入 / 输出技术(用外围机 + 磁带完成),并由监督程序负责控制作业的输入、输出,通过外围机把程序提前存到磁带里

目标是追求吞吐量,提高资源利用率

# 脱机

在主机以外的设备上进行输入 / 输出操作,需要时再送主机处理。

# 批处理 bash

后端运行的作业,开始运行之后就不再需要任何交互。由于无法交互控制程序,所以还不算真正意义上的操作系统。

# 单道批处理系统

也叫简单批处理系统。已经出现操作系统的一些特征:

  • 用户态、内核态(monitor)
  • 时钟

主要优点:

缓解了一定程度的人机速度矛盾,资源利用率有所提升。


主要缺点:

内存中仅能有一道程序运行,只有该程序运行结束之后才能调入下一道程序。

CPU 有大量的时间是在空闲等待 1/0 完成。资源利用率依然很低

没有人机交互功能。

# 多道程序设计

多道程序的运行环境比单道程序等更加复杂。

特点:

  • 多道 —— 计算机内存中同时存放多道相互独立的程序
  • 宏观上并行
  • 微观上串行
  • 非封闭、非顺序 —— 引入多道程序后,程序的执行就失去了封闭性和顺序性
  • 相互制约 —— 程序执行因为共享资源以及相互协同的原因相互制约
  • 断续性 —— 考虑到竞争的公平性,程序的执行是断续的

多道程序设计的实现需要解决如下问题:

  • 处理机的分配
  • 多道程序的内存分配
  • I/O 设备的分配
  • 如何组织和存放大量的程序和数据,以方便用户使用并保证一致性安全性
    • 一定需要实现虚拟存储吗?—— 不一定,早期多道批处理操作系统将所有进程数据全部调入主存

这些问题的处理也会增加系统开销。

多道程序设计开始引入中断,目的是使 CPU 和 I/O 设备并行运行,提高资源利用率。

# 多道批处理系统(操作系统开始出现)

在批处理系统中采用多道程序设计就形成了多道批处理系统。

每次往内存中读入多道程序,操作系统正式诞生,用于支持多道程序并发运行。


主要优点:

多道程序并发执行,共享计算机资源。资源利用率大幅提升,CPU 和其他资源更能保持 “忙碌” 状态,系统吞吐量增大。


主要缺点:

用户响应时间长,仍然没有人机交互功能(用户提交自己的作业之后就只能等待计算机处理完成,中间不能控制自己的作业执行。eg:无法调试程序 / 无法在程序运行过程中输入一些参数)

# 分时操作系统

计算机以时间片为单位轮流为各个用户 / 作业服务,各个用户可通过终端与计算机进行交互。

目标是追求时延(latency)


主要特征:

  • 同时性、也叫多路性
  • 交互性
  • 独立性
  • 及时性

主要优点:

用户请求可以被即时响应,解决了人机交互问题。允许多个用户同时使用一台计算机,并且用户对计算机的操作相互独立,感受不到别人的存在。


主要缺点:

不能优先处理一些紧急任务。操作系统对各个用户 / 作业都是完全公平的,循环地为每个用户 / 作业服务一个时间片,不区分任务的紧急性。

# 实时操作系统

主要优点:

能够优先响应一些紧急任务,某些紧急任务不需时间片排队。

在实时操作系统的控制下,计算机系统接收到外部信号后及时进行处理,并且要在严格的时限内处理完事件。实时操作系统的主要特点是及时性可靠性

# 硬实时系统

必须在绝对严格的规定时间内完成处理

eg: 导弹控制系统、自动驾驶系统

# 软实时系统

能接受偶尔违反时间规定

如:12306 火车订票系统

# 网络操作系统

是伴随着计算机网络的发展而诞生的,能把网络中各个计算机有机地结合起来,实现数据传送等功能,实现网络中各种资源的共享(如文件共享)和各台计算机之间的通信。(如:Windows NT 就是一种典型的网络操作系统,网站服务器就可以使用)

# 分布式操作系统

主要特点是分布性和并行性。系统中的各台计算机地位相同,任何工作都可以分布在这些计算机上,由它们并行、协同完成这个任务。

# 个人计算机操作系统

eg: windows、macos

# 操作系统服务

  • 资源分配
  • 记账
  • 日志服务

# 内核

内核是操作系统最重要最核心的部分,也是最接近硬件的部分

甚至可以説,一个操作系統只要有内核就够了(eg:Docker-> 仅需 Linux 内核)

操作系统的功能未必都在内核中,如图形化用户界面 GUI

由很多内核程序组成了 “操作系统内核”,或简称 “内核、(Kernel)”

# 内核程序 —— 运行在内核态

微软、苹果有一帮人负责实现操作系统,他们写的是 “内核程序”。操作系统内核作为 “管理者”,有时会让 CPU 执行一些 “特权指令”,如:内存清零指令。这些指令影响重大,只允许 “管理者”—— 即操作系统内核来使用

普通程序员写的程序就是 “应用程序”,应用程序只能使用 “非特权指令”,如:加法指令、减法指令等

在 CPU 设计和生产的时候就划分了特权指令和非特权指令,因此 CPU 执行一条指令前就能判断出其类型

CPU 中有一个寄存器叫 程序状态字寄存器(PSW),其中有个二进制位,1 表示 “内核态”,0 表示 “用户态”

# 内核态 —— 运行内核程序

CPU 有两种状态,“内核态” 和 “用户态”。处于内核态时,说明此时正在运行的是内核程序,此时可以执行特权指令处于用户态时,说明此时正在运行的是应用程序,此时只能执行非特权指令

内核态 = 核心态 = 管态;用户态 = 目态

# 内核态和用户态的切换 (变态)

变态的过程是有成本的,要消耗不少时间,频繁地变态会降低系统性能

# 内核态 -> 用户态

执行一条特权指令一一修改 PSW 的标志位为 “用户态”,这个动作意味着操作系统将主动让出 CPU 使用权

# 用户态 -> 内核态

由 “中断” 引发,硬件自动完成变态过程,触发中断信号意味着操作系统将强行夺回 CPU 的使用权。除了非法使用特权指令之外,还有很多事件会触发中断信号。一个共性是,旦凡需要操作系统介入的地方,都会触发中断信号

# 系统调用

对象与系统调用、库函数的关系
普通应用程序可直接进行系统调用,也可使用库函数。 有的库函数涉及系统调用,有的不涉及
编程语言向上提供库函数。有时会将系统调用封装成库函数,以隐藏系统调用的一些细节,使程序员编程更加方便。
操作系统向上提供系统调用,使得上层程序能请求内核的服务
裸机

不涉及系统调用的库函数.eg

  • “取绝对值” 的函数

涉及系统调用的库函数.eg

  • “创建一个新文件” 的函数

# 按功能分类

  • 设备管理 —— 完成设备请求 / 释放 / 启动 等功能
  • 文件管理 —— 完成文件读 / 写 / 创建 / 删除 等功能
  • 进程控制 —— 完成进程创建 / 撒销 / 阻塞 / 唤醒 等功能
  • 进程通信 —— 完成进程之间的 消息传递 / 信号传递 等功能
  • 内存管理 —— 完成内存分配 / 回收 等功能

应用程序通过系统调用请求操作系统的服务。而系统中的各种共享资源都由操作系统内核统一掌管,因此凡是与共享资源有关的操作(如存储分配、1/0 操作、文件管理等),都必须通过系统调用的方式向操作系统内核提出服务请求,由操作系统内核代为完成。这样可以保证系统的稳定性和安全性,防止用户进行非法操作。

# 系统调用过程

  1. 传递系统调用参数
    • 寄存器传递参数
    • 内存中存储在块或表中的参数,以及作为参数在寄存器中传递的块地址
      • linux 和 solaris 采用这种方式
    • 由程序放置或推送到堆栈上并由操作系统弹出堆栈到参数

块和堆栈的方式传递参数大小不受限制

  1. 执行陷入指令(用户态)
  2. 执行相应的内请求核程序处理系统调用(内核态)
  3. 返回应用程序

陷入指令 = trap 指令 = 访管指令

陷入指令是在用户态执行的,执行陷入指令之后立即引发一个内中断,使 CPU 进入内核态

发出系统调用请求是在用户态,而对系统调用的相应处理内核态下进行

# 计算计组成原理相关基础概念

# 中断和异常

参考这个

没有中断就没有并发,也就没有操作系统

中断是让操作系统内核夺回 CPU 使用权的唯一途径,使 CPU 由用户态变为内核态

通用概念产生 原因AArch64x86-64
中断硬件 异步异步异常 (重置 / 中断)中断 (可屏蔽 / 不可屏蔽)
异常软件 同步同步异常 (终止 / 异常指令)异常 (Fault/Trap/Abort)

中断

(广义上的中断包括)Interrupt Handlers used in all 3 scenarios :

  • HW -> CPU -> Kernel: Classic HW Interrupt (狭义上的中断)
  • User -> Kernel: SW Interrupt
  • CPU -> Kernel: Exception

# 其他类型 (非狭义) 中断

  • SW Interrupt
    • Interrupts caused by the execution of a software instruction: INT<interrupt_number>
    • Used by the system call interrupt()
    • Initiated by the running (user level) process
    • Cause current processing to be interrupted and transfers control to the corresponding interrupt handler in the kernel
  • Exceptions
    • Initiated by processor hardware itself
    • Example: divide by zero
    • Cause a transfer of control to the kernel to handle the exception (like a software interrupt)

# Linux 系统的中断

  • 在中断处理中做尽量少的事
  • 推迟非关键行为

结构:

  • Top half :马上做,找到 handler

    • 最小的、公共行为

      • 保存寄存器、屏蔽其他中断
      • 恢复寄存器,返回原来场景

      最重要:调用合适的由硬件驱动提供的中断处理 handler

      因为中断被屏蔽,所以不要做太多事情 (时间、空间)

      使用将请求放入队列,或者设置标志位将其他处理推迟到 bottom half

      现代处理器中,多个 I/O 设备共享一个 IRQ 和中断向量 v 多个 ISR (interrupt service routines) 可以结合在一个向量上
      调用每个设备对应该 IRQ 的 ISR

  • Bottom half : 推迟处理 (softirq, tasklets, 工作队列,内核线程)

    • 提供一些推迟完成任务的机制

    • softirqs

    • tasklets (建立在 softirqs 之上)

    • 工作队列

    • 内核线程

    这些工作可以被中断

linux中断

中断处理没有进程上下文!

中断 (和异常相比) 和具体的某条指令无关

也和中断时正在跑的进程、用户程序无关

中断处理 handler 不能睡眠!

中断处理的一些约束条件:

  • 不能睡眠
    • 或者调用可能会睡眠的任务
  • 不能调用 schedule () 调度
  • 不能释放信号或调用可能睡眠的操作
  • 不能和用户地址空间交换数据

# 中断向量表

每一个处理器有一个中断向量表,由操作系统内核建立,指向处理不同时间的中断处理程序入口

结构:

中断向量表

# 需要中断的场景举例

Hardware devices may need asynchronous and immediate service. For example:

  • Timer interrupt: Timers and time-dependent activities need to be updated with the passage of time at precise intervals
  • Network interrupt: The network card interrupts the CPU when data arrives from the network
  • I/O device interrupt: I/O devices (such as mouse and keyboard) issue hardware interrupts when they have input (e.g., a new character or mouse click)

# 多核系统上的中断

Howareinterruptshandledonmulticoremachines?

  • On x86 systems each CPU gets its own local Advanced Programmable Interrupt Controller (APIC). They are wired in a way that allows routing device interrupts to any selected local APIC.
  • The OS can program the APICs to determine which interrupts get routed to which CPUs.
  • The default (unless OS states otherwise) is to route all interrupts to processor 0

# 陷入指令

执行 “陷入指令”,意味着应用程序主动地将 CPU 控制权还给操作系统内核。“系统调用” 就是通过陷入指令完成的

# I/O (输入输出系统)

# BUS (总线)

# 并行系统

# 多核处理器

# 多处理器系统

又称并行系统、紧耦合系统

区分 多处理器系统多核系统 ,实际计算机往往既是多核的也是多处理器的

多核和多处理器系统都用于加速计算过程。多核包含在单个 CPU 中的多个核或处理单元。多处理器由多个 CPU 组成。多核处理器不需要像多处理器那样复杂的配置。相反,多处理器更可靠并且能够运行许多程序。

# 三个优点一个缺点???

老师出的作业题😅难道本来是想问多道批处理系统?而且那个也是单处理器系统啊)

  • 增加吞吐量,并行处理?
  • 规模经济,降低成本,比多核处理器便宜?
  • 增加可靠性?
  • ???

# 非对称多处理器系统 (AMP)

非对称多处理是指一种计算机结构,其中有多个处理器,但它们并不都是一样的。这意味着,一个 CPU 可能正在处理操作系统代码,而另一个 CPU 正在执行输入和输出工作。它使用两个或更多的处理器由一个主处理器处理。所有的 CPU 都是相互连接的,但不是自我调度的。它用于根据任务的优先级和重要性将特定任务安排到一个 CPU。

非对称处理器的应用场景:被用于嵌入式系统,在这些系统中,特定任务需要并发执行,但系统不需要像对称多处理系统那样的通用计算能力

# 对称多处理器系统 (SMP)

SMP(Sysmmetric Multi-Processor System,对称多处理器),它由多个具有对称关系的处理器组成。所谓对称,即处理器之间没有主从之分。SMP 架构使得一台计算机不再由单个 CPU 组成,而是由两个或更多的处理器连接到一个共享的主存储器上,并能够共同执行任务。这些处理器通常是相同的,能够运行分配给它们的任何任务。这可以提高性能,因为任务可以在处理器之间分配,使其更快完成。

对称多处理将多个 CPU 应用于一个任务,以并行和更快的方式完成。因此,在对称多处理系统中,两个或更多的 CPU 被连接到一个共享的主存储器。同时,所有这些 CPU 都可以完全访问输入和输出设备。在对称多处理系统中,操作系统认为所有的处理器都是平等的。

对称处理器 (SMP) 架构同时也是 UMA 架构

SMP 是一个紧密耦合的多处理器系统,它有一组独立运行的相同的 CPU。每个 CPU 处理不同的程序,执行不同的数据集。对称多处理系统共享公共资源,如输入设备、输出设备、内存等。

# 问题

所有处理器相同,没有考虑不同任务要求处理器的差异性

# 多处理器环境的 3 种内存共享模型

# UMA

UMA(Uniform Memory Access,一致性存储器访问),实际上就是 SMP 。其中,一致性指的就是在任意时刻,多个处理器只能为内存的每个数据保存或共享一个唯一的数值。它的结构特征就是多处理器共享一个集中式存储器,每个处理器访问存储器所需的时间一致,工作负载能够均匀的分配到所有可用处理器上,极大地提高了整个系统的数据处理能力。但是,如果多个处理器同时请求访问共享资源时,就会引发资源竞争,需要软硬件实现加锁机制来解决这个问题。

因此,这样的架构设计无法拥有良好的处理器数量扩展性,因为共享内存的资源竞态总是存在的,处理器利用率最好的情况只能停留在 2 到 4 颗。

# NUMA

NUMA(Non-Uniform Memory Access,非一致性存储器访问)架构优化了 SMP 架构扩展性差以及存储器带宽窄的问题。采用了分布式存储器,将处理器和存储器划分为不同的节点(NUMA Node),每个节点都包含了若干的处理器与内存资源。多节点的设计有效提高了存储器的带宽和处理器的扩展性。

另一方面,NUMA 节点的处理器可以访问到整体存储器。按照节点内外,内存被分为:

  • 节点内部的本地内存
  • 节点外部的远程内存

当处理器访问本地内存时,走的是内部总线,当处理器访问远程内存时,走的是主板上的 QPI 互联模块。访问前者的速度要远快于后者,NUMA(非一致性存储器访问)因此而得名。

# 问题

各个处理器访问自己的内存速度很快,但如果出现需要跨处理器访存,即访问另一处理器的内存时会非常缓慢

# COMA

Cache-only Memory Access (COMA) 是 ccNUMA (Cache Coherent NUMA, 缓存一致性 NUMA) 的一种演变。COMA 可以看成是专用的 NUMA,将 NUMA 中的分布式内存用高速缓存来取代。全局地址空间由高速缓存组成。访问远端的高速缓存借助分布式高速缓存目录进行。

# 集群系统

类似多处理系统,集群系统时多个机器,每台机器有自己的操作系统,并行工作。

  • Usually sharing storage via a storage-area network (SAN)

  • Provides a high-availability service which survives failures

    • Asymmetric clustering has one machine in hot-standby mode
    • Symmetric clustering has multiple nodes running applications, monitoring each other
  • Some clusters are for high-performance computing (HPC)

    • Applications must be written to use parallelization
  • Some have distributed lock manager (DLM) to avoid conflicting operations

# 操作系统的结构

不同结构操作系统举例:

  • 大内核 / 宏内核 / 单内核: Windows、Android、iOS、UNIX、Linux、MacOS
  • 微内核:Windows NT、Mach、Fuchsia、鸿蒙
  • 模块化:Solaris
操作系统体系结构区别优点缺点
大内核 / 宏内核 / 单内核将操作系统的主要功能模块都作为系统内核,运行在核心态高性能内核代码庞大,结构混乱,难以维护
微内核只把最基本的功能保留在内核内核功能少,结构清晰,方便维护需要频繁地在核心态和用户态之间切换,性能低
特性、思想优点缺点
分层结构内核分多层,每层可单向调用更低一层提供的接1. 便于调试和验证,自底向上逐层调试验证1. 仅可调用相邻低层,难以合理定义各层的边界
2. 效率低,不可跨层调用,系统调用执行时间长2. 效率低,不可跨层调用,系统调用执行时间长
模块化将内核划分为多个模块,各模块之间相互协作。内核 = 主模块 + 可加载内核模块1. 模块间逻辑清晰易于维护,确定模块间接口后即可多模块同时开发1. 模块间的接口定义未必合理、实用
主模块:只负责核心功能,如进程调度、内存管2. 支持动态加载新的内核模块(如:安装设备驱动程序、安装新的文件系统模块到内核),增强 OS 适应性2. 模块间相互依赖,更难调试和验证
可加载内核模块:可以动态加载新模块到内核,而无需重新编译整个内核3. 任何模块都可以直接调用其他模块,无需采用消息传递进行通信,效率高
宏内核 (大内核)所有的系统功能都放在内核里(大内核结构的 OS 通常也采用了 " 模块化” 的设计思想)性能高,内核内部各种功能都可以直接相互调用1. 内核庞大功能复杂,难以维护
2. 大内核中某个功能模块出错,就可能导致整个 系统崩溃
微内核只把中断、原语、进程通信等最核心的功能放入内核。进程管理、文件管理、设备管理等功能以用户进程的形式运行在用户态1. 内核小功能少、易于维护,内核可靠性高1. 性能低,需要频繁的切换 用户态 / 核心态。用户态下的各功能模块不可以直接相互调用,只能通过内核的 "消息传递" 来间接通信
2. 内核外的某个功能模块出错不会导致整个系统 崩溃2. 用户态下的各功能模块不可以直接相互调用,只能通过内核的 "消息传递" 来间接通信
外核 (exokernel)内核负责进程调度、进程通信等功能,外核负责为用户进程分配未经抽象的硬件资源,且由外核负责保证资源使用安全1. 外核可直接给用户进程分配 "不虚拟、不抽象" 的硬件资源,使用户进程可以更灵活的使用硬件1. 降低了系统的一致性
2. 减少了虚拟硬件资源的 “映射层”,提升效率2. 使系统变得更复杂

# 非内核功能(如 GUI)

操作系统的非内核功能运行在用户态

# (大) 内核

内核是操作系统最基本、最核心的部分。

实现操作系统内核功能的那些程序就是内核程序。

操作系统内核需要运行在内核态

# 对系统资源进行管理的功能

大内核结构中运行在内核态,所以大内核结构操作系统变态不那么频繁

微内核结构中运行在用户态,所以微内核结构操作系统变态更加频繁

# 进程管理

# 存储器管理

# 设备管理等功能

# (微内核)

# 时钟管理

实现计时功能

# 中断处理

负责实现中断机制

# 原语(设备驱动、CPU 切换等)

是一种特殊的程序,具有如下特点:

  • 处于操作系统最底层,是最接近硬件的部分
  • 这种程序的运行具有原子性 —— 其运行只能一气呵成,不可中断
  • 运行时间较短、调用频繁

# 操作系统的引导

操作系统引导过程

操作系统引导过程

  1. CPU 从一个特定主存地址开始,取指令,执行 ROM 中的引导程序(先进行硬件自检,再开机)
  2. 将磁盘的第一块 —— 主引导记录 读入内存,执行磁盘引导程序,扫描分区表
  3. 从活动分区(又称主分区,即安装了操作系统的分区)读入分区引导记录,执行其中的程序
  4. 从根目录下找到完整的操作系统初始化程序(即启动管理器)并执行,完成 “开机” 的一系列动作
    1. 加载内核
      • BIOS
      • UEFI,逐渐取代 BIOS,加载更简洁
      • GRUB,更加复杂,可以选择加载不同的内核
    2. 启动系统守护进程(在内核之外提供的服务)
    3. 启动内核中断驱动(硬件和软件)
      1. 启动设备的硬件中断
      2. 启动软件中断(异常或陷阱)
        • 软件错误(例如,除零)
        • 操作系统服务请求 - 系统调用
        • 故障处理:其他进程问题包括无限循环、进程相互修改,甚至修改操作系统;

不同体系结构下,不同 OS 启动也有不同:

x86 需要兼顾 “历史包袱”,需要兼容 32 位

ARM

完整的操作系统初始化程序(即启动管理器)可在根目录下找到

Eg : windows 操作系统完整的开机初始化程序在 根目录/Windows/Boot

# 双 / 多 模式操作

# 双模式操作

即经典的内核态、用户态两个模式

# 多重模式操作

两模式扩展到多模式,典型场景是虚拟化

支持虚拟化技术的 CPU 有一种单独模式,用于表示虚拟机管理器 VMM;

这种模式的特权多于用户,但少于内核;

多重模式执行

# 虚拟机

虚拟机:使用虚拟化技术,将一台物理机器虚拟化多台虚拟机器(Virtual Machine, VM),每个虚拟机器都可以独立运行一个操作系统

同义术语:

  • 虚拟机管理程序
  • 虚拟机监控程序
  • Virtual Machine Monitor
  • Hypervisor

当源 CPU 类型不同于目标类型(例如 PowerPC 到 Intel x86)时使用仿真

当计算机语言未编译本机代码时进行解释

# 第一类 VMM

直接运行在硬件上

第一类VMM

KVM(Kernel-based Virtual Machine)是一种基于硬件虚拟化扩展的完全虚拟化技术。使用 KVM,虚拟机可以在真实硬件上运行,并获得对硬件的直接访问。每个 KVM 虚拟机都被视为一个独立的虚拟计算机,具有自己的虚拟硬件,包括虚拟的 CPU、内存、磁盘和网络接口等。

WSL(Windows Subsystem for Linux)是一项由 Microsoft 开发的技术,旨在在 Windows 操作系统上运行本地的 Linux 环境。WSL 提供了一个兼容层,允许在 Windows 上运行原生的 Linux 二进制文件(如命令行工具、实用程序和应用程序)。在 WSL 中,并没有采用传统的虚拟化技术来创建完全虚拟化的虚拟机。相反,WSL 利用 Windows 操作系统的内核功能,通过在用户模式和内核模式之间进行转换,提供了对 Linux 系统调用的兼容支持。

# 第二类 VMM

运行在宿主操作系统上

第二类VMM.png

LXC(Linux Containers)是一种操作系统级虚拟化技术,也被称为容器化。使用 LXC,虚拟机实际上是在宿主机的操作系统内运行的,共享宿主机的内核。这些虚拟机被称为容器,它们与宿主机共享相同的内核和一些系统资源。相比于 KVM,LXC 提供了更轻量级的虚拟化解决方案,更适合运行基于 Linux 的应用程序。

VMware:完全虚拟化

VirtualBox:“半虚拟化”

PVE 中的虚拟机就是 KVM 技术实现,而容器 CT 就是 LXC 技术实现

# 两类 VMM 的对比

第一类 VMM第二类 VMM
对物理资源的控制权直接运行在硬件之上,能直接控制和分配物理资 源运行在 Host OS 之上,依赖于 Host OS 为其分配物理资源
资源分配方式在安装 Guest OS 时,VMM 要在原本的硬盘上自行分配存储空间,类似于 “外核” 的分配方式,分配未经抽象的物理硬件GuestOS 拥有自己的虚拟磁盘,该盘实际上是 Host OS 文件系统中的一个大文件。GuestOS 分配到的内存是虚拟内存
性能性能更好性能更差,需要 HostOS 作为 “中介 "
可支持的虚拟机数量更多,不需要和 Host OS 竞争资源,相同的硬件资源可以支持更多的虚拟机更少,Host OS 本身需要使用物理资源,Host OS 上运行的其他进程也需要物理资源
虚拟机的可迁移性更差更好,只需导出虚拟机镜像文件即可迁移到另一台 HostOS 上,商业化应用更广泛
运行模式第一类 VMM 运行在最高特权级(Ring O),可以执行最高特权的指令;上层操作系统内核运行在次高特权级(Ring 1);上层操作系统非内核程序程序运行在次高特权级(Ring 1)第二类 VMM 部分运行在用户态、部分运行在内核态。GuestOS 发出的系统调用会被 VMM 截获,并转化为 VMM 对 HostOS 的系统调用
Edited on Views times
\ No newline at end of file +操作系统绪论 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 操作系统的定义

实际上操作系统没有普遍接受的定义

操作系统 (Operating System,OS)是指控制管理整个计算机系统的硬件和软件资源,并合理地组织调度计算机的工作资源分配;以提供给用户其他软件方便的接口环境;它是计算机系统中最基本的系统软件

# 操作系统的功能和目标

# 作为系统资源的管理者

# 提供的功能

  • 处理机管理

  • 存储器管理

  • 文件管理

  • 设备管理

# 目标

安全、高效

# 向上层提供方便易用的服务

# GUI

(Graphical User Interface) 图形化用户接口

# CLI

(Command Line Interface) 命令行接口

  • 联机命令接口 = 交互式命令接口
  • 脱机命令接口 = 批处理命令接口

# 程序接口

可以在程序中进行系统调用来使用程序接口。普通用户不能直接使用程序接口,只能通过程序代码间接使用。

软件和程序员才能使用程序接口

封装思想:操作系统把一些丑陋的硬件功能封装成简单易用的服务,使用户能更方便地使用计算机,用户无需关心底层硬件的原理,只需要对操作系统发出命令即可

# 作为最接近硬件的层次

目标:实现对硬件机器的拓展

没有任何软件支持的计算机称为裸机。在裸机上安装的操作系统,可以提供资源管理功能和方便用户的服务功能,将裸机改造成功能更强、使用更方便的机器

通常把覆盖了软件的机器成为扩充机器,又称之虚拟机

# 操作系统的特征

# 并发

并发:指两个或多个事件在同一时间间隔内发生。这些事件宏观上是同时发生的,但微观上是交替发生的

操作系统的并发性:计算机系统中 “同时” 运行着多个程序,这些程序宏观上看是同时运行着的,而微观上看是交替运行的。

操作系统就是伴随着 “多道程序技术” 而出现的。因此,操作系统和程序并发是一起诞生的。

注意(重要考点):单核 CPU 同一时刻只能执行一个程序,各个程序只能并发地执行多核 CPU 同一时刻可以同时执行多个程序,多个程序可以并行地执行

# 共享

共享即资源共享,是指系统中的资源可供内存中多个并发执行的进程共同使用。

# 互斥共享方式

系统中的某些资源,虽然可以提供给多个进程使用,但一个时间段内只允许一个进程访问该资源

# 同时共享方式

系统中的某些资源,允许一个时间段内由多个进程 “同时” 对它们进行访问

所谓的 “同时” 往往是宏观上的,而在微观上,这些进程可能是交替地对该资源进行访问的(即分时共享)

并发共享 的关系是相互依存,不可分割

如果失去并发性,则系统中只有一个程序正在运行,则共享性失去存在的意义;

如果失去共享性,则不同的程序不能同时访问硬盘资源,就无法实现同时发送文件,也就无法并发

# 虚拟

虚拟是指把一个物理上的实体变为若干个逻辑上的对应物。物理实体(前者)是实际存在的,而逻辑上对应物(后者)是用户感受到的。

# 空分复用技术

如虚拟存储器技术

# 时分复用技术

如虚拟处理器

并发共享 的关系是相互依存,不可分割

如果失去了并发性,则一个时间段内系统中只需运行一道程序,那么就失去了实现虚拟性的意义了。因此,没有并发性,就谈不上虚拟性

# 异步

异步指,在多道程序环境下,允许多个程序并发执行,但由于资源有限,进程的执行不是一贯到底的,而是走走停停,以不可预知的速度向前推进,这就是进程的异步性。

# 操作系统的发展和分类

# 手工操作阶段

主要缺点:

用户独占全机、人机速度矛盾导致资源利用率极低

# 批处理阶段

引入脱机输入 / 输出技术(用外围机 + 磁带完成),并由监督程序负责控制作业的输入、输出,通过外围机把程序提前存到磁带里

目标是追求吞吐量,提高资源利用率

# 脱机

在主机以外的设备上进行输入 / 输出操作,需要时再送主机处理。

# 批处理 bash

后端运行的作业,开始运行之后就不再需要任何交互。由于无法交互控制程序,所以还不算真正意义上的操作系统。

# 单道批处理系统

也叫简单批处理系统。已经出现操作系统的一些特征:

  • 用户态、内核态(monitor)
  • 时钟

主要优点:

缓解了一定程度的人机速度矛盾,资源利用率有所提升。


主要缺点:

内存中仅能有一道程序运行,只有该程序运行结束之后才能调入下一道程序。

CPU 有大量的时间是在空闲等待 1/0 完成。资源利用率依然很低

没有人机交互功能。

# 多道程序设计

多道程序的运行环境比单道程序等更加复杂。

特点:

  • 多道 —— 计算机内存中同时存放多道相互独立的程序
  • 宏观上并行
  • 微观上串行
  • 非封闭、非顺序 —— 引入多道程序后,程序的执行就失去了封闭性和顺序性
  • 相互制约 —— 程序执行因为共享资源以及相互协同的原因相互制约
  • 断续性 —— 考虑到竞争的公平性,程序的执行是断续的

多道程序设计的实现需要解决如下问题:

  • 处理机的分配
  • 多道程序的内存分配
  • I/O 设备的分配
  • 如何组织和存放大量的程序和数据,以方便用户使用并保证一致性安全性
    • 一定需要实现虚拟存储吗?—— 不一定,早期多道批处理操作系统将所有进程数据全部调入主存

这些问题的处理也会增加系统开销。

多道程序设计开始引入中断,目的是使 CPU 和 I/O 设备并行运行,提高资源利用率。

# 多道批处理系统(操作系统开始出现)

在批处理系统中采用多道程序设计就形成了多道批处理系统。

每次往内存中读入多道程序,操作系统正式诞生,用于支持多道程序并发运行。


主要优点:

多道程序并发执行,共享计算机资源。资源利用率大幅提升,CPU 和其他资源更能保持 “忙碌” 状态,系统吞吐量增大。


主要缺点:

用户响应时间长,仍然没有人机交互功能(用户提交自己的作业之后就只能等待计算机处理完成,中间不能控制自己的作业执行。eg:无法调试程序 / 无法在程序运行过程中输入一些参数)

# 分时操作系统

计算机以时间片为单位轮流为各个用户 / 作业服务,各个用户可通过终端与计算机进行交互。

目标是追求时延(latency)


主要特征:

  • 同时性、也叫多路性
  • 交互性
  • 独立性
  • 及时性

主要优点:

用户请求可以被即时响应,解决了人机交互问题。允许多个用户同时使用一台计算机,并且用户对计算机的操作相互独立,感受不到别人的存在。


主要缺点:

不能优先处理一些紧急任务。操作系统对各个用户 / 作业都是完全公平的,循环地为每个用户 / 作业服务一个时间片,不区分任务的紧急性。

# 实时操作系统

主要优点:

能够优先响应一些紧急任务,某些紧急任务不需时间片排队。

在实时操作系统的控制下,计算机系统接收到外部信号后及时进行处理,并且要在严格的时限内处理完事件。实时操作系统的主要特点是及时性可靠性

# 硬实时系统

必须在绝对严格的规定时间内完成处理

eg: 导弹控制系统、自动驾驶系统

# 软实时系统

能接受偶尔违反时间规定

如:12306 火车订票系统

# 网络操作系统

是伴随着计算机网络的发展而诞生的,能把网络中各个计算机有机地结合起来,实现数据传送等功能,实现网络中各种资源的共享(如文件共享)和各台计算机之间的通信。(如:Windows NT 就是一种典型的网络操作系统,网站服务器就可以使用)

# 分布式操作系统

主要特点是分布性和并行性。系统中的各台计算机地位相同,任何工作都可以分布在这些计算机上,由它们并行、协同完成这个任务。

# 个人计算机操作系统

eg: windows、macos

# 操作系统服务

  • 资源分配
  • 记账
  • 日志服务

# 内核

内核是操作系统最重要最核心的部分,也是最接近硬件的部分

甚至可以説,一个操作系統只要有内核就够了(eg:Docker-> 仅需 Linux 内核)

操作系统的功能未必都在内核中,如图形化用户界面 GUI

由很多内核程序组成了 “操作系统内核”,或简称 “内核、(Kernel)”

# 内核程序 —— 运行在内核态

微软、苹果有一帮人负责实现操作系统,他们写的是 “内核程序”。操作系统内核作为 “管理者”,有时会让 CPU 执行一些 “特权指令”,如:内存清零指令。这些指令影响重大,只允许 “管理者”—— 即操作系统内核来使用

普通程序员写的程序就是 “应用程序”,应用程序只能使用 “非特权指令”,如:加法指令、减法指令等

在 CPU 设计和生产的时候就划分了特权指令和非特权指令,因此 CPU 执行一条指令前就能判断出其类型

CPU 中有一个寄存器叫 程序状态字寄存器(PSW),其中有个二进制位,1 表示 “内核态”,0 表示 “用户态”

# 内核态 —— 运行内核程序

CPU 有两种状态,“内核态” 和 “用户态”。处于内核态时,说明此时正在运行的是内核程序,此时可以执行特权指令处于用户态时,说明此时正在运行的是应用程序,此时只能执行非特权指令

内核态 = 核心态 = 管态;用户态 = 目态

# 内核态和用户态的切换 (变态)

变态的过程是有成本的,要消耗不少时间,频繁地变态会降低系统性能

# 内核态 -> 用户态

执行一条特权指令一一修改 PSW 的标志位为 “用户态”,这个动作意味着操作系统将主动让出 CPU 使用权

# 用户态 -> 内核态

由 “中断” 引发,硬件自动完成变态过程,触发中断信号意味着操作系统将强行夺回 CPU 的使用权。除了非法使用特权指令之外,还有很多事件会触发中断信号。一个共性是,旦凡需要操作系统介入的地方,都会触发中断信号

# 系统调用

对象与系统调用、库函数的关系
普通应用程序可直接进行系统调用,也可使用库函数。 有的库函数涉及系统调用,有的不涉及
编程语言向上提供库函数。有时会将系统调用封装成库函数,以隐藏系统调用的一些细节,使程序员编程更加方便。
操作系统向上提供系统调用,使得上层程序能请求内核的服务
裸机

不涉及系统调用的库函数.eg

  • “取绝对值” 的函数

涉及系统调用的库函数.eg

  • “创建一个新文件” 的函数

# 按功能分类

  • 设备管理 —— 完成设备请求 / 释放 / 启动 等功能
  • 文件管理 —— 完成文件读 / 写 / 创建 / 删除 等功能
  • 进程控制 —— 完成进程创建 / 撒销 / 阻塞 / 唤醒 等功能
  • 进程通信 —— 完成进程之间的 消息传递 / 信号传递 等功能
  • 内存管理 —— 完成内存分配 / 回收 等功能

应用程序通过系统调用请求操作系统的服务。而系统中的各种共享资源都由操作系统内核统一掌管,因此凡是与共享资源有关的操作(如存储分配、1/0 操作、文件管理等),都必须通过系统调用的方式向操作系统内核提出服务请求,由操作系统内核代为完成。这样可以保证系统的稳定性和安全性,防止用户进行非法操作。

# 系统调用过程

  1. 传递系统调用参数
    • 寄存器传递参数
    • 内存中存储在块或表中的参数,以及作为参数在寄存器中传递的块地址
      • linux 和 solaris 采用这种方式
    • 由程序放置或推送到堆栈上并由操作系统弹出堆栈到参数

块和堆栈的方式传递参数大小不受限制

  1. 执行陷入指令(用户态)
  2. 执行相应的内请求核程序处理系统调用(内核态)
  3. 返回应用程序

陷入指令 = trap 指令 = 访管指令

陷入指令是在用户态执行的,执行陷入指令之后立即引发一个内中断,使 CPU 进入内核态

发出系统调用请求是在用户态,而对系统调用的相应处理内核态下进行

# 计算计组成原理相关基础概念

# 中断和异常

参考这个

没有中断就没有并发,也就没有操作系统

中断是让操作系统内核夺回 CPU 使用权的唯一途径,使 CPU 由用户态变为内核态

通用概念产生 原因AArch64x86-64
中断硬件 异步异步异常 (重置 / 中断)中断 (可屏蔽 / 不可屏蔽)
异常软件 同步同步异常 (终止 / 异常指令)异常 (Fault/Trap/Abort)

中断

(广义上的中断包括)Interrupt Handlers used in all 3 scenarios :

  • HW -> CPU -> Kernel: Classic HW Interrupt (狭义上的中断)
  • User -> Kernel: SW Interrupt
  • CPU -> Kernel: Exception

# 其他类型 (非狭义) 中断

  • SW Interrupt
    • Interrupts caused by the execution of a software instruction: INT<interrupt_number>
    • Used by the system call interrupt()
    • Initiated by the running (user level) process
    • Cause current processing to be interrupted and transfers control to the corresponding interrupt handler in the kernel
  • Exceptions
    • Initiated by processor hardware itself
    • Example: divide by zero
    • Cause a transfer of control to the kernel to handle the exception (like a software interrupt)

# Linux 系统的中断

  • 在中断处理中做尽量少的事
  • 推迟非关键行为

结构:

  • Top half :马上做,找到 handler

    • 最小的、公共行为

      • 保存寄存器、屏蔽其他中断
      • 恢复寄存器,返回原来场景

      最重要:调用合适的由硬件驱动提供的中断处理 handler

      因为中断被屏蔽,所以不要做太多事情 (时间、空间)

      使用将请求放入队列,或者设置标志位将其他处理推迟到 bottom half

      现代处理器中,多个 I/O 设备共享一个 IRQ 和中断向量 v 多个 ISR (interrupt service routines) 可以结合在一个向量上
      调用每个设备对应该 IRQ 的 ISR

  • Bottom half : 推迟处理 (softirq, tasklets, 工作队列,内核线程)

    • 提供一些推迟完成任务的机制

    • softirqs

    • tasklets (建立在 softirqs 之上)

    • 工作队列

    • 内核线程

    这些工作可以被中断

linux中断

中断处理没有进程上下文!

中断 (和异常相比) 和具体的某条指令无关

也和中断时正在跑的进程、用户程序无关

中断处理 handler 不能睡眠!

中断处理的一些约束条件:

  • 不能睡眠
    • 或者调用可能会睡眠的任务
  • 不能调用 schedule () 调度
  • 不能释放信号或调用可能睡眠的操作
  • 不能和用户地址空间交换数据

# 中断向量表

每一个处理器有一个中断向量表,由操作系统内核建立,指向处理不同时间的中断处理程序入口

结构:

中断向量表

# 需要中断的场景举例

Hardware devices may need asynchronous and immediate service. For example:

  • Timer interrupt: Timers and time-dependent activities need to be updated with the passage of time at precise intervals
  • Network interrupt: The network card interrupts the CPU when data arrives from the network
  • I/O device interrupt: I/O devices (such as mouse and keyboard) issue hardware interrupts when they have input (e.g., a new character or mouse click)

# 多核系统上的中断

Howareinterruptshandledonmulticoremachines?

  • On x86 systems each CPU gets its own local Advanced Programmable Interrupt Controller (APIC). They are wired in a way that allows routing device interrupts to any selected local APIC.
  • The OS can program the APICs to determine which interrupts get routed to which CPUs.
  • The default (unless OS states otherwise) is to route all interrupts to processor 0

# 陷入指令

执行 “陷入指令”,意味着应用程序主动地将 CPU 控制权还给操作系统内核。“系统调用” 就是通过陷入指令完成的

# I/O (输入输出系统)

# BUS (总线)

# 并行系统

# 多核处理器

# 多处理器系统

又称并行系统、紧耦合系统

区分 多处理器系统多核系统 ,实际计算机往往既是多核的也是多处理器的

多核和多处理器系统都用于加速计算过程。多核包含在单个 CPU 中的多个核或处理单元。多处理器由多个 CPU 组成。多核处理器不需要像多处理器那样复杂的配置。相反,多处理器更可靠并且能够运行许多程序。

# 三个优点一个缺点???

老师出的作业题😅难道本来是想问多道批处理系统?而且那个也是单处理器系统啊)

  • 增加吞吐量,并行处理?
  • 规模经济,降低成本,比多核处理器便宜?
  • 增加可靠性?
  • ???

# 非对称多处理器系统 (AMP)

非对称多处理是指一种计算机结构,其中有多个处理器,但它们并不都是一样的。这意味着,一个 CPU 可能正在处理操作系统代码,而另一个 CPU 正在执行输入和输出工作。它使用两个或更多的处理器由一个主处理器处理。所有的 CPU 都是相互连接的,但不是自我调度的。它用于根据任务的优先级和重要性将特定任务安排到一个 CPU。

非对称处理器的应用场景:被用于嵌入式系统,在这些系统中,特定任务需要并发执行,但系统不需要像对称多处理系统那样的通用计算能力

# 对称多处理器系统 (SMP)

SMP(Sysmmetric Multi-Processor System,对称多处理器),它由多个具有对称关系的处理器组成。所谓对称,即处理器之间没有主从之分。SMP 架构使得一台计算机不再由单个 CPU 组成,而是由两个或更多的处理器连接到一个共享的主存储器上,并能够共同执行任务。这些处理器通常是相同的,能够运行分配给它们的任何任务。这可以提高性能,因为任务可以在处理器之间分配,使其更快完成。

对称多处理将多个 CPU 应用于一个任务,以并行和更快的方式完成。因此,在对称多处理系统中,两个或更多的 CPU 被连接到一个共享的主存储器。同时,所有这些 CPU 都可以完全访问输入和输出设备。在对称多处理系统中,操作系统认为所有的处理器都是平等的。

对称处理器 (SMP) 架构同时也是 UMA 架构

SMP 是一个紧密耦合的多处理器系统,它有一组独立运行的相同的 CPU。每个 CPU 处理不同的程序,执行不同的数据集。对称多处理系统共享公共资源,如输入设备、输出设备、内存等。

# 问题

所有处理器相同,没有考虑不同任务要求处理器的差异性

# 多处理器环境的 3 种内存共享模型

# UMA

UMA(Uniform Memory Access,一致性存储器访问),实际上就是 SMP 。其中,一致性指的就是在任意时刻,多个处理器只能为内存的每个数据保存或共享一个唯一的数值。它的结构特征就是多处理器共享一个集中式存储器,每个处理器访问存储器所需的时间一致,工作负载能够均匀的分配到所有可用处理器上,极大地提高了整个系统的数据处理能力。但是,如果多个处理器同时请求访问共享资源时,就会引发资源竞争,需要软硬件实现加锁机制来解决这个问题。

因此,这样的架构设计无法拥有良好的处理器数量扩展性,因为共享内存的资源竞态总是存在的,处理器利用率最好的情况只能停留在 2 到 4 颗。

# NUMA

NUMA(Non-Uniform Memory Access,非一致性存储器访问)架构优化了 SMP 架构扩展性差以及存储器带宽窄的问题。采用了分布式存储器,将处理器和存储器划分为不同的节点(NUMA Node),每个节点都包含了若干的处理器与内存资源。多节点的设计有效提高了存储器的带宽和处理器的扩展性。

另一方面,NUMA 节点的处理器可以访问到整体存储器。按照节点内外,内存被分为:

  • 节点内部的本地内存
  • 节点外部的远程内存

当处理器访问本地内存时,走的是内部总线,当处理器访问远程内存时,走的是主板上的 QPI 互联模块。访问前者的速度要远快于后者,NUMA(非一致性存储器访问)因此而得名。

# 问题

各个处理器访问自己的内存速度很快,但如果出现需要跨处理器访存,即访问另一处理器的内存时会非常缓慢

# COMA

Cache-only Memory Access (COMA) 是 ccNUMA (Cache Coherent NUMA, 缓存一致性 NUMA) 的一种演变。COMA 可以看成是专用的 NUMA,将 NUMA 中的分布式内存用高速缓存来取代。全局地址空间由高速缓存组成。访问远端的高速缓存借助分布式高速缓存目录进行。

# 集群系统

类似多处理系统,集群系统时多个机器,每台机器有自己的操作系统,并行工作。

  • Usually sharing storage via a storage-area network (SAN)

  • Provides a high-availability service which survives failures

    • Asymmetric clustering has one machine in hot-standby mode
    • Symmetric clustering has multiple nodes running applications, monitoring each other
  • Some clusters are for high-performance computing (HPC)

    • Applications must be written to use parallelization
  • Some have distributed lock manager (DLM) to avoid conflicting operations

# 操作系统的结构

不同结构操作系统举例:

  • 大内核 / 宏内核 / 单内核: Windows、Android、iOS、UNIX、Linux、MacOS
  • 微内核:Windows NT、Mach、Fuchsia、鸿蒙
  • 模块化:Solaris
操作系统体系结构区别优点缺点
大内核 / 宏内核 / 单内核将操作系统的主要功能模块都作为系统内核,运行在核心态高性能内核代码庞大,结构混乱,难以维护
微内核只把最基本的功能保留在内核内核功能少,结构清晰,方便维护需要频繁地在核心态和用户态之间切换,性能低
特性、思想优点缺点
分层结构内核分多层,每层可单向调用更低一层提供的接1. 便于调试和验证,自底向上逐层调试验证1. 仅可调用相邻低层,难以合理定义各层的边界
2. 效率低,不可跨层调用,系统调用执行时间长2. 效率低,不可跨层调用,系统调用执行时间长
模块化将内核划分为多个模块,各模块之间相互协作。内核 = 主模块 + 可加载内核模块1. 模块间逻辑清晰易于维护,确定模块间接口后即可多模块同时开发1. 模块间的接口定义未必合理、实用
主模块:只负责核心功能,如进程调度、内存管2. 支持动态加载新的内核模块(如:安装设备驱动程序、安装新的文件系统模块到内核),增强 OS 适应性2. 模块间相互依赖,更难调试和验证
可加载内核模块:可以动态加载新模块到内核,而无需重新编译整个内核3. 任何模块都可以直接调用其他模块,无需采用消息传递进行通信,效率高
宏内核 (大内核)所有的系统功能都放在内核里(大内核结构的 OS 通常也采用了 " 模块化” 的设计思想)性能高,内核内部各种功能都可以直接相互调用1. 内核庞大功能复杂,难以维护
2. 大内核中某个功能模块出错,就可能导致整个 系统崩溃
微内核只把中断、原语、进程通信等最核心的功能放入内核。进程管理、文件管理、设备管理等功能以用户进程的形式运行在用户态1. 内核小功能少、易于维护,内核可靠性高1. 性能低,需要频繁的切换 用户态 / 核心态。用户态下的各功能模块不可以直接相互调用,只能通过内核的 "消息传递" 来间接通信
2. 内核外的某个功能模块出错不会导致整个系统 崩溃2. 用户态下的各功能模块不可以直接相互调用,只能通过内核的 "消息传递" 来间接通信
外核 (exokernel)内核负责进程调度、进程通信等功能,外核负责为用户进程分配未经抽象的硬件资源,且由外核负责保证资源使用安全1. 外核可直接给用户进程分配 "不虚拟、不抽象" 的硬件资源,使用户进程可以更灵活的使用硬件1. 降低了系统的一致性
2. 减少了虚拟硬件资源的 “映射层”,提升效率2. 使系统变得更复杂

# 非内核功能(如 GUI)

操作系统的非内核功能运行在用户态

# (大) 内核

内核是操作系统最基本、最核心的部分。

实现操作系统内核功能的那些程序就是内核程序。

操作系统内核需要运行在内核态

# 对系统资源进行管理的功能

大内核结构中运行在内核态,所以大内核结构操作系统变态不那么频繁

微内核结构中运行在用户态,所以微内核结构操作系统变态更加频繁

# 进程管理

# 存储器管理

# 设备管理等功能

# (微内核)

# 时钟管理

实现计时功能

# 中断处理

负责实现中断机制

# 原语(设备驱动、CPU 切换等)

是一种特殊的程序,具有如下特点:

  • 处于操作系统最底层,是最接近硬件的部分
  • 这种程序的运行具有原子性 —— 其运行只能一气呵成,不可中断
  • 运行时间较短、调用频繁

# 操作系统的引导

操作系统引导过程

操作系统引导过程

  1. CPU 从一个特定主存地址开始,取指令,执行 ROM 中的引导程序(先进行硬件自检,再开机)
  2. 将磁盘的第一块 —— 主引导记录 读入内存,执行磁盘引导程序,扫描分区表
  3. 从活动分区(又称主分区,即安装了操作系统的分区)读入分区引导记录,执行其中的程序
  4. 从根目录下找到完整的操作系统初始化程序(即启动管理器)并执行,完成 “开机” 的一系列动作
    1. 加载内核
      • BIOS
      • UEFI,逐渐取代 BIOS,加载更简洁
      • GRUB,更加复杂,可以选择加载不同的内核
    2. 启动系统守护进程(在内核之外提供的服务)
    3. 启动内核中断驱动(硬件和软件)
      1. 启动设备的硬件中断
      2. 启动软件中断(异常或陷阱)
        • 软件错误(例如,除零)
        • 操作系统服务请求 - 系统调用
        • 故障处理:其他进程问题包括无限循环、进程相互修改,甚至修改操作系统;

不同体系结构下,不同 OS 启动也有不同:

x86 需要兼顾 “历史包袱”,需要兼容 32 位

ARM

完整的操作系统初始化程序(即启动管理器)可在根目录下找到

Eg : windows 操作系统完整的开机初始化程序在 根目录/Windows/Boot

# 双 / 多 模式操作

# 双模式操作

即经典的内核态、用户态两个模式

# 多重模式操作

两模式扩展到多模式,典型场景是虚拟化

支持虚拟化技术的 CPU 有一种单独模式,用于表示虚拟机管理器 VMM;

这种模式的特权多于用户,但少于内核;

多重模式执行

# 虚拟机

虚拟机:使用虚拟化技术,将一台物理机器虚拟化多台虚拟机器(Virtual Machine, VM),每个虚拟机器都可以独立运行一个操作系统

同义术语:

  • 虚拟机管理程序
  • 虚拟机监控程序
  • Virtual Machine Monitor
  • Hypervisor

当源 CPU 类型不同于目标类型(例如 PowerPC 到 Intel x86)时使用仿真

当计算机语言未编译本机代码时进行解释

# 第一类 VMM

直接运行在硬件上

第一类VMM

KVM(Kernel-based Virtual Machine)是一种基于硬件虚拟化扩展的完全虚拟化技术。使用 KVM,虚拟机可以在真实硬件上运行,并获得对硬件的直接访问。每个 KVM 虚拟机都被视为一个独立的虚拟计算机,具有自己的虚拟硬件,包括虚拟的 CPU、内存、磁盘和网络接口等。

WSL(Windows Subsystem for Linux)是一项由 Microsoft 开发的技术,旨在在 Windows 操作系统上运行本地的 Linux 环境。WSL 提供了一个兼容层,允许在 Windows 上运行原生的 Linux 二进制文件(如命令行工具、实用程序和应用程序)。在 WSL 中,并没有采用传统的虚拟化技术来创建完全虚拟化的虚拟机。相反,WSL 利用 Windows 操作系统的内核功能,通过在用户模式和内核模式之间进行转换,提供了对 Linux 系统调用的兼容支持。

# 第二类 VMM

运行在宿主操作系统上

第二类VMM.png

LXC(Linux Containers)是一种操作系统级虚拟化技术,也被称为容器化。使用 LXC,虚拟机实际上是在宿主机的操作系统内运行的,共享宿主机的内核。这些虚拟机被称为容器,它们与宿主机共享相同的内核和一些系统资源。相比于 KVM,LXC 提供了更轻量级的虚拟化解决方案,更适合运行基于 Linux 的应用程序。

VMware:完全虚拟化

VirtualBox:“半虚拟化”

PVE 中的虚拟机就是 KVM 技术实现,而容器 CT 就是 LXC 技术实现

# 两类 VMM 的对比

第一类 VMM第二类 VMM
对物理资源的控制权直接运行在硬件之上,能直接控制和分配物理资 源运行在 Host OS 之上,依赖于 Host OS 为其分配物理资源
资源分配方式在安装 Guest OS 时,VMM 要在原本的硬盘上自行分配存储空间,类似于 “外核” 的分配方式,分配未经抽象的物理硬件GuestOS 拥有自己的虚拟磁盘,该盘实际上是 Host OS 文件系统中的一个大文件。GuestOS 分配到的内存是虚拟内存
性能性能更好性能更差,需要 HostOS 作为 “中介 "
可支持的虚拟机数量更多,不需要和 Host OS 竞争资源,相同的硬件资源可以支持更多的虚拟机更少,Host OS 本身需要使用物理资源,Host OS 上运行的其他进程也需要物理资源
虚拟机的可迁移性更差更好,只需导出虚拟机镜像文件即可迁移到另一台 HostOS 上,商业化应用更广泛
运行模式第一类 VMM 运行在最高特权级(Ring O),可以执行最高特权的指令;上层操作系统内核运行在次高特权级(Ring 1);上层操作系统非内核程序程序运行在次高特权级(Ring 1)第二类 VMM 部分运行在用户态、部分运行在内核态。GuestOS 发出的系统调用会被 VMM 截获,并转化为 VMM 对 HostOS 的系统调用
Edited on Views times
\ No newline at end of file diff --git a/cs/os/deadlock/index.html b/cs/os/deadlock/index.html index 6bfe78b7..f99339ba 100644 --- a/cs/os/deadlock/index.html +++ b/cs/os/deadlock/index.html @@ -1 +1 @@ -死锁 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# Intro

死锁的必要条件

  • 互斥:一次只有一个进程使用一个资源,其他进程不能访问分配给其他进程的资源
  • 占有等待 (持有且等待):当一个进程等待其他进程时,继续占有已分配的资源
  • 非抢占:不能强行抢占进程已占有的资源
  • 循环等待:存在一个闭合的进程链,每个进程至少占有此链中下一个进程所需的一个资源前三个只会导致死锁的可能性,而最后一个循环等待是导致死锁的 “最终极条件”

处理死锁的方法:

  • 确保系统永远不会进入死锁状态
    • 锁预防,在 OS 设计阶段就设计成不会出现死锁
    • 死锁避免,在 OS 运行的时候尽量避免死锁产生条件
  • 允许系统进入死锁状态,然后检测和恢复
  • 忽略该问题,并假装系统中从未发生死锁
    • 绝大多数操作系统所采用的的方法
    • 合理性:死锁的发生实际上是一个小概率性事件

# 死锁预防

使死锁的四个必要条件之一无效,破坏任意一个死锁必要条件:

  • 互斥:通常不能否定互斥条件来预防死锁,必须保留不可共享的资源
  • 持有且等待:必须保证每当进程请求资源时,它不会占有任何其他资源
    • 一种实现:在进程开始执行之前请求并分配其所有资源
    • 另一种实现:仅当进程在未分配任何资源时才允许进程请求资源
  • 非抢占
    • 如果持有某些资源的进程请求另一个无法立即分配给它的资源,那么当前持有的所有资源都将被释放 (隐式释放)
    • 被抢占资源被添加到进程正在等待的资源列表中
    • 只有当进程能够恢复其原有的资源以及它所请求的新资源 时,才会重新启动进程
  • 循环等待 (最常见)
    • 强制所有类型的资源进行完全排序,也就是为每个资源 (即互斥锁) 分配一个唯一的编号,并要求每个进程以同一特定顺序 (例如递增) 请求资源
    • 可以反证这样的做法不存在循环等待
    • 如果能够动态获得锁,那么制定一个加锁顺序并不保证死锁预防,因为并不能保证请求资源的顺序是同一特定顺序

动态获得锁:获得锁的函数与输入的参数有关

问题

  • 一个进程需要多少资源无法精确预测
  • 副作用是设备使用率低,系统吞吐率低

# 死锁避免

死锁避免使用算法动态检查资源分配状态,以确保不存在循环等待条件

优势:

  • 无须死锁预防中的抢占和回滚进程
  • 与死锁预防相比限制较少

限制:

  • 必须事先声明每一个进程请求的最大资源;
  • 所讨论的进程必须是无关的,即他们的执行顺序必须没有任何同步要求的限制;
  • 分配的资源数量必须是固定的;
  • 在占有资源时,进程不能退出;

这些限制使得银行家算法这样的死锁避免算法实际上是不可行的,只能用于理论检测

# 安全状态

只有至少存在一个安全序列,系统才处于安全状态

系统中存在所有进程的序列 <P1,P2,,Pn><P_1,P_2,\cdots,P_n> 在当前分配状态下为安全序列是指:

对于每个 PiP_iPiP_i 请求的资源可以通过 当前可用资源 + 所有 Pj(j<i)P_j(j<i) 持有的资源 来满足。

即:

  • 如果 PiP_i 资源需求不能立即可用,则 PiP_i 可以等待所有 PjP_j 完成,释放资源
  • PjP_j 完成时,PiP_i 可以获得所需的资源、执行、返回分配的资源并终止
  • PiP_i 终止时,Pi+1P_{i+1} 可以获得它所需的资源,依此类推

⚠️安全状态一定不是死锁状态,非安全状态只是死锁的必要条件,可能导致死锁,但不是死锁的充分条件。

safe-unsafe-deadlock

死锁避免两种方法

  • 在进程某次请求资源的时候,如果为其分配资源后系统进入非安全状态,则拒绝分配
  • 进程启动拒绝:在进程初始化启动的时候,如果对某种资源,它的最大需求 + 当前所以进程的需求 > 系统总资源量,则拒绝分配

# 资源分配图算法

⚠️每种资源都只有一个实例(都是唯一)的时候才能依据资源分配图判断死锁是否产生:

  • 资源分配图中没有环,那么系统就没有进程死锁
  • 如果有环,可能存在死锁

⚠️必须在系统中预先声明资源;也就是只有当进程 PiP_i 的所有边都为需求边时,才能允许将需求边增加到图中

# 银行家算法

⚠️每个进程都必须先验地给出最大需求资源的数量

# 数据结构

n = 进程数, m = 资源类型数。

Available : 长度为 m 的向量。如果 Available[j]=k ,则有 k 个资源类型 Rj 的实例可用;

Max : nxm 矩阵,定义每个进程的最大需求。如果 Max[i, j]=k ,那么进程 Pi 最多可以请求 k 个资源类型 Rj 的实例

Allocation : n×m 矩阵,定义每个进程现在分配的每种资 源类型的实例数量。如果 Allocation[i,j]=k ,则 Pi 当前被分配给了 Rj 的 k 个实例

Need : nxm 矩阵,表示每个进程还需要的剩余资源。如果 Need[i,j]=k ,那么 Pi 可能还需要 k 个 Rj 实例来完成它的任务 Need[i,j]=Max[i,j]–Allocation[i,j]

# 算法流程

判断安全状态:

judge_safe()

  1. Let Work and Finish be vectors of length m and n, respectively.

    Initialize:

    Work = Available

    Finish [i] = false for i = 0, 1, ..., n- 1

  2. Find an i such that both:

    • (a) Finish [i] = false

    • (b) Needi <= Work

    If no such i exists, go to step 4

  3. Work = Work + Allocationi

    Finish[i] = true

    go to step 2

  4. If Finish [i] == true for all i, then the system is in a safe state

判断是否允许某次资源请求:

Requesti = request vector for process Pi. If Requesti [j] = k then process Pi wants k instances of resource type Rj

  1. If Requesti <= Needi go to step 2.

    Otherwise, raise error condition, since process has exceeded its maximum claim

  2. If Requesti <= Available, go to step 3.

    Otherwise Pi must wait, since resources are not available

  3. Pretend to allocate requested resources to Pi by modifying the state as follows:

    • Available = Available – Requesti;

    • Allocationi = Allocationi + Requesti;

    • Needi = Needi – Requesti;

    If judge_safe() => the resources are allocated to Pi

    else => Pi must wait, and the old resource-allocation state is restored

# 死锁检测与恢复

# 死锁检测

允许系统进入死锁状态,死锁检测可以频繁地在每个资源请求发生时进行,也可以检测得少一些,具体取决于发生死锁的可能性。检测出死锁之后进行死锁恢复。

优点:

  • 尽早地检测死锁情况
  • 算法相对简单

缺点

  • 频繁的检测会耗费相当多的处理器时间

何时以及多久调用一次取决于:

  • 死锁可能发生的频率有多高?
  • 需要回滚多少个进程?

如果任意调用检测算法,资源图中可能会有许多循环,因此我们无法判断是哪些死锁进程 “导致” 了死锁

死锁检测产生大量的代价,可以周期性检测死锁,或者 CPU 的利用率低于某个阈值时再执行死锁检测

# 等待图

在资源分配图的基础上,只画出进程,不再画出资源。

和资源分配图一样,只适用于所有类型的资源都是唯一的,只有一个实例的情况。

# 死锁恢复

  • 取消所有的死锁进程,这是实际操作系统最常用的方法
  • 把每个死锁进程回滚到前面定义的某些检查点,并重新启动所有进程,要求在系统中构建回滚和重启机制
  • 连续取消死锁进程直到不再存在死锁,所取消的进程的顺序应基于某种最小代价原则
  • 连续抢占资源直到不再存在死锁,需要使用一种基于代价的选择方法,且需要在抢占后重新调用检测算法

后两种策略的选择 (受害者) 原则:

  • 目前为止消耗的处理器时间最少
  • 目前为止产生的输出最少
  • 预计剩下的时间最长
  • 目前为止分配的资源总量最少
  • 优先级最低

实际上 OS 的死锁恢复

  • 重启
  • 随机 sleep
Edited on Views times
\ No newline at end of file +死锁 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# Intro

死锁的必要条件

  • 互斥:一次只有一个进程使用一个资源,其他进程不能访问分配给其他进程的资源
  • 占有等待 (持有且等待):当一个进程等待其他进程时,继续占有已分配的资源
  • 非抢占:不能强行抢占进程已占有的资源
  • 循环等待:存在一个闭合的进程链,每个进程至少占有此链中下一个进程所需的一个资源前三个只会导致死锁的可能性,而最后一个循环等待是导致死锁的 “最终极条件”

处理死锁的方法:

  • 确保系统永远不会进入死锁状态
    • 锁预防,在 OS 设计阶段就设计成不会出现死锁
    • 死锁避免,在 OS 运行的时候尽量避免死锁产生条件
  • 允许系统进入死锁状态,然后检测和恢复
  • 忽略该问题,并假装系统中从未发生死锁
    • 绝大多数操作系统所采用的的方法
    • 合理性:死锁的发生实际上是一个小概率性事件

# 死锁预防

使死锁的四个必要条件之一无效,破坏任意一个死锁必要条件:

  • 互斥:通常不能否定互斥条件来预防死锁,必须保留不可共享的资源
  • 持有且等待:必须保证每当进程请求资源时,它不会占有任何其他资源
    • 一种实现:在进程开始执行之前请求并分配其所有资源
    • 另一种实现:仅当进程在未分配任何资源时才允许进程请求资源
  • 非抢占
    • 如果持有某些资源的进程请求另一个无法立即分配给它的资源,那么当前持有的所有资源都将被释放 (隐式释放)
    • 被抢占资源被添加到进程正在等待的资源列表中
    • 只有当进程能够恢复其原有的资源以及它所请求的新资源 时,才会重新启动进程
  • 循环等待 (最常见)
    • 强制所有类型的资源进行完全排序,也就是为每个资源 (即互斥锁) 分配一个唯一的编号,并要求每个进程以同一特定顺序 (例如递增) 请求资源
    • 可以反证这样的做法不存在循环等待
    • 如果能够动态获得锁,那么制定一个加锁顺序并不保证死锁预防,因为并不能保证请求资源的顺序是同一特定顺序

动态获得锁:获得锁的函数与输入的参数有关

问题

  • 一个进程需要多少资源无法精确预测
  • 副作用是设备使用率低,系统吞吐率低

# 死锁避免

死锁避免使用算法动态检查资源分配状态,以确保不存在循环等待条件

优势:

  • 无须死锁预防中的抢占和回滚进程
  • 与死锁预防相比限制较少

限制:

  • 必须事先声明每一个进程请求的最大资源;
  • 所讨论的进程必须是无关的,即他们的执行顺序必须没有任何同步要求的限制;
  • 分配的资源数量必须是固定的;
  • 在占有资源时,进程不能退出;

这些限制使得银行家算法这样的死锁避免算法实际上是不可行的,只能用于理论检测

# 安全状态

只有至少存在一个安全序列,系统才处于安全状态

系统中存在所有进程的序列 <P1,P2,,Pn><P_1,P_2,\cdots,P_n> 在当前分配状态下为安全序列是指:

对于每个 PiP_iPiP_i 请求的资源可以通过 当前可用资源 + 所有 Pj(j<i)P_j(j<i) 持有的资源 来满足。

即:

  • 如果 PiP_i 资源需求不能立即可用,则 PiP_i 可以等待所有 PjP_j 完成,释放资源
  • PjP_j 完成时,PiP_i 可以获得所需的资源、执行、返回分配的资源并终止
  • PiP_i 终止时,Pi+1P_{i+1} 可以获得它所需的资源,依此类推

⚠️安全状态一定不是死锁状态,非安全状态只是死锁的必要条件,可能导致死锁,但不是死锁的充分条件。

safe-unsafe-deadlock

死锁避免两种方法

  • 在进程某次请求资源的时候,如果为其分配资源后系统进入非安全状态,则拒绝分配
  • 进程启动拒绝:在进程初始化启动的时候,如果对某种资源,它的最大需求 + 当前所以进程的需求 > 系统总资源量,则拒绝分配

# 资源分配图算法

⚠️每种资源都只有一个实例(都是唯一)的时候才能依据资源分配图判断死锁是否产生:

  • 资源分配图中没有环,那么系统就没有进程死锁
  • 如果有环,可能存在死锁

⚠️必须在系统中预先声明资源;也就是只有当进程 PiP_i 的所有边都为需求边时,才能允许将需求边增加到图中

# 银行家算法

⚠️每个进程都必须先验地给出最大需求资源的数量

# 数据结构

n = 进程数, m = 资源类型数。

Available : 长度为 m 的向量。如果 Available[j]=k ,则有 k 个资源类型 Rj 的实例可用;

Max : nxm 矩阵,定义每个进程的最大需求。如果 Max[i, j]=k ,那么进程 Pi 最多可以请求 k 个资源类型 Rj 的实例

Allocation : n×m 矩阵,定义每个进程现在分配的每种资 源类型的实例数量。如果 Allocation[i,j]=k ,则 Pi 当前被分配给了 Rj 的 k 个实例

Need : nxm 矩阵,表示每个进程还需要的剩余资源。如果 Need[i,j]=k ,那么 Pi 可能还需要 k 个 Rj 实例来完成它的任务 Need[i,j]=Max[i,j]–Allocation[i,j]

# 算法流程

判断安全状态:

judge_safe()

  1. Let Work and Finish be vectors of length m and n, respectively.

    Initialize:

    Work = Available

    Finish [i] = false for i = 0, 1, ..., n- 1

  2. Find an i such that both:

    • (a) Finish [i] = false

    • (b) Needi <= Work

    If no such i exists, go to step 4

  3. Work = Work + Allocationi

    Finish[i] = true

    go to step 2

  4. If Finish [i] == true for all i, then the system is in a safe state

判断是否允许某次资源请求:

Requesti = request vector for process Pi. If Requesti [j] = k then process Pi wants k instances of resource type Rj

  1. If Requesti <= Needi go to step 2.

    Otherwise, raise error condition, since process has exceeded its maximum claim

  2. If Requesti <= Available, go to step 3.

    Otherwise Pi must wait, since resources are not available

  3. Pretend to allocate requested resources to Pi by modifying the state as follows:

    • Available = Available – Requesti;

    • Allocationi = Allocationi + Requesti;

    • Needi = Needi – Requesti;

    If judge_safe() => the resources are allocated to Pi

    else => Pi must wait, and the old resource-allocation state is restored

# 死锁检测与恢复

# 死锁检测

允许系统进入死锁状态,死锁检测可以频繁地在每个资源请求发生时进行,也可以检测得少一些,具体取决于发生死锁的可能性。检测出死锁之后进行死锁恢复。

优点:

  • 尽早地检测死锁情况
  • 算法相对简单

缺点

  • 频繁的检测会耗费相当多的处理器时间

何时以及多久调用一次取决于:

  • 死锁可能发生的频率有多高?
  • 需要回滚多少个进程?

如果任意调用检测算法,资源图中可能会有许多循环,因此我们无法判断是哪些死锁进程 “导致” 了死锁

死锁检测产生大量的代价,可以周期性检测死锁,或者 CPU 的利用率低于某个阈值时再执行死锁检测

# 等待图

在资源分配图的基础上,只画出进程,不再画出资源。

和资源分配图一样,只适用于所有类型的资源都是唯一的,只有一个实例的情况。

# 死锁恢复

  • 取消所有的死锁进程,这是实际操作系统最常用的方法
  • 把每个死锁进程回滚到前面定义的某些检查点,并重新启动所有进程,要求在系统中构建回滚和重启机制
  • 连续取消死锁进程直到不再存在死锁,所取消的进程的顺序应基于某种最小代价原则
  • 连续抢占资源直到不再存在死锁,需要使用一种基于代价的选择方法,且需要在抢占后重新调用检测算法

后两种策略的选择 (受害者) 原则:

  • 目前为止消耗的处理器时间最少
  • 目前为止产生的输出最少
  • 预计剩下的时间最长
  • 目前为止分配的资源总量最少
  • 优先级最低

实际上 OS 的死锁恢复

  • 重启
  • 随机 sleep
Edited on Views times
\ No newline at end of file diff --git a/cs/os/fs/index.html b/cs/os/fs/index.html index c4f2d073..a3e760f6 100644 --- a/cs/os/fs/index.html +++ b/cs/os/fs/index.html @@ -1 +1 @@ -文件系统 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

磁盘的 block 和文件系统的 block 不是一回事:

  • 磁盘的 block :往往是固定的 512 B;
  • 文件系统的 block 是基本单位,可以自定义,不一定和磁盘的 block 大小相等。
    • 文件系统分配空间的基本单位往往是页面大小 4 KB ,

文件系统结构:(自上而下分层)

  • application programs,应用程序
  • logical file system,逻辑文件系统
  • file-organization module,文件组织模块
  • basic file system,基本文件系统
  • I/O control,I/O 控制
  • devices,设备

修改文件要写回磁盘!计算访问磁盘次数的时候要注意写操作比读操作多 1

# 数据结构

面向对象

# FCB

别名:文件目录项文件控制块

包含:

  • 指向关联的 inode 的指针
  • 指向父目录、子目录的指针

# 文件目录

FCB 的有序集合

# inode

别名:索引节点文件描述信息、index node

ext2ext3 采用 inode 表

将 FCB 中的一部分文件描述信息分离出来,这些是检索目录时不需要的不必放在内存的,所以只将指向这部分的一个指针放在内存的目录项里。

采用 inode 可以减少查找文件时的 I/O 信息量,相当于简化了内存中的文件目录项 (FCB),将其中一部分留在磁盘,只保留指向他们的指针。例如 Linux 的文件目录项就只包含文件名和指向 indoe 的指针。

⭐️硬连接和软链接与 inode

  • 硬链接文件指向同一个 inode
  • 软链接文件指向不同的 inode,相当于不同的文件,只不过存的是路径

在文件的物理结构中,则 inode 中就存储了索引文件的主索引表

直接以数组方式存储的 indoe 表,相当于单级索引;也可以有多级索引

  • 磁盘索引节点,每个文件唯一都有一个
    • 文件主标识符
    • 文件类型
    • 文件存取权限
    • 文件物理地址
    • 文件长度
    • 文件链接计数
      • ⭐️ count ,实现硬链接文件共享,表示链接到本索引节点的用户目录项的数量。只有 count=0 的时候才能删除文件。
    • 文件存取时间
  • 内存索引节点,文件被打开时,磁盘索引节点复制放在内存的副本
    • 索引节点号,用于标识内存索引节点
    • 状态,是否被上锁
    • 访问计数,为 0 时文件关闭
    • 逻辑设备号
    • 链接指针,指向空闲列表或散列队列

# 打开文件表

本质上是实现只需要一次访问磁盘定位文件在磁盘的位置,将其存储到内存,后续在内存可以找到文件在磁盘的位置。

两级表:

  • 整个系统一个表,包含与进程无关的信息,每一个文件条目包含:
    • 文件描述符 (File Descriptor, FD)
      • 这是 Linux 中的名字,Windows 中也叫文件句柄
    • 文件打开次数
      • 变为 0 之后就可以 “关闭文件”,从表中删除该项
    • 文件磁盘位置
    • 访问日期
    • 文件大小
  • 每个进程有一个表,包含与进程有关的信息,每一个文件条目包含:
    • 读写指针
    • 访问权限
    • 指向系统打开文件表的对应文件条目指针

⚠️系统只会在第一次打开一个文件的时候使用其文件名在磁盘上定位,然后在内存中创建文件表中的条目,此后就不再需要文件名。

⚠️ open 系统调用由用户调用,一个文件可能对某一用户是第一次打开,但是对系统而言不是第一次,只会在用户进程的打开文件表增加条目。

# 文件保护

  • 口令保护
  • 加密保护
  • 访问控制

# 文件访问控制表

可能也有叫做存取控制矩阵之类的 (?)

为每个文件和目录设置一个文件访问控制表。用来管理不同用户、用户组对该文件或目录的访问权限

# 文件结构

# 文件逻辑结构

文件访问、存取,或者文件中查找数据的方式,是由文件的逻辑结构决定的。

文件的逻辑结构分为:

  • 无结构文件,也叫做流式文件,对该类型文件中记录的访问只能通过穷举搜索。
  • 有结构文件,也叫做记录式文件,这里讨论的都是这种,这样的文件是由一个以上的记录构成的。
    • 定长记录
    • 变长记录

# 顺序

每次读写大批量数据时,顺序文件的效率是最高的。

# 直接

直接文件也叫做散列文件、哈希文件。

  • 优点
    • 存取速度快

# 索引

建立一张索引表,索引表本身是定长记录的顺序文件,其中的每一个索引表项包含:指向记录的指针、记录的长度

  • 优点
    • 提升了查找速度
  • 缺点
    • 索引表增加了存储空间

# 索引顺序

在索引文件的基础上,索引表项指向的单个记录变为一组记录组成的顺序表,就得到了一级索引的索引顺序文件。

优缺点和索引文件仍然一样...

# 记录成组分解

记录成组分解技术是指若干逻辑记录存入一个块,一个逻辑记录不能跨越 2 个块。

搭配隐式链接,每个个块存储固定长度的若干逻辑记录,剩余的字节用于存储指向下一个块的指针。

# 文件物理结构

# 连续分配

配合使用空闲表法管理空闲磁盘空间。

进程访问磁盘时所需的寻道数和寻道时间最小

文件-连续分配

⚠️磁带只能使用连续分配,只能顺序存取!

# 扩展连续分配

例如: ext4ext3

FCB 中比连续分配多增加一项为指向下一个扩展块的指针

# 链接分配 (隐式链接)

每一个块包含该文件指向下一个块的指针,这些指针对用户来说是透明的,空指针表示文件末尾。

  • 优点:

    • 不会产生外部碎片,提高了磁盘利用率。
  • 缺点:

    • 只支持顺序访问,随机访问效率低

    • 稳定性可靠性低,链指针 “断掉” 就会导文件数据丢失

    • 指向下一个盘块的指针消耗了磁盘空间

文件-隐式链接

# 显式链接 (FAT)

用于链接文件各个物理块的指针显式地存放在内存地一张唯一的链接表中,称为文件分配表 (Fils Alloction Table, FAT),每个表项存放指向下一个块的指针。

⚠️FAT 本身就可以实现空闲磁盘块管理,若磁盘块空闲,则其表项可标记为 -1

FAT 在系统启动时被读入内存,检索记录都在内存中进行。

  • 优点:

    • 支持顺序访问随机访问(磁盘,不是 FAT)

    • 检索在内存中完成,速度快效率高,减少了磁盘访问次数

  • 缺点:

    • FAT 表需要占用一定的内存空间

FAT

以 “簇”(cluster) 为单位分配,cluster 01 保留,从 2 开始计数

LFN 目录项

# 索引分配

建立一张索引表

  • 优点:

    • 支持直接访问,索引表的第 i 个条目指向的就是第 i 个块
    • 不会产生外部碎片,提高了磁盘利用率。
  • 缺点:

    • 索引块增加了额外磁盘存储开销

文件-索引分配

可以分为:

  • 单级索引

    • 局限:
      • 只适用于小文件
  • 多级索引

    • 通过主索引查找二级索引......
    • 优点:
      • 极大加快了对大型文件的查找速度
    • 问题:
      • 对小文件来说没必要使用深层级的索引,会造成磁盘存储浪费和访问开销增大
  • 混合索引

    • 文件-混合索引

UNIX 采用最深为三级的混合索引

# 目录

# 目录逻辑结构

# 单级目录

实现了按名存取,每个文件名对应唯一一个文件。

缺点:

  • 文件不允许重名
  • 不方便文件共享

# 两级目录

  • 主文件目录 Maste File Directory (MFD)
    • 用户文件目录 User File Directory (UFD)
    • 用户文件目录 User File Directory (UFD)
    • 用户文件目录 User File Directory (UFD)
    • ......

解决了多用户之间文件重名的问题。

# 树形目录

理论上可以实现无限深度的目录层次。

出现了相对路径绝对路径的概念。

# 无环图目录

比树形目录多了共享子目录,实现了文件、目录共享。

一个文件可以有多个路径,称为别名。例如:

  • Linux 中的软链接、硬链接
  • Windows 的快捷方式

# 通用图目录

允许了环的出现,实现了自引用的特殊需求。

# 目录物理实现

目录第物理实现决定了目录检索的方式,包括 2 中检索方式:

  • 顺序检索
  • 散列法 / 哈希表

# 线性列表

查找比较费时。

# 哈希表

  • 优点:
    • 查找非常迅速
    • 插入、删除比较简单
  • 缺点:
    • 会有冲突,链式处理溢出。

# 空闲空间管理

# 空闲表

属于连续分配方式,建立一张空闲表,和连续分配方式的目录类似,每一个表项记录一个空闲盘区,包括第一个空闲盘块号和空闲盘块数。

空闲盘区分配与回收与内存动态分配、回收类似。

# 空闲链表

free-space list

  • 空闲盘块链
    • 以盘块为单位拉成一条链
    • 优点:回收分配过程简单
    • 缺点:简单但是需要重复多次效率低,且盘块链会很长
  • 空闲盘区链
    • 以盘区为单位拉成一条链
    • 优点:分配回收效率高
    • 缺点:回收分配过程复杂

# 位 (示) 图

bit vector or bit map,似乎也叫空闲向量表

  • 优点:
    • 容易找到一个或一组连续的空闲磁盘块
    • 位示图小,可以放在内存中,节省访问磁盘的开销
  • 缺点:
    • 位示图大小随磁盘容量增大而增大,因而常用于小型计算机

# Space Maps

位示图的改进,将磁盘设备分为 metaslab 的单位,每一个 metslab 内对空闲盘块计数

# 成组链接

grouping

⭐️ UNIX 采用该方法

第一组空闲盘块总数和空闲盘块号称为空闲盘块号栈

# 超级块

super block

包含:

  • 空闲向量表 / 位 (示) 图 / 空闲盘块号栈
  • 卷中目录区、文件区的划分信息

一般放在卷头位置,超级块要预先读入内存才能对该卷文件操作,并且经常保持内存与磁盘超级块的一致性。

缓存

  • page cache,为用户程序服务(用户程序以页的方式访问)
  • disk block cache,为操作系统管理文件服务

A unified buffer cache uses the same page cache to cache both memory-mapped pages and ordinary file system I/O to avoid double caching

But which caches get priority, and what replacement algorithms to use?

Linux VFS 对象:

  • 超级块
  • 索引节点
  • 目录项
  • 文件
Edited on Views times
\ No newline at end of file +文件系统 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

磁盘的 block 和文件系统的 block 不是一回事:

  • 磁盘的 block :往往是固定的 512 B;
  • 文件系统的 block 是基本单位,可以自定义,不一定和磁盘的 block 大小相等。
    • 文件系统分配空间的基本单位往往是页面大小 4 KB ,

文件系统结构:(自上而下分层)

  • application programs,应用程序
  • logical file system,逻辑文件系统
  • file-organization module,文件组织模块
  • basic file system,基本文件系统
  • I/O control,I/O 控制
  • devices,设备

修改文件要写回磁盘!计算访问磁盘次数的时候要注意写操作比读操作多 1

# 数据结构

面向对象

# FCB

别名:文件目录项文件控制块

包含:

  • 指向关联的 inode 的指针
  • 指向父目录、子目录的指针

# 文件目录

FCB 的有序集合

# inode

别名:索引节点文件描述信息、index node

ext2ext3 采用 inode 表

将 FCB 中的一部分文件描述信息分离出来,这些是检索目录时不需要的不必放在内存的,所以只将指向这部分的一个指针放在内存的目录项里。

采用 inode 可以减少查找文件时的 I/O 信息量,相当于简化了内存中的文件目录项 (FCB),将其中一部分留在磁盘,只保留指向他们的指针。例如 Linux 的文件目录项就只包含文件名和指向 indoe 的指针。

⭐️硬连接和软链接与 inode

  • 硬链接文件指向同一个 inode
  • 软链接文件指向不同的 inode,相当于不同的文件,只不过存的是路径

在文件的物理结构中,则 inode 中就存储了索引文件的主索引表

直接以数组方式存储的 indoe 表,相当于单级索引;也可以有多级索引

  • 磁盘索引节点,每个文件唯一都有一个
    • 文件主标识符
    • 文件类型
    • 文件存取权限
    • 文件物理地址
    • 文件长度
    • 文件链接计数
      • ⭐️ count ,实现硬链接文件共享,表示链接到本索引节点的用户目录项的数量。只有 count=0 的时候才能删除文件。
    • 文件存取时间
  • 内存索引节点,文件被打开时,磁盘索引节点复制放在内存的副本
    • 索引节点号,用于标识内存索引节点
    • 状态,是否被上锁
    • 访问计数,为 0 时文件关闭
    • 逻辑设备号
    • 链接指针,指向空闲列表或散列队列

# 打开文件表

本质上是实现只需要一次访问磁盘定位文件在磁盘的位置,将其存储到内存,后续在内存可以找到文件在磁盘的位置。

两级表:

  • 整个系统一个表,包含与进程无关的信息,每一个文件条目包含:
    • 文件描述符 (File Descriptor, FD)
      • 这是 Linux 中的名字,Windows 中也叫文件句柄
    • 文件打开次数
      • 变为 0 之后就可以 “关闭文件”,从表中删除该项
    • 文件磁盘位置
    • 访问日期
    • 文件大小
  • 每个进程有一个表,包含与进程有关的信息,每一个文件条目包含:
    • 读写指针
    • 访问权限
    • 指向系统打开文件表的对应文件条目指针

⚠️系统只会在第一次打开一个文件的时候使用其文件名在磁盘上定位,然后在内存中创建文件表中的条目,此后就不再需要文件名。

⚠️ open 系统调用由用户调用,一个文件可能对某一用户是第一次打开,但是对系统而言不是第一次,只会在用户进程的打开文件表增加条目。

# 文件保护

  • 口令保护
  • 加密保护
  • 访问控制

# 文件访问控制表

可能也有叫做存取控制矩阵之类的 (?)

为每个文件和目录设置一个文件访问控制表。用来管理不同用户、用户组对该文件或目录的访问权限

# 文件结构

# 文件逻辑结构

文件访问、存取,或者文件中查找数据的方式,是由文件的逻辑结构决定的。

文件的逻辑结构分为:

  • 无结构文件,也叫做流式文件,对该类型文件中记录的访问只能通过穷举搜索。
  • 有结构文件,也叫做记录式文件,这里讨论的都是这种,这样的文件是由一个以上的记录构成的。
    • 定长记录
    • 变长记录

# 顺序

每次读写大批量数据时,顺序文件的效率是最高的。

# 直接

直接文件也叫做散列文件、哈希文件。

  • 优点
    • 存取速度快

# 索引

建立一张索引表,索引表本身是定长记录的顺序文件,其中的每一个索引表项包含:指向记录的指针、记录的长度

  • 优点
    • 提升了查找速度
  • 缺点
    • 索引表增加了存储空间

# 索引顺序

在索引文件的基础上,索引表项指向的单个记录变为一组记录组成的顺序表,就得到了一级索引的索引顺序文件。

优缺点和索引文件仍然一样...

# 记录成组分解

记录成组分解技术是指若干逻辑记录存入一个块,一个逻辑记录不能跨越 2 个块。

搭配隐式链接,每个个块存储固定长度的若干逻辑记录,剩余的字节用于存储指向下一个块的指针。

# 文件物理结构

# 连续分配

配合使用空闲表法管理空闲磁盘空间。

进程访问磁盘时所需的寻道数和寻道时间最小

文件-连续分配

⚠️磁带只能使用连续分配,只能顺序存取!

# 扩展连续分配

例如: ext4ext3

FCB 中比连续分配多增加一项为指向下一个扩展块的指针

# 链接分配 (隐式链接)

每一个块包含该文件指向下一个块的指针,这些指针对用户来说是透明的,空指针表示文件末尾。

  • 优点:

    • 不会产生外部碎片,提高了磁盘利用率。
  • 缺点:

    • 只支持顺序访问,随机访问效率低

    • 稳定性可靠性低,链指针 “断掉” 就会导文件数据丢失

    • 指向下一个盘块的指针消耗了磁盘空间

文件-隐式链接

# 显式链接 (FAT)

用于链接文件各个物理块的指针显式地存放在内存地一张唯一的链接表中,称为文件分配表 (Fils Alloction Table, FAT),每个表项存放指向下一个块的指针。

⚠️FAT 本身就可以实现空闲磁盘块管理,若磁盘块空闲,则其表项可标记为 -1

FAT 在系统启动时被读入内存,检索记录都在内存中进行。

  • 优点:

    • 支持顺序访问随机访问(磁盘,不是 FAT)

    • 检索在内存中完成,速度快效率高,减少了磁盘访问次数

  • 缺点:

    • FAT 表需要占用一定的内存空间

FAT

以 “簇”(cluster) 为单位分配,cluster 01 保留,从 2 开始计数

LFN 目录项

# 索引分配

建立一张索引表

  • 优点:

    • 支持直接访问,索引表的第 i 个条目指向的就是第 i 个块
    • 不会产生外部碎片,提高了磁盘利用率。
  • 缺点:

    • 索引块增加了额外磁盘存储开销

文件-索引分配

可以分为:

  • 单级索引

    • 局限:
      • 只适用于小文件
  • 多级索引

    • 通过主索引查找二级索引......
    • 优点:
      • 极大加快了对大型文件的查找速度
    • 问题:
      • 对小文件来说没必要使用深层级的索引,会造成磁盘存储浪费和访问开销增大
  • 混合索引

    • 文件-混合索引

UNIX 采用最深为三级的混合索引

# 目录

# 目录逻辑结构

# 单级目录

实现了按名存取,每个文件名对应唯一一个文件。

缺点:

  • 文件不允许重名
  • 不方便文件共享

# 两级目录

  • 主文件目录 Maste File Directory (MFD)
    • 用户文件目录 User File Directory (UFD)
    • 用户文件目录 User File Directory (UFD)
    • 用户文件目录 User File Directory (UFD)
    • ......

解决了多用户之间文件重名的问题。

# 树形目录

理论上可以实现无限深度的目录层次。

出现了相对路径绝对路径的概念。

# 无环图目录

比树形目录多了共享子目录,实现了文件、目录共享。

一个文件可以有多个路径,称为别名。例如:

  • Linux 中的软链接、硬链接
  • Windows 的快捷方式

# 通用图目录

允许了环的出现,实现了自引用的特殊需求。

# 目录物理实现

目录第物理实现决定了目录检索的方式,包括 2 中检索方式:

  • 顺序检索
  • 散列法 / 哈希表

# 线性列表

查找比较费时。

# 哈希表

  • 优点:
    • 查找非常迅速
    • 插入、删除比较简单
  • 缺点:
    • 会有冲突,链式处理溢出。

# 空闲空间管理

# 空闲表

属于连续分配方式,建立一张空闲表,和连续分配方式的目录类似,每一个表项记录一个空闲盘区,包括第一个空闲盘块号和空闲盘块数。

空闲盘区分配与回收与内存动态分配、回收类似。

# 空闲链表

free-space list

  • 空闲盘块链
    • 以盘块为单位拉成一条链
    • 优点:回收分配过程简单
    • 缺点:简单但是需要重复多次效率低,且盘块链会很长
  • 空闲盘区链
    • 以盘区为单位拉成一条链
    • 优点:分配回收效率高
    • 缺点:回收分配过程复杂

# 位 (示) 图

bit vector or bit map,似乎也叫空闲向量表

  • 优点:
    • 容易找到一个或一组连续的空闲磁盘块
    • 位示图小,可以放在内存中,节省访问磁盘的开销
  • 缺点:
    • 位示图大小随磁盘容量增大而增大,因而常用于小型计算机

# Space Maps

位示图的改进,将磁盘设备分为 metaslab 的单位,每一个 metslab 内对空闲盘块计数

# 成组链接

grouping

⭐️ UNIX 采用该方法

第一组空闲盘块总数和空闲盘块号称为空闲盘块号栈

# 超级块

super block

包含:

  • 空闲向量表 / 位 (示) 图 / 空闲盘块号栈
  • 卷中目录区、文件区的划分信息

一般放在卷头位置,超级块要预先读入内存才能对该卷文件操作,并且经常保持内存与磁盘超级块的一致性。

缓存

  • page cache,为用户程序服务(用户程序以页的方式访问)
  • disk block cache,为操作系统管理文件服务

A unified buffer cache uses the same page cache to cache both memory-mapped pages and ordinary file system I/O to avoid double caching

But which caches get priority, and what replacement algorithms to use?

Linux VFS 对象:

  • 超级块
  • 索引节点
  • 目录项
  • 文件
Edited on Views times
\ No newline at end of file diff --git a/cs/os/io/index.html b/cs/os/io/index.html index 06fccbbd..669eb8bd 100644 --- a/cs/os/io/index.html +++ b/cs/os/io/index.html @@ -1 +1 @@ -I/O - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

I/O 的访问、管理分为两种类型:(或者说按照编址类型划分)

  • I/O 指令(独立编址)
    • 通过 I/O 端口号访问设备管理器
    • 涉及模态转换、状态更迭时才采用
  • 内存映射 I/O (统一编址)
    • 设备的寄存器或存储被映射到内存物理地址空间中;
    • 通过内存 load/store 指令完成 I/O 操作;
    • MMU 设置映射,硬件跳线或程序在启动时设置地址;
    • 实际上绝大多数采用的方式

I/O 控制:

  • 轮询,或者程序直接控制
    • 通过忙等待(轮询)检查 I/O 控制器状态
    • 完全交给 CPU
  • 中断
    • 等待中断来得到 I/O 控制器状态信息
    • 中断到来前 CPU 可以干其他事(CPU、I/O 并行)
  • DMA
    • 磁盘和 I/O 设备之间直接传输数据
    • CPU 极少介入,仅在数据传输完成时介入,其他时候 CPU、I/O 并行工作
    • CPU 上专门的部件作为 DMA 控制器
  • * 通道控制
    • 一种特殊的、独立于 CPU 的处理机,相当于独立性更强的 DMA
    • 指令类型单一,与 CPU 共享内存
    • 实现 CPU、通道、I/O 三者并行工作

# 磁盘调度算法

给定磁盘访问 LBA 序列: 55, 58, 39, 18, 90, 160, 150, 38, 184

# FIFO

无论在哪个场景都是最公平的调度算法

FIFO

# 优先级 (PRI)

调度的控制超出了磁盘管理软件的控制范围

目标不是优化磁盘利用率,而是实现其他目标

短批作业和交互式作业的优先级更
提供良好的交互式响应时间

较长的工作可能需要等待过长的时间
对数据库系统是一种糟糕策略

# 最短服务时间优先 (SSTF)

选择使磁头臂从当前位置开始移动最少的磁盘 I/O 请求

总是选择导致最小寻道时间的请求

SSTF

# 扫描算法 (SCAN)

也叫电梯算法、NOOP 算法、SCAN 算法。

非公平的,不同请求获得的优先级是不一样的:越靠近外侧的扇区请求响应的优先级更高

SCAN

# 循环扫描算法 (C-SCAN)

C-SCAN 也就是 Circular Scan 算法。

C-SCAN

# 其他 SCAN 变种

以下介绍的 2 中变种 SCAN 调度算法的目的在于避免磁臂黏着现象,具体可参考:https://blog.csdn.net/m0_52733659/article/details/133840705

# N 步 SCAN

设置多个队列,每个队列容量为 N ,轮流对每个队列采用 SCAN 扫描算法,该队列不接受请求,所有请求按照 FIFO 放入下一个队列。每一次扫描,都只处理 N 个请求。

# FSCAN

设置 2 个队列,轮流对 2 个队列采用 SCAN 扫描算法,扫描其中一个队列的时候,该队列不接受请求,所有请求按照 FIFO 放入另一个队列

# 总结

SSTF 是常见的,具有天然的吸引力

SCAN 和 C-SCAN 对于磁盘负载较大的系统性能更好

# NVM 调度

没有磁头或旋转延迟,但仍有优化空间

在 RHEL 7 中,使用 NOOP (无操作、电梯调度),但合并相邻的 LBA 请求

  • ⭐️ NVM 最佳随机 I/O
  • ⭐️ 硬盘最佳顺序 I/O

# 存储设备管理

# 低级格式化

低级格式化,或者说物理格式化

将磁盘划分为磁盘控制器可以读写的扇区

每个扇区可以保存头信息、数据和纠错码 (ECC)

通常 512 字节的数据,但可以选择

# 高级格式化

高级格式化,或者说逻辑格式化、“创建文件系统”

文件系统的单位往往和低级格式化的扇区不一样!

将磁盘划分为一组或多组柱面,每组柱面都视为逻辑磁盘

为了提高效率,大多数文件系统将块分组到簇中

  • 磁盘 I/O 在块中完成
  • 文件 I/O 在簇中完成

# 原始磁盘访问

绕过操作系统的文件系统,也就是绕过操作系统的高级格式化,往往适用于自己进行数据管理的应用程序(例如数据库)

# RAID

CategoryLevelDescriptionDisks requiredData availabilityLarge I/O data transfer capacitySmall I/O request rate
Striping0NonredundantNNLower than single diskVery highVery high for both read and write
Mirroring1Mirrored2N2NHigher than RAID 2, 3, 4, or 5; lower than RAID 6Higher than single disk for read; similar to single disk for writeUp to twice that of a single disk for read; similar to single disk for write
Parallel access2Redundant via Hamming codeN+mN+mMuch higher than single disk; comparable to RAID 3, 4, or 5Highest of all listed alternativesApproximately twice that of a single disk
3Bit-interleaved parityN+1N+1Much higher than single disk; comparable to RAID 2, 4, or 5Highest of all listed alternativesApproximately twice that of a single disk
Independent access4Block-interleaved parityN+1N+1Much higher than single disk; comparable to RAID 2,3, or 5Similar to RAID O for read; significantly lower than single disk for writeSimilar to RAID 0 for read; significantly lower than single disk for write
5Block-interleaved distributed parityN+1N+1Much higher than single disk; comparable to RAID 2,3, or 4Similar to RAID 0 for read; lower than single disk for writeSimilar to RAID 0 for read; generally lower than single disk for write
6Block-interleaved dual distributed parityN+2N+2Highest of all listed alternativesSimilar to RAID 0 for read; lower than RAID 5 for writeSimilar to RAID 0 for read; significantly lower than RAID 5 for write
Edited on Views times
\ No newline at end of file +I/O - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

I/O 的访问、管理分为两种类型:(或者说按照编址类型划分)

  • I/O 指令(独立编址)
    • 通过 I/O 端口号访问设备管理器
    • 涉及模态转换、状态更迭时才采用
  • 内存映射 I/O (统一编址)
    • 设备的寄存器或存储被映射到内存物理地址空间中;
    • 通过内存 load/store 指令完成 I/O 操作;
    • MMU 设置映射,硬件跳线或程序在启动时设置地址;
    • 实际上绝大多数采用的方式

I/O 控制:

  • 轮询,或者程序直接控制
    • 通过忙等待(轮询)检查 I/O 控制器状态
    • 完全交给 CPU
  • 中断
    • 等待中断来得到 I/O 控制器状态信息
    • 中断到来前 CPU 可以干其他事(CPU、I/O 并行)
  • DMA
    • 磁盘和 I/O 设备之间直接传输数据
    • CPU 极少介入,仅在数据传输完成时介入,其他时候 CPU、I/O 并行工作
    • CPU 上专门的部件作为 DMA 控制器
  • * 通道控制
    • 一种特殊的、独立于 CPU 的处理机,相当于独立性更强的 DMA
    • 指令类型单一,与 CPU 共享内存
    • 实现 CPU、通道、I/O 三者并行工作

# 磁盘调度算法

给定磁盘访问 LBA 序列: 55, 58, 39, 18, 90, 160, 150, 38, 184

# FIFO

无论在哪个场景都是最公平的调度算法

FIFO

# 优先级 (PRI)

调度的控制超出了磁盘管理软件的控制范围

目标不是优化磁盘利用率,而是实现其他目标

短批作业和交互式作业的优先级更
提供良好的交互式响应时间

较长的工作可能需要等待过长的时间
对数据库系统是一种糟糕策略

# 最短服务时间优先 (SSTF)

选择使磁头臂从当前位置开始移动最少的磁盘 I/O 请求

总是选择导致最小寻道时间的请求

SSTF

# 扫描算法 (SCAN)

也叫电梯算法、NOOP 算法、SCAN 算法。

非公平的,不同请求获得的优先级是不一样的:越靠近外侧的扇区请求响应的优先级更高

SCAN

# 循环扫描算法 (C-SCAN)

C-SCAN 也就是 Circular Scan 算法。

C-SCAN

# 其他 SCAN 变种

以下介绍的 2 中变种 SCAN 调度算法的目的在于避免磁臂黏着现象,具体可参考:https://blog.csdn.net/m0_52733659/article/details/133840705

# N 步 SCAN

设置多个队列,每个队列容量为 N ,轮流对每个队列采用 SCAN 扫描算法,该队列不接受请求,所有请求按照 FIFO 放入下一个队列。每一次扫描,都只处理 N 个请求。

# FSCAN

设置 2 个队列,轮流对 2 个队列采用 SCAN 扫描算法,扫描其中一个队列的时候,该队列不接受请求,所有请求按照 FIFO 放入另一个队列

# 总结

SSTF 是常见的,具有天然的吸引力

SCAN 和 C-SCAN 对于磁盘负载较大的系统性能更好

# NVM 调度

没有磁头或旋转延迟,但仍有优化空间

在 RHEL 7 中,使用 NOOP (无操作、电梯调度),但合并相邻的 LBA 请求

  • ⭐️ NVM 最佳随机 I/O
  • ⭐️ 硬盘最佳顺序 I/O

# 存储设备管理

# 低级格式化

低级格式化,或者说物理格式化

将磁盘划分为磁盘控制器可以读写的扇区

每个扇区可以保存头信息、数据和纠错码 (ECC)

通常 512 字节的数据,但可以选择

# 高级格式化

高级格式化,或者说逻辑格式化、“创建文件系统”

文件系统的单位往往和低级格式化的扇区不一样!

将磁盘划分为一组或多组柱面,每组柱面都视为逻辑磁盘

为了提高效率,大多数文件系统将块分组到簇中

  • 磁盘 I/O 在块中完成
  • 文件 I/O 在簇中完成

# 原始磁盘访问

绕过操作系统的文件系统,也就是绕过操作系统的高级格式化,往往适用于自己进行数据管理的应用程序(例如数据库)

# RAID

CategoryLevelDescriptionDisks requiredData availabilityLarge I/O data transfer capacitySmall I/O request rate
Striping0NonredundantNNLower than single diskVery highVery high for both read and write
Mirroring1Mirrored2N2NHigher than RAID 2, 3, 4, or 5; lower than RAID 6Higher than single disk for read; similar to single disk for writeUp to twice that of a single disk for read; similar to single disk for write
Parallel access2Redundant via Hamming codeN+mN+mMuch higher than single disk; comparable to RAID 3, 4, or 5Highest of all listed alternativesApproximately twice that of a single disk
3Bit-interleaved parityN+1N+1Much higher than single disk; comparable to RAID 2, 4, or 5Highest of all listed alternativesApproximately twice that of a single disk
Independent access4Block-interleaved parityN+1N+1Much higher than single disk; comparable to RAID 2,3, or 5Similar to RAID O for read; significantly lower than single disk for writeSimilar to RAID 0 for read; significantly lower than single disk for write
5Block-interleaved distributed parityN+1N+1Much higher than single disk; comparable to RAID 2,3, or 4Similar to RAID 0 for read; lower than single disk for writeSimilar to RAID 0 for read; generally lower than single disk for write
6Block-interleaved dual distributed parityN+2N+2Highest of all listed alternativesSimilar to RAID 0 for read; lower than RAID 5 for writeSimilar to RAID 0 for read; significantly lower than RAID 5 for write
Edited on Views times
\ No newline at end of file diff --git a/cs/os/linux-customized-syscall/index.html b/cs/os/linux-customized-syscall/index.html index a18c3ec5..68912592 100644 --- a/cs/os/linux-customized-syscall/index.html +++ b/cs/os/linux-customized-syscall/index.html @@ -1 +1 @@ -给 Linux 内核增加自定义系统调用 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

这是老师布置的一个小作业,让我们在 linux 内核源码里增加自定义的系统调用程序,用这篇文章记录一下完整的操作过程;

这样扩展 Linux 内核的传统方式需要每次都重新编译内核,更现代的方式是使用 eBPF

使用清华镜像源下载 linux 内核 5.10.19 版本,解压然后进入解压目录:

shell
wget https://mirrors.tuna.tsinghua.edu.cn/kernel/v5.x/linux-5.10.19.tar.gz
......
tar -zxvf linux-5.10.19.tar.gz
......
cd linux-5.10.19

kernel/sys.c 中用 SYSCALL 宏增加系统调用源代码:

c
SYSCALL_DEFINE1(myhello, int, arg)
{
	printk("\x1B[1;46mHello, world! from LSY %d\x1B[m", arg);
	return 0;
}

include/linux/syscalls.h 中增加自定义系统调用的声明:

c
asmlinkage void sys_myhello(int arg);

arch/x86/entry/syscalls/syscall_32.tblarch/x86/entry/syscalls/syscall_64.tbl 中增加调用号:

raw
441	64	myhello		sys_myhello

然后配置:

shell
make i386_defconfig
make menuconfig

make menuconfig 打开的图像界面中依次选择 Kernel hackingCompile-time checks and compiler options ,最后在 [ ] Compile the kernel with debug info 输入 Y 勾选,保存退出;

然后就可以编译内核:

shell
make -j$(nproc)

写一个简单的 initramfs 程序 helloworld.c 调用自定义的系统调用函数,传入我的学号作为参数,源代码如下:

c
#include<stdio.h>
void main(){
    syscall(441, 22342043);
    fflush(stdout);
    while (1);
}

将该程序编译:

shell
gcc -o helloworld -m32 -static helloworld.c

用 cpio 打包 initramfs :

shell
echo helloworld | cpio -o --format=newc > hwinitramfs

调试模式启动内核,并加载 initramfs ,让内核程序暂停运行等待 gdb 连接 :

shell
qemu-system-i386 -kernel linux-5.10.19/arch/x86/boot/bzImage -initrd hwinitramfs -s -S -append "console=ttyS0 rdinit=helloworld" -nographic

然后启动 gdb :

shell
gdb

加载符号表,并连接 qemu 调试服务提供的默认端口 1234 ,然后就可以输入 c 继续运行内核:

gdb
file linux-5.10.19/vmlinux
target remote:1234
c

输出结果:

结果

\ No newline at end of file +给 Linux 内核增加自定义系统调用 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

这是老师布置的一个小作业,让我们在 linux 内核源码里增加自定义的系统调用程序,用这篇文章记录一下完整的操作过程;

这样扩展 Linux 内核的传统方式需要每次都重新编译内核,更现代的方式是使用 eBPF

使用清华镜像源下载 linux 内核 5.10.19 版本,解压然后进入解压目录:

shell
wget https://mirrors.tuna.tsinghua.edu.cn/kernel/v5.x/linux-5.10.19.tar.gz
......
tar -zxvf linux-5.10.19.tar.gz
......
cd linux-5.10.19

kernel/sys.c 中用 SYSCALL 宏增加系统调用源代码:

c
SYSCALL_DEFINE1(myhello, int, arg)
{
	printk("\x1B[1;46mHello, world! from LSY %d\x1B[m", arg);
	return 0;
}

include/linux/syscalls.h 中增加自定义系统调用的声明:

c
asmlinkage void sys_myhello(int arg);

arch/x86/entry/syscalls/syscall_32.tblarch/x86/entry/syscalls/syscall_64.tbl 中增加调用号:

raw
441	64	myhello		sys_myhello

然后配置:

shell
make i386_defconfig
make menuconfig

make menuconfig 打开的图像界面中依次选择 Kernel hackingCompile-time checks and compiler options ,最后在 [ ] Compile the kernel with debug info 输入 Y 勾选,保存退出;

然后就可以编译内核:

shell
make -j$(nproc)

写一个简单的 initramfs 程序 helloworld.c 调用自定义的系统调用函数,传入我的学号作为参数,源代码如下:

c
#include<stdio.h>
void main(){
    syscall(441, 22342043);
    fflush(stdout);
    while (1);
}

将该程序编译:

shell
gcc -o helloworld -m32 -static helloworld.c

用 cpio 打包 initramfs :

shell
echo helloworld | cpio -o --format=newc > hwinitramfs

调试模式启动内核,并加载 initramfs ,让内核程序暂停运行等待 gdb 连接 :

shell
qemu-system-i386 -kernel linux-5.10.19/arch/x86/boot/bzImage -initrd hwinitramfs -s -S -append "console=ttyS0 rdinit=helloworld" -nographic

然后启动 gdb :

shell
gdb

加载符号表,并连接 qemu 调试服务提供的默认端口 1234 ,然后就可以输入 c 继续运行内核:

gdb
file linux-5.10.19/vmlinux
target remote:1234
c

输出结果:

结果

\ No newline at end of file diff --git a/cs/os/memory-management/index.html b/cs/os/memory-management/index.html index 7f27be48..6bda7d44 100644 --- a/cs/os/memory-management/index.html +++ b/cs/os/memory-management/index.html @@ -1 +1 @@ -内存管理 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

冯・诺伊曼计算机体系决定了操作系统需要内存管理

# 虚拟内存物理实现

  • 连续分配
    • 单一连续分配
    • 分区
      • 固定分区分配
      • 动态分区分配
  • 非连续分配
    • 段式
    • 页式
    • 段页式

⭐️内部碎片和外部碎片

  • 内部碎片
    • 是已经被分配给某个进程的,该进程没有利用的
    • 固定分区分配产生这种碎片
  • 外部碎片
    • 是无法被分配给任何进程的,不属于任何进程的
    • 动态分区分配产生这种碎片
    • 可以通过紧凑技术克服,需要动态重定位寄存器硬件支持

# 分区 (连续分配)

# 单一连续分配

将内存分为两部分:

  • 系统区
  • 用户区
    • 唯一一个用户程序独占整个用户区

内存中只有一个用户程序,只能用于单用户、单任务的操作系统。

有内部碎片,无外部碎片。

# 固定分区

使用空闲分区链 / 表

有内部碎片,无外部碎片。

# 动态分区

使用空闲分区链 / 表

无内部碎片,有外部碎片。

# 首次适应

空闲分区按地址递增顺序排列。

每次分配时从头开始顺序查找到第一个满足大小的空闲分区。

性能最好。

# 邻近适应

空闲分区按地址递增顺序排列。和首次适应一样。

每次分配时从上次查找结束位置开始查找到第一个满足大小的空闲分区。

# 最佳适应

空闲分区按容量递增顺序排列。

产生最多外部碎片

# 最坏适应

空闲分区按容量递减顺序排列。

前面三种都基于顺序搜索,后面三种则都基于索引搜索

# 快速适应

基于索引分配,对空闲分区按大小相同的分为一类,每一类单独设置一个空闲分区链。建立一张索引表管理所有空闲分区链,索引表项包含对应大小的空闲分区链的头指针

根据进程需要的大小,在索引表中找到能容纳它的最小的空闲分区链表,直接从链表取出第一块进行分配。

优劣:

  • 优点
    • 查找效率高
    • 不产生内部碎片(当然啊这不是动态分区吗)
  • 缺点
    • 回收分区复杂,导致算法复杂、系统开销大

# 伙伴系统

我感觉应该算固定分区分配才对?

规定所有分区大小为 22kk 次幂。

每次分配大小为 nn (2i1<n2i2^{i-1}<n\leq 2^i) 的分区时,在

导致过多内部碎片⚠️

Slab 分配器 —— 一般只有内核内存使用

# 哈希算法

根据空闲分区链表的分布规律建立哈希函数,构建一张以哈希表:

  • 关键字 key 为空闲分区大小
  • 表项 value 为对应空闲分区链的头指针

# 分段

程序员或者编译器会把程序和数据指定到不同的分段,需要知道段的最大长度限制

将程序产生的二维地址即 <段号,偏移><段号,偏移> 映射到一维物理地址, 这个地址是通过段表实现;

段表中每个条目由段基址和段界限构成

CPU 去哪里找段表?—— GDTR 寄存器,GDTR 寄存器的结构如下:

  • 低 2 字节(16 位)存储了 limit ,全局描述符表的大小(以字节为单位),减去 1 的结果。
  • 高 4 字节(32 位)存储了 base ,全局描述符表的基地址。

# 分页

页放到页帧 / 框里,区分:⚠️

  • 页(Page)
  • 页帧(Page frame)或者页框,是空的,没有数据

页框 \geq 页,现代操作系统大多二者是相等的,方便管理

# 页表

系统中有一个唯一的页表寄存器(PTR),包含页表首地址(PTBR),只能由特权指令访问。

页表长度寄存器(PTLR),可以直接用于判断是否越界(好像不一定有)

x86_64 , i386 中的 PTR 寄存器叫做 CR3 寄存器

页表从属于进程,每创建一个新进程就需要创建一个独立的新页表给它。

# TLB

转换表缓冲区 / 快表 /... 详细参考计组

# 共享页

共享代码

  • 进程 (即文本编辑器、编译器、窗口系统) 之间共享的只读 (可重入) 代码的一个副本;
  • 类似于共享同一进程空间的多个线程;
  • 如果允许共享读写页面,则还可用于进程间通信;

# 多级 / 层页表

经典:在现代计算机上考虑 32 位逻辑地址空间,页面大小为 4KB (2122^{12}),页面表将有 4M 个条目 (232/212=2202^{32}/2^{12}=2^{20}) ,如果每个条目为 4B ,每个进程需要为页表分配 16MB 的物理地址空间,这片连续的物理空间太大了!

相同条件下考虑 64 位,即使采用 2 级分页,外层页表也需要 16384GB 大小的连续物理空间!所以 x86_64 采用 4 级页表

现代 OS 大多采用 3 到 4 级页表

64 位下的 2 级页表 和 3 级页表:

64-2-3

# 散列页表 / 哈希表

# 聚簇页表

64 位地址的变体,哈希值对应的不是一个页,而是一簇页(一个页族)

特别适用于稀疏地址空间 (内存引用不连续且分散)

# 倒排页表

不再为每个进程设置一个页表并跟踪所有可能的逻辑页,而是跟踪所有物理页,此时整个架构自 CPU 开始到 OS 都有较大变化

内存的每一物理页有一个条目,条目包含:

  • 存储在该实际内存位置的页的虚拟地址
  • 有关拥有该页的进程的信息组成

CPU 产生的逻辑地址:

倒排页表

优点:

  • 减少存储每个页表所需的内存

缺点:

  • 发生页引用时增加搜索表所需的时间
  • 共享内存不太容易实现:虚拟地址到共享物理地址的一种映射

# 现代 OS 举例

# Oracle SPARC Solaris

考虑现代 64 位操作系统目标是效率,低开销

基于哈希,但更复杂

两个哈希表

  • 一个内核
  • 一个用于所有用户进程

每个都将内存地址从虚拟内存映射到物理内存

每个条目表示映射虚拟内存的连续区域

比为每个页面提供单独的哈希表条目更高效

每个条目都有基址和跨距 (表示条目所代表的页数)

# IA-32/64

英特尔 IA-32 和 IA-64 均支持分段、分页管理

记录段号的基地址的描述符表,按私有、公有分为:

  • LDT 局部描述符表
  • GDT 全局描述符表

早期 IA-32 利用 PAE 实现页地址扩展

# ARM

Apple

段页混合式管理,较大连续内存走分段,较小连续内存走分页:

arm

# 虚拟内存软件实现

⭐️虚拟内存的实现建立在离散分配的内存管理方式基础上

三个特征:

  • 多次性
  • 对换性
  • 虚拟性

虚拟内存可以通过以下方式实现:

  • 请求分页
  • 请求分段(按需分段)
  • 请求段页式存储管理

# 请求分页

按需分页

  • 固定分配局部置换
  • 可变分配全局置换
  • 可变分配局部置换

请求分页系统的外存

  • 文件区
    • 存放文件,采用离散分配方式
  • 对换区(交换区)
    • 存放对换页面,采用连续分配方式,I/O 速度更快

可以在加载时将整个进程放入内存或者只在需要时才将页面放入内存

所需的 I/O 更少,没有不必要的 I/O

  • 所需内存更少
  • 更快的响应
  • 更支持多用户

类似于带交换的分页系统 (需要硬件支持)

  • 页面是必需的 —— 引用它
  • 无效引用 —— 终止
  • 不在内存中 —— 调入内存

惰性交换程序:除非需要页,否则永远不要将页交换到内存中

处理页面的交换程序是 “调页程序”

# 处理缺页

  1. 检查进程的内部表,通常与 PCB 一起保存,以确定内存引用是否有效;
  2. 如果:(页面错误 (缺页) )
    • 无效,那么终止进程
    • 引用有效但是未调入页面, 那么发生缺页中断;
  3. 找到空闲帧;(或 victim 帧)
  4. 通过磁盘调度操作将页面交换到刚分配的帧中;
  5. 当磁盘操作读取完成后,重置内部表和页表,以指示当前页面在内存中;
  6. 重新启动导致缺页的指令,该进程能够访问所需的页;(指令重启

# 问题

# 启动进程时内存中没有页面

操作系统将指令指针设置为进程的第一条指令,非内存驻留 -> 页面错误

  • 进程其他页面的访问也是一样;
  • 纯请求分页;

# 多页错误

  • 考虑从内存中将 2 个数加和并将结果存储回内存的指令的读取和解码,可能产生多个缺页错误;
  • 产生性能痛点,幸运的是因为局部引用的存在,使得请求分页 具有较为合理的性能;

# 硬件支持

具有有效 / 无效位的页表
辅助内存 (带交换空间的交换设备)

指令重启,在缺页错误后能够重启任何指令;

# 指令重启

  • 微代码计算试图访问源块和目的块的两端,如果出现缺页错误,那么在这一步出现,完成缺页逻辑后,执行移动操作;
  • 使用临时寄存器来保存覆盖位置的值,如果有缺页错误,则在陷阱发生之前,所有旧值都将写回到内存中。该动作是将内存恢复到指令启动之前的状态,这样能够重复执行该指令;

# 写时复制

写时复制 (CoW) 允许父进程和子进程最初共享内存中的相同页面

如果任一进程修改了共享页面,则该页面被复制

CoW 允许更高效的进程创建 (fork) ,因为只复制修改过的页面

# 系统抖动

频繁发生缺页,系统忙于进行页面的换入和换出,而没有进行有效的计算。

系统抖动

导致 CPU 利用率低,并发度低。

系统还会自动检测 CPU 利用率,系统抖动时检测到 CPU 利用率降低,会创建更多精进程来提高 CPU 利用率,但这会反而加剧系统抖动。

局部性原理告诉我们,访问磁盘总是在一个局部到另一个局部变化。而系统抖动从这个角度来说,就是局部性访问的大小超过了内存大小,所以导致了系统抖动。

本地或优先级替换算法来缓解系统抖动。

# 工作集

WSSiWSS_i (Working Set of Process PiP_i ):进程在某一个固定的时间窗口 Δ\Delta(可以按时间算、指令数算)内,访问的所有页面

  • if Δ\Delta too small will not encompass entire locality
  • if Δ\Delta too large will encompass several localities
  • if Δ=\Delta=\infin will encompass entire program

最理想的情况就是 WSS 能够被全部放在 TLB 中

⭐️ tt 时刻的工作集为该时刻及其以前 Δ\Delta 时间窗口范围内的访问的页面。

解决方案 1

建立 “可接受的” PFF (page-fault frequency) 并使用本地替换策略

内核的内存管理就比较简单,因为它在内存里一定是连续的,可以完全利用线性地址偏移解决。

预调页

访问到某一内存页,很有可能下次就要访问它的邻居内存页,所以利用空间局部性

在程序启动的时候可以减少大量的缺页

当然也是有可能造成 I/O 和内存的浪费的

# 帧分配

在进程之间如何分配固定数量的可用内存?

  • 固定分配

  • 优先级分配

  • 全局置换 —— 进程从所有帧集中选择替换帧,一个进程可以从另一个进程获取帧

    • 高优先级进程可以置换低优先级进程
    • 缺点:进程不能控制他自己的缺页错误率
  • 局部置换 —— 每个进程仅从其自己的一组分配帧中进行选择

    • 每个进程的性能更加一致
    • 但可能是未充分利用的内存

# 页面回收

# 性能指标

Three major activities

  • Service the interrupt – careful coding means just several hundred instructions needed
  • Read the page – lots of time
  • Restart the process – again just a small amount of time

Effective Access Time (EAT)

EAT=(1p)×MA+p×(PFO+SPOSPI)EAT=(1–p)\times MA+p\times(PFO+SPO-SPI)

  • Page Fault Rate 0p10\leq p\leq1
    • if p=0p=0, no page faults
    • if p=1p=1, every reference is a fault
  • MAMA : memory access
  • PFOPFO : page fault overhead
  • SPOSPO : swap page out ( if dirty )
  • SPISPI : swap page in

# 性能优化

交换空间 I/O 比文件系统 I/O 快,即使在同一设备上也是如此

交换分配在更大的块中,比文件系统所需的管理更少;

在进程加载时将整个进程映像复制到交换空间

然后在交换空间内执行调页;
在旧的 BSD Unix 中使用;

从磁盘上的程序二进制文件请求分页,但在释放帧时将页面直 接放弃 (被覆盖),而不是分页调出;

在 Solaris 和当前 BSD 中使用 § 仍然需要写入以交换空间

与文件不关联的页面 (如栈和堆)- 匿名内存

在内存中修改但尚未写回文件系统的页面;v 移动系统

通常不支持交换
相反,从文件系统请求页面并回收只读页面 (如代码)

# 页面置换算法

# 空闲帧列表

当出现页面错误时,操作系统必须将所需页面从辅助存储器带入主存。

大多数操作系统都维护一个空闲帧列表 —— 一个用于满足此类请求的空闲帧池。

操作系统通常使用一种称为按需零填充 (zero-fill-on-demand) 的技术来分配空闲帧,即在分配前将帧的内容清零。

当系统启动时,所有可用内存都会放在空闲帧列表中。

# 页面置换

一定发生在缺页故障处理中,空闲帧列表基础上的补充,防止内存过度分配

  • 不一定要在空闲帧列表为空的时候才进行页面置换,也可能在空闲帧数量低于某一阈值的时候就开始
  • 往往不是一个页面一个页面置换,因为这样效率比较低,而是批处理多个页面进行置换

使用修改 (dirty) 位来减少⻚面(内存到磁盘)传输的开销 —— 只有修改过的 victim ⻚面才会写入磁盘;

⻚面替换完成了逻辑内存和物理内存之间的分离 —— 可以 在较小的物理内存上提供较大的虚拟内存;

# FIFO

页面错误与帧数关系图

Belady 异常,出现帧数增加后缺页异常数量也增加的现象,只会在 FIFO 调度中出现

页面错误与帧数关系图belady

# OPT 算法

最优页面置换算法

替换在最长时间内不使用的页面,实际上不能预测,所以是不可行的,但可以用于理论上测量其他算法性能,作为比较的基线

# LRU 算法

最少最近使用 (LRU) 算法

使用过去的知识而不是未来的知识,替换在最长时间内未使用的页面,将最后一次使用的时间与每页关联

一般来说,算法很好,经常使用

  • 计数器实现,为每一个页面(页表项)设置计数位,每次页面被引用,将当前时钟的时间戳复制到计数位
  • 使用堆栈记录最近的页面引用,栈顶为最近一次引用的页面,使用双向链表排序

# 额外引用位算法

通过定期记录引用位,可以获得额外的排序信息;

为每个页面的页表项设置一个 8 位的字节;

将每个页面的引用位移到 8 位字节的高位,右移一位,并丢 弃最低位,保存 8 个时间周期的页面使用情况;

具有 11000100 的历史寄存器值的页面比具有值为 01110111 的 页面更为 “最近使用”;

替换最小编号;

# 第二次机会 / 时钟算法

通常为 FIFO,加上硬件提供的引用位。为每个页面设置一个访问位,再将内存中的页面都通过链接指针链接成一个循环队列

一般默认初始情况没有调入任何页面,依次调入页面后,各个页面的访问位为 1 ,替换指针指向第一个页帧。

替换指针总是指向上一次被调入页面的下一个页帧!若为最后一个页帧则回到第一个页帧!

替换规则:

  • 引用位 = 0 ,替换它,然后替换指针指向下一个页帧。
  • 引用位 = 1 ,则:
    • 设置引用位 0 ,将页面保留在内存中
    • 替换指针指向下一个页帧,继续找按该规则 victim

第二轮扫描中一定会有访问位为 0 的页面,因此简单的 CLOCK 算法选择一个淘汰页面最多会经过两轮扫描

# 增强型第二次机会算法

在第二次机会 / 时钟置换算法的基础上,除了考虑一个页面最近有没有被访问过之外,操作系统还应考虑页面有没有被修改过。在其他条件都相同时,应优先淘汰没有修改过的页面。

为每个页面页表项增加修改位(dirty):

  • 修改位 = 0 ,表示页面没有被修改过;
  • 修改位 = 1 ,表示页面被修改过。

方便讨论,用 (访问位,修改位) 的形式表示各页面状态:

  • (0,0) 最近未使用未修改 —— 要替换的最佳页面
  • (0,1) 最近未使用但已修改 —— 不太好,必须在置换之前将页面写出;
  • (1,0) 最近使用但没有修改 —— 可能很快会再次使用
  • (1,1) 最近使用和修改的 —— 可能很快会再次使用,需要在更换前将页面写出;

将所有可能被置换的页面排成一个循环队列,和原本的时钟置换相比,每一轮的操作都有不同。

  • 第一轮:从当前位置开始扫描到第一个 (0,0) 的帧用于替换。本轮扫描不修改任何标志位
  • 第二轮:若第一轮扫描失败,则重新扫描,查找第一个 (0,1) 的帧用于替换。本轮将所有扫描过的帧访问位设为 0
  • 第三轮:若第二轮扫描失败,则重新扫描,查找第一个 (0,0) 的帧用于替换。本轮扫描不修改任何标志位
  • 第四轮:若第三轮扫描失败,则重新扫描,查找第一个 (0,1) 的帧用于替换。

这里的第 2、3 轮相当于原来的时钟置换算法的 (可能的), 2 轮。

由于第二轮已将所有帧的访问位设为 0 ,因此经过第三轮、第四轮扫描一定会有一个帧被选中,因此改进型时钟置换算法选择一个淘汰页面最多会进行四轮扫描

# 页面缓冲算法

始终保持一个空闲帧池

  • 当出现缺页错误时,会像以前一样选择一个牺牲帧;

  • 将页面读入空闲帧,选择要退出的牺牲帧并添加到空闲 池;

  • 方便时,驱逐牺牲帧,无需等待写出牺牲帧;v 可能的话,保留修改过的页面列表

    当备份存储为空闲时,在那里写入页面并设置为非脏;增加了无需写出的页面的概率;

可能的话,保持空闲帧池,并且记住哪些页面在哪些帧内;

如果在重用之前再次引用,则无需再次从磁盘加载内容

如果选择了错误的受害者帧,通常有助于减少惩罚

双缓冲

  • 操作系统将页面副本作为 I/O 缓冲区保存在内存中
  • 应用程序将页保留在内存中以供自己工作;

可能带来好处,也可能带来坏处

\ No newline at end of file +内存管理 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

冯・诺伊曼计算机体系决定了操作系统需要内存管理

# 虚拟内存物理实现

  • 连续分配
    • 单一连续分配
    • 分区
      • 固定分区分配
      • 动态分区分配
  • 非连续分配
    • 段式
    • 页式
    • 段页式

⭐️内部碎片和外部碎片

  • 内部碎片
    • 是已经被分配给某个进程的,该进程没有利用的
    • 固定分区分配产生这种碎片
  • 外部碎片
    • 是无法被分配给任何进程的,不属于任何进程的
    • 动态分区分配产生这种碎片
    • 可以通过紧凑技术克服,需要动态重定位寄存器硬件支持

# 分区 (连续分配)

# 单一连续分配

将内存分为两部分:

  • 系统区
  • 用户区
    • 唯一一个用户程序独占整个用户区

内存中只有一个用户程序,只能用于单用户、单任务的操作系统。

有内部碎片,无外部碎片。

# 固定分区

使用空闲分区链 / 表

有内部碎片,无外部碎片。

# 动态分区

使用空闲分区链 / 表

无内部碎片,有外部碎片。

# 首次适应

空闲分区按地址递增顺序排列。

每次分配时从头开始顺序查找到第一个满足大小的空闲分区。

性能最好。

# 邻近适应

空闲分区按地址递增顺序排列。和首次适应一样。

每次分配时从上次查找结束位置开始查找到第一个满足大小的空闲分区。

# 最佳适应

空闲分区按容量递增顺序排列。

产生最多外部碎片

# 最坏适应

空闲分区按容量递减顺序排列。

前面三种都基于顺序搜索,后面三种则都基于索引搜索

# 快速适应

基于索引分配,对空闲分区按大小相同的分为一类,每一类单独设置一个空闲分区链。建立一张索引表管理所有空闲分区链,索引表项包含对应大小的空闲分区链的头指针

根据进程需要的大小,在索引表中找到能容纳它的最小的空闲分区链表,直接从链表取出第一块进行分配。

优劣:

  • 优点
    • 查找效率高
    • 不产生内部碎片(当然啊这不是动态分区吗)
  • 缺点
    • 回收分区复杂,导致算法复杂、系统开销大

# 伙伴系统

我感觉应该算固定分区分配才对?

规定所有分区大小为 22kk 次幂。

每次分配大小为 nn (2i1<n2i2^{i-1}<n\leq 2^i) 的分区时,在

导致过多内部碎片⚠️

Slab 分配器 —— 一般只有内核内存使用

# 哈希算法

根据空闲分区链表的分布规律建立哈希函数,构建一张以哈希表:

  • 关键字 key 为空闲分区大小
  • 表项 value 为对应空闲分区链的头指针

# 分段

程序员或者编译器会把程序和数据指定到不同的分段,需要知道段的最大长度限制

将程序产生的二维地址即 <段号,偏移><段号,偏移> 映射到一维物理地址, 这个地址是通过段表实现;

段表中每个条目由段基址和段界限构成

CPU 去哪里找段表?—— GDTR 寄存器,GDTR 寄存器的结构如下:

  • 低 2 字节(16 位)存储了 limit ,全局描述符表的大小(以字节为单位),减去 1 的结果。
  • 高 4 字节(32 位)存储了 base ,全局描述符表的基地址。

# 分页

页放到页帧 / 框里,区分:⚠️

  • 页(Page)
  • 页帧(Page frame)或者页框,是空的,没有数据

页框 \geq 页,现代操作系统大多二者是相等的,方便管理

# 页表

系统中有一个唯一的页表寄存器(PTR),包含页表首地址(PTBR),只能由特权指令访问。

页表长度寄存器(PTLR),可以直接用于判断是否越界(好像不一定有)

x86_64 , i386 中的 PTR 寄存器叫做 CR3 寄存器

页表从属于进程,每创建一个新进程就需要创建一个独立的新页表给它。

# TLB

转换表缓冲区 / 快表 /... 详细参考计组

# 共享页

共享代码

  • 进程 (即文本编辑器、编译器、窗口系统) 之间共享的只读 (可重入) 代码的一个副本;
  • 类似于共享同一进程空间的多个线程;
  • 如果允许共享读写页面,则还可用于进程间通信;

# 多级 / 层页表

经典:在现代计算机上考虑 32 位逻辑地址空间,页面大小为 4KB (2122^{12}),页面表将有 4M 个条目 (232/212=2202^{32}/2^{12}=2^{20}) ,如果每个条目为 4B ,每个进程需要为页表分配 16MB 的物理地址空间,这片连续的物理空间太大了!

相同条件下考虑 64 位,即使采用 2 级分页,外层页表也需要 16384GB 大小的连续物理空间!所以 x86_64 采用 4 级页表

现代 OS 大多采用 3 到 4 级页表

64 位下的 2 级页表 和 3 级页表:

64-2-3

# 散列页表 / 哈希表

# 聚簇页表

64 位地址的变体,哈希值对应的不是一个页,而是一簇页(一个页族)

特别适用于稀疏地址空间 (内存引用不连续且分散)

# 倒排页表

不再为每个进程设置一个页表并跟踪所有可能的逻辑页,而是跟踪所有物理页,此时整个架构自 CPU 开始到 OS 都有较大变化

内存的每一物理页有一个条目,条目包含:

  • 存储在该实际内存位置的页的虚拟地址
  • 有关拥有该页的进程的信息组成

CPU 产生的逻辑地址:

倒排页表

优点:

  • 减少存储每个页表所需的内存

缺点:

  • 发生页引用时增加搜索表所需的时间
  • 共享内存不太容易实现:虚拟地址到共享物理地址的一种映射

# 现代 OS 举例

# Oracle SPARC Solaris

考虑现代 64 位操作系统目标是效率,低开销

基于哈希,但更复杂

两个哈希表

  • 一个内核
  • 一个用于所有用户进程

每个都将内存地址从虚拟内存映射到物理内存

每个条目表示映射虚拟内存的连续区域

比为每个页面提供单独的哈希表条目更高效

每个条目都有基址和跨距 (表示条目所代表的页数)

# IA-32/64

英特尔 IA-32 和 IA-64 均支持分段、分页管理

记录段号的基地址的描述符表,按私有、公有分为:

  • LDT 局部描述符表
  • GDT 全局描述符表

早期 IA-32 利用 PAE 实现页地址扩展

# ARM

Apple

段页混合式管理,较大连续内存走分段,较小连续内存走分页:

arm

# 虚拟内存软件实现

⭐️虚拟内存的实现建立在离散分配的内存管理方式基础上

三个特征:

  • 多次性
  • 对换性
  • 虚拟性

虚拟内存可以通过以下方式实现:

  • 请求分页
  • 请求分段(按需分段)
  • 请求段页式存储管理

# 请求分页

按需分页

  • 固定分配局部置换
  • 可变分配全局置换
  • 可变分配局部置换

请求分页系统的外存

  • 文件区
    • 存放文件,采用离散分配方式
  • 对换区(交换区)
    • 存放对换页面,采用连续分配方式,I/O 速度更快

可以在加载时将整个进程放入内存或者只在需要时才将页面放入内存

所需的 I/O 更少,没有不必要的 I/O

  • 所需内存更少
  • 更快的响应
  • 更支持多用户

类似于带交换的分页系统 (需要硬件支持)

  • 页面是必需的 —— 引用它
  • 无效引用 —— 终止
  • 不在内存中 —— 调入内存

惰性交换程序:除非需要页,否则永远不要将页交换到内存中

处理页面的交换程序是 “调页程序”

# 处理缺页

  1. 检查进程的内部表,通常与 PCB 一起保存,以确定内存引用是否有效;
  2. 如果:(页面错误 (缺页) )
    • 无效,那么终止进程
    • 引用有效但是未调入页面, 那么发生缺页中断;
  3. 找到空闲帧;(或 victim 帧)
  4. 通过磁盘调度操作将页面交换到刚分配的帧中;
  5. 当磁盘操作读取完成后,重置内部表和页表,以指示当前页面在内存中;
  6. 重新启动导致缺页的指令,该进程能够访问所需的页;(指令重启

# 问题

# 启动进程时内存中没有页面

操作系统将指令指针设置为进程的第一条指令,非内存驻留 -> 页面错误

  • 进程其他页面的访问也是一样;
  • 纯请求分页;

# 多页错误

  • 考虑从内存中将 2 个数加和并将结果存储回内存的指令的读取和解码,可能产生多个缺页错误;
  • 产生性能痛点,幸运的是因为局部引用的存在,使得请求分页 具有较为合理的性能;

# 硬件支持

具有有效 / 无效位的页表
辅助内存 (带交换空间的交换设备)

指令重启,在缺页错误后能够重启任何指令;

# 指令重启

  • 微代码计算试图访问源块和目的块的两端,如果出现缺页错误,那么在这一步出现,完成缺页逻辑后,执行移动操作;
  • 使用临时寄存器来保存覆盖位置的值,如果有缺页错误,则在陷阱发生之前,所有旧值都将写回到内存中。该动作是将内存恢复到指令启动之前的状态,这样能够重复执行该指令;

# 写时复制

写时复制 (CoW) 允许父进程和子进程最初共享内存中的相同页面

如果任一进程修改了共享页面,则该页面被复制

CoW 允许更高效的进程创建 (fork) ,因为只复制修改过的页面

# 系统抖动

频繁发生缺页,系统忙于进行页面的换入和换出,而没有进行有效的计算。

系统抖动

导致 CPU 利用率低,并发度低。

系统还会自动检测 CPU 利用率,系统抖动时检测到 CPU 利用率降低,会创建更多精进程来提高 CPU 利用率,但这会反而加剧系统抖动。

局部性原理告诉我们,访问磁盘总是在一个局部到另一个局部变化。而系统抖动从这个角度来说,就是局部性访问的大小超过了内存大小,所以导致了系统抖动。

本地或优先级替换算法来缓解系统抖动。

# 工作集

WSSiWSS_i (Working Set of Process PiP_i ):进程在某一个固定的时间窗口 Δ\Delta(可以按时间算、指令数算)内,访问的所有页面

  • if Δ\Delta too small will not encompass entire locality
  • if Δ\Delta too large will encompass several localities
  • if Δ=\Delta=\infin will encompass entire program

最理想的情况就是 WSS 能够被全部放在 TLB 中

⭐️ tt 时刻的工作集为该时刻及其以前 Δ\Delta 时间窗口范围内的访问的页面。

解决方案 1

建立 “可接受的” PFF (page-fault frequency) 并使用本地替换策略

内核的内存管理就比较简单,因为它在内存里一定是连续的,可以完全利用线性地址偏移解决。

预调页

访问到某一内存页,很有可能下次就要访问它的邻居内存页,所以利用空间局部性

在程序启动的时候可以减少大量的缺页

当然也是有可能造成 I/O 和内存的浪费的

# 帧分配

在进程之间如何分配固定数量的可用内存?

  • 固定分配

  • 优先级分配

  • 全局置换 —— 进程从所有帧集中选择替换帧,一个进程可以从另一个进程获取帧

    • 高优先级进程可以置换低优先级进程
    • 缺点:进程不能控制他自己的缺页错误率
  • 局部置换 —— 每个进程仅从其自己的一组分配帧中进行选择

    • 每个进程的性能更加一致
    • 但可能是未充分利用的内存

# 页面回收

# 性能指标

Three major activities

  • Service the interrupt – careful coding means just several hundred instructions needed
  • Read the page – lots of time
  • Restart the process – again just a small amount of time

Effective Access Time (EAT)

EAT=(1p)×MA+p×(PFO+SPOSPI)EAT=(1–p)\times MA+p\times(PFO+SPO-SPI)

  • Page Fault Rate 0p10\leq p\leq1
    • if p=0p=0, no page faults
    • if p=1p=1, every reference is a fault
  • MAMA : memory access
  • PFOPFO : page fault overhead
  • SPOSPO : swap page out ( if dirty )
  • SPISPI : swap page in

# 性能优化

交换空间 I/O 比文件系统 I/O 快,即使在同一设备上也是如此

交换分配在更大的块中,比文件系统所需的管理更少;

在进程加载时将整个进程映像复制到交换空间

然后在交换空间内执行调页;
在旧的 BSD Unix 中使用;

从磁盘上的程序二进制文件请求分页,但在释放帧时将页面直 接放弃 (被覆盖),而不是分页调出;

在 Solaris 和当前 BSD 中使用 § 仍然需要写入以交换空间

与文件不关联的页面 (如栈和堆)- 匿名内存

在内存中修改但尚未写回文件系统的页面;v 移动系统

通常不支持交换
相反,从文件系统请求页面并回收只读页面 (如代码)

# 页面置换算法

# 空闲帧列表

当出现页面错误时,操作系统必须将所需页面从辅助存储器带入主存。

大多数操作系统都维护一个空闲帧列表 —— 一个用于满足此类请求的空闲帧池。

操作系统通常使用一种称为按需零填充 (zero-fill-on-demand) 的技术来分配空闲帧,即在分配前将帧的内容清零。

当系统启动时,所有可用内存都会放在空闲帧列表中。

# 页面置换

一定发生在缺页故障处理中,空闲帧列表基础上的补充,防止内存过度分配

  • 不一定要在空闲帧列表为空的时候才进行页面置换,也可能在空闲帧数量低于某一阈值的时候就开始
  • 往往不是一个页面一个页面置换,因为这样效率比较低,而是批处理多个页面进行置换

使用修改 (dirty) 位来减少⻚面(内存到磁盘)传输的开销 —— 只有修改过的 victim ⻚面才会写入磁盘;

⻚面替换完成了逻辑内存和物理内存之间的分离 —— 可以 在较小的物理内存上提供较大的虚拟内存;

# FIFO

页面错误与帧数关系图

Belady 异常,出现帧数增加后缺页异常数量也增加的现象,只会在 FIFO 调度中出现

页面错误与帧数关系图belady

# OPT 算法

最优页面置换算法

替换在最长时间内不使用的页面,实际上不能预测,所以是不可行的,但可以用于理论上测量其他算法性能,作为比较的基线

# LRU 算法

最少最近使用 (LRU) 算法

使用过去的知识而不是未来的知识,替换在最长时间内未使用的页面,将最后一次使用的时间与每页关联

一般来说,算法很好,经常使用

  • 计数器实现,为每一个页面(页表项)设置计数位,每次页面被引用,将当前时钟的时间戳复制到计数位
  • 使用堆栈记录最近的页面引用,栈顶为最近一次引用的页面,使用双向链表排序

# 额外引用位算法

通过定期记录引用位,可以获得额外的排序信息;

为每个页面的页表项设置一个 8 位的字节;

将每个页面的引用位移到 8 位字节的高位,右移一位,并丢 弃最低位,保存 8 个时间周期的页面使用情况;

具有 11000100 的历史寄存器值的页面比具有值为 01110111 的 页面更为 “最近使用”;

替换最小编号;

# 第二次机会 / 时钟算法

通常为 FIFO,加上硬件提供的引用位。为每个页面设置一个访问位,再将内存中的页面都通过链接指针链接成一个循环队列

一般默认初始情况没有调入任何页面,依次调入页面后,各个页面的访问位为 1 ,替换指针指向第一个页帧。

替换指针总是指向上一次被调入页面的下一个页帧!若为最后一个页帧则回到第一个页帧!

替换规则:

  • 引用位 = 0 ,替换它,然后替换指针指向下一个页帧。
  • 引用位 = 1 ,则:
    • 设置引用位 0 ,将页面保留在内存中
    • 替换指针指向下一个页帧,继续找按该规则 victim

第二轮扫描中一定会有访问位为 0 的页面,因此简单的 CLOCK 算法选择一个淘汰页面最多会经过两轮扫描

# 增强型第二次机会算法

在第二次机会 / 时钟置换算法的基础上,除了考虑一个页面最近有没有被访问过之外,操作系统还应考虑页面有没有被修改过。在其他条件都相同时,应优先淘汰没有修改过的页面。

为每个页面页表项增加修改位(dirty):

  • 修改位 = 0 ,表示页面没有被修改过;
  • 修改位 = 1 ,表示页面被修改过。

方便讨论,用 (访问位,修改位) 的形式表示各页面状态:

  • (0,0) 最近未使用未修改 —— 要替换的最佳页面
  • (0,1) 最近未使用但已修改 —— 不太好,必须在置换之前将页面写出;
  • (1,0) 最近使用但没有修改 —— 可能很快会再次使用
  • (1,1) 最近使用和修改的 —— 可能很快会再次使用,需要在更换前将页面写出;

将所有可能被置换的页面排成一个循环队列,和原本的时钟置换相比,每一轮的操作都有不同。

  • 第一轮:从当前位置开始扫描到第一个 (0,0) 的帧用于替换。本轮扫描不修改任何标志位
  • 第二轮:若第一轮扫描失败,则重新扫描,查找第一个 (0,1) 的帧用于替换。本轮将所有扫描过的帧访问位设为 0
  • 第三轮:若第二轮扫描失败,则重新扫描,查找第一个 (0,0) 的帧用于替换。本轮扫描不修改任何标志位
  • 第四轮:若第三轮扫描失败,则重新扫描,查找第一个 (0,1) 的帧用于替换。

这里的第 2、3 轮相当于原来的时钟置换算法的 (可能的), 2 轮。

由于第二轮已将所有帧的访问位设为 0 ,因此经过第三轮、第四轮扫描一定会有一个帧被选中,因此改进型时钟置换算法选择一个淘汰页面最多会进行四轮扫描

# 页面缓冲算法

始终保持一个空闲帧池

  • 当出现缺页错误时,会像以前一样选择一个牺牲帧;

  • 将页面读入空闲帧,选择要退出的牺牲帧并添加到空闲 池;

  • 方便时,驱逐牺牲帧,无需等待写出牺牲帧;v 可能的话,保留修改过的页面列表

    当备份存储为空闲时,在那里写入页面并设置为非脏;增加了无需写出的页面的概率;

可能的话,保持空闲帧池,并且记住哪些页面在哪些帧内;

如果在重用之前再次引用,则无需再次从磁盘加载内容

如果选择了错误的受害者帧,通常有助于减少惩罚

双缓冲

  • 操作系统将页面副本作为 I/O 缓冲区保存在内存中
  • 应用程序将页保留在内存中以供自己工作;

可能带来好处,也可能带来坏处

\ No newline at end of file diff --git a/cs/os/process/index.html b/cs/os/process/index.html index 2142fea9..5796fc70 100644 --- a/cs/os/process/index.html +++ b/cs/os/process/index.html @@ -1 +1 @@ -进程 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 进程的基本概念

# 进程的定义

典型的定义:

  • 进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位 ==
  • 一个具有独立功能的程序在一个数据集合上运行的过程

# 区分进程程序进程实体

  • 程序(Program):是静态的,就是个存放在磁盘里的可执行文件,就是一系列的指令集合

    • 静态连接
    • 动态链接
  • 进程(Process):是动态的,是程序的一次执行过程

  • 进程实体(进程映像):是静态的,反应了进程在某一时刻的状态

# 进程实体的组成

一个 == 进程实体(进程映像)== 由三个部分组成:

  • PCB
    • 进程描述信息
    • 进程控制和管理信息
    • 资源分配清单
    • 处理机状态信息(CPU 上下文
  • 程序段
    • 程序的代码(指令序列)
  • 数据段
    • 运行过程中产生的各种数据(如:程序中定义的变量)

PCB 是给操作系统用的;程序段、数据段是给进程自己用的,与进程自身的运行逻辑有关

# PCB

PCB 位于内存的内核空间里,创建之后常驻内存。

PCB 是进程存在的唯一标志,当进程被创建时,操作系统为其创建 PCB,当进程结束时,会会回收其 PCB。

PCB 几乎完备的表示了进程的状态,也就是说只要有一个进程的 PCB,就可以恢复对应的进程

# PCB 的结构

  • 进程描述信息

    • 进程标识符 PID
    • 用户标识符 UID
  • 进程控制和管理信息

    • CPU、磁盘、网络流量使用情况统计⋯
      • 进入内存时间
      • CPU 占用时间
      • 信号量使用
    • 进程当前状态:就绪态 / 阻塞态 / 运行态
    • 代码运行入口地址
    • 程序的外存地址
    • 程序优先级
  • 资源分配清单

    • 正在使用(依赖)哪些文件
      • 文件描述符
    • 正在使用哪些内存区域
      • 代码段指针
      • 数据段指针
      • 堆栈段指针
    • 正在使用哪些 I/O 设备
  • 处理机相关信息,也叫 CPU 的上下文(the context of the processor)

    • user-visible registers
    • control and status registers (CSR)
    • stack pointers
    • PSW
      • eg: EFLAGS in x86

# Linux 的 PCB

Linux 中的进程控制块 PCB 源码位于 linux-x.xx.xx/include/linux/sched.h

Linux 不区分进程和线程,将它们都视为 task

由 C 结构 task_struct 表示:

c
{
  pid t_pid;/* 进程标识符 */
  unsigned int time_slice /* 调度信息 */
  struct task_struct* 父进程;/* 此进程的父级 */
  struct list_head children;/* 此进程的子进程 */
  struct *files;/* 打开文件列表 */
  struct mm_struct*mm;/* 此进程的地址空间 */
  ...
}

task_struct

# 进程的特征

  • 动态性 —— 进程是程序的一次执行过程,是动态地产生、变化和消亡的(动态性是进程最基本的特征)
  • 并发性 —— 内存中有多个进程实体,各进程可并发执行
  • 独立性 —— 进程是能独立运行、独立获得资源、独立接受调度的基本单位
  • 异步性 —— 各进程按各自独立的、不可预知的速度向前推进,操作系统要提供 “进程同步机制 " 来解决异步问题
  • 结构性 —— 每个进程都会配置一个 PCB。结构上看,进程由程序段、数据段、PCB 组成

# 进程的状态与转换

The steps in a full process switch are:

  1. save the context of the processor
  2. update the PCB of the process currently in the Running state
  3. move the PCB of this process to the appropriate queue
  4. select another process for execution
  5. update the PCB of the process selected
  6. update memory management data structures
  7. restore the context of the processor to that which existed at the time the selected process was last switched out

# 五状态模型

五状态模型

# 七状态模型

增加了挂起状态的进程


挂起进程的特征:

  • 进程不能立即执行(上处理机)

  • 进程可能有也可能么有等待一个事件(为什么那么像废话)

  • 为阻止该进程执行,可通过代理使其处于挂起状态;代理可以是:

    • 进程本身

    • 父进程

    • 操作系统

  • 只有代理程序显示地命令操作系统进行状态轮换,才能使该进程从挂起的状态转移


进程挂起的原因:

  • Swaping
  • Other OS reason
  • Interactive user request
  • Timing
  • Parent pocess request

双挂起状态的进程模型:

七状态模型

# 进程组织

进程组织的数据结构

# 链接式组织进程

链式组织进程

# 索引式组织进程

索引式组织进程

# 进程控制

也就是对进程的操作,这些基本操作几乎全部都是系统调用实现的

# 系统调用

Some basic and important system calls

PCB 的访问:

getpid()

  • fork()
  • exec*()
  • wait()
  • exit()

# Linux 举例

父进程创建子进程,子进程又创建其他进程,形成进程树;父子之间不同角度可能有不同关系:

  • 资源共享
    • 父和子共享所有资源 (Linux 中父进程 vfork )
    • 子进程共享父进程资源的子集 (Linux 中父进程 vfork )
    • 父进程和子进程不共享任何资源 (Linux 中父进程 fork )
  • 执行
    • 父进程和子进程同时并发执行
    • 父进程等待直到子进程终止 (Linux 中父进程 wait(0) )
  • 地址空间
    • 子进程是父进程的复制品 (Linux 中父进程 fork )
    • 子进程加载另一个新的程序
    • 子进程完全覆盖父进程 (Linux 中父进程 fork + exec )
      • exec family 有 6 个成员
      • execl 装载新的文件

# fork

Linux 中,由父进程调用系统调用 fork() 创建子进程

c
#include<stdio.h>
#include<unistd.h>
int main (){
  for(int i=0;i<4;++i){
    fork();
  }
	printf("This is a test printed by %d\n", getpid());
return 0;
}

编译运行上述程序将打印出 16 次!因为这里子进程是父进程的复制品:

shell
node1@vm1:~/Desktop$ gcc -o test test.c
node1@vm1:~/Desktop$ ./test
This is a test printed by 139377
This is a test printed by 139382
This is a test printed by 139380
This is a test printed by 139379
This is a test printed by 139378
This is a test printed by 139383
node1@vm1:~/Desktop$ This is a test printed by 139381 # 父进程结束
This is a test printed by 139386
This is a test printed by 139387
This is a test printed by 139385
This is a test printed by 139388
This is a test printed by 139389
This is a test printed by 139384
This is a test printed by 139390
This is a test printed by 139391
This is a test printed by 139392

fork 会克隆的内容:

Cloned itemsDescriptions
Program code [File & Memory]They are sharing the same piece of code.
MemoryIncluding local variables, global variables, and dynamically allocated memory.
Opened files [Kernel's internal]If the parent has opened a file "A", then the child will also have file "A" opened automatically.
Program counter [CPU register]That's why they both execute from the same line of code after fork() returns.

fork 不克隆的内容:

Distinct itemsParentChild
Return value of fork() PID of the child process.0
PIDUnchanged.Different, not necessarily be "Parent PID + 1"
Parent processUnchanged.Doesn't have the same parent as that of the parent process.
Running timeCumulated.Just created, so should be 0.

vfork 函数是 fork 函数基础上的修正, fork 函数创建一个完全分离的进程,而 vfork 用于创建一个共享的进程,没有克隆操作,这意味着父进程子进程可以互相看到对方,共享同样的物理地址

# exec*

exec* 系统调用,会 “鸠占鹊巢”,替换掉原进程的代码,但是 PID、父子关系、进程运行时间都不变,也就是:

  • 内核里的内容不变,包括 PCB 等
  • 用户态里的代码被替换
c
#include<stdio.h>
#include<unistd.h>
int main(void) {
	printf("before execl ...\n"); // 原进程代码可以执行
	execl("/bin/ls", "/bin/ls", NULL); //exec 的一个成员函数
	printf("after execl ...\n"); // 原进程代码无法执行
	return 0;
}

编译执行结果:

shell
node1@vm2:~/Desktop$ gcc -o test test.c
node1@vm2:~/Desktop$ ./test
before execl ...
sdb  stack_rwx.c  test  test01  test.c  ysos

# waitwaitpid

wait()waitpid()
Wait for any one of the children.Depending on the parameters, waitpid() will wait for a particular child only.
Detect child termination only.Depending on the parameters, waitpid() can detect child's status changing: -from running to suspended, and -from suspended to running.

# fork + exec*

执行顺序是不确定的

c
#include<stdio.h>
#include<unistd.h>
int system_test(const char *cmd_str) {
    if(cmd_str == -1)
        return -1;
    if(fork() == 0) {
        execl(cmd_str, cmd_str, NULL);
        fprintf(stderr,"%s: command not found\n", cmd_str);
        exit(-1);
    }
    return 0;
}
int main(void) {
    printf("before...\n\n");
    system_test("/bin/ls");
    printf("\nafter...\n");
    return 0;
}

编译执行结果:

shell
node1@vm2:~/Desktop$ gcc -o test test.c
node1@vm2:~/Desktop$ ./test
before...
after...
sdb  stack_rwx.c  test  test01  test.c  ysos # 执行 ls

类似于一个 shell 或 system ,不过 system 创建子进程,时串行执行,执行顺序是确定的。

# fork + exec* + wait

等价于 system

c
#include<stdio.h>
#include<unistd.h>
int system_test(const char *cmd_str) {
    if (cmd_str == -1)
        return -1;
    if(fork() == 0) {
        execl("/bin/sh", "/bin/sh","-c", cmd_str, NULL);
        fprintf(stderr,"%s: command not found\n", cmd_str);
        exit(-1);
    }
    wait(NULL);
    return 0;
}
int main(void) {
    printf ("before...\n\n"); system_test("/bin/1s");
    printf("\nafter...\n");
    return 0;
}

编译执行结果:

shell
node1@vm2:~/Desktop$ gcc -o test test.c
node1@vm2:~/Desktop$ ./test
before...
sdb  stack_rwx.c  test  test01  test.c  ysos
after...

# exit

父进程 wait 和子进程 exit 搭配食用。子进程执行最后一条语句,然后调用 exit 系统调用请求操作系统删除它自己,然后子进程将发送 SIGCHLD 给父进程,并变僵尸进程;父进程接收到 SIGCHLD 后被唤醒(原本被 wait 休眠),处理 SIGCHLD 之后,子进程才被彻底销毁。

c
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main(void){
    int count = 1;
    pid_t childpid, terminatedid;
    childpid = fork(); /* child duplicates parent’s address space */
    if (childpid < 0) {
        perror("fork()");
        return EXIT_FAILURE;
    }
    else if (childpid == 0) { /* This is child pro */
        count++;
        printf("child pro pid = %d, count = %d (addr = %p)\n", getpid(), count, &count);
        printf("child sleeping ...\n");
        sleep(5); /* parent wait() during this period */
        printf("\nchild waking up!\n");
    }
    else { /* This is parent pro */
        terminatedid = wait(0);
        printf("parent pro pid = %d, terminated pid = %d, count = %d (addr = %p)\n",
        getpid(), terminatedid, count, &count);
    }
    printf("\nTesting point by %d\n", getpid()); /* executed by child and parent */
    return EXIT_SUCCESS;
}

编译运行结果:

shell
node1@vm2:~/Desktop$ ./test
child pro pid = 197382, count = 2 (addr = 0x7ffc33c444cc)
child sleeping ...
# 这里等待了 5 秒钟
child waking up!
Testing point by 197382
parent pro pid = 197381, terminated pid = 197382, count = 1 (addr = 0x7ffc33c444cc)
Testing point by 197381

僵尸进程:空有 PCB “外壳”,但是没有用户态的代码,无法执行;

注意区分孤儿进程

# abort

父进程可以使用 abort 系统调用终止子进程的执行。这样做的一些原因:

  • 子进程已超出分配的资源
  • 不再需要分配给子进程的任务
  • 父进程正在退出,如果父进程终止,操作系统不允许子进程继续

# 进程控制原语

进程控制由原语实现

如果不能像原语 “一气呵成”,就有可能导致操作系统中的某些关键数据结构信息不统一的情况,这会影响操作系统进行别的管理工作

原语的执行具有原子性,即执行过程只能一气呵成,期间不允许被中断。

可以用 “关中断指令”“开中断指令” 这两个特权指令实现原子性

无论哪个进程控制原语,要做的无非三类事情:

  • 更新 PCB 中的信息
    • 修改进程状态(state)
    • 保存 / 恢复运行环境
  • 将 PCB 插入合适的队列
  • 分配 / 回收资源

# 创建

  • 申请空白 PCB
  • 为新进程分配所需资源
  • 初始化 PCB
  • 将 PCB 插入就绪队列(进程由阻塞态转变为就绪态

引起进程创建的事件可能有:

  • 用户登录 —— 分时系统中,用户登录成功,系统会建立为其建立一个新的进程
  • 作业调度 —— 多道批处理系统中,有新的作业放入内存时,会为其建立一个新的进程
  • 提供服务 —— 用户向操作系统提出某些请求时,会新建一个进程处理该请求
  • 应用请求 —— 由用户进程主动请求创建一个子进程

所有进程都是以父进程创建子进程的方式创建的:

  • 有些是显式的
    • 用户进程创建的
  • 有些是隐式的
    • 操作系统 “0 号” 根进程创建的(所有进程的祖先)

# 根进程

The first process -- The kernel, while it is booting up, creates the firstprocess -- init .

The init process:

  • has PID = 1
  • and is running the program code “/sbin/init”.
  • Its first task is to create more processes…

# 孤儿进程

父进程创建子进程一层一层创建,但若其中某一个父进程 terminate 了,也就是被终止了,那么被终止进程所创建的进程就变成了孤儿进程。孤儿进程会消耗资源,需要被重新管理起来。

  • Linux 中,使用 re-parent operation 处理孤儿进程, The “init” process will become the step-mother of all orphans.
  • Windows maintains a forest-like hierarchy.

# 撤销

这一过程进程: 就绪态 / 阻塞态 / 运行态 -> 终止态 -> 无

  • 从 PCB 集合中找到终止进程的 PCB
  • 若进程正在运行,立即剥夺 CPU,将 CPU 分配给其他进程
  • 终止其所有子进程
  • 将该进程拥有的所有资源归还给父进程或操作系统
  • 删除 PCB

引起进程终止的事件可能有:

  • 正常结束 —— 进程自己请求终止(exit 系统调用)
  • 异常结束 —— 被操作系统强行杀掉
    • 整数除以 O
    • 非法使用特权指令
  • 外界干预 —— 用户选择杀掉进程
    • Ctrl+Alt+delete
    • kill pid

# 阻塞

  • 找到要阻塞的进程对应的 PCB
  • 保护进程运行现场,将 PCB 状态信息设置为 “阻塞态 ",暂时停止进程运行
  • 将 PCB 插入相应事件的等待队列

引起进程阻塞的事件可能有:

  • 需要等待系统分配某种资源
  • 需要等待相互合作的其他进程完成工作

# 唤醒

  • 在事件等待队列中找到 PCB
  • 将 PCB 从等待队列移除,设置进程为就绪态
  • 将 PCB 插入就绪队列,等待被调度

引起进程唤醒的事件可能有:

  • 等待的事件发生

# 切换

  • 将运行环境信息存入 PCB
  • PCB 移入相应队列
  • 选择另一个进程执行,并更新其 PCB
  • 根据 PCB 恢复新进程所需的运行环境

系统切换:

系统切换

引起进程切换的事件可能有:

  • 当前进程时间片到
  • 有更高优先级的进程到达
  • 当前进程主动阻塞
  • 当前进程终止

# 进程通信

进程间通信(Inter-Process Communication, IPC)是指两个进程之间产生数据交互。

⚠️为什么需要进程通信:

  • 进程是分配系统资源的单位(包括内存地址空间),因此各进程拥有的内存地址空间相互独立
  • 为了保证安全,一个进程不能直接访问另一个进程的地址空间
  • 多核处理器系统中,消息传递优于共享内存,因为没有 cache 的一致性问题

Linux 的 IPC 限制信息可在 /etc/sysctl.conf 中查看

ipcs 可以查看当前操作系统里有多少消息队列、共享内存块、信号量

  • 低级通信
    • 共享文件,信号量 PV 操作
  • 高级通信 —— 以较高的效率传输大量数据
    • 共享内存
    • 消息传递
    • 管道通信

# 共享存储

为避免出错,各个进程对共享空间的访问应该是互斥

# 基于存储区共享

操作系统在内存中划出一块共享存储区,数据的形式、存放位置都由通信进程控制,而不是操作系统。这种共享方式速度很快,是一种高级通信方式

通过 “增加页表项 / 段表项” 即可将同一片共享内存区映射到各个进程的地址空间中

# Linux 共享内存

c
//shm 即 share memory 的缩写
int shm_open (...);
// 通过 shm_open 系统调用,申请一片共享内存区
void * mmap (...);
// 通过 mmap 系统调用,将共享内存区映射到进程自己的地址空间
# Key ID
c
#include <sys/shm.h>
key_t ftok(const char *pathname, int id);
/* key_t is of type int. ftok() convert a pathname and a project identifie
to an IPC key */
key_t key = ftok(/home/myshm", 0x27);
if((key == -1) {
	perror(ftok()");
} else
	printf("key = 0x%x\n", key);
# Create
c
int shmget(key_t key, int size, int shmflg);
/* shmget() allocates a shared memory segment */
/* upper bound of size: 1.9G */
int shmid = shmget(IPC_PRIVATE, 4096, IPC_CREATE|IPC_EXCL|0660);
if(shmid == -1) {
  perror("shmget()");
}

# 基于数据结构的共享

比如共享空间里只能放一个长度为 10 的数组。这种共享方式速度慢限制多,是一种低级通信方式

# 消息传递

进程间的数据交换以格式化的消息(Message)单位。进程通过操作系统提供的两个原语进行数据交换:

  • 发送原语, send(X, msg) ,X 是发送目标
  • 接收消息, receive(X, &msg) ,X 是从哪里接收

格式化的消息(Message)的结构:

  • 消息头
    • 发送进程 ID
    • 接受进程 ID
    • 消息长度等格式化的信息
  • 消息体

# 直接通信方式

P 传递消息给 Q 的过程:

  • P 发送原语 send(Q, msg)
    • msg 数据被封装为格式化消息
    • 格式化消息被从 P 的地址空间转移到操作系统内核的地址空间中进程 Q 的消息队列
  • Q 接收原语 receive(P, &msg)
    • 格式化消息被从操作系统内核的地址空间中进程 Q 的消息队列转移到 Q 的地址空间
    • 解析格式化的消息

特性:

  • 链接是自动建立的
  • 链路仅与一对通信进程相关联
  • 每对之间只存在一个链接
  • 链路可能是单向的,但通常是双向的

这种通信方式展示了寻址的对称性,即发送和接收进程必须指定对方,以便通信。

也可以采用寻址的非对称性,即只要发送者指定接收者,而接收者不需要指定发送者

# 间接通信方式

以 “信箱”(或某些特定的端口)作为中间实体进行消息传递,可以多个进程往同一个信箱 send 消息,也可以多个进程从同一个信箱中 receive 消息;

每个邮箱都有一个唯一的 id ,进程只有在共享邮箱时才能通信;

允许链接最多与两个进程关联

一次只允许一个进程执行接收操作

允许系统任意选择接收器。通知发送方接收者是谁。

间接通信

P 传递消息给 Q 的过程:

  • (创建邮箱)
  • P 发送原语 send(A, msg) ,发送给信箱 A
    • msg 数据被封装为格式化消息
    • 格式化消息被从 P 的地址空间转移到操作系统内核的地址空间中信箱 A 中
  • Q 接收原语 receive(A, &msg) ,从信箱 A 接收消息
    • 格式化消息被从操作系统内核的地址空间中信箱 A 转移到 Q 的地址空间
    • 解析格式化的消息
  • (删除邮箱)

特性:

  • 仅当进程共享公共邮箱时才建立链接
  • 链接可能与许多进程相关联
  • 每对进程可以共享多个通信链路
  • 链路可以是单向的或双向的

邮箱所有者:

  • 邮箱可以被进程拥有;
  • 邮箱被操作系统拥有;
  • 邮箱可以转移

# 同步 / 异步

消息传递可以是阻塞的,也可以是非阻塞的

  • 阻塞被认为是同步的
    • 阻塞发送 — 在接收进程或者邮箱收到消息之前,发送进程阻塞;
    • Blocking receive(阻塞接收)—— 在消息可用之前,接收进程将被阻塞
  • 非阻塞被认为是异步的
    • 非阻塞发送 —— 发送进程发送消息并继续执行;
    • 非阻塞接收 —— 接收进程接收:
      • 有效消息
      • 或空消息
  • 可能有不同的组合
    • 如果发送和接收都是阻塞的,双方之间有一个交会。

与其他课程的阻塞、同步异步关系可能不太一样

# 缓存

附加到链接的消息队列,不管通信是直接还是间接的;以三种方式之一实现队列:

  • 1. 零容量–链路上没有消息排队。发送方必须等待接收方
  • 2. 有限容量–有限长度的 n 条消息,如果链路已满,则发送者必须等待
  • 3. 无限容量–无限长,发送方从不等待

# Linux 接口实现

msgdata.h

c
#define TEXT_SIZE 512
/* considering
------ Messages Limits --------
max queues system wide = 32000
max size of message (bytes) = 8192
default max size of queue (bytes) = 16384
------------------------------------------
The size of message is set to be 512, the total number of messages is 16384/512 = 32
If we take the max size 8192, the number would be 16384/8192 = 2. It is not reasonable
*/
/* message structure */
struct msg_struct {
long int msg_type;
char mtext[TEXT_SIZE]; /* binary data */
};
#define PERM S_IRUSR|S_IWUSR|IPC_CREAT
#define ERR_EXIT(m) \
  do { \
    perror(m); \
    exit(EXIT_FAILURE); \
  } while(0)

msgsnd.c

c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "msgdata.h"
int main(int argc, char *argv[])
{
  struct msg_struct data;
  long int msg_type;
  char buffer[TEXT_SIZE], pathname[80];
  int msqid, ret, count = 0;
  key_t key;
  FILE *fp;
  struct stat fileattr;
  if(argc < 2) {
    printf("Usage: ./a.out pathname\n");
    return EXIT_FAILURE;
  }
  strcpy(pathname, argv[1]);
  if(stat(pathname, &fileattr) == -1) {
    ret = creat(pathname, O_RDWR);
    if (ret == -1) {
    	ERR_EXIT("creat()");
    }
    printf("shared file object created\n");
  }
  key = ftok(pathname, 0x27); /* project_id can be any nonzero integer */
  if(key < 0) {
  	ERR_EXIT("ftok()");
  }
  printf("\nIPC key = 0x%x\n", key);
  msqid = msgget((key_t)key, 0666 | IPC_CREAT);
  if(msqid == -1) {
  	ERR_EXIT("msgget()");
  }
  fp = fopen("./msgsnd.txt", "rb");
  if(!fp) {
  	ERR_EXIT("source data file: ./msgsnd.txt fopen()");
  }
  struct msqid_ds msqattr;
  ret = msgctl(msqid, IPC_STAT, &msqattr);
  printf("number of messages remainded = %ld, empty slots = %ld\n",
  msqattr.msg_qnum, 16384/TEXT_SIZE-msqattr.msg_qnum);
  printf("Blocking Sending ... \n");
  while (!feof(fp)) {
    ret = fscanf(fp, "%ld %s", &msg_type, buffer);
    if (ret == EOF) break;
    printf("%ld %s\n", msg_type, buffer);
    data.msg_type = msg_type;
    strcpy(data.mtext, buffer);
    ret = msgsnd(msqid, (void *)&data, TEXT_SIZE, 0);
    /* 0: blocking send, waiting when msg queue is full */
    if(ret == -1) {
    	ERR_EXIT("msgsnd()");
    }
    count++;
  }
  printf("number of sent messages = %d\n", count);
  fclose(fp);
  system("ipcs -q");
  exit(EXIT_SUCCESS);
}

msgrcv.c

c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include "msgdata.h"
int main(int argc, char *argv[])
{
  key_t key;
  struct stat fileattr;
  char pathname[80];
  int msqid, ret, count = 0;
  struct msg_struct data;
  long int msgtype = 0; /* 0 - type of any messages */
  if(argc < 2) {
    printf("Usage: ./msgrcv pathname msg_type\n");
    return EXIT_FAILURE;
  }
  strcpy(pathname, argv[1]);
  if(stat(pathname, &fileattr) == -1) {
  	ERR_EXIT("shared file object stat error");
  }
  if((key = ftok(pathname, 0x27)) < 0) {
  	ERR_EXIT("ftok()");
  }
  printf("\nIPC key = 0x%x\n", key);
  msqid = msgget((key_t)key, 0666); /* do not create a new msg queue */
  if(msqid == -1) {
  	ERR_EXIT("msgget()");
  }
  if(argc < 3)
  	msgtype = 0;
  else {
  	msgtype = atol(argv[2]);
  	if (msgtype < 0)
 			msgtype = 0;
  } /* determin msgtype (class number) */
  printf("Selected message type = %ld\n", msgtype);
  while (1) {
    ret = msgrcv(msqid, (void *)&data, TEXT_SIZE, msgtype, IPC_NOWAIT);
    /* Non_blocking receive */
    if(ret == -1) { /* end of this msgtype */
      printf("number of received messages = %d\n", count);
      break;
    }
    printf("%ld %s\n", data.msg_type, data.mtext);
    count++;
  }
  struct msqid_ds msqattr;
  ret = msgctl(msqid, IPC_STAT, &msqattr);
  printf("number of messages remainding = %ld\n", msqattr.msg_qnum);
  if(msqattr.msg_qnum == 0) {
  	printf("do you want to delete this msg queue?(y/n)");
  if (getchar() == 'y') {
    if(msgctl(msqid, IPC_RMID, 0) == -1)
    	perror("msgctl(IPC_RMID)");
    }
  }
  system("ipcs -q");
  exit(EXIT_SUCCESS);
}

# POSIX (pthread) 实现

c
#include <mqueue.h>
# Open, Close and Unlink
mqd_t mq_open(const char *name, int oflag, mode_t mode, struct mq_attr *attr ); /* return the mqdes, or -1 if failed */
mqd_t mqID;
mqID = mq_open("/anonymQueue", O_RDWR | O_CREAT, 0666, NULL);
mqd_t mq_close(mqd_t mqdes);
mqd_t mq_unlink(const char *name); /* return -1 if failed */
# Send and Receive
mqd_t mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio); /* return 0, or -1 if failed */
mq_send(mqID, msg, sizeof(msg), i)
mqd_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio); /* return the number of char received, or -1 if failed */
mq_attr mqAttr;
mq_getattr(mqID, &mqAttr);
mq_receive(mqID, buf, mqAttr.mq_msgsize, NULL)

Note that the Linux ipcs utility is not fully compatible to the POSIX ipcs utility. The message queues, shared memory and semaphores in POSIX can not be sensed by System V bash command such as ipcs -q

# Mach

Mach 作为微内核结构,其通信是基于消息传递的设计,甚至系统调用也是消息传递

  • 每个任务在创建时获得两个端口 - 内核和通知
  • 使用 mach_msg() 函数发送和接收消息
  • 通信所需的端口,通过创建 mach 端口分配
  • 收发灵活;例如,邮箱已满时有四个选项:
    • 无限期地等待
    • 最多等待 n 毫秒
    • 立即返回
    • 临时缓存消息

# Windows

通过高级本地过程调用(ALPC)设施以消息传递为中心,仅在同一系统上的两个进程之间工作,类似 RPC;

  • 使用端口(如邮箱)建立和维护通信通道;
  • 使用两种类型的端口:
    • 连接端口
    • 通信端口

通讯工作如下:

  • 客户端打开子系统连接端口对象的句柄;
  • 客户端发送一个连接请求;
  • 服务器创建一对专用通信端口,并将其中一个端口的句柄返回给客户端;
  • 客户端和服务器使用相应的端口句柄发送消息或回调,并监听回复;

windows消息传递

Windows 对不同大小的消息有不同的策略;When an ALPC channel is created, one of three message-passing techniques is chosen:

  1. For small messages (up to 256 bytes), the port’s message queue is used as intermediate storage, and the messages are copied from one process to the other.

  2. Larger messages must be passed through a section object, which is a region of shared memory associated with the channel.

  3. When the amount of data is too large to fit into a section object, an API is available that allows server processes to read and write directly into the address space of a client.

# 管道通信

“管道” 是一个特殊的共享文件,又名 pipe 文件。其实就是在内存中开辟一个大小固定的内存缓冲区

  • 普通管道 (匿名管道)—— 无法从创建它的进程外部访问。通常,父进程创建管道并使用它与它创建的子进程通信。是单向的、半双工的。
    普通管道
  • 命名管道 —— 可以在没有父子关系的情况下访问。是双向的全双工的。

管道通信的规则、限制:

  • 管道只能采用半双工通信,某一时间段内只能实现单向的传输。
  • 如果要实现双向同时通信,则需要设置两个管道。
  • 各进程要互斥地访问管道(由操作系统实现)
  • 当管道写满时,写进程阻塞,直到读进程将管道中的数据取走,即可唤醒写进程。
  • 当管道读空时,读进程阻塞,直到写进程往管道中写入数据,即可唤醒读进程。
  • 管道中的数据一旦被读出,就彻底消失。因此,当多个进程读同一个管道时,可能会错乱。对此,通常有两种解决方案:
    • 一个管道允许多个写进程一个读进程(2014 年 408 真题高教社官方答案);
    • 允许有多个写进程多个读进程,但系统会让各个读进程轮流从管道中读数据(Linux 的方案)。

管道通信

写进程往管道写数据,即便管道没被写满,只要管道没空,读进程就可以从管道读数据

读进程从管道读数据,即便管道没被读空,只要管道没满,写进程就可以往管道写数据

# Linux 实现

c
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define BUFFER SIZE 25
#define READ END 0
#define WRITE END 1
int main(void)
{
  char write msg[BUFFER SIZE] = "Greetings";
  char read msg[BUFFER SIZE];
  int fd[2];
  pid t pid;
  /* Program continues in Figure 3.22 */
  /* create the pipe */
  if (pipe(fd) == -1) {
    fprintf(stderr,"Pipe failed");
    return 1;
  }
  /* fork a child process */
  pid = fork();
  if (pid < 0) { /* error occurred */
    fprintf(stderr, "Fork Failed");
    return 1;
  }
  if (pid > 0) { /* parent process */
    /* close the unused end of the pipe */
    close(fd[READ END]);
    /* write to the pipe */
    write(fd[WRITE END], write msg, strlen(write msg)+1);
    /* close the write end of the pipe */
    close(fd[WRITE END]);
  }
  else { /* child process */
    /* close the unused end of the pipe */
    close(fd[WRITE END]);
    /* read from the pipe */
    read(fd[READ END], read msg, BUFFER SIZE);
    printf("read %s",read msg);
    /* close the read end of the pipe */
    close(fd[READ END]);
  }
  return 0;
}

利用 libc 创建、操作管道:

c
// 普通管道
int pipefd[2];
int pipe(int pipefd);
int fcntl(int pipefd[0|1], int cmd);
int fcntl(int pipefd[0|1], int cmd, long arg);
ssize_t write(int pipefd[1], void* buf, size_t count);
ssize_t read(int pipefd[0], void* buf, size_t count);
close(pipefd[0]);
close(pipefd[1]);
// 命名管道
#define FIFO pathname /* pathname: "/tmp/my_fifo" */
unlink(FIFO); /*delete a name and possibly the file it refers to */
mkfifo(FIFO, 0666);
int fdw = open(FIFO, O_RDWR);
mkfifo(FIFO, 0444);
int fdr = open(FIFO, O_RDONLY);
ssize_t write(int fdw, void* buf, size_t count);
/* ssizt_t = signed int, sizt_t = unsigned int */
ssize_t read(int fdr, void* buf, size_t count);
close(fdw);
close(fdr);

管道缓冲

c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#define ERR_EXIT(m) \
  do { \
    perror(m); \
    exit(EXIT_FAILURE); \
  } while (0)
int main(int argc, char *argv[])
{
  int pipefd[2];
  int bufsize;
  char *buffer;
  int flags, ret, lastwritten, count, totalwritten;
  if(pipe(pipefd) == -1) /* create an ordinary pipe */
  	ERR_EXIT("pipe()");
  flags = fcntl(pipefd[1], F_GETFL);
  fcntl(pipefd[1], F_SETFL, flags | O_NONBLOCK); /* set write_end NONBLOCK */
  bufsize = atoi(argv[1]);
  printf("testing buffer size = %d\n", bufsize);
  buffer = (char *)malloc(bufsize*sizeof(char));
  if(buffer == NULL || bufsize == 0)
  	ERR_EXIT("malloc()");
  count = 0;
  while (1) {
    ret = write(pipefd[1], buffer, bufsize);
    /* bufsize is better to be 2^k */
    if(ret == -1) {
      perror("write()");
      break;
    }
    lastwritten = ret;
    count++;
  }
  totalwritten = (count-1)*bufsize +
  lastwritten;
  printf("single pipe buffer count = %d, last written = %d bytes\n", count, lastwritten);
  printf("total written = %d bytes = %d KiB\n", totalwritten, totalwritten/1024); /* pipe buffer */
  return 0;
}

# Pipes in UNIX CLI

A pipe can be constructed on the UNIX command line using the | character. The complete command is ls | less

The commands ls and less are running as individual processes. The output of ls is delivered as the input to less.

这里的 shell 和 ls 之间、ls 和 less 之间都是普通管道通信

# Windows 实现

c
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define BUFFER SIZE 25
int main(VOID)
{
  HANDLE ReadHandle, WriteHandle;
  STARTUPINFO si;
  PROCESS INFORMATION pi;
  char message[BUFFER SIZE] = "Greetings";
  DWORD written;
  /* Program continues in Figure 3.24 */
  /* set up security attributes allowing pipes to be inherited */
  SECURITY ATTRIBUTES sa = {sizeof(SECURITY ATTRIBUTES),NULL,TRUE};
  /* allocate memory */
  ZeroMemory(&pi, sizeof(pi));
  /* create the pipe */
  if (!CreatePipe(&ReadHandle, &WriteHandle, &sa, 0)) {
    fprintf(stderr, "Create Pipe Failed");
    return 1;
  }
  /* establish the START INFO structure for the child process */
  GetStartupInfo(&si);
  si.hStdOutput = GetStdHandle(STD OUTPUT HANDLE);
  /* redirect standard input to the read end of the pipe */
  si.hStdInput = ReadHandle;
  si.dwFlags = STARTF USESTDHANDLES;
  /* don’t allow the child to inherit the write end of pipe */
  SetHandleInformation(WriteHandle, HANDLE FLAG INHERIT, 0);
  /* create the child process */
  CreateProcess(NULL, "child.exe", NULL, NULL,
                TRUE, /* inherit handles */
                0, NULL, NULL, &si, &pi);
  /* close the unused end of the pipe */
  CloseHandle(ReadHandle);
  /* the parent writes to the pipe */
  if (!WriteFile(WriteHandle, message,BUFFER SIZE,&written,NULL))
  	fprintf(stderr, "Error writing to pipe.");
  /* close the write end of the pipe */
  CloseHandle(WriteHandle);
  /* wait for the child to exit */
  WaitForSingleObject(pi.hProcess, INFINITE);
  CloseHandle(pi.hProcess);
  CloseHandle(pi.hThread);
  return 0;
}

# 客户机 - 服务器系统中的通信

  • 套接字(Socket)
  • 远程过程调用(RPC)

# 套间字 (Socket)

套接字被定义为通信的端点,是很多协议的底层实现方式,通信由一对套接字组成

IP 地址和端口的串联–包含在消息包开头的数字,用于区分主机上的网络服务;例如:套接字 161.25.19.8:1625 引用主机 161.25.19.8 上的端口 1625 ;

  • 1024 以下的所有端口都是相对固定的,用于标准服务;
  • 特殊 IP 地址 127.0.0.1 (环回),用于表示正在运行进程的系统;

三种类型的套接字

  • 面向连接(TCP)
  • 无连接(UDP)
  • Multicast Socket 类:数据可以发送到多个收件人

# 远程过程调用 (RPC)

远程过程调用(RPC)是抽象网络系统上进程之间的过程调用,也使用端口进行服务区分

Stubs(桩函数)—— 服务器上实际过程的客户端代理,提供封装好的调用接口:

  • 客户端存根定位服务器并封送参数
  • 服务器端存根接收此消息,解压缩封送的参数,并在服务器上执行该过程

通过外部数据表示(XDL)格式处理数据表示,以考虑不同的体系结构,例如大端和小端;

远程通信比本地通信有更多的故障场景,消息可以只传递一次,而不是最多一次

操作系统通常提供会合(或配对)服务来连接客户端和服务器

在 Windows 上,存根代码根据用 Microsoft 接口定义语言(MIDL)编写的规范编译

远程过程调用

# DCE RPC

参考:Distributed Computing Environment ,OSF(开放软件基金会)下的一个软件系统框架(慢慢消亡)

DCE 的构成:

  • 远程过程调用 DCE/RPC;
  • 命名 / 目录服务;
  • 时间服务;
  • 安全服务;
  • 分布式文件系统 DCE/DFS;

目前 Linux 标配 RPC

# 进程调度

Process scheduler 从可用进程中选择下一个在 CPU 核心上执行的进程

目标 —— 最大限度地利用 CPU,快速将进程切换到 CPU 核心

维护进程的调度队列

  • 就绪队列 (ready queue)—— 驻留在主内存中、就绪并等待执行的所有进程的集合
  • 等待队列 (wait queue)—— 等待事件(即 I/O)的一组进程
    • I/O wait queue
    • child termination wait queue
    • interrupt wait queue
  • 进程在各种队列之间迁移
Edited on Views times
\ No newline at end of file +进程 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 进程的基本概念

# 进程的定义

典型的定义:

  • 进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位 ==
  • 一个具有独立功能的程序在一个数据集合上运行的过程

# 区分进程程序进程实体

  • 程序(Program):是静态的,就是个存放在磁盘里的可执行文件,就是一系列的指令集合

    • 静态连接
    • 动态链接
  • 进程(Process):是动态的,是程序的一次执行过程

  • 进程实体(进程映像):是静态的,反应了进程在某一时刻的状态

# 进程实体的组成

一个 == 进程实体(进程映像)== 由三个部分组成:

  • PCB
    • 进程描述信息
    • 进程控制和管理信息
    • 资源分配清单
    • 处理机状态信息(CPU 上下文
  • 程序段
    • 程序的代码(指令序列)
  • 数据段
    • 运行过程中产生的各种数据(如:程序中定义的变量)

PCB 是给操作系统用的;程序段、数据段是给进程自己用的,与进程自身的运行逻辑有关

# PCB

PCB 位于内存的内核空间里,创建之后常驻内存。

PCB 是进程存在的唯一标志,当进程被创建时,操作系统为其创建 PCB,当进程结束时,会会回收其 PCB。

PCB 几乎完备的表示了进程的状态,也就是说只要有一个进程的 PCB,就可以恢复对应的进程

# PCB 的结构

  • 进程描述信息

    • 进程标识符 PID
    • 用户标识符 UID
  • 进程控制和管理信息

    • CPU、磁盘、网络流量使用情况统计⋯
      • 进入内存时间
      • CPU 占用时间
      • 信号量使用
    • 进程当前状态:就绪态 / 阻塞态 / 运行态
    • 代码运行入口地址
    • 程序的外存地址
    • 程序优先级
  • 资源分配清单

    • 正在使用(依赖)哪些文件
      • 文件描述符
    • 正在使用哪些内存区域
      • 代码段指针
      • 数据段指针
      • 堆栈段指针
    • 正在使用哪些 I/O 设备
  • 处理机相关信息,也叫 CPU 的上下文(the context of the processor)

    • user-visible registers
    • control and status registers (CSR)
    • stack pointers
    • PSW
      • eg: EFLAGS in x86

# Linux 的 PCB

Linux 中的进程控制块 PCB 源码位于 linux-x.xx.xx/include/linux/sched.h

Linux 不区分进程和线程,将它们都视为 task

由 C 结构 task_struct 表示:

c
{
  pid t_pid;/* 进程标识符 */
  unsigned int time_slice /* 调度信息 */
  struct task_struct* 父进程;/* 此进程的父级 */
  struct list_head children;/* 此进程的子进程 */
  struct *files;/* 打开文件列表 */
  struct mm_struct*mm;/* 此进程的地址空间 */
  ...
}

task_struct

# 进程的特征

  • 动态性 —— 进程是程序的一次执行过程,是动态地产生、变化和消亡的(动态性是进程最基本的特征)
  • 并发性 —— 内存中有多个进程实体,各进程可并发执行
  • 独立性 —— 进程是能独立运行、独立获得资源、独立接受调度的基本单位
  • 异步性 —— 各进程按各自独立的、不可预知的速度向前推进,操作系统要提供 “进程同步机制 " 来解决异步问题
  • 结构性 —— 每个进程都会配置一个 PCB。结构上看,进程由程序段、数据段、PCB 组成

# 进程的状态与转换

The steps in a full process switch are:

  1. save the context of the processor
  2. update the PCB of the process currently in the Running state
  3. move the PCB of this process to the appropriate queue
  4. select another process for execution
  5. update the PCB of the process selected
  6. update memory management data structures
  7. restore the context of the processor to that which existed at the time the selected process was last switched out

# 五状态模型

五状态模型

# 七状态模型

增加了挂起状态的进程


挂起进程的特征:

  • 进程不能立即执行(上处理机)

  • 进程可能有也可能么有等待一个事件(为什么那么像废话)

  • 为阻止该进程执行,可通过代理使其处于挂起状态;代理可以是:

    • 进程本身

    • 父进程

    • 操作系统

  • 只有代理程序显示地命令操作系统进行状态轮换,才能使该进程从挂起的状态转移


进程挂起的原因:

  • Swaping
  • Other OS reason
  • Interactive user request
  • Timing
  • Parent pocess request

双挂起状态的进程模型:

七状态模型

# 进程组织

进程组织的数据结构

# 链接式组织进程

链式组织进程

# 索引式组织进程

索引式组织进程

# 进程控制

也就是对进程的操作,这些基本操作几乎全部都是系统调用实现的

# 系统调用

Some basic and important system calls

PCB 的访问:

getpid()

  • fork()
  • exec*()
  • wait()
  • exit()

# Linux 举例

父进程创建子进程,子进程又创建其他进程,形成进程树;父子之间不同角度可能有不同关系:

  • 资源共享
    • 父和子共享所有资源 (Linux 中父进程 vfork )
    • 子进程共享父进程资源的子集 (Linux 中父进程 vfork )
    • 父进程和子进程不共享任何资源 (Linux 中父进程 fork )
  • 执行
    • 父进程和子进程同时并发执行
    • 父进程等待直到子进程终止 (Linux 中父进程 wait(0) )
  • 地址空间
    • 子进程是父进程的复制品 (Linux 中父进程 fork )
    • 子进程加载另一个新的程序
    • 子进程完全覆盖父进程 (Linux 中父进程 fork + exec )
      • exec family 有 6 个成员
      • execl 装载新的文件

# fork

Linux 中,由父进程调用系统调用 fork() 创建子进程

c
#include<stdio.h>
#include<unistd.h>
int main (){
  for(int i=0;i<4;++i){
    fork();
  }
	printf("This is a test printed by %d\n", getpid());
return 0;
}

编译运行上述程序将打印出 16 次!因为这里子进程是父进程的复制品:

shell
node1@vm1:~/Desktop$ gcc -o test test.c
node1@vm1:~/Desktop$ ./test
This is a test printed by 139377
This is a test printed by 139382
This is a test printed by 139380
This is a test printed by 139379
This is a test printed by 139378
This is a test printed by 139383
node1@vm1:~/Desktop$ This is a test printed by 139381 # 父进程结束
This is a test printed by 139386
This is a test printed by 139387
This is a test printed by 139385
This is a test printed by 139388
This is a test printed by 139389
This is a test printed by 139384
This is a test printed by 139390
This is a test printed by 139391
This is a test printed by 139392

fork 会克隆的内容:

Cloned itemsDescriptions
Program code [File & Memory]They are sharing the same piece of code.
MemoryIncluding local variables, global variables, and dynamically allocated memory.
Opened files [Kernel's internal]If the parent has opened a file "A", then the child will also have file "A" opened automatically.
Program counter [CPU register]That's why they both execute from the same line of code after fork() returns.

fork 不克隆的内容:

Distinct itemsParentChild
Return value of fork() PID of the child process.0
PIDUnchanged.Different, not necessarily be "Parent PID + 1"
Parent processUnchanged.Doesn't have the same parent as that of the parent process.
Running timeCumulated.Just created, so should be 0.

vfork 函数是 fork 函数基础上的修正, fork 函数创建一个完全分离的进程,而 vfork 用于创建一个共享的进程,没有克隆操作,这意味着父进程子进程可以互相看到对方,共享同样的物理地址

# exec*

exec* 系统调用,会 “鸠占鹊巢”,替换掉原进程的代码,但是 PID、父子关系、进程运行时间都不变,也就是:

  • 内核里的内容不变,包括 PCB 等
  • 用户态里的代码被替换
c
#include<stdio.h>
#include<unistd.h>
int main(void) {
	printf("before execl ...\n"); // 原进程代码可以执行
	execl("/bin/ls", "/bin/ls", NULL); //exec 的一个成员函数
	printf("after execl ...\n"); // 原进程代码无法执行
	return 0;
}

编译执行结果:

shell
node1@vm2:~/Desktop$ gcc -o test test.c
node1@vm2:~/Desktop$ ./test
before execl ...
sdb  stack_rwx.c  test  test01  test.c  ysos

# waitwaitpid

wait()waitpid()
Wait for any one of the children.Depending on the parameters, waitpid() will wait for a particular child only.
Detect child termination only.Depending on the parameters, waitpid() can detect child's status changing: -from running to suspended, and -from suspended to running.

# fork + exec*

执行顺序是不确定的

c
#include<stdio.h>
#include<unistd.h>
int system_test(const char *cmd_str) {
    if(cmd_str == -1)
        return -1;
    if(fork() == 0) {
        execl(cmd_str, cmd_str, NULL);
        fprintf(stderr,"%s: command not found\n", cmd_str);
        exit(-1);
    }
    return 0;
}
int main(void) {
    printf("before...\n\n");
    system_test("/bin/ls");
    printf("\nafter...\n");
    return 0;
}

编译执行结果:

shell
node1@vm2:~/Desktop$ gcc -o test test.c
node1@vm2:~/Desktop$ ./test
before...
after...
sdb  stack_rwx.c  test  test01  test.c  ysos # 执行 ls

类似于一个 shell 或 system ,不过 system 创建子进程,时串行执行,执行顺序是确定的。

# fork + exec* + wait

等价于 system

c
#include<stdio.h>
#include<unistd.h>
int system_test(const char *cmd_str) {
    if (cmd_str == -1)
        return -1;
    if(fork() == 0) {
        execl("/bin/sh", "/bin/sh","-c", cmd_str, NULL);
        fprintf(stderr,"%s: command not found\n", cmd_str);
        exit(-1);
    }
    wait(NULL);
    return 0;
}
int main(void) {
    printf ("before...\n\n"); system_test("/bin/1s");
    printf("\nafter...\n");
    return 0;
}

编译执行结果:

shell
node1@vm2:~/Desktop$ gcc -o test test.c
node1@vm2:~/Desktop$ ./test
before...
sdb  stack_rwx.c  test  test01  test.c  ysos
after...

# exit

父进程 wait 和子进程 exit 搭配食用。子进程执行最后一条语句,然后调用 exit 系统调用请求操作系统删除它自己,然后子进程将发送 SIGCHLD 给父进程,并变僵尸进程;父进程接收到 SIGCHLD 后被唤醒(原本被 wait 休眠),处理 SIGCHLD 之后,子进程才被彻底销毁。

c
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main(void){
    int count = 1;
    pid_t childpid, terminatedid;
    childpid = fork(); /* child duplicates parent’s address space */
    if (childpid < 0) {
        perror("fork()");
        return EXIT_FAILURE;
    }
    else if (childpid == 0) { /* This is child pro */
        count++;
        printf("child pro pid = %d, count = %d (addr = %p)\n", getpid(), count, &count);
        printf("child sleeping ...\n");
        sleep(5); /* parent wait() during this period */
        printf("\nchild waking up!\n");
    }
    else { /* This is parent pro */
        terminatedid = wait(0);
        printf("parent pro pid = %d, terminated pid = %d, count = %d (addr = %p)\n",
        getpid(), terminatedid, count, &count);
    }
    printf("\nTesting point by %d\n", getpid()); /* executed by child and parent */
    return EXIT_SUCCESS;
}

编译运行结果:

shell
node1@vm2:~/Desktop$ ./test
child pro pid = 197382, count = 2 (addr = 0x7ffc33c444cc)
child sleeping ...
# 这里等待了 5 秒钟
child waking up!
Testing point by 197382
parent pro pid = 197381, terminated pid = 197382, count = 1 (addr = 0x7ffc33c444cc)
Testing point by 197381

僵尸进程:空有 PCB “外壳”,但是没有用户态的代码,无法执行;

注意区分孤儿进程

# abort

父进程可以使用 abort 系统调用终止子进程的执行。这样做的一些原因:

  • 子进程已超出分配的资源
  • 不再需要分配给子进程的任务
  • 父进程正在退出,如果父进程终止,操作系统不允许子进程继续

# 进程控制原语

进程控制由原语实现

如果不能像原语 “一气呵成”,就有可能导致操作系统中的某些关键数据结构信息不统一的情况,这会影响操作系统进行别的管理工作

原语的执行具有原子性,即执行过程只能一气呵成,期间不允许被中断。

可以用 “关中断指令”“开中断指令” 这两个特权指令实现原子性

无论哪个进程控制原语,要做的无非三类事情:

  • 更新 PCB 中的信息
    • 修改进程状态(state)
    • 保存 / 恢复运行环境
  • 将 PCB 插入合适的队列
  • 分配 / 回收资源

# 创建

  • 申请空白 PCB
  • 为新进程分配所需资源
  • 初始化 PCB
  • 将 PCB 插入就绪队列(进程由阻塞态转变为就绪态

引起进程创建的事件可能有:

  • 用户登录 —— 分时系统中,用户登录成功,系统会建立为其建立一个新的进程
  • 作业调度 —— 多道批处理系统中,有新的作业放入内存时,会为其建立一个新的进程
  • 提供服务 —— 用户向操作系统提出某些请求时,会新建一个进程处理该请求
  • 应用请求 —— 由用户进程主动请求创建一个子进程

所有进程都是以父进程创建子进程的方式创建的:

  • 有些是显式的
    • 用户进程创建的
  • 有些是隐式的
    • 操作系统 “0 号” 根进程创建的(所有进程的祖先)

# 根进程

The first process -- The kernel, while it is booting up, creates the firstprocess -- init .

The init process:

  • has PID = 1
  • and is running the program code “/sbin/init”.
  • Its first task is to create more processes…

# 孤儿进程

父进程创建子进程一层一层创建,但若其中某一个父进程 terminate 了,也就是被终止了,那么被终止进程所创建的进程就变成了孤儿进程。孤儿进程会消耗资源,需要被重新管理起来。

  • Linux 中,使用 re-parent operation 处理孤儿进程, The “init” process will become the step-mother of all orphans.
  • Windows maintains a forest-like hierarchy.

# 撤销

这一过程进程: 就绪态 / 阻塞态 / 运行态 -> 终止态 -> 无

  • 从 PCB 集合中找到终止进程的 PCB
  • 若进程正在运行,立即剥夺 CPU,将 CPU 分配给其他进程
  • 终止其所有子进程
  • 将该进程拥有的所有资源归还给父进程或操作系统
  • 删除 PCB

引起进程终止的事件可能有:

  • 正常结束 —— 进程自己请求终止(exit 系统调用)
  • 异常结束 —— 被操作系统强行杀掉
    • 整数除以 O
    • 非法使用特权指令
  • 外界干预 —— 用户选择杀掉进程
    • Ctrl+Alt+delete
    • kill pid

# 阻塞

  • 找到要阻塞的进程对应的 PCB
  • 保护进程运行现场,将 PCB 状态信息设置为 “阻塞态 ",暂时停止进程运行
  • 将 PCB 插入相应事件的等待队列

引起进程阻塞的事件可能有:

  • 需要等待系统分配某种资源
  • 需要等待相互合作的其他进程完成工作

# 唤醒

  • 在事件等待队列中找到 PCB
  • 将 PCB 从等待队列移除,设置进程为就绪态
  • 将 PCB 插入就绪队列,等待被调度

引起进程唤醒的事件可能有:

  • 等待的事件发生

# 切换

  • 将运行环境信息存入 PCB
  • PCB 移入相应队列
  • 选择另一个进程执行,并更新其 PCB
  • 根据 PCB 恢复新进程所需的运行环境

系统切换:

系统切换

引起进程切换的事件可能有:

  • 当前进程时间片到
  • 有更高优先级的进程到达
  • 当前进程主动阻塞
  • 当前进程终止

# 进程通信

进程间通信(Inter-Process Communication, IPC)是指两个进程之间产生数据交互。

⚠️为什么需要进程通信:

  • 进程是分配系统资源的单位(包括内存地址空间),因此各进程拥有的内存地址空间相互独立
  • 为了保证安全,一个进程不能直接访问另一个进程的地址空间
  • 多核处理器系统中,消息传递优于共享内存,因为没有 cache 的一致性问题

Linux 的 IPC 限制信息可在 /etc/sysctl.conf 中查看

ipcs 可以查看当前操作系统里有多少消息队列、共享内存块、信号量

  • 低级通信
    • 共享文件,信号量 PV 操作
  • 高级通信 —— 以较高的效率传输大量数据
    • 共享内存
    • 消息传递
    • 管道通信

# 共享存储

为避免出错,各个进程对共享空间的访问应该是互斥

# 基于存储区共享

操作系统在内存中划出一块共享存储区,数据的形式、存放位置都由通信进程控制,而不是操作系统。这种共享方式速度很快,是一种高级通信方式

通过 “增加页表项 / 段表项” 即可将同一片共享内存区映射到各个进程的地址空间中

# Linux 共享内存

c
//shm 即 share memory 的缩写
int shm_open (...);
// 通过 shm_open 系统调用,申请一片共享内存区
void * mmap (...);
// 通过 mmap 系统调用,将共享内存区映射到进程自己的地址空间
# Key ID
c
#include <sys/shm.h>
key_t ftok(const char *pathname, int id);
/* key_t is of type int. ftok() convert a pathname and a project identifie
to an IPC key */
key_t key = ftok(/home/myshm", 0x27);
if((key == -1) {
	perror(ftok()");
} else
	printf("key = 0x%x\n", key);
# Create
c
int shmget(key_t key, int size, int shmflg);
/* shmget() allocates a shared memory segment */
/* upper bound of size: 1.9G */
int shmid = shmget(IPC_PRIVATE, 4096, IPC_CREATE|IPC_EXCL|0660);
if(shmid == -1) {
  perror("shmget()");
}

# 基于数据结构的共享

比如共享空间里只能放一个长度为 10 的数组。这种共享方式速度慢限制多,是一种低级通信方式

# 消息传递

进程间的数据交换以格式化的消息(Message)单位。进程通过操作系统提供的两个原语进行数据交换:

  • 发送原语, send(X, msg) ,X 是发送目标
  • 接收消息, receive(X, &msg) ,X 是从哪里接收

格式化的消息(Message)的结构:

  • 消息头
    • 发送进程 ID
    • 接受进程 ID
    • 消息长度等格式化的信息
  • 消息体

# 直接通信方式

P 传递消息给 Q 的过程:

  • P 发送原语 send(Q, msg)
    • msg 数据被封装为格式化消息
    • 格式化消息被从 P 的地址空间转移到操作系统内核的地址空间中进程 Q 的消息队列
  • Q 接收原语 receive(P, &msg)
    • 格式化消息被从操作系统内核的地址空间中进程 Q 的消息队列转移到 Q 的地址空间
    • 解析格式化的消息

特性:

  • 链接是自动建立的
  • 链路仅与一对通信进程相关联
  • 每对之间只存在一个链接
  • 链路可能是单向的,但通常是双向的

这种通信方式展示了寻址的对称性,即发送和接收进程必须指定对方,以便通信。

也可以采用寻址的非对称性,即只要发送者指定接收者,而接收者不需要指定发送者

# 间接通信方式

以 “信箱”(或某些特定的端口)作为中间实体进行消息传递,可以多个进程往同一个信箱 send 消息,也可以多个进程从同一个信箱中 receive 消息;

每个邮箱都有一个唯一的 id ,进程只有在共享邮箱时才能通信;

允许链接最多与两个进程关联

一次只允许一个进程执行接收操作

允许系统任意选择接收器。通知发送方接收者是谁。

间接通信

P 传递消息给 Q 的过程:

  • (创建邮箱)
  • P 发送原语 send(A, msg) ,发送给信箱 A
    • msg 数据被封装为格式化消息
    • 格式化消息被从 P 的地址空间转移到操作系统内核的地址空间中信箱 A 中
  • Q 接收原语 receive(A, &msg) ,从信箱 A 接收消息
    • 格式化消息被从操作系统内核的地址空间中信箱 A 转移到 Q 的地址空间
    • 解析格式化的消息
  • (删除邮箱)

特性:

  • 仅当进程共享公共邮箱时才建立链接
  • 链接可能与许多进程相关联
  • 每对进程可以共享多个通信链路
  • 链路可以是单向的或双向的

邮箱所有者:

  • 邮箱可以被进程拥有;
  • 邮箱被操作系统拥有;
  • 邮箱可以转移

# 同步 / 异步

消息传递可以是阻塞的,也可以是非阻塞的

  • 阻塞被认为是同步的
    • 阻塞发送 — 在接收进程或者邮箱收到消息之前,发送进程阻塞;
    • Blocking receive(阻塞接收)—— 在消息可用之前,接收进程将被阻塞
  • 非阻塞被认为是异步的
    • 非阻塞发送 —— 发送进程发送消息并继续执行;
    • 非阻塞接收 —— 接收进程接收:
      • 有效消息
      • 或空消息
  • 可能有不同的组合
    • 如果发送和接收都是阻塞的,双方之间有一个交会。

与其他课程的阻塞、同步异步关系可能不太一样

# 缓存

附加到链接的消息队列,不管通信是直接还是间接的;以三种方式之一实现队列:

  • 1. 零容量–链路上没有消息排队。发送方必须等待接收方
  • 2. 有限容量–有限长度的 n 条消息,如果链路已满,则发送者必须等待
  • 3. 无限容量–无限长,发送方从不等待

# Linux 接口实现

msgdata.h

c
#define TEXT_SIZE 512
/* considering
------ Messages Limits --------
max queues system wide = 32000
max size of message (bytes) = 8192
default max size of queue (bytes) = 16384
------------------------------------------
The size of message is set to be 512, the total number of messages is 16384/512 = 32
If we take the max size 8192, the number would be 16384/8192 = 2. It is not reasonable
*/
/* message structure */
struct msg_struct {
long int msg_type;
char mtext[TEXT_SIZE]; /* binary data */
};
#define PERM S_IRUSR|S_IWUSR|IPC_CREAT
#define ERR_EXIT(m) \
  do { \
    perror(m); \
    exit(EXIT_FAILURE); \
  } while(0)

msgsnd.c

c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "msgdata.h"
int main(int argc, char *argv[])
{
  struct msg_struct data;
  long int msg_type;
  char buffer[TEXT_SIZE], pathname[80];
  int msqid, ret, count = 0;
  key_t key;
  FILE *fp;
  struct stat fileattr;
  if(argc < 2) {
    printf("Usage: ./a.out pathname\n");
    return EXIT_FAILURE;
  }
  strcpy(pathname, argv[1]);
  if(stat(pathname, &fileattr) == -1) {
    ret = creat(pathname, O_RDWR);
    if (ret == -1) {
    	ERR_EXIT("creat()");
    }
    printf("shared file object created\n");
  }
  key = ftok(pathname, 0x27); /* project_id can be any nonzero integer */
  if(key < 0) {
  	ERR_EXIT("ftok()");
  }
  printf("\nIPC key = 0x%x\n", key);
  msqid = msgget((key_t)key, 0666 | IPC_CREAT);
  if(msqid == -1) {
  	ERR_EXIT("msgget()");
  }
  fp = fopen("./msgsnd.txt", "rb");
  if(!fp) {
  	ERR_EXIT("source data file: ./msgsnd.txt fopen()");
  }
  struct msqid_ds msqattr;
  ret = msgctl(msqid, IPC_STAT, &msqattr);
  printf("number of messages remainded = %ld, empty slots = %ld\n",
  msqattr.msg_qnum, 16384/TEXT_SIZE-msqattr.msg_qnum);
  printf("Blocking Sending ... \n");
  while (!feof(fp)) {
    ret = fscanf(fp, "%ld %s", &msg_type, buffer);
    if (ret == EOF) break;
    printf("%ld %s\n", msg_type, buffer);
    data.msg_type = msg_type;
    strcpy(data.mtext, buffer);
    ret = msgsnd(msqid, (void *)&data, TEXT_SIZE, 0);
    /* 0: blocking send, waiting when msg queue is full */
    if(ret == -1) {
    	ERR_EXIT("msgsnd()");
    }
    count++;
  }
  printf("number of sent messages = %d\n", count);
  fclose(fp);
  system("ipcs -q");
  exit(EXIT_SUCCESS);
}

msgrcv.c

c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include "msgdata.h"
int main(int argc, char *argv[])
{
  key_t key;
  struct stat fileattr;
  char pathname[80];
  int msqid, ret, count = 0;
  struct msg_struct data;
  long int msgtype = 0; /* 0 - type of any messages */
  if(argc < 2) {
    printf("Usage: ./msgrcv pathname msg_type\n");
    return EXIT_FAILURE;
  }
  strcpy(pathname, argv[1]);
  if(stat(pathname, &fileattr) == -1) {
  	ERR_EXIT("shared file object stat error");
  }
  if((key = ftok(pathname, 0x27)) < 0) {
  	ERR_EXIT("ftok()");
  }
  printf("\nIPC key = 0x%x\n", key);
  msqid = msgget((key_t)key, 0666); /* do not create a new msg queue */
  if(msqid == -1) {
  	ERR_EXIT("msgget()");
  }
  if(argc < 3)
  	msgtype = 0;
  else {
  	msgtype = atol(argv[2]);
  	if (msgtype < 0)
 			msgtype = 0;
  } /* determin msgtype (class number) */
  printf("Selected message type = %ld\n", msgtype);
  while (1) {
    ret = msgrcv(msqid, (void *)&data, TEXT_SIZE, msgtype, IPC_NOWAIT);
    /* Non_blocking receive */
    if(ret == -1) { /* end of this msgtype */
      printf("number of received messages = %d\n", count);
      break;
    }
    printf("%ld %s\n", data.msg_type, data.mtext);
    count++;
  }
  struct msqid_ds msqattr;
  ret = msgctl(msqid, IPC_STAT, &msqattr);
  printf("number of messages remainding = %ld\n", msqattr.msg_qnum);
  if(msqattr.msg_qnum == 0) {
  	printf("do you want to delete this msg queue?(y/n)");
  if (getchar() == 'y') {
    if(msgctl(msqid, IPC_RMID, 0) == -1)
    	perror("msgctl(IPC_RMID)");
    }
  }
  system("ipcs -q");
  exit(EXIT_SUCCESS);
}

# POSIX (pthread) 实现

c
#include <mqueue.h>
# Open, Close and Unlink
mqd_t mq_open(const char *name, int oflag, mode_t mode, struct mq_attr *attr ); /* return the mqdes, or -1 if failed */
mqd_t mqID;
mqID = mq_open("/anonymQueue", O_RDWR | O_CREAT, 0666, NULL);
mqd_t mq_close(mqd_t mqdes);
mqd_t mq_unlink(const char *name); /* return -1 if failed */
# Send and Receive
mqd_t mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio); /* return 0, or -1 if failed */
mq_send(mqID, msg, sizeof(msg), i)
mqd_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio); /* return the number of char received, or -1 if failed */
mq_attr mqAttr;
mq_getattr(mqID, &mqAttr);
mq_receive(mqID, buf, mqAttr.mq_msgsize, NULL)

Note that the Linux ipcs utility is not fully compatible to the POSIX ipcs utility. The message queues, shared memory and semaphores in POSIX can not be sensed by System V bash command such as ipcs -q

# Mach

Mach 作为微内核结构,其通信是基于消息传递的设计,甚至系统调用也是消息传递

  • 每个任务在创建时获得两个端口 - 内核和通知
  • 使用 mach_msg() 函数发送和接收消息
  • 通信所需的端口,通过创建 mach 端口分配
  • 收发灵活;例如,邮箱已满时有四个选项:
    • 无限期地等待
    • 最多等待 n 毫秒
    • 立即返回
    • 临时缓存消息

# Windows

通过高级本地过程调用(ALPC)设施以消息传递为中心,仅在同一系统上的两个进程之间工作,类似 RPC;

  • 使用端口(如邮箱)建立和维护通信通道;
  • 使用两种类型的端口:
    • 连接端口
    • 通信端口

通讯工作如下:

  • 客户端打开子系统连接端口对象的句柄;
  • 客户端发送一个连接请求;
  • 服务器创建一对专用通信端口,并将其中一个端口的句柄返回给客户端;
  • 客户端和服务器使用相应的端口句柄发送消息或回调,并监听回复;

windows消息传递

Windows 对不同大小的消息有不同的策略;When an ALPC channel is created, one of three message-passing techniques is chosen:

  1. For small messages (up to 256 bytes), the port’s message queue is used as intermediate storage, and the messages are copied from one process to the other.

  2. Larger messages must be passed through a section object, which is a region of shared memory associated with the channel.

  3. When the amount of data is too large to fit into a section object, an API is available that allows server processes to read and write directly into the address space of a client.

# 管道通信

“管道” 是一个特殊的共享文件,又名 pipe 文件。其实就是在内存中开辟一个大小固定的内存缓冲区

  • 普通管道 (匿名管道)—— 无法从创建它的进程外部访问。通常,父进程创建管道并使用它与它创建的子进程通信。是单向的、半双工的。
    普通管道
  • 命名管道 —— 可以在没有父子关系的情况下访问。是双向的全双工的。

管道通信的规则、限制:

  • 管道只能采用半双工通信,某一时间段内只能实现单向的传输。
  • 如果要实现双向同时通信,则需要设置两个管道。
  • 各进程要互斥地访问管道(由操作系统实现)
  • 当管道写满时,写进程阻塞,直到读进程将管道中的数据取走,即可唤醒写进程。
  • 当管道读空时,读进程阻塞,直到写进程往管道中写入数据,即可唤醒读进程。
  • 管道中的数据一旦被读出,就彻底消失。因此,当多个进程读同一个管道时,可能会错乱。对此,通常有两种解决方案:
    • 一个管道允许多个写进程一个读进程(2014 年 408 真题高教社官方答案);
    • 允许有多个写进程多个读进程,但系统会让各个读进程轮流从管道中读数据(Linux 的方案)。

管道通信

写进程往管道写数据,即便管道没被写满,只要管道没空,读进程就可以从管道读数据

读进程从管道读数据,即便管道没被读空,只要管道没满,写进程就可以往管道写数据

# Linux 实现

c
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define BUFFER SIZE 25
#define READ END 0
#define WRITE END 1
int main(void)
{
  char write msg[BUFFER SIZE] = "Greetings";
  char read msg[BUFFER SIZE];
  int fd[2];
  pid t pid;
  /* Program continues in Figure 3.22 */
  /* create the pipe */
  if (pipe(fd) == -1) {
    fprintf(stderr,"Pipe failed");
    return 1;
  }
  /* fork a child process */
  pid = fork();
  if (pid < 0) { /* error occurred */
    fprintf(stderr, "Fork Failed");
    return 1;
  }
  if (pid > 0) { /* parent process */
    /* close the unused end of the pipe */
    close(fd[READ END]);
    /* write to the pipe */
    write(fd[WRITE END], write msg, strlen(write msg)+1);
    /* close the write end of the pipe */
    close(fd[WRITE END]);
  }
  else { /* child process */
    /* close the unused end of the pipe */
    close(fd[WRITE END]);
    /* read from the pipe */
    read(fd[READ END], read msg, BUFFER SIZE);
    printf("read %s",read msg);
    /* close the read end of the pipe */
    close(fd[READ END]);
  }
  return 0;
}

利用 libc 创建、操作管道:

c
// 普通管道
int pipefd[2];
int pipe(int pipefd);
int fcntl(int pipefd[0|1], int cmd);
int fcntl(int pipefd[0|1], int cmd, long arg);
ssize_t write(int pipefd[1], void* buf, size_t count);
ssize_t read(int pipefd[0], void* buf, size_t count);
close(pipefd[0]);
close(pipefd[1]);
// 命名管道
#define FIFO pathname /* pathname: "/tmp/my_fifo" */
unlink(FIFO); /*delete a name and possibly the file it refers to */
mkfifo(FIFO, 0666);
int fdw = open(FIFO, O_RDWR);
mkfifo(FIFO, 0444);
int fdr = open(FIFO, O_RDONLY);
ssize_t write(int fdw, void* buf, size_t count);
/* ssizt_t = signed int, sizt_t = unsigned int */
ssize_t read(int fdr, void* buf, size_t count);
close(fdw);
close(fdr);

管道缓冲

c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#define ERR_EXIT(m) \
  do { \
    perror(m); \
    exit(EXIT_FAILURE); \
  } while (0)
int main(int argc, char *argv[])
{
  int pipefd[2];
  int bufsize;
  char *buffer;
  int flags, ret, lastwritten, count, totalwritten;
  if(pipe(pipefd) == -1) /* create an ordinary pipe */
  	ERR_EXIT("pipe()");
  flags = fcntl(pipefd[1], F_GETFL);
  fcntl(pipefd[1], F_SETFL, flags | O_NONBLOCK); /* set write_end NONBLOCK */
  bufsize = atoi(argv[1]);
  printf("testing buffer size = %d\n", bufsize);
  buffer = (char *)malloc(bufsize*sizeof(char));
  if(buffer == NULL || bufsize == 0)
  	ERR_EXIT("malloc()");
  count = 0;
  while (1) {
    ret = write(pipefd[1], buffer, bufsize);
    /* bufsize is better to be 2^k */
    if(ret == -1) {
      perror("write()");
      break;
    }
    lastwritten = ret;
    count++;
  }
  totalwritten = (count-1)*bufsize +
  lastwritten;
  printf("single pipe buffer count = %d, last written = %d bytes\n", count, lastwritten);
  printf("total written = %d bytes = %d KiB\n", totalwritten, totalwritten/1024); /* pipe buffer */
  return 0;
}

# Pipes in UNIX CLI

A pipe can be constructed on the UNIX command line using the | character. The complete command is ls | less

The commands ls and less are running as individual processes. The output of ls is delivered as the input to less.

这里的 shell 和 ls 之间、ls 和 less 之间都是普通管道通信

# Windows 实现

c
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define BUFFER SIZE 25
int main(VOID)
{
  HANDLE ReadHandle, WriteHandle;
  STARTUPINFO si;
  PROCESS INFORMATION pi;
  char message[BUFFER SIZE] = "Greetings";
  DWORD written;
  /* Program continues in Figure 3.24 */
  /* set up security attributes allowing pipes to be inherited */
  SECURITY ATTRIBUTES sa = {sizeof(SECURITY ATTRIBUTES),NULL,TRUE};
  /* allocate memory */
  ZeroMemory(&pi, sizeof(pi));
  /* create the pipe */
  if (!CreatePipe(&ReadHandle, &WriteHandle, &sa, 0)) {
    fprintf(stderr, "Create Pipe Failed");
    return 1;
  }
  /* establish the START INFO structure for the child process */
  GetStartupInfo(&si);
  si.hStdOutput = GetStdHandle(STD OUTPUT HANDLE);
  /* redirect standard input to the read end of the pipe */
  si.hStdInput = ReadHandle;
  si.dwFlags = STARTF USESTDHANDLES;
  /* don’t allow the child to inherit the write end of pipe */
  SetHandleInformation(WriteHandle, HANDLE FLAG INHERIT, 0);
  /* create the child process */
  CreateProcess(NULL, "child.exe", NULL, NULL,
                TRUE, /* inherit handles */
                0, NULL, NULL, &si, &pi);
  /* close the unused end of the pipe */
  CloseHandle(ReadHandle);
  /* the parent writes to the pipe */
  if (!WriteFile(WriteHandle, message,BUFFER SIZE,&written,NULL))
  	fprintf(stderr, "Error writing to pipe.");
  /* close the write end of the pipe */
  CloseHandle(WriteHandle);
  /* wait for the child to exit */
  WaitForSingleObject(pi.hProcess, INFINITE);
  CloseHandle(pi.hProcess);
  CloseHandle(pi.hThread);
  return 0;
}

# 客户机 - 服务器系统中的通信

  • 套接字(Socket)
  • 远程过程调用(RPC)

# 套间字 (Socket)

套接字被定义为通信的端点,是很多协议的底层实现方式,通信由一对套接字组成

IP 地址和端口的串联–包含在消息包开头的数字,用于区分主机上的网络服务;例如:套接字 161.25.19.8:1625 引用主机 161.25.19.8 上的端口 1625 ;

  • 1024 以下的所有端口都是相对固定的,用于标准服务;
  • 特殊 IP 地址 127.0.0.1 (环回),用于表示正在运行进程的系统;

三种类型的套接字

  • 面向连接(TCP)
  • 无连接(UDP)
  • Multicast Socket 类:数据可以发送到多个收件人

# 远程过程调用 (RPC)

远程过程调用(RPC)是抽象网络系统上进程之间的过程调用,也使用端口进行服务区分

Stubs(桩函数)—— 服务器上实际过程的客户端代理,提供封装好的调用接口:

  • 客户端存根定位服务器并封送参数
  • 服务器端存根接收此消息,解压缩封送的参数,并在服务器上执行该过程

通过外部数据表示(XDL)格式处理数据表示,以考虑不同的体系结构,例如大端和小端;

远程通信比本地通信有更多的故障场景,消息可以只传递一次,而不是最多一次

操作系统通常提供会合(或配对)服务来连接客户端和服务器

在 Windows 上,存根代码根据用 Microsoft 接口定义语言(MIDL)编写的规范编译

远程过程调用

# DCE RPC

参考:Distributed Computing Environment ,OSF(开放软件基金会)下的一个软件系统框架(慢慢消亡)

DCE 的构成:

  • 远程过程调用 DCE/RPC;
  • 命名 / 目录服务;
  • 时间服务;
  • 安全服务;
  • 分布式文件系统 DCE/DFS;

目前 Linux 标配 RPC

# 进程调度

Process scheduler 从可用进程中选择下一个在 CPU 核心上执行的进程

目标 —— 最大限度地利用 CPU,快速将进程切换到 CPU 核心

维护进程的调度队列

  • 就绪队列 (ready queue)—— 驻留在主内存中、就绪并等待执行的所有进程的集合
  • 等待队列 (wait queue)—— 等待事件(即 I/O)的一组进程
    • I/O wait queue
    • child termination wait queue
    • interrupt wait queue
  • 进程在各种队列之间迁移
Edited on Views times
\ No newline at end of file diff --git a/cs/os/scheduling/index.html b/cs/os/scheduling/index.html index 3dab5ee0..b5b4bbee 100644 --- a/cs/os/scheduling/index.html +++ b/cs/os/scheduling/index.html @@ -1 +1 @@ -调度 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 调度相关概念

为什么需要调度?

释放被阻塞、挂起的进程占用的 CPU 资源

实现 I/O 操作和 CPU 并行执行( I/O 密集型和 CPU 密集型)


调度的层次、类型

  • 处理器 / CPU 调度⭐️(进程调度的主要内容)

    • 作业调度 /long-term scheduling / 长程调度 / 高级调度

      The decision to add to the pool of processes to be executed

    • 内存调度 /medium-term scheduling / 中程调度 / 中级调度

      The decision to add to the number of processes that are partially or fully in main memory

    • (狭义?) 进程调度 /short-term scheduling / 短程调度 / 初级调度

      The decision as to which available process will be executed by the processor

  • 微调度 —— CPU 内部的指令调度(计组的内容了)

  • I/O scheduling

    The decision as to which process's pending I/O request shall be handled by an available I/O device

# 三种层次进程调度

进程调度的层次

三种层次 CPU 进程调度频繁程度:长程 < 中程 < 短程

# 长程调度

控制了系统的并发度

创建的进程越多,每个进程的执行时间的百分比越小,系统并发度越高;

长程调度程序可能会限制系统的并发度,为了给当前的进程提供满意的服务;

多道批处理系统中大多配有该层次进程调度,而其他系统中则通常没有;

每个进程只会被该层次调度 2 次 :

  • 调入 1 次
  • 调出 1 次

作业与进程不一定是一一对应的!也可能是一个作业对应多个进程!

# 中程调度

中程调度是交换功能的一部分,

典型的情况下,换入(swapping-in)决定取决于管理系统并发度的需求。

存储管理是一个问题,换入决策将考虑换出进程的存储需求;

严格来讲,是进程在内存和系统盘交换区之间的交换

关掉交换区 swqpoff ,进程就会被锁到内存里执行,可以大幅提高内存占用率高的程序效率

# 短程调度

也称为分派程序(dispatcher),是最基本的调度,任何系统都需要配置这种调度

精确决定 CPU 下次执行哪一个进程;在 Ready、Running、Blocked 之间切换进程状态

导致当前进程阻塞抢占当前运行进程的事件发生时,触发短程调度程序;

触发三种层次进程调度的事件:

Process
A new process is created.When fork() is invoked and returns successfully. Then, whether the parent or the child is scheduled is up to the scheduler's decision.
An existing process is terminated.The CPU is freed. The scheduler should choose another process to run.
A process waits for I/OThe CPU is freed if the process is using CPU. The scheduler should choose another process to run.
A process finishes waiting for I/OThe interrupt handling routine makes a scheduling request, if necessary.

# 调度算法的概念

# 分类

# Offline

在提前知道所有进程所有事件的前提下。

只是用来评测的(做题就是这样的?),实际应用不可能实现。

# Online

实际应用的算法都是这种类型

# 非抢占式

Non-preemptive

在非抢占式调度下,一旦 CPU 分配给进程,进程将保持 CPU ,直到通过终止或切换到等待状态释放 CPU 为止。也就调度仅在以下情况发生:

  • 从运行状态切换到等待状态( I/O 请求或 wait() 调用)
  • 终止

# 抢占式

Preemptive

几乎所有现代操作系统,包括 Windows、MacOS、Linux 和 UNIX ,都使用抢占式调度算法。

CPU 调度决策可能在以下情况下发生:

  • 从运行状态切换到等待状态( I/O 请求或 wait() 调用)
  • 从运行状态切换到就绪状态(出现中断)
  • 从等待切换到就绪 ( I/O 完成)
  • 终止

当数据在多个进程之间共享时,抢占式调度可能导致竞争条件:考虑两个共享数据的进程的情况,当一个进程更新数据时,它被抢占,以便第二个进程可以运行。然后,第二个进程可能读取处于不一致状态的数据。

抢占也影响操作系统内核的设计,在上下文切换之前,等待系统调用的完成,或者等待 I/O 阻塞的发生。确保内核简单,但是难以应用于实时系统中。

# 评价标准与优化

评价标准也叫做调度准则,包括:

# CPU 利用率

CPU utilization

CPU利用率=CPU有效工作时间CPU有效工作时间+CPU空闲等待时间\text{CPU利用率}=\frac{\text{CPU有效工作时间}}{\text{CPU有效工作时间}+\text{CPU空闲等待时间}}

# 吞吐量

Throughput

吞吐量=单位时间CPU完成的作业数量\text{吞吐量}=\frac{\text{单位时间}}{\text{CPU完成的作业数量}}

# 周转时间

Turnaround time

一个作业的周转时间=作业完成时间作业提交时间n个作业的平均周转时间=作业1的周转时间+作业2的周转时间++作业n的周转时间n一个作业的带权周转时间=作业的周转时间作业实际运行时间n个作业的平均带权周转时间=作业1的带权周转时间+作业2的带权周转时间++作业n的带权周转时间n\begin{aligned} \text{一个作业的周转时间}&=\text{作业完成时间}-\text{作业提交时间}\\ n\text{个作业的平均周转时间}&=\frac{\text{作业1的周转时间}+\text{作业2的周转时间}+\cdots+\text{作业n的周转时间}}{n}\\ \text{一个作业的带权周转时间}&=\frac{\text{作业的周转时间}}{\text{作业实际运行时间}}\\ n\text{个作业的平均带权周转时间}&=\frac{\text{作业1的带权周转时间}+\text{作业2的带权周转时间}+\cdots+\text{作业n的带权周转时间}}{n}\\ \end{aligned}

# 等待时间

Waiting time

一个作业的等待时间=作业处于等待CPU的时间之和\text{一个作业的等待时间}=\text{作业处于等待CPU的时间之和}

# 响应时间

Response time

一个作业的响应时间=系统首次产生响应的时间用户提交请求的时间(作业提交时间?)\text{一个作业的响应时间}=\text{系统首次产生响应的时间}-\text{用户提交请求的时间(作业提交时间?)}

# 响应比

一个作业的响应比=作业的周转时间作业的等待时间\text{一个作业的响应比}=\frac{\text{作业的周转时间}}{\text{作业的等待时间}}

# 优化原则

  • 最大 CPU 利用率
  • 最大吞吐量
  • 最小周转时间
  • 最小等待时间
  • 最小响应时间

大多数情况下,优化的是平均值;有些情况下优化的是最小值或最大值,也可以最小化方差;

调度准则的冲突

# 基本调度算法

AlgorithmsPreemptive?Target System
First-come, first-served or First-in, First-out ( FCFS / FIFO )No.Out-of-date
Shortest-job-first (SJF)Can be both.Out-of-date
Round-robin (RR)Yes.Modern
Priority schedulingYes.Modern
Priority scheduling with multiple queues.The realimplementation!

# FCFS/FIFO

先来先服务调度。先请求 CPU 的进程首先分配到 CPU ,通过 FIFO 队列容易实现

各个评价指标受进程到达就绪队列的时间顺序影响大,也就是对输入敏感

# 护航效应

FCFS / FIFO 算法容易引发护航效应,也就是很多后来的短作业被先来的长作业阻塞,导致平均等待时时间、平均周转时间长

# 非抢占 SJF

最短作业优先调度的非抢占式版本

# 抢占 SJF

⚠️需要限制发生抢占的条件!在这里只允许有一个新进程到来的时候(被用户提交)才发生抢占

优点:

  • 平均等待时间降低
  • 平均周转时间降低

代价是增加了上下文切换的成本

可以证明 SJF 调度算法是最优的,因为 SJF 的平均等待时间最小;但是这个算法需要预先知道所有进程剩余 CPU 执行时间,这在实际应用中世不可能的

# RR

Round Robin

RR 专门为分时系统设计,类似 FCFS 但是增加了抢占以切换进程。

RR 是抢占式调度的;(preemptive)

每个进程给定一个较小的时间单位成为时间片,时间片用完后,

CPU 选择另外一个进程调度执行;

CPU 调度程序循环整个就绪队列,一个一个执行;

每个进程获得一个小的 CPU 时间单位(时间量和时间片),通常为 10-100 毫秒。此时间过后,进程将被抢占并添加到就绪队列的末尾。

如果就绪队列中有 nn 个进程,且时间片为 qq ,则每个进程一次最多以 qq 个时间单位的块获取 1n\frac{1}{n} 的 CPU 时间。没有进程等待超过 n1n-1 个时间单位。

计时器中断每个时间片以安排下一个进程

# 时间片

quantum—— 时间片(量子化思想?)

  • 时间片 qq 如果非常大, 退化为先进先出(FCFS),性能降低;
  • 时间片 qq 如果非常小,导致大量的上下文切换,性能降低;
    • 所以相对于上下文切换,qq 必须很大,否则开销太高

现代操作系统往往提供了设置时间片大小的接口

⚠️:时间片的大小和平均周转时间等指标没有规律性的关系,实际时间片的大小设置往往是依据实验经验的

# 性能

相比 SJF ,RR 的平均等待时间、平均周转时间都更差!但是响应性得到了提升!这就是 RR 的最大优势!

# 优先级调度

# 实时系统

对于实时调度,调度器必须支持抢占式、基于优先级的调度,但只能保证软实时性;

对于硬实时系统,还必须提供满足截止期限的能力,需要添加新的调度特征;

进程新的特点:周期性进程需要以固定的时间间隔使用 CPU

具有处理时间 TT、截止日期 DD、周期 PP0TDP0≤ T≤ D≤ P

定期任务的速率为 1p\frac{1}{p}

# 基本优先级调度

优先级编号(整数)与每个进程相关联;CPU 分配给具有最高优先级(一般默认最小整数,除非题目额外说明)的进程(最高优先级)

定义优先级

  • 内部定义
  • 外部定义

⚠️误区:基于优先级的调度算法并非都是抢占式的:

  • 可以是抢占式的
  • 也可以是非抢占式

SJF 也是优先级调度,其中优先级是预测的下一个 CPU 执行时间的倒数;

问题:饥饿 —— 低优先级进程可能永远不会执行;

解决方案:老化 (aging)—— 随着时间的推移,进程的优先级会增加;

# 多级队列调度

仍然是优先级调度,也就是 “多 (优先) 级队列调度”;

就绪作业队列分成多个单独的队列,每个队列具有不同的调度算法;

例如分成前台进程(RR)和后台进程(FCFS);

eg:

PriorityScheduling algorithm
Priority class 5Non-preemptive, FIFO
Priority class 4Non-preemptive, SJF
Priority class 3RR with quantum = 10 units.
Priority class 2RR with quantum = 20 units.
Priority class 1RR with quantum = 40 units.

不同的队列之间应用调度,通常采用固定优先级抢占调度,如前台队列可以比后台队列具有绝对的优先,只要前台队列非空,后台队列的进程就无法被调度;

# 多级反馈调度队列

为了解决多级反馈调度队列中固定化优先级导致的饥饿问题,在调度程序运行时不断调整进程的优先级

通常,多级反馈队列调度程序可由以下参数定义:

  • 队列数量;
  • 每个队列的调度算法;
  • 用于确定何时升级到高优先级队列的方法;
  • 用于确定何时降级到更低优先级队列的方法;
  • 用于确定当某个进程需要服务时该进程将进入哪个队列的方法;

成为最通用的调度算法,通过配置适应特定的系统,也是最复杂的调度方法;

老化可以使用多级反馈队列来实现;

# 单调速率调度

单调速率调度算法采用抢占的、静态优先级的策略,调度周期性任务;

每个周期性任务分配一个优先;

优先级是根据其周期的倒数来分配的;

  • 周期越短 => 优先级越高;
  • 周期越长 => 优先级越低;

P1 (周期为 50, 处理时间为 20) 的优先级高于 P2(周期为 100,处理时间为 35);截止时间为下一个周期开始的时间

单调速率调度可认为是最优的,因为如果一组进程不能由此算法调度,它不能由任何其他分配静态优先级的算法调度

# 错过截止时间

单调速率调度有一个限制 ——CPU 利用率是有限的,并不能完全最大化 CPU 资源利用率,调度 N 个进程的最坏情况下的 CPU 利用率为:

n(21n1)n(2^{\frac{1}{n}}-1)

# 最早截止期限有限调度 (EDF)

调度根据截止期限动态分配优先级;截止期限越早,优先级越高;截止期限越晚,优先级越低;

单调速率调度的优先级是固定的,而 EDF 是动态的;

此外,EDF 调度不要求进程是周期执行的,也不要求进程的 CPU 时间是固定的,唯一的要求是:进程在变成可运行时,应给出它的截止时间。

理论上,最佳情况下 CPU 利用率会到 100%。

# 优先级翻转现象

低优先的进程占有了高优先级进程需要的资源,特别是一些共享资源,导致高优先级进程被阻塞,这种现象就叫优先级翻转

  • 有界优先级翻转,发生优先级翻转,没有外界干预的情况下也能自己恢复
  • 无界优先级翻转,一旦发生优先级翻转,没有外界干预的情况下将无法恢复,高优先级永远被阻塞

# 优先级继承

# 选择函数

选择函数决定选择哪个就绪进程下次执行;

这个函数可以根据优先级、资源需求或进程的执行特性来进行选择;

对于执行特性,可以根据以下三个重要的参数:

  • w (wait) = 目前为止在系统中的等待时间;
  • e (exec) = 目前为止花费的执行时间;
  • s (serv) = 进程所需要的总服务时间,包括 e;这个参数通常须进行估计或由用户提供;
FCFSRound robinSPNSRTHRRNFeedback
Selection functionmax[w]\max[w]constantmin[s]\min[s]min[se]\min[s-e]\max \frac{w+s}(see text)
Decision modeNon-preemptivePreemptive (at time quantum)Non-preemptivePreemptive (at arrival)Non-preemptivePreemptive (at time quantum)
ThroughPutNot emphasizedMay be low if guantum is too smallHighHighHighNot emphasized
Response timeMay be high, especially if there is a large variance in process execution timesProvides good response time for short processesProvides good response time for short processesProvides good response timeProvides good response timeNot emphasized
OverheadMinimumMinimumCan be highCan be highCan be highCan be high
Effect on processesPenalizes short processes; penalizes I/0 bound processesFair treatmentPenalizes long processesPenalizes long processesGood balanceMay favor I/0 bound processes
StarvationNoNoPossiblePossibleNoPossible

TrTs=w+ss=11ρ\frac{T_r}{T_s}=\frac{w+s}{s}=\frac{1}{1-\rho}

ρ\rho 是处理器利用率(processor utilization)

# 公平调度算法

# 传统的 Unix 调度

调度形式化:

CPUj(i)=CPUj(i1)2Pj(i)=Basej+CPUj(i)2+nicej\begin{aligned} CPU_j(i)&=\frac{CPU_j(i-1)}{2}\\ P_j(i)&=Base_j+\frac{CPU_j(i)}{2}+nice_j \end{aligned}

chrt -m 可以用于在 Linux OS 中查看调度相关的信息

chrt -f -p [priority-level] [pid] 修改进程的调度策略以及优先级

# 比例分享调度

调度程序在所有进程之间分配 TT 股(通证);

应用程序接收 NN 股,其中 N<TN<T

这确保每个应用程序将收到总处理器时间的 NT\frac{N}{T}

采用准入控制策略,以确保每个进程能够得到分配时间。

准入控制策略是:只有客户请求的股数小于可用的股数,才能允许客户进入。

现代很多网络、磁盘共享等需要共享的情况下往往采用这种调度方式,这是一种比较公平的调度算法

# 线程调度

  • PCS —— Process Contention Scope ,进程级争用范围、作用域,调度竞争在进程内
    • 通常情况下,PCS 采用优先级调度
  • SCS —— System Contention Scope ,系统级争用范围、作用域,调度到可用 CPU 上的内核线程,系统中所有线程之间的竞争
    • 对于一对一模型的系统,如 Windows、Linux、Solaris 等只采用 SCS 调度

# 多处理器调度

前面讲述的内容都是单处理器系统的调度问题,如果有多个处理器,负载分配成为可能,但是调度问题更加复杂

主要关注同构处理器:(SMP)

  • 非对称多处理器,太复杂,不关注
  • 对称多处理器(SMP)

对称多处理(SMP)是指每个处理器都是自调度的。

  • 所有线程都可能位于公共就绪队列(a)中
  • 每个处理器可能有自己的线程专用队列(b)

多线程多核处理器需要两个级别的调度:

  • 一个级别由操作系统调度;
  • 另一个级别是指定每个核心如何运行哪个硬件线程

# Linux

# CFS

完全公平调度,内核在 2.6 以后采用

Linux 系统的调度基于调度类;

每个调度类都有特定的优先权;

调度程序在最高调度类中选择优先级最高的任务;

而不是基于固定时间分配的时间片,基于 CPU 时间的比例;

包括两个调度类,可以添加其他调度类;

  • 采用 CFS 调度算法的默认调度类;
  • 实时

# 调度优先级

# 调度算法评估

# 排队模型

描述进程的到达,以及 CPU 和 I/O 执行的概率

通常是指数型的,用平均值来描述

计算平均吞吐量、利用率、等待时间等。

描述为服务器网络的计算机系统,每个服务器都有等待进程队列

了解到达率和服务率

计算利用率、平均队列长度、平均等待时间等

# Little's Law

# CPU 调度仿真

排队模型能力有限

更精确的模拟

计算机系统的程序模型

时钟是一个变量

收集指示算法性能的统计信息

用于驱动通过以下方式收集的模拟的数据:

基于概率的随机数发生器

数学上或经验上定义的分布

跟踪磁带记录真实系统中真实事件的序列

Edited on Views times
\ No newline at end of file +调度 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 调度相关概念

为什么需要调度?

释放被阻塞、挂起的进程占用的 CPU 资源

实现 I/O 操作和 CPU 并行执行( I/O 密集型和 CPU 密集型)


调度的层次、类型

  • 处理器 / CPU 调度⭐️(进程调度的主要内容)

    • 作业调度 /long-term scheduling / 长程调度 / 高级调度

      The decision to add to the pool of processes to be executed

    • 内存调度 /medium-term scheduling / 中程调度 / 中级调度

      The decision to add to the number of processes that are partially or fully in main memory

    • (狭义?) 进程调度 /short-term scheduling / 短程调度 / 初级调度

      The decision as to which available process will be executed by the processor

  • 微调度 —— CPU 内部的指令调度(计组的内容了)

  • I/O scheduling

    The decision as to which process's pending I/O request shall be handled by an available I/O device

# 三种层次进程调度

进程调度的层次

三种层次 CPU 进程调度频繁程度:长程 < 中程 < 短程

# 长程调度

控制了系统的并发度

创建的进程越多,每个进程的执行时间的百分比越小,系统并发度越高;

长程调度程序可能会限制系统的并发度,为了给当前的进程提供满意的服务;

多道批处理系统中大多配有该层次进程调度,而其他系统中则通常没有;

每个进程只会被该层次调度 2 次 :

  • 调入 1 次
  • 调出 1 次

作业与进程不一定是一一对应的!也可能是一个作业对应多个进程!

# 中程调度

中程调度是交换功能的一部分,

典型的情况下,换入(swapping-in)决定取决于管理系统并发度的需求。

存储管理是一个问题,换入决策将考虑换出进程的存储需求;

严格来讲,是进程在内存和系统盘交换区之间的交换

关掉交换区 swqpoff ,进程就会被锁到内存里执行,可以大幅提高内存占用率高的程序效率

# 短程调度

也称为分派程序(dispatcher),是最基本的调度,任何系统都需要配置这种调度

精确决定 CPU 下次执行哪一个进程;在 Ready、Running、Blocked 之间切换进程状态

导致当前进程阻塞抢占当前运行进程的事件发生时,触发短程调度程序;

触发三种层次进程调度的事件:

Process
A new process is created.When fork() is invoked and returns successfully. Then, whether the parent or the child is scheduled is up to the scheduler's decision.
An existing process is terminated.The CPU is freed. The scheduler should choose another process to run.
A process waits for I/OThe CPU is freed if the process is using CPU. The scheduler should choose another process to run.
A process finishes waiting for I/OThe interrupt handling routine makes a scheduling request, if necessary.

# 调度算法的概念

# 分类

# Offline

在提前知道所有进程所有事件的前提下。

只是用来评测的(做题就是这样的?),实际应用不可能实现。

# Online

实际应用的算法都是这种类型

# 非抢占式

Non-preemptive

在非抢占式调度下,一旦 CPU 分配给进程,进程将保持 CPU ,直到通过终止或切换到等待状态释放 CPU 为止。也就调度仅在以下情况发生:

  • 从运行状态切换到等待状态( I/O 请求或 wait() 调用)
  • 终止

# 抢占式

Preemptive

几乎所有现代操作系统,包括 Windows、MacOS、Linux 和 UNIX ,都使用抢占式调度算法。

CPU 调度决策可能在以下情况下发生:

  • 从运行状态切换到等待状态( I/O 请求或 wait() 调用)
  • 从运行状态切换到就绪状态(出现中断)
  • 从等待切换到就绪 ( I/O 完成)
  • 终止

当数据在多个进程之间共享时,抢占式调度可能导致竞争条件:考虑两个共享数据的进程的情况,当一个进程更新数据时,它被抢占,以便第二个进程可以运行。然后,第二个进程可能读取处于不一致状态的数据。

抢占也影响操作系统内核的设计,在上下文切换之前,等待系统调用的完成,或者等待 I/O 阻塞的发生。确保内核简单,但是难以应用于实时系统中。

# 评价标准与优化

评价标准也叫做调度准则,包括:

# CPU 利用率

CPU utilization

CPU利用率=CPU有效工作时间CPU有效工作时间+CPU空闲等待时间\text{CPU利用率}=\frac{\text{CPU有效工作时间}}{\text{CPU有效工作时间}+\text{CPU空闲等待时间}}

# 吞吐量

Throughput

吞吐量=单位时间CPU完成的作业数量\text{吞吐量}=\frac{\text{单位时间}}{\text{CPU完成的作业数量}}

# 周转时间

Turnaround time

一个作业的周转时间=作业完成时间作业提交时间n个作业的平均周转时间=作业1的周转时间+作业2的周转时间++作业n的周转时间n一个作业的带权周转时间=作业的周转时间作业实际运行时间n个作业的平均带权周转时间=作业1的带权周转时间+作业2的带权周转时间++作业n的带权周转时间n\begin{aligned} \text{一个作业的周转时间}&=\text{作业完成时间}-\text{作业提交时间}\\ n\text{个作业的平均周转时间}&=\frac{\text{作业1的周转时间}+\text{作业2的周转时间}+\cdots+\text{作业n的周转时间}}{n}\\ \text{一个作业的带权周转时间}&=\frac{\text{作业的周转时间}}{\text{作业实际运行时间}}\\ n\text{个作业的平均带权周转时间}&=\frac{\text{作业1的带权周转时间}+\text{作业2的带权周转时间}+\cdots+\text{作业n的带权周转时间}}{n}\\ \end{aligned}

# 等待时间

Waiting time

一个作业的等待时间=作业处于等待CPU的时间之和\text{一个作业的等待时间}=\text{作业处于等待CPU的时间之和}

# 响应时间

Response time

一个作业的响应时间=系统首次产生响应的时间用户提交请求的时间(作业提交时间?)\text{一个作业的响应时间}=\text{系统首次产生响应的时间}-\text{用户提交请求的时间(作业提交时间?)}

# 响应比

一个作业的响应比=作业的周转时间作业的等待时间\text{一个作业的响应比}=\frac{\text{作业的周转时间}}{\text{作业的等待时间}}

# 优化原则

  • 最大 CPU 利用率
  • 最大吞吐量
  • 最小周转时间
  • 最小等待时间
  • 最小响应时间

大多数情况下,优化的是平均值;有些情况下优化的是最小值或最大值,也可以最小化方差;

调度准则的冲突

# 基本调度算法

AlgorithmsPreemptive?Target System
First-come, first-served or First-in, First-out ( FCFS / FIFO )No.Out-of-date
Shortest-job-first (SJF)Can be both.Out-of-date
Round-robin (RR)Yes.Modern
Priority schedulingYes.Modern
Priority scheduling with multiple queues.The realimplementation!

# FCFS/FIFO

先来先服务调度。先请求 CPU 的进程首先分配到 CPU ,通过 FIFO 队列容易实现

各个评价指标受进程到达就绪队列的时间顺序影响大,也就是对输入敏感

# 护航效应

FCFS / FIFO 算法容易引发护航效应,也就是很多后来的短作业被先来的长作业阻塞,导致平均等待时时间、平均周转时间长

# 非抢占 SJF

最短作业优先调度的非抢占式版本

# 抢占 SJF

⚠️需要限制发生抢占的条件!在这里只允许有一个新进程到来的时候(被用户提交)才发生抢占

优点:

  • 平均等待时间降低
  • 平均周转时间降低

代价是增加了上下文切换的成本

可以证明 SJF 调度算法是最优的,因为 SJF 的平均等待时间最小;但是这个算法需要预先知道所有进程剩余 CPU 执行时间,这在实际应用中世不可能的

# RR

Round Robin

RR 专门为分时系统设计,类似 FCFS 但是增加了抢占以切换进程。

RR 是抢占式调度的;(preemptive)

每个进程给定一个较小的时间单位成为时间片,时间片用完后,

CPU 选择另外一个进程调度执行;

CPU 调度程序循环整个就绪队列,一个一个执行;

每个进程获得一个小的 CPU 时间单位(时间量和时间片),通常为 10-100 毫秒。此时间过后,进程将被抢占并添加到就绪队列的末尾。

如果就绪队列中有 nn 个进程,且时间片为 qq ,则每个进程一次最多以 qq 个时间单位的块获取 1n\frac{1}{n} 的 CPU 时间。没有进程等待超过 n1n-1 个时间单位。

计时器中断每个时间片以安排下一个进程

# 时间片

quantum—— 时间片(量子化思想?)

  • 时间片 qq 如果非常大, 退化为先进先出(FCFS),性能降低;
  • 时间片 qq 如果非常小,导致大量的上下文切换,性能降低;
    • 所以相对于上下文切换,qq 必须很大,否则开销太高

现代操作系统往往提供了设置时间片大小的接口

⚠️:时间片的大小和平均周转时间等指标没有规律性的关系,实际时间片的大小设置往往是依据实验经验的

# 性能

相比 SJF ,RR 的平均等待时间、平均周转时间都更差!但是响应性得到了提升!这就是 RR 的最大优势!

# 优先级调度

# 实时系统

对于实时调度,调度器必须支持抢占式、基于优先级的调度,但只能保证软实时性;

对于硬实时系统,还必须提供满足截止期限的能力,需要添加新的调度特征;

进程新的特点:周期性进程需要以固定的时间间隔使用 CPU

具有处理时间 TT、截止日期 DD、周期 PP0TDP0≤ T≤ D≤ P

定期任务的速率为 1p\frac{1}{p}

# 基本优先级调度

优先级编号(整数)与每个进程相关联;CPU 分配给具有最高优先级(一般默认最小整数,除非题目额外说明)的进程(最高优先级)

定义优先级

  • 内部定义
  • 外部定义

⚠️误区:基于优先级的调度算法并非都是抢占式的:

  • 可以是抢占式的
  • 也可以是非抢占式

SJF 也是优先级调度,其中优先级是预测的下一个 CPU 执行时间的倒数;

问题:饥饿 —— 低优先级进程可能永远不会执行;

解决方案:老化 (aging)—— 随着时间的推移,进程的优先级会增加;

# 多级队列调度

仍然是优先级调度,也就是 “多 (优先) 级队列调度”;

就绪作业队列分成多个单独的队列,每个队列具有不同的调度算法;

例如分成前台进程(RR)和后台进程(FCFS);

eg:

PriorityScheduling algorithm
Priority class 5Non-preemptive, FIFO
Priority class 4Non-preemptive, SJF
Priority class 3RR with quantum = 10 units.
Priority class 2RR with quantum = 20 units.
Priority class 1RR with quantum = 40 units.

不同的队列之间应用调度,通常采用固定优先级抢占调度,如前台队列可以比后台队列具有绝对的优先,只要前台队列非空,后台队列的进程就无法被调度;

# 多级反馈调度队列

为了解决多级反馈调度队列中固定化优先级导致的饥饿问题,在调度程序运行时不断调整进程的优先级

通常,多级反馈队列调度程序可由以下参数定义:

  • 队列数量;
  • 每个队列的调度算法;
  • 用于确定何时升级到高优先级队列的方法;
  • 用于确定何时降级到更低优先级队列的方法;
  • 用于确定当某个进程需要服务时该进程将进入哪个队列的方法;

成为最通用的调度算法,通过配置适应特定的系统,也是最复杂的调度方法;

老化可以使用多级反馈队列来实现;

# 单调速率调度

单调速率调度算法采用抢占的、静态优先级的策略,调度周期性任务;

每个周期性任务分配一个优先;

优先级是根据其周期的倒数来分配的;

  • 周期越短 => 优先级越高;
  • 周期越长 => 优先级越低;

P1 (周期为 50, 处理时间为 20) 的优先级高于 P2(周期为 100,处理时间为 35);截止时间为下一个周期开始的时间

单调速率调度可认为是最优的,因为如果一组进程不能由此算法调度,它不能由任何其他分配静态优先级的算法调度

# 错过截止时间

单调速率调度有一个限制 ——CPU 利用率是有限的,并不能完全最大化 CPU 资源利用率,调度 N 个进程的最坏情况下的 CPU 利用率为:

n(21n1)n(2^{\frac{1}{n}}-1)

# 最早截止期限有限调度 (EDF)

调度根据截止期限动态分配优先级;截止期限越早,优先级越高;截止期限越晚,优先级越低;

单调速率调度的优先级是固定的,而 EDF 是动态的;

此外,EDF 调度不要求进程是周期执行的,也不要求进程的 CPU 时间是固定的,唯一的要求是:进程在变成可运行时,应给出它的截止时间。

理论上,最佳情况下 CPU 利用率会到 100%。

# 优先级翻转现象

低优先的进程占有了高优先级进程需要的资源,特别是一些共享资源,导致高优先级进程被阻塞,这种现象就叫优先级翻转

  • 有界优先级翻转,发生优先级翻转,没有外界干预的情况下也能自己恢复
  • 无界优先级翻转,一旦发生优先级翻转,没有外界干预的情况下将无法恢复,高优先级永远被阻塞

# 优先级继承

# 选择函数

选择函数决定选择哪个就绪进程下次执行;

这个函数可以根据优先级、资源需求或进程的执行特性来进行选择;

对于执行特性,可以根据以下三个重要的参数:

  • w (wait) = 目前为止在系统中的等待时间;
  • e (exec) = 目前为止花费的执行时间;
  • s (serv) = 进程所需要的总服务时间,包括 e;这个参数通常须进行估计或由用户提供;
FCFSRound robinSPNSRTHRRNFeedback
Selection functionmax[w]\max[w]constantmin[s]\min[s]min[se]\min[s-e]\max \frac{w+s}(see text)
Decision modeNon-preemptivePreemptive (at time quantum)Non-preemptivePreemptive (at arrival)Non-preemptivePreemptive (at time quantum)
ThroughPutNot emphasizedMay be low if guantum is too smallHighHighHighNot emphasized
Response timeMay be high, especially if there is a large variance in process execution timesProvides good response time for short processesProvides good response time for short processesProvides good response timeProvides good response timeNot emphasized
OverheadMinimumMinimumCan be highCan be highCan be highCan be high
Effect on processesPenalizes short processes; penalizes I/0 bound processesFair treatmentPenalizes long processesPenalizes long processesGood balanceMay favor I/0 bound processes
StarvationNoNoPossiblePossibleNoPossible

TrTs=w+ss=11ρ\frac{T_r}{T_s}=\frac{w+s}{s}=\frac{1}{1-\rho}

ρ\rho 是处理器利用率(processor utilization)

# 公平调度算法

# 传统的 Unix 调度

调度形式化:

CPUj(i)=CPUj(i1)2Pj(i)=Basej+CPUj(i)2+nicej\begin{aligned} CPU_j(i)&=\frac{CPU_j(i-1)}{2}\\ P_j(i)&=Base_j+\frac{CPU_j(i)}{2}+nice_j \end{aligned}

chrt -m 可以用于在 Linux OS 中查看调度相关的信息

chrt -f -p [priority-level] [pid] 修改进程的调度策略以及优先级

# 比例分享调度

调度程序在所有进程之间分配 TT 股(通证);

应用程序接收 NN 股,其中 N<TN<T

这确保每个应用程序将收到总处理器时间的 NT\frac{N}{T}

采用准入控制策略,以确保每个进程能够得到分配时间。

准入控制策略是:只有客户请求的股数小于可用的股数,才能允许客户进入。

现代很多网络、磁盘共享等需要共享的情况下往往采用这种调度方式,这是一种比较公平的调度算法

# 线程调度

  • PCS —— Process Contention Scope ,进程级争用范围、作用域,调度竞争在进程内
    • 通常情况下,PCS 采用优先级调度
  • SCS —— System Contention Scope ,系统级争用范围、作用域,调度到可用 CPU 上的内核线程,系统中所有线程之间的竞争
    • 对于一对一模型的系统,如 Windows、Linux、Solaris 等只采用 SCS 调度

# 多处理器调度

前面讲述的内容都是单处理器系统的调度问题,如果有多个处理器,负载分配成为可能,但是调度问题更加复杂

主要关注同构处理器:(SMP)

  • 非对称多处理器,太复杂,不关注
  • 对称多处理器(SMP)

对称多处理(SMP)是指每个处理器都是自调度的。

  • 所有线程都可能位于公共就绪队列(a)中
  • 每个处理器可能有自己的线程专用队列(b)

多线程多核处理器需要两个级别的调度:

  • 一个级别由操作系统调度;
  • 另一个级别是指定每个核心如何运行哪个硬件线程

# Linux

# CFS

完全公平调度,内核在 2.6 以后采用

Linux 系统的调度基于调度类;

每个调度类都有特定的优先权;

调度程序在最高调度类中选择优先级最高的任务;

而不是基于固定时间分配的时间片,基于 CPU 时间的比例;

包括两个调度类,可以添加其他调度类;

  • 采用 CFS 调度算法的默认调度类;
  • 实时

# 调度优先级

# 调度算法评估

# 排队模型

描述进程的到达,以及 CPU 和 I/O 执行的概率

通常是指数型的,用平均值来描述

计算平均吞吐量、利用率、等待时间等。

描述为服务器网络的计算机系统,每个服务器都有等待进程队列

了解到达率和服务率

计算利用率、平均队列长度、平均等待时间等

# Little's Law

# CPU 调度仿真

排队模型能力有限

更精确的模拟

计算机系统的程序模型

时钟是一个变量

收集指示算法性能的统计信息

用于驱动通过以下方式收集的模拟的数据:

基于概率的随机数发生器

数学上或经验上定义的分布

跟踪磁带记录真实系统中真实事件的序列

Edited on Views times
\ No newline at end of file diff --git a/cs/os/sync/index.html b/cs/os/sync/index.html index de0c6c69..69ef7b79 100644 --- a/cs/os/sync/index.html +++ b/cs/os/sync/index.html @@ -1 +1 @@ -经典进程同步问题 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

This article isn't finished yet...

# 严格备选

(Strict Alternation)

# PetersonSolution

# 互斥锁

互斥锁是一种外部强加的控制方案,或者说是全局控制;

获得锁:

伪代码
acquire {
    while (!available)
    ; /* busy wait */
    available = false;
}

释放锁:

伪代码
release {
  	available = true;
}

利用互斥锁的临界区问题解决方案:

伪代码
while (true) {
  	acquire lock
      	/* critical section */
    release lock
      	/* others */
}

但是这个方案需要繁忙的等待,所以也叫自旋锁(Spinlock)

存在优点:当进程在等待锁时,没有上下文切换,在使用锁的时间较短时,自旋锁是有用的;自旋锁通常用于多处理器系统

# 信号量

信号量是一种内部主动的控制方案,或者说是局部控制;

# 管程

管程(monitor)是一种面向对象的高级程序设计语言结构,它提供的功能与信号量相同,但更易于控制;

管程结构在很多程序设计语言中得以实现,包括:

  • 并发 Pascal
  • Pascal
  • Pascal-Plus
  • Modula-2
  • Modula-3
  • Java

现在已经被作为一个程序库实现;

管程是由一个或多个进程、一个初始化序列和局部数据组成的软件模块;(使用信号的管程)

c
monitor monitor name
{
    /* shared variable declarations */
    function P1 ( ... ) {
    		...
    }
    function P2 ( ... ) {
    		...
    }
    .
    .
    .
    function Pn ( ... ) {
    		...
    }
    initialization code ( ... ) {
    		...
    }
}

# 条件变量

定义附加的同步机制,可以由条件(condition)结构来提供;

当程序员需要编写定制的同步方案时,可以定义一个或者多个类型为 condition 的变量;

对于条件变量,只有操作 wait()signal 可以调用;

利用条件变量实现互斥访问以及控制执行顺序,这里 S1 必须在 S2 之前执行:

c
F1(){
    S1;
    		done = true;
    x.signal();
}
F2(){
    if done == false
    		x.wait()
    S2;
}

# 信号量实现

c
// Variables
    semaphore mutex; // (initially = 1)
    semaphore next; // (initially = 0)
    int next_count = 0; // number of processes waiting
// inside the monitor
// Each function P will be replaced by
    wait(mutex);
        ...
        body of P;
        ...
    if (next_count > 0)
        signal(next)
    else
        signal(mutex);
// Mutual exclusion within a monitor is ensured

# 条件变量实现

c
//For each condition variable x, we have:
    semaphore x_sem; // (initially = 0)
    int x_count = 0;
//The operation x.wait() can be implemented as:
    x_count++;
    if (next_count > 0)
        signal(next);
    else
        signal(mutex);
    wait(x_sem);
    x_count--;

其中 signal 方法实现参考:

c
if (x_count > 0) {
    next_count++;
    signal(x_sem);
    wait(next);
    next_count--;
}

# 进程恢复

  • 唤醒并等待(signal and wait)
    • 进程 P 等待进程直到进程 Q 离开管程,或者等待另一个条件;
    • 等待 Q 的时候若 P 想再次执行,需要测试 P 是否还具有执行的环境条件
  • 唤醒并继续(signal and continue)
    • 进程 Q 等待直到进程 P 离开管程或者等待另一个条件;

# java

java
public class BlockedQueue<T> (
    final Lock lock = new ReentrantLock () ;
    // 条件变量:队列不满
    final Condition notFull = lock.newCondition () ;
    // 条件变量:队列不空
    final Condition notEmpty = lock.newCondition ();
    // 入队
    void enq (T x) {
        lock. lock() ;
        try {
            whileStack已满){
                // 等待队列不满
                notFull.await () ;
            }
            // 省略入队操作
            // 入队后,通知可出队
            notEmpty.signal ();
        } finally {
        		lock.unlock () ;
        }
    }
    // 出队
    void deq() {
        lock.lock () ;
        try {
            while(队列已空){
            // 等待队列不空
            notEmpty.await () ;
            }
            // 省略出队操作.
            // 出队后,通知可入队
            notFull.signal () ;
        } finally {
        		lock.unlock () ;
    }
}

# 管程模型 (补充)

Hasen、Hoare 和 MESA 模型区别

Hasen 模型、Hoare 模型和 MESA 模型的一个核心区别就是当条件满足后,如何通知相关线程。管程要求同一时刻只允许一个线程执行,那当线程 T2 的操作使线程 T1 等待的条件满足时,T1 和 T2 究竟谁可以执行呢?

  • Hasen 模型里面,要求 notify() 放在代码的最后,这样 T2 通知完 T1 后,T2 就结束了,然后 T1 再执行,这样就能保证同一时刻只有一个线程执行。
  • Hoare 模型里面,T2 通知完 T1 后,T2 阻塞,T1 马上执行;等 T1 执行完,再唤醒 T2,也能保证同一时刻只有一个线程执行。但是相比 Hasen 模型,T2 多了一次阻塞唤醒操作。
  • MESA 管程里面,T2 通知完 T1 后,T2 还是会接着执行,T1 并不立即执行,仅仅是从条件变量的等待队列进到入口等待队列里面。这样做的好处是 notify() 不用放到代码的最后,T2 也没有多余的阻塞唤醒操作。但是也有个副作用,就是当 T1 再次执行的时候,可能曾经满足的条件,现在已经不满足了,所以需要以循环方式检验条件变量。

对于 MESA 管程来说,有一个编程范式,就是需要在一个 while 循环里面调用 wait() 。这个是 MESA 管程特有的!

# 生产者 - 消费者问题

# 信号量实现

producer
while (true) {
    ...
    /* produce an item in next produced */
    ...
    wait(empty);
    wait(mutex);  // 对应的 signal 不是本进程的,而一定是 consumer 进程的 signal !
    ...
    /* add next produced to the buffer */
    ...
    signal(mutex);  // 对应的 wait 不是本进程的,而一定是 consumer 进程的 wait !
    signal(full);
}
consumer
while (true) {
    wait(full);
    wait(mutex);  // 对应的 signal 不是本进程的,而一定是 producer 进程的 signal !
    ...
    /* remove an item from buffer to next consumed */
    ...
    signal(mutex);  // 对应的 wait 不是本进程的,而一定是 producer 进程的 wait !
    signal(empty);
    ...
    /* consume the item in next consumed */
    ...
}

# 错误案例

c
int n;
binary_semaphore s = 1, delay = 0;
void producer(){
    while (true) {
        produce();
        semWaitB(s);
        append();
        n++;
        if (n==1) semSignalB(delay);
        semSignalB(s);
    }
}
void consumer(){
    semWaitB(delay);
    while (true) {
        semWaitB(s);
        take();
        n--;
        semSignalB(s);
        consume();  /* 这里没有互斥,producer 打断则会导致后续 n 出现负值 */
        if (n==0) semWaitB(delay);
    }
}
void main(){
    n = 0;
    parbegin (producer, consumer);
}

consumer 的正确实现:

c
void consumer (){
    int m; /* a local variable */
  	semWaitB(delay) ;
    while (true) {
        semWaitB(s);
        take ( );
        n--;
        m = ni
        semSignalB(s) ;
        consume () ;
        if (m==0) semWaitB(delay);
    }
}

# 无限队列生产者消费者问题实现

缓冲区无大小限制

c
/* program producerconsumer */
semaphore n = 0, s = 1;
void producer(){
    while (true) {
        produce();
        semWait(s);
        append();
        semSignal(s);
        semSignal(n);
    }
}
void consumer(){
    while (true) {
        semWait(n);
        semWait(s);
        take();
        semSignal(s);
        consume();
    }
}
void main(){
		parbegin (producer, consumer);
}

# 管程实现

c
void append (char x){
    while (count == N) wait(notfull);   /* buffer is full; avoid overflow */
    buffer [nextin] = x;
    nextin = (nextin + 1) % N;
    count++                             /* one more item in buffer */
    cnotify (notempty) ;                /* notify any waiting consumer */
}
void take (char x){
    while (count == 0) wait(notempty) ; /* buffer is empty; avoid underflow */
    x = buffer[nextout];
    nextout = (nextout + 1) % N;
    count --;                           /* one fewer item in buffer */
  	cnotify(notfull) ;                  /* notify any waiting producer */
}

# 共享内存方式 (pthread)

利用 POSIX API (c 的 pthread) 实现共享内存。The API is supported by Linux 2.4 and later, FreeBSD, … 编译时需要: gcc -lrt filename.c

shmpthreadcon.c

c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "shmdata.h"
/* gcc -lrt */
int main(int argc, char *argv[])
{
  char pathname[80], cmd_str[80];
  struct stat fileattr;
  int fd, shmsize, ret;
  pid_t childpid1, childpid2;
  if(argc < 2) {
    printf("Usage: ./a.out filename\n");
    return EXIT_FAILURE;
  }
  fd = shm_open(argv[1], O_CREAT|O_RDWR, 0666);
  /* /dev/shm/filename as the shared object, creating if not exist */
  if(fd == -1) {
  	ERR_EXIT("con: shm_open()");
  }
  system("ls -l /dev/shm/");
  shmsize = TEXT_NUM*sizeof(struct shared_struct);
  ret = ftruncate(fd, shmsize);
  if(ret == -1) {
    ERR_EXIT"con: ftruncate()");
    char *argv1[] = {" ", argv[1], 0};
    childpid1 = vfork();
    if(childpid1 < 0) {
    	ERR_EXIT("shmpthreadcon: 1st vfork()");
    }
    else if(childpid1 == 0) {
    	execv("./shmproducer", argv1); /* call producer with filename */
    }
    else {
    	childpid2 = vfork();
    if(childpid2 < 0)
    	ERR_EXIT("shmpthreadcon: 2nd vfork()");
    else if (childpid2 == 0)
    	execv("shmconsumer.o", argv1); /* call consumer with filename */
    else {
      wait(&childpid1);
      wait(&childpid2);
      ret = shm_unlink(argv[1]);
      if(ret == -1) {
      	ERR_EXIT("con: shm_unlink()");
      } /* shared object can be removed by any process knew the filename */
      system("ls -l /dev/shm/");
    }
  }
	exit(EXIT_SUCCESS);
}

# 读者 - 写者问题

一个数据集在多个并发进程之间共享

  • Readers—— 仅读取数据集;它们不执行任何更新
  • Writer—— 既能读又能写

🤔问题:允许多个读者同时读取

  • 只有一个写者程序可以同时访问共享数据;
  • 写者在访问数据时,不允许读者访问数据;

读者和作者的考虑方式有几种不同 —— 都涉及某种形式的

优先权

  • 第一读者写者问题:读者优先;会导致写者饥饿
  • 第二读者写者问题:写者优先;会导致读者饥饿(相对复杂一些)

# 信号量实现读者优先

c
int readcount;
semaphore x = 1, wsem = 1;
void reader (){
    while (true) {
        semWait (x);
        readcount++;
        if (readcount == 1) semWait(wsem);
      	semSignal(x);
        READUNIT();
        semWait(x);
        readcount--;
        if (readcount == 0) semSignal(wsem);
      	semSignal (x);
    }
}
void writer (){
    while (true) {
        semWait (wsem) ;
        WRITEUNIT () ;
        semSignal (wsem) ;
    }
}
void main (){
    readcount = 0;
    parbegin (reader, writer);
}

# 单读者 - 单写者

Single-writer-single-reader problem

# 共享内存方式

利用 Linux 的接口实现

shmdata.h

c
#define TEXT_SIZE 4*1024 /* = PAGE_SIZE, size of each message */
#define TEXT_NUM 1 /* maximal number of messages */
/* total size can not exceed current shmmax, or an 'invalid argument' error occurs when shmget */
#define PERM S_IRUSR|S_IWUSR|IPC_CREAT
#define ERR_EXIT(m) \
  do { \
    perror(m); \
    exit(EXIT_FAILURE); \
  } while(0)
/* a demo structure, modified as needed */
struct shared_struct {
	int written; /* flag = 0: buffer writable; others: readable */
	char mtext[TEXT_SIZE]; /* buffer for message reading and writing */
};

shmcon.c

c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <fcntl.h>
#include "alg.8-0-shmdata.h"
int main(int argc, char *argv[]){
  struct stat fileattr;
  key_t key; /* of type int */
  int shmid; /* shared memory ID */
  void *shmptr;
  struct shared_struct *shared; /* structured shm */
  pid_t childpid1, childpid2;
  char pathname[80], key_str[10], cmd_str[80];
  int shmsize, ret;
  shmsize = TEXT_NUM*sizeof(struct shared_struct);
  printf("max record number = %d, shm size = %d\n", TEXT_NUM, shmsize);
  if(argc <2) {
    printf("Usage: ./a.out pathname\n");
    return EXIT_FAILURE;
  }
  strcpy(pathname, argv[1]);
  if(stat(pathname, &fileattr) == -1) {
      ret = creat(pathname, O_RDWR);
    if (ret == -1) {
      ERR_EXIT("creat()");
    }
    printf("shared file object created\n");
  }
  key = ftok(pathname, 0x27); /* 0x27 a pro_id 0x0001 - 0xffff, 8 least bits used */
  if(key == -1) {
  	ERR_EXIT("shmcon: ftok()");
  }
  printf("key generated: IPC key = 0x%x\n", key); /* set any key>0 without ftok() */
  shmid = shmget((key_t)key, shmsize, 0666|PERM);
  if(shmid == -1) {
  	ERR_EXIT("shmcon: shmget()");
  }
  printf("shmcon: shmid = %d\n", shmid);
  shmptr = shmat(shmid, 0, 0); /* returns the virtual base address mapping to the
  shared memory, *shmaddr=0 decided by kernel */
  if(shmptr == (void *)-1) {
  	ERR_EXIT("shmcon: shmat()");
  }
  printf("shmcon: shared Memory attached at %p\n", shmptr);
  shared = (struct shared_struct *)shmptr;
  shared->written = 0;
  sprintf(cmd_str, "ipcs -m | grep '%d'\n", shmid);
  printf("\n------ Shared Memory Segments ------\n");
  system(cmd_str);
  if(shmdt(shmptr) == -1) {
  	ERR_EXIT("shmcon: shmdt()");
  }
  printf("\n------ Shared Memory Segments ------\n");
  system(cmd_str);
  sprintf(key_str, "%x", key);
  char *argv1[] = {" ", key_str, 0};
  childpid1 = vfork();
  if(childpid1 < 0) {
  	ERR_EXIT("shmcon: 1st vfork()");
  }
  else if(childpid1 == 0) {
  	execv("./alg.8-2-shmread.o", argv1); /* call shm_read with IPC key */
  }
  else {
  	childpid2 = vfork();
    if(childpid2 < 0) {
      ERR_EXIT("shmcon: 2nd vfork()");
    }
    else if (childpid2 == 0) {
      execv("./alg.8-3-shmwrite.o", argv1); /* call shmwrite with IPC key */
    } else {
      wait(&childpid1);
      wait(&childpid2);
      /* shmid can be removed by any process known the
      IPC key */
      if (shmctl(shmid, IPC_RMID, 0) == -1) {
        ERR_EXIT("shmcon: shmctl(IPC_RMID)");
      } else {
        printf("shmcon: shmid = %d removed \n", shmid);
        printf("\n------ Shared Memory Segments ------\n");
        system(cmd_str);
        printf("nothing found ...\n");
        return EXIT_SUCCESS;
      }
    }
  }
}

shmread.c

c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/shm.h>
#include "alg.8-0-shmdata.h"
int main(int argc, char *argv[])
{
  void *shmptr = NULL;
  struct shared_struct *shared;
  int shmid;
  key_t key;
  sscanf(argv[1], "%x", &key);
  printf("%*sshmread: IPC key = 0x%x\n", 30, " ", key);
  shmid = shmget((key_t)key, TEXT_NUM*sizeof(struct shared_struct), 0666|PERM);
  if (shmid == -1) {
    ERR_EXIT("shread: shmget()");
  }
  shmptr = shmat(shmid, 0, 0);
  if(shmptr == (void *)-1) {
  	ERR_EXIT("shread: shmat()");
  }
  printf("%*sshmread: shmid = %d\n", 30, " ", shmid);
  printf("%*sshmread: shared memory attached at %p\n", 30, " ", shmptr);
  printf("%*sshmread process ready ...\n", 30, " ");
  shared = (struct shared_struct *)shmptr;
  while (1) {
    while (shared->written == 0) {
      sleep(1); /* message not ready, waiting ... */
    }
    printf("%*sYou wrote: %s\n", 30, " ", shared->mtext);
    shared->written = 0;
    if (strncmp(shared->mtext, "end", 3) == 0) {
      break;
    }
  } /* it is not reliable to use shared->written for process synchronization */
  if (shmdt(shmptr) == -1) {
  	ERR_EXIT("shmread: shmdt()");
  }
  sleep(1);
  exit(EXIT_SUCCESS);
}

shmwrite.c

c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/shm.h>
#include "alg.8-0-shmdata.h"
int main(int argc, char *argv[])
{
  void *shmptr = NULL;
  struct shared_struct *shared = NULL;
  int shmid;
  key_t key;
  char buffer[BUFSIZ + 1]; /* 8192bytes, saved from stdin */
  sscanf(argv[1], "%x", &key);
  printf("shmwrite: IPC key = 0x%x\n", key);
  shmid = shmget((key_t)key, TEXT_NUM*sizeof(struct shared_struct), 0666|PERM);
  if (shmid == -1) {
  	ERR_EXIT("shmwite: shmget()");
  }
  shmptr = shmat(shmid, 0, 0);
  if(shmptr == (void *)-1) {
  	ERR_EXIT("shmwrite: shmat()");
  }
  printf("shmwrite: shmid = %d\n", shmid);
  printf("shmwrite: shared memory attached at %p\n", shmptr);
  printf("shmwrite precess ready ...\n");
  shared = (struct shared_struct *)shmptr;
  while (1) {
    while (shared->written == 1) {
      sleep(1); /* message not read yet, waiting ... */
    }
    printf("Enter some text: ");
    fgets(buffer, BUFSIZ, stdin);
    strncpy(shared->mtext, buffer, TEXT_SIZE);
    printf("shared buffer: %s\n",shared->mtext);
    shared->written = 1; /* message prepared */
    if(strncmp(buffer, "end", 3) == 0) {
      break;
    }
  }
  /* detach the shared memory */
  if(shmdt(shmptr) == -1) {
  	ERR_EXIT("shmwrite: shmdt()");
  }
  sleep(1);
  exit(EXIT_SUCCESS);
}

ipcs 查看当前操作系统里有多少消息队列、共享内存块、信号量。

分别编译三个 .c 文件得到三个可执行文件: shmcon,shmread,shmwrite ,然后运行 ./shmcon myshm

# 哲学家问题

对称解决方案会导致死锁问题,可以考虑非对称解决方案

经典的非对称方案:

  • 单号哲学家先拿起左边的筷子,再拿起右边的筷子;而双号的哲学家先拿起右边的筷子,再拿起左边的筷子;

限制哲学家拿起筷子:

  • 只有哲学家的两根筷子都可用时,才能拿起筷子(哲学家可能饿死)

# 补充

被历史抛弃的事务型内存

Edited on Views times
\ No newline at end of file +经典进程同步问题 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

This article isn't finished yet...

# 严格备选

(Strict Alternation)

# PetersonSolution

# 互斥锁

互斥锁是一种外部强加的控制方案,或者说是全局控制;

获得锁:

伪代码
acquire {
    while (!available)
    ; /* busy wait */
    available = false;
}

释放锁:

伪代码
release {
  	available = true;
}

利用互斥锁的临界区问题解决方案:

伪代码
while (true) {
  	acquire lock
      	/* critical section */
    release lock
      	/* others */
}

但是这个方案需要繁忙的等待,所以也叫自旋锁(Spinlock)

存在优点:当进程在等待锁时,没有上下文切换,在使用锁的时间较短时,自旋锁是有用的;自旋锁通常用于多处理器系统

# 信号量

信号量是一种内部主动的控制方案,或者说是局部控制;

# 管程

管程(monitor)是一种面向对象的高级程序设计语言结构,它提供的功能与信号量相同,但更易于控制;

管程结构在很多程序设计语言中得以实现,包括:

  • 并发 Pascal
  • Pascal
  • Pascal-Plus
  • Modula-2
  • Modula-3
  • Java

现在已经被作为一个程序库实现;

管程是由一个或多个进程、一个初始化序列和局部数据组成的软件模块;(使用信号的管程)

c
monitor monitor name
{
    /* shared variable declarations */
    function P1 ( ... ) {
    		...
    }
    function P2 ( ... ) {
    		...
    }
    .
    .
    .
    function Pn ( ... ) {
    		...
    }
    initialization code ( ... ) {
    		...
    }
}

# 条件变量

定义附加的同步机制,可以由条件(condition)结构来提供;

当程序员需要编写定制的同步方案时,可以定义一个或者多个类型为 condition 的变量;

对于条件变量,只有操作 wait()signal 可以调用;

利用条件变量实现互斥访问以及控制执行顺序,这里 S1 必须在 S2 之前执行:

c
F1(){
    S1;
    		done = true;
    x.signal();
}
F2(){
    if done == false
    		x.wait()
    S2;
}

# 信号量实现

c
// Variables
    semaphore mutex; // (initially = 1)
    semaphore next; // (initially = 0)
    int next_count = 0; // number of processes waiting
// inside the monitor
// Each function P will be replaced by
    wait(mutex);
        ...
        body of P;
        ...
    if (next_count > 0)
        signal(next)
    else
        signal(mutex);
// Mutual exclusion within a monitor is ensured

# 条件变量实现

c
//For each condition variable x, we have:
    semaphore x_sem; // (initially = 0)
    int x_count = 0;
//The operation x.wait() can be implemented as:
    x_count++;
    if (next_count > 0)
        signal(next);
    else
        signal(mutex);
    wait(x_sem);
    x_count--;

其中 signal 方法实现参考:

c
if (x_count > 0) {
    next_count++;
    signal(x_sem);
    wait(next);
    next_count--;
}

# 进程恢复

  • 唤醒并等待(signal and wait)
    • 进程 P 等待进程直到进程 Q 离开管程,或者等待另一个条件;
    • 等待 Q 的时候若 P 想再次执行,需要测试 P 是否还具有执行的环境条件
  • 唤醒并继续(signal and continue)
    • 进程 Q 等待直到进程 P 离开管程或者等待另一个条件;

# java

java
public class BlockedQueue<T> (
    final Lock lock = new ReentrantLock () ;
    // 条件变量:队列不满
    final Condition notFull = lock.newCondition () ;
    // 条件变量:队列不空
    final Condition notEmpty = lock.newCondition ();
    // 入队
    void enq (T x) {
        lock. lock() ;
        try {
            whileStack已满){
                // 等待队列不满
                notFull.await () ;
            }
            // 省略入队操作
            // 入队后,通知可出队
            notEmpty.signal ();
        } finally {
        		lock.unlock () ;
        }
    }
    // 出队
    void deq() {
        lock.lock () ;
        try {
            while(队列已空){
            // 等待队列不空
            notEmpty.await () ;
            }
            // 省略出队操作.
            // 出队后,通知可入队
            notFull.signal () ;
        } finally {
        		lock.unlock () ;
    }
}

# 管程模型 (补充)

Hasen、Hoare 和 MESA 模型区别

Hasen 模型、Hoare 模型和 MESA 模型的一个核心区别就是当条件满足后,如何通知相关线程。管程要求同一时刻只允许一个线程执行,那当线程 T2 的操作使线程 T1 等待的条件满足时,T1 和 T2 究竟谁可以执行呢?

  • Hasen 模型里面,要求 notify() 放在代码的最后,这样 T2 通知完 T1 后,T2 就结束了,然后 T1 再执行,这样就能保证同一时刻只有一个线程执行。
  • Hoare 模型里面,T2 通知完 T1 后,T2 阻塞,T1 马上执行;等 T1 执行完,再唤醒 T2,也能保证同一时刻只有一个线程执行。但是相比 Hasen 模型,T2 多了一次阻塞唤醒操作。
  • MESA 管程里面,T2 通知完 T1 后,T2 还是会接着执行,T1 并不立即执行,仅仅是从条件变量的等待队列进到入口等待队列里面。这样做的好处是 notify() 不用放到代码的最后,T2 也没有多余的阻塞唤醒操作。但是也有个副作用,就是当 T1 再次执行的时候,可能曾经满足的条件,现在已经不满足了,所以需要以循环方式检验条件变量。

对于 MESA 管程来说,有一个编程范式,就是需要在一个 while 循环里面调用 wait() 。这个是 MESA 管程特有的!

# 生产者 - 消费者问题

# 信号量实现

producer
while (true) {
    ...
    /* produce an item in next produced */
    ...
    wait(empty);
    wait(mutex);  // 对应的 signal 不是本进程的,而一定是 consumer 进程的 signal !
    ...
    /* add next produced to the buffer */
    ...
    signal(mutex);  // 对应的 wait 不是本进程的,而一定是 consumer 进程的 wait !
    signal(full);
}
consumer
while (true) {
    wait(full);
    wait(mutex);  // 对应的 signal 不是本进程的,而一定是 producer 进程的 signal !
    ...
    /* remove an item from buffer to next consumed */
    ...
    signal(mutex);  // 对应的 wait 不是本进程的,而一定是 producer 进程的 wait !
    signal(empty);
    ...
    /* consume the item in next consumed */
    ...
}

# 错误案例

c
int n;
binary_semaphore s = 1, delay = 0;
void producer(){
    while (true) {
        produce();
        semWaitB(s);
        append();
        n++;
        if (n==1) semSignalB(delay);
        semSignalB(s);
    }
}
void consumer(){
    semWaitB(delay);
    while (true) {
        semWaitB(s);
        take();
        n--;
        semSignalB(s);
        consume();  /* 这里没有互斥,producer 打断则会导致后续 n 出现负值 */
        if (n==0) semWaitB(delay);
    }
}
void main(){
    n = 0;
    parbegin (producer, consumer);
}

consumer 的正确实现:

c
void consumer (){
    int m; /* a local variable */
  	semWaitB(delay) ;
    while (true) {
        semWaitB(s);
        take ( );
        n--;
        m = ni
        semSignalB(s) ;
        consume () ;
        if (m==0) semWaitB(delay);
    }
}

# 无限队列生产者消费者问题实现

缓冲区无大小限制

c
/* program producerconsumer */
semaphore n = 0, s = 1;
void producer(){
    while (true) {
        produce();
        semWait(s);
        append();
        semSignal(s);
        semSignal(n);
    }
}
void consumer(){
    while (true) {
        semWait(n);
        semWait(s);
        take();
        semSignal(s);
        consume();
    }
}
void main(){
		parbegin (producer, consumer);
}

# 管程实现

c
void append (char x){
    while (count == N) wait(notfull);   /* buffer is full; avoid overflow */
    buffer [nextin] = x;
    nextin = (nextin + 1) % N;
    count++                             /* one more item in buffer */
    cnotify (notempty) ;                /* notify any waiting consumer */
}
void take (char x){
    while (count == 0) wait(notempty) ; /* buffer is empty; avoid underflow */
    x = buffer[nextout];
    nextout = (nextout + 1) % N;
    count --;                           /* one fewer item in buffer */
  	cnotify(notfull) ;                  /* notify any waiting producer */
}

# 共享内存方式 (pthread)

利用 POSIX API (c 的 pthread) 实现共享内存。The API is supported by Linux 2.4 and later, FreeBSD, … 编译时需要: gcc -lrt filename.c

shmpthreadcon.c

c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "shmdata.h"
/* gcc -lrt */
int main(int argc, char *argv[])
{
  char pathname[80], cmd_str[80];
  struct stat fileattr;
  int fd, shmsize, ret;
  pid_t childpid1, childpid2;
  if(argc < 2) {
    printf("Usage: ./a.out filename\n");
    return EXIT_FAILURE;
  }
  fd = shm_open(argv[1], O_CREAT|O_RDWR, 0666);
  /* /dev/shm/filename as the shared object, creating if not exist */
  if(fd == -1) {
  	ERR_EXIT("con: shm_open()");
  }
  system("ls -l /dev/shm/");
  shmsize = TEXT_NUM*sizeof(struct shared_struct);
  ret = ftruncate(fd, shmsize);
  if(ret == -1) {
    ERR_EXIT"con: ftruncate()");
    char *argv1[] = {" ", argv[1], 0};
    childpid1 = vfork();
    if(childpid1 < 0) {
    	ERR_EXIT("shmpthreadcon: 1st vfork()");
    }
    else if(childpid1 == 0) {
    	execv("./shmproducer", argv1); /* call producer with filename */
    }
    else {
    	childpid2 = vfork();
    if(childpid2 < 0)
    	ERR_EXIT("shmpthreadcon: 2nd vfork()");
    else if (childpid2 == 0)
    	execv("shmconsumer.o", argv1); /* call consumer with filename */
    else {
      wait(&childpid1);
      wait(&childpid2);
      ret = shm_unlink(argv[1]);
      if(ret == -1) {
      	ERR_EXIT("con: shm_unlink()");
      } /* shared object can be removed by any process knew the filename */
      system("ls -l /dev/shm/");
    }
  }
	exit(EXIT_SUCCESS);
}

# 读者 - 写者问题

一个数据集在多个并发进程之间共享

  • Readers—— 仅读取数据集;它们不执行任何更新
  • Writer—— 既能读又能写

🤔问题:允许多个读者同时读取

  • 只有一个写者程序可以同时访问共享数据;
  • 写者在访问数据时,不允许读者访问数据;

读者和作者的考虑方式有几种不同 —— 都涉及某种形式的

优先权

  • 第一读者写者问题:读者优先;会导致写者饥饿
  • 第二读者写者问题:写者优先;会导致读者饥饿(相对复杂一些)

# 信号量实现读者优先

c
int readcount;
semaphore x = 1, wsem = 1;
void reader (){
    while (true) {
        semWait (x);
        readcount++;
        if (readcount == 1) semWait(wsem);
      	semSignal(x);
        READUNIT();
        semWait(x);
        readcount--;
        if (readcount == 0) semSignal(wsem);
      	semSignal (x);
    }
}
void writer (){
    while (true) {
        semWait (wsem) ;
        WRITEUNIT () ;
        semSignal (wsem) ;
    }
}
void main (){
    readcount = 0;
    parbegin (reader, writer);
}

# 单读者 - 单写者

Single-writer-single-reader problem

# 共享内存方式

利用 Linux 的接口实现

shmdata.h

c
#define TEXT_SIZE 4*1024 /* = PAGE_SIZE, size of each message */
#define TEXT_NUM 1 /* maximal number of messages */
/* total size can not exceed current shmmax, or an 'invalid argument' error occurs when shmget */
#define PERM S_IRUSR|S_IWUSR|IPC_CREAT
#define ERR_EXIT(m) \
  do { \
    perror(m); \
    exit(EXIT_FAILURE); \
  } while(0)
/* a demo structure, modified as needed */
struct shared_struct {
	int written; /* flag = 0: buffer writable; others: readable */
	char mtext[TEXT_SIZE]; /* buffer for message reading and writing */
};

shmcon.c

c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <fcntl.h>
#include "alg.8-0-shmdata.h"
int main(int argc, char *argv[]){
  struct stat fileattr;
  key_t key; /* of type int */
  int shmid; /* shared memory ID */
  void *shmptr;
  struct shared_struct *shared; /* structured shm */
  pid_t childpid1, childpid2;
  char pathname[80], key_str[10], cmd_str[80];
  int shmsize, ret;
  shmsize = TEXT_NUM*sizeof(struct shared_struct);
  printf("max record number = %d, shm size = %d\n", TEXT_NUM, shmsize);
  if(argc <2) {
    printf("Usage: ./a.out pathname\n");
    return EXIT_FAILURE;
  }
  strcpy(pathname, argv[1]);
  if(stat(pathname, &fileattr) == -1) {
      ret = creat(pathname, O_RDWR);
    if (ret == -1) {
      ERR_EXIT("creat()");
    }
    printf("shared file object created\n");
  }
  key = ftok(pathname, 0x27); /* 0x27 a pro_id 0x0001 - 0xffff, 8 least bits used */
  if(key == -1) {
  	ERR_EXIT("shmcon: ftok()");
  }
  printf("key generated: IPC key = 0x%x\n", key); /* set any key>0 without ftok() */
  shmid = shmget((key_t)key, shmsize, 0666|PERM);
  if(shmid == -1) {
  	ERR_EXIT("shmcon: shmget()");
  }
  printf("shmcon: shmid = %d\n", shmid);
  shmptr = shmat(shmid, 0, 0); /* returns the virtual base address mapping to the
  shared memory, *shmaddr=0 decided by kernel */
  if(shmptr == (void *)-1) {
  	ERR_EXIT("shmcon: shmat()");
  }
  printf("shmcon: shared Memory attached at %p\n", shmptr);
  shared = (struct shared_struct *)shmptr;
  shared->written = 0;
  sprintf(cmd_str, "ipcs -m | grep '%d'\n", shmid);
  printf("\n------ Shared Memory Segments ------\n");
  system(cmd_str);
  if(shmdt(shmptr) == -1) {
  	ERR_EXIT("shmcon: shmdt()");
  }
  printf("\n------ Shared Memory Segments ------\n");
  system(cmd_str);
  sprintf(key_str, "%x", key);
  char *argv1[] = {" ", key_str, 0};
  childpid1 = vfork();
  if(childpid1 < 0) {
  	ERR_EXIT("shmcon: 1st vfork()");
  }
  else if(childpid1 == 0) {
  	execv("./alg.8-2-shmread.o", argv1); /* call shm_read with IPC key */
  }
  else {
  	childpid2 = vfork();
    if(childpid2 < 0) {
      ERR_EXIT("shmcon: 2nd vfork()");
    }
    else if (childpid2 == 0) {
      execv("./alg.8-3-shmwrite.o", argv1); /* call shmwrite with IPC key */
    } else {
      wait(&childpid1);
      wait(&childpid2);
      /* shmid can be removed by any process known the
      IPC key */
      if (shmctl(shmid, IPC_RMID, 0) == -1) {
        ERR_EXIT("shmcon: shmctl(IPC_RMID)");
      } else {
        printf("shmcon: shmid = %d removed \n", shmid);
        printf("\n------ Shared Memory Segments ------\n");
        system(cmd_str);
        printf("nothing found ...\n");
        return EXIT_SUCCESS;
      }
    }
  }
}

shmread.c

c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/shm.h>
#include "alg.8-0-shmdata.h"
int main(int argc, char *argv[])
{
  void *shmptr = NULL;
  struct shared_struct *shared;
  int shmid;
  key_t key;
  sscanf(argv[1], "%x", &key);
  printf("%*sshmread: IPC key = 0x%x\n", 30, " ", key);
  shmid = shmget((key_t)key, TEXT_NUM*sizeof(struct shared_struct), 0666|PERM);
  if (shmid == -1) {
    ERR_EXIT("shread: shmget()");
  }
  shmptr = shmat(shmid, 0, 0);
  if(shmptr == (void *)-1) {
  	ERR_EXIT("shread: shmat()");
  }
  printf("%*sshmread: shmid = %d\n", 30, " ", shmid);
  printf("%*sshmread: shared memory attached at %p\n", 30, " ", shmptr);
  printf("%*sshmread process ready ...\n", 30, " ");
  shared = (struct shared_struct *)shmptr;
  while (1) {
    while (shared->written == 0) {
      sleep(1); /* message not ready, waiting ... */
    }
    printf("%*sYou wrote: %s\n", 30, " ", shared->mtext);
    shared->written = 0;
    if (strncmp(shared->mtext, "end", 3) == 0) {
      break;
    }
  } /* it is not reliable to use shared->written for process synchronization */
  if (shmdt(shmptr) == -1) {
  	ERR_EXIT("shmread: shmdt()");
  }
  sleep(1);
  exit(EXIT_SUCCESS);
}

shmwrite.c

c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/shm.h>
#include "alg.8-0-shmdata.h"
int main(int argc, char *argv[])
{
  void *shmptr = NULL;
  struct shared_struct *shared = NULL;
  int shmid;
  key_t key;
  char buffer[BUFSIZ + 1]; /* 8192bytes, saved from stdin */
  sscanf(argv[1], "%x", &key);
  printf("shmwrite: IPC key = 0x%x\n", key);
  shmid = shmget((key_t)key, TEXT_NUM*sizeof(struct shared_struct), 0666|PERM);
  if (shmid == -1) {
  	ERR_EXIT("shmwite: shmget()");
  }
  shmptr = shmat(shmid, 0, 0);
  if(shmptr == (void *)-1) {
  	ERR_EXIT("shmwrite: shmat()");
  }
  printf("shmwrite: shmid = %d\n", shmid);
  printf("shmwrite: shared memory attached at %p\n", shmptr);
  printf("shmwrite precess ready ...\n");
  shared = (struct shared_struct *)shmptr;
  while (1) {
    while (shared->written == 1) {
      sleep(1); /* message not read yet, waiting ... */
    }
    printf("Enter some text: ");
    fgets(buffer, BUFSIZ, stdin);
    strncpy(shared->mtext, buffer, TEXT_SIZE);
    printf("shared buffer: %s\n",shared->mtext);
    shared->written = 1; /* message prepared */
    if(strncmp(buffer, "end", 3) == 0) {
      break;
    }
  }
  /* detach the shared memory */
  if(shmdt(shmptr) == -1) {
  	ERR_EXIT("shmwrite: shmdt()");
  }
  sleep(1);
  exit(EXIT_SUCCESS);
}

ipcs 查看当前操作系统里有多少消息队列、共享内存块、信号量。

分别编译三个 .c 文件得到三个可执行文件: shmcon,shmread,shmwrite ,然后运行 ./shmcon myshm

# 哲学家问题

对称解决方案会导致死锁问题,可以考虑非对称解决方案

经典的非对称方案:

  • 单号哲学家先拿起左边的筷子,再拿起右边的筷子;而双号的哲学家先拿起右边的筷子,再拿起左边的筷子;

限制哲学家拿起筷子:

  • 只有哲学家的两根筷子都可用时,才能拿起筷子(哲学家可能饿死)

# 补充

被历史抛弃的事务型内存

Edited on Views times
\ No newline at end of file diff --git a/cs/os/thread/index.html b/cs/os/thread/index.html index 0b759b0b..e1487ea5 100644 --- a/cs/os/thread/index.html +++ b/cs/os/thread/index.html @@ -1 +1 @@ -线程 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 线程的基本概念

# 为什么需要线程

有的进程可能需要 “同时” 做很多事,而传统的进程只能串行地执行一系列程序。为此,引入了 “线程”,来增加并发度。

大多数现代应用程序都是多线程的,线程在应用程序中运行,应用程序的多个任务可以由单独的线程实现

如 Web 浏览器:

  • 更新显示
  • 获取数据
  • 拼写检查
  • 响应网络请求

进程创建很重载,而线程创建很轻量

可以简化代码,提高效率;

内核 (作为内核程序进程) 通常是多线程的,多个线程在内核中运行,每个线程执行一个特定的任务;

现代服务器 —— 多线程服务器,可以同时处理多个并发请求

# 线程进程对比

系统资源分配与处理器调度

引入线程后,进程只作为除 CPU 之外的系统资源 的 基本分配单元 (最小单位)(如打印机、内存地址空间等都是分配给进程的);CPU 的 分配单元 则是线程


并发性

引入线程之后,不仅是进程之间可以并发,进程内的各线程之间也可以并发,从而进一步提升了系统的并发度,使得一个进程内也可以并发处理各种任务。


系统开销

  • 传统的进程间并发,需要切换进程的运行环境,系统开销很大
  • 线程间并发,如果是同一进程内的线程切换,则不需要切换进程环境,系统开销小

独立性

某个进程中的线程对其他进程是不可见的

每个进程都拥有独立的地址空间和资源,除了共享全局变量不允许其他进程访问


支持多处理器系统

  • 传统单线程进程不管系统有多少 CPU ,进程只能运行在一个 CPU 上
  • 对于多线程进程,进程多个线程可以分配到多个 CPU 上执行

# 线程的组成

线程也有叫做轻量级进程(LWP),线程只包含运行时的状态

  • (用户空间)静态部分由进程提供,与其他线程共享:
    • 代码段 text
    • 数据段 data
    • 堆 heap
    • 其他操作系统资源
  • (内核空间)TCB—— 包括了执行所需的最小状态 (主要是寄存器和栈);
    • TID
    • 程序计数器 PC
    • 寄存器
    • 栈 stack(的指针)(每个线程拥有自己的栈,内核中也有为线程准备的内核栈)
    • 指向父进程 / 线程的指针
    • 指向子进程 / 线程的指针

一个进程可以包含多个线程

  • 每个线程共享同一地址空间 (方便数据共享和交互);
  • 允许进程内并行;

# 单线程

早期操作系统多为单线程进程的结构,实际上也没有形成线程的概念。例如 MS-DOS

单线程进程

# 多线程

多线程是指操作系统在单个进程内支持多个并发执行路径的能力。

多线程进程

多线程的优点:

  • 响应性 —— 如果部分线程被阻塞,仍可以继续执行,这对于 用户界面设计尤其重要,快速响应;
  • 资源共享 —— 线程共享进程资源,比进程共享内存或消息传 递更容易,允许一个应用程序在同一地址空间内有多个不 同的活跃线程;
  • 经济 —— 比进程创建更便宜,线程切换比上下文切换开销更 低。进程创建是线程创建的几十倍,进程切换比线程切换 慢 5 倍;
  • 可扩展性 (可伸缩性)—— 线程可以利用多核体系结构;

# 多核并行

单核下只能并发执行的任务,现在可以通过多核(多线程)并行执行

# 两类并行

  • 数据并行性 —— 将相同数据的子集分布在多个核上,每个核上的操作相同;

    数据并行

  • 任务并行性 —— 将任务而不是数据分配到多个计算核心, 每个线程执行唯一的操作,不同线程可以操作相同的数据,也可以操作不同的数据;

    任务并行

OpenAI 采用的就是数据并行、任务并行混合使用

# Amdahl 定律

N 条并行,串行占比 S :

speedup1S+(1S)N+speedup\leq\frac{1}{S+\frac{(1-S)}{N}+\cdots}

定律是否考虑了当代多核系统?—— 分母部分会增加 “通信项”,代表核间通信的开销

# TCB

Linux 中进程与线程使用的是同一种数据结构 task_struct ,大多数操作系统也都是线程进程共享这样的数据结构

# 线程的实现方式

“用户级线程” 就是 “从用户视角看能看到的线程”,早期操作系统只有用户级线程

“内核级线程” 就是 “从操作系统内核视角看能看到的线程” ,现代操作系统支持内核级线程

# 用户级线程

User-Level Thread,ULT

用户级线程

  1. 用户级线程由应用程序通过线程库(例如 pthreads )实现,所有的线程管理工作都由应用程序负责(包括线程切换)
  2. 用户级线程中,线程切换可以在用户态下即可完成,无需操作系统干预。
  3. 在用户看来,是有多个线程。但是从内核、操作系统的角度来看,并意识不到线程的存在。

线程不存在挂起态,因为线程不拥有资源!进程才拥有资源,才有 “挂起态”。

三状态线程模型:

三状态线程模型

优缺点

  • 优点:

    • 用户级线程的切换在用户空间即可完成,不需要切换到核心态,线程管理的系统开销小效率高
    • 可以由用户程序自己的调度算法来调度线程
    • 跨平台,在任何操作系统都可以运行,可迁移性强
  • 缺点:

    • 当一个用户级线程被阻塞后,整个进程都会被阻塞,并发度不高。多个线程不可在多核处理机上并行运行。

      • 没有内核线程在阻塞时提供并行能力
      • 解决方案:
        • 套管(Jacketing)把一个产生阻塞的系统调用转化为一个非阻塞的系统调用;
        • 把应用程序写成一个多进程程序而非多线程程序,每次切换都变成进程间的切换而非线程间切换,例如 Python
    • 在纯 ULT 策略中,多线程应用程序不能利用多处理技术。内核一次只把一个进程分配给一个处理器,因此一个进程中只有一个线程可以执行。

# 内核级线程

Kernel-Level Thread, KLT,又称 “内核支持的线程”

  1. 内核级线程管理工作由操作系统内核完成。
  2. 线程调度、切换等工作都由内核负责,因此内核级线程的切换必然需要在核心态下才能完成。
  3. 操作系统会为每个内核级线程建立相应的 TCB (Thread Control Block, 线程控制块),通过 TCB 对线程进行管理。
  4. 应用级没有线程管理代码,只有一个内核线程设施的应用编程接口(API),例如 Windows

优缺点

  • 优点:

    • 内核可以同时把同一个进程中的多个线程调度到多个处理器;
    • 当一个线程被阻塞后,别的线程还可以继续执行,并发能力强。多线程可在多核处理机上并行执行。
    • 内核线程自身也可以是多线程
  • 缺点:

    • 一个用户进程会占用多个内核级线程,线程切换由操作系统内核完成,需要切换到核心态,因此线程管理能成本高开销大

# 多线程模型

在支持内核级线程的系统中,根据用户级线程和内核级线程的映射关系,可以划分为几种多线程模型

# 多对一模型

个人理解就是只支持用户级线程,而不支持内核级线程的情况,早期操作系统的类型

多个用户级线程映射到一个内核级线程。且一个进程只被分配一个内核级线程。

例如 UNIX

多对一模型

  • 优点:
    • 用户级线程的切换在用户空间即可完成,不需要切换到核心态,线程管理的系统开销小,效率高
  • 缺点:
    • 当一个用户级线程被阻塞后,整个进程都会被阻塞
    • 并发度不高。多个线程不可在多核处理机上并行运行

操作系统只 “看得见” 内核级线程,因此只有内核级线程才是处理机分配的单位。

# 一对一模型

一个用户级线程映射到一个内核级线程。每个用户进程有与用户级线程同数量的内核级线程。

例如 Linux 、Windows

一对一模型

  • 优点:
    • 当一个线程被阻塞后,别的线程还可以继续执行
    • 并发能力强。多线程可在多核处理机上并行执行
  • 缺点:
    • 一个用户进程会占用多个内核级线程, 线程切换由操作系统内核完成,需要切换到核心态,开销大
    • 由于内核存储空间的限制,无法创建太多的线程
    • 每创建一个用户线程就要创建一个内核线程,一个用户进程可能占用很多内核线程,开销大

# 多对多模型

ULT 和 KLT 混合的模式,例如 Solaris 。实际上非常复杂,目前没有操作系统能够很好地实现这种模型

多对多模型:n 用户及线程映射到 m 个内核级线程(nmn\geq m)。每个用户进程对应 m 个内核级线程。

多对多模型

  • 克服了多对一模型并发度不高的缺点(一个阻塞全体阻塞)
  • 克服了一对一模型中一个用户进程占用太多内核级线程,开销太大的缺点

可以这么理解:

  • 用户级线程是 “代码逻辑” 的载体
  • 内核级线程是 “运行机会” 的载体

内核级线程中可以运行任意一个有映射关系的用户级线程代码,一个进程只有所有与其有映射关系的内核级线程中正在运行的代码逻辑都阻塞时,这个进程才会阻塞

  • 优点:
    • 可以创建很多线程
    • 并发度高
  • 缺点:
    • 复杂、难以管理、难实现

# 一对多模型?

一个线程对应多个进程

执行过程中发生状态的迁移,就需要将线程从一个进程迁移到另一个进程

例如银行系统,一个请求会多个有一模一样的进程处理,如果其中一个出现了错误,就会将其他正确的进程迁移过去

# 现代多线程

  • 异步线程 Asynchronous threading

    父线程创建子线程后继续运行,父子线程并发、独立运行。

  • 同步线程 Synchronous threading

    父线程创建子线程后等待子线程结束后再继续运行,采用 Fork-join strategy ,类似于 Linux 进程中的 fork+wait+exit 。

# 线程库

线程库程序员提供了创建和管理线程的 API;

两种主要的实施方式:

  • 第一种方式:在用户空间中提供一个没有内核支持的库;
  • 第二种方法:实现操作系统支持的内核级库;

三种主要的线程库:

  • POSIX Pthreads(用户层次或者内核层次);

    • #include<pthread>
  • Windows API(内核层次);

    • 特色: WaitForSingleObject(...) / WaitForMultipleObject(...)
    • 支持线程池
  • Java(利用 Windows API 或者 pthreads 来实现);

    • 由 JVM 管理,通常使用底层操作系统提供的线程模型实现

    • Java 线程可以通过以下方式创建:

      • 扩展线程类
      • 实现可运行接口
      • 标准实践是实现可运行接口
    • 允许围绕 Executor 接口创建线程,典型的线程池

      • static ExecutorService newSingleThreadExecutor()
      • static ExecutorService newFixedThreadPool (int size)
      • static ExecutorService newCachedThreadPool()

# Linux 线程

Linux 将它们称为任务(task)而不是线程

线程创建是通过 clone() 系统调用完成的(Linux 上用 pthread 库的创建线程也是使用这个系统调用)

clone() 允许子任务共享父任务 (进程) 的地址空间

标记控件行为...

结构 task_struct 指向流程数据结构 (共享或唯一)

# 隐式多线程

随着线程数量的增加,程序员来控制多线程程序变得越来越困难,于是诞生了由编译器和运行时库而不是程序员创建和管理线程的隐式多线程

探索了五种方法

  • 线程池

  • Fork-Join

    • 适用于超算、高性能计算场景,利用嵌套创建子线程可以短时间创建数百万子线程
  • OpenMP

    • 让编译器实现程序的多线程并行化
    • 指令指定代码编译为多线程并行程序
      • #pragma omp parallel {...}
      • #pragma omp for ...
  • 中央大调度 (GCD) (eg: Apple...)

    • 目标是自动识别程序的并行部分并实现并行化
    • C、C++ 和 Obj-C 语言、API 和运行库的扩展
  • 英特尔线程构件 (TBB)

    • 设计并行 C++ 程序的模板库
    • parallel_forfor 的并行化版本

# 多线程引入的问题

  • fork()exec() 系统调用的语义
    • fork() 是只复制调用线程,还是复制该进程的所有线程?
      • 有些 UNIX 有 2 种 fork 版本
    • exec() 通常正常工作,替换正在运行的进程,包括所有线程

UNIX 中的信号 —— 用于通知进程某个特定事件已发生。

信号处理器用于处理信号

  1. 信号由特定事件产生

  2. 信号被传送到进程

  3. 信号由两个信号处理程序之一处理:

    • 缺省的信号处理程序
    • 用户定义

每个信号都有内核在处理信号时运行的默认处理程序

  • 用户定义的信号处理程序可以覆盖默认值
  • 对于单线程,信号传输到进程
  • 信号处理

    • 同步 / 异步
    • 多线程的信号应该在哪里传递?
      • 将信号传递到应用该信号的线程(一对一)
      • 将信号传递给进程中的每个线程(一对多)
      • 将信号传递给进程中的某些线程(一对一)
      • 指定一个特定线程来接收进程的所有信号(多对一)
  • 线程取消(要终止的线程一般叫做目标线程)

    • 异步 —— 立即终止目标线程
    • 延迟 —— 允许目标线程定期 —— 也就是执行到代码中的 “取消点” 的时候 —— 检查是否应该取消,缺省情况下都是这种情况
    • Linux 由信号处理,而且应该是一对一的
    • Java 用 interrupt 方法
  • 线程本地存储

    • 线程本地存储 (TLS) 允许每个线程拥有自己的数据副本,有这些好处:

      • 当无法控制线程创建过程时 (即,当使用线程池时),此功能非常有用
      • 可以避免不同线程之间访问同一互斥变量带来的性能损失
    • 与局部变量不同

      • 局部变量仅在单个函数调用期间可见
      • TLS 在函数调用中可见
    • 类似于静态数据

      • TLS 对于每个线程都是唯一的
  • 调度程序激活

    • 多对多模型和一对一模型都需要通信来维护分配给应用程序的适当数量的内核线程

    • 通常在用户线程和内核线程之间使用中间数据结构 —— 轻量级进程 (LWP, Light Weight Process)

      • 似乎是一个虚拟处理器,进程可以 在该处理器上调度用户线程运行
      • 每个 LWP 都连接到内核线程
      • 要创建多少 LWP?
    • 调度器激活提供了 upcall —— 一种从内核到线程库中 upcall 处理程序的通信机制

    • 这种通信允许应用程序保持正确的内核线程数

Edited on Views times
\ No newline at end of file +线程 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 线程的基本概念

# 为什么需要线程

有的进程可能需要 “同时” 做很多事,而传统的进程只能串行地执行一系列程序。为此,引入了 “线程”,来增加并发度。

大多数现代应用程序都是多线程的,线程在应用程序中运行,应用程序的多个任务可以由单独的线程实现

如 Web 浏览器:

  • 更新显示
  • 获取数据
  • 拼写检查
  • 响应网络请求

进程创建很重载,而线程创建很轻量

可以简化代码,提高效率;

内核 (作为内核程序进程) 通常是多线程的,多个线程在内核中运行,每个线程执行一个特定的任务;

现代服务器 —— 多线程服务器,可以同时处理多个并发请求

# 线程进程对比

系统资源分配与处理器调度

引入线程后,进程只作为除 CPU 之外的系统资源 的 基本分配单元 (最小单位)(如打印机、内存地址空间等都是分配给进程的);CPU 的 分配单元 则是线程


并发性

引入线程之后,不仅是进程之间可以并发,进程内的各线程之间也可以并发,从而进一步提升了系统的并发度,使得一个进程内也可以并发处理各种任务。


系统开销

  • 传统的进程间并发,需要切换进程的运行环境,系统开销很大
  • 线程间并发,如果是同一进程内的线程切换,则不需要切换进程环境,系统开销小

独立性

某个进程中的线程对其他进程是不可见的

每个进程都拥有独立的地址空间和资源,除了共享全局变量不允许其他进程访问


支持多处理器系统

  • 传统单线程进程不管系统有多少 CPU ,进程只能运行在一个 CPU 上
  • 对于多线程进程,进程多个线程可以分配到多个 CPU 上执行

# 线程的组成

线程也有叫做轻量级进程(LWP),线程只包含运行时的状态

  • (用户空间)静态部分由进程提供,与其他线程共享:
    • 代码段 text
    • 数据段 data
    • 堆 heap
    • 其他操作系统资源
  • (内核空间)TCB—— 包括了执行所需的最小状态 (主要是寄存器和栈);
    • TID
    • 程序计数器 PC
    • 寄存器
    • 栈 stack(的指针)(每个线程拥有自己的栈,内核中也有为线程准备的内核栈)
    • 指向父进程 / 线程的指针
    • 指向子进程 / 线程的指针

一个进程可以包含多个线程

  • 每个线程共享同一地址空间 (方便数据共享和交互);
  • 允许进程内并行;

# 单线程

早期操作系统多为单线程进程的结构,实际上也没有形成线程的概念。例如 MS-DOS

单线程进程

# 多线程

多线程是指操作系统在单个进程内支持多个并发执行路径的能力。

多线程进程

多线程的优点:

  • 响应性 —— 如果部分线程被阻塞,仍可以继续执行,这对于 用户界面设计尤其重要,快速响应;
  • 资源共享 —— 线程共享进程资源,比进程共享内存或消息传 递更容易,允许一个应用程序在同一地址空间内有多个不 同的活跃线程;
  • 经济 —— 比进程创建更便宜,线程切换比上下文切换开销更 低。进程创建是线程创建的几十倍,进程切换比线程切换 慢 5 倍;
  • 可扩展性 (可伸缩性)—— 线程可以利用多核体系结构;

# 多核并行

单核下只能并发执行的任务,现在可以通过多核(多线程)并行执行

# 两类并行

  • 数据并行性 —— 将相同数据的子集分布在多个核上,每个核上的操作相同;

    数据并行

  • 任务并行性 —— 将任务而不是数据分配到多个计算核心, 每个线程执行唯一的操作,不同线程可以操作相同的数据,也可以操作不同的数据;

    任务并行

OpenAI 采用的就是数据并行、任务并行混合使用

# Amdahl 定律

N 条并行,串行占比 S :

speedup1S+(1S)N+speedup\leq\frac{1}{S+\frac{(1-S)}{N}+\cdots}

定律是否考虑了当代多核系统?—— 分母部分会增加 “通信项”,代表核间通信的开销

# TCB

Linux 中进程与线程使用的是同一种数据结构 task_struct ,大多数操作系统也都是线程进程共享这样的数据结构

# 线程的实现方式

“用户级线程” 就是 “从用户视角看能看到的线程”,早期操作系统只有用户级线程

“内核级线程” 就是 “从操作系统内核视角看能看到的线程” ,现代操作系统支持内核级线程

# 用户级线程

User-Level Thread,ULT

用户级线程

  1. 用户级线程由应用程序通过线程库(例如 pthreads )实现,所有的线程管理工作都由应用程序负责(包括线程切换)
  2. 用户级线程中,线程切换可以在用户态下即可完成,无需操作系统干预。
  3. 在用户看来,是有多个线程。但是从内核、操作系统的角度来看,并意识不到线程的存在。

线程不存在挂起态,因为线程不拥有资源!进程才拥有资源,才有 “挂起态”。

三状态线程模型:

三状态线程模型

优缺点

  • 优点:

    • 用户级线程的切换在用户空间即可完成,不需要切换到核心态,线程管理的系统开销小效率高
    • 可以由用户程序自己的调度算法来调度线程
    • 跨平台,在任何操作系统都可以运行,可迁移性强
  • 缺点:

    • 当一个用户级线程被阻塞后,整个进程都会被阻塞,并发度不高。多个线程不可在多核处理机上并行运行。

      • 没有内核线程在阻塞时提供并行能力
      • 解决方案:
        • 套管(Jacketing)把一个产生阻塞的系统调用转化为一个非阻塞的系统调用;
        • 把应用程序写成一个多进程程序而非多线程程序,每次切换都变成进程间的切换而非线程间切换,例如 Python
    • 在纯 ULT 策略中,多线程应用程序不能利用多处理技术。内核一次只把一个进程分配给一个处理器,因此一个进程中只有一个线程可以执行。

# 内核级线程

Kernel-Level Thread, KLT,又称 “内核支持的线程”

  1. 内核级线程管理工作由操作系统内核完成。
  2. 线程调度、切换等工作都由内核负责,因此内核级线程的切换必然需要在核心态下才能完成。
  3. 操作系统会为每个内核级线程建立相应的 TCB (Thread Control Block, 线程控制块),通过 TCB 对线程进行管理。
  4. 应用级没有线程管理代码,只有一个内核线程设施的应用编程接口(API),例如 Windows

优缺点

  • 优点:

    • 内核可以同时把同一个进程中的多个线程调度到多个处理器;
    • 当一个线程被阻塞后,别的线程还可以继续执行,并发能力强。多线程可在多核处理机上并行执行。
    • 内核线程自身也可以是多线程
  • 缺点:

    • 一个用户进程会占用多个内核级线程,线程切换由操作系统内核完成,需要切换到核心态,因此线程管理能成本高开销大

# 多线程模型

在支持内核级线程的系统中,根据用户级线程和内核级线程的映射关系,可以划分为几种多线程模型

# 多对一模型

个人理解就是只支持用户级线程,而不支持内核级线程的情况,早期操作系统的类型

多个用户级线程映射到一个内核级线程。且一个进程只被分配一个内核级线程。

例如 UNIX

多对一模型

  • 优点:
    • 用户级线程的切换在用户空间即可完成,不需要切换到核心态,线程管理的系统开销小,效率高
  • 缺点:
    • 当一个用户级线程被阻塞后,整个进程都会被阻塞
    • 并发度不高。多个线程不可在多核处理机上并行运行

操作系统只 “看得见” 内核级线程,因此只有内核级线程才是处理机分配的单位。

# 一对一模型

一个用户级线程映射到一个内核级线程。每个用户进程有与用户级线程同数量的内核级线程。

例如 Linux 、Windows

一对一模型

  • 优点:
    • 当一个线程被阻塞后,别的线程还可以继续执行
    • 并发能力强。多线程可在多核处理机上并行执行
  • 缺点:
    • 一个用户进程会占用多个内核级线程, 线程切换由操作系统内核完成,需要切换到核心态,开销大
    • 由于内核存储空间的限制,无法创建太多的线程
    • 每创建一个用户线程就要创建一个内核线程,一个用户进程可能占用很多内核线程,开销大

# 多对多模型

ULT 和 KLT 混合的模式,例如 Solaris 。实际上非常复杂,目前没有操作系统能够很好地实现这种模型

多对多模型:n 用户及线程映射到 m 个内核级线程(nmn\geq m)。每个用户进程对应 m 个内核级线程。

多对多模型

  • 克服了多对一模型并发度不高的缺点(一个阻塞全体阻塞)
  • 克服了一对一模型中一个用户进程占用太多内核级线程,开销太大的缺点

可以这么理解:

  • 用户级线程是 “代码逻辑” 的载体
  • 内核级线程是 “运行机会” 的载体

内核级线程中可以运行任意一个有映射关系的用户级线程代码,一个进程只有所有与其有映射关系的内核级线程中正在运行的代码逻辑都阻塞时,这个进程才会阻塞

  • 优点:
    • 可以创建很多线程
    • 并发度高
  • 缺点:
    • 复杂、难以管理、难实现

# 一对多模型?

一个线程对应多个进程

执行过程中发生状态的迁移,就需要将线程从一个进程迁移到另一个进程

例如银行系统,一个请求会多个有一模一样的进程处理,如果其中一个出现了错误,就会将其他正确的进程迁移过去

# 现代多线程

  • 异步线程 Asynchronous threading

    父线程创建子线程后继续运行,父子线程并发、独立运行。

  • 同步线程 Synchronous threading

    父线程创建子线程后等待子线程结束后再继续运行,采用 Fork-join strategy ,类似于 Linux 进程中的 fork+wait+exit 。

# 线程库

线程库程序员提供了创建和管理线程的 API;

两种主要的实施方式:

  • 第一种方式:在用户空间中提供一个没有内核支持的库;
  • 第二种方法:实现操作系统支持的内核级库;

三种主要的线程库:

  • POSIX Pthreads(用户层次或者内核层次);

    • #include<pthread>
  • Windows API(内核层次);

    • 特色: WaitForSingleObject(...) / WaitForMultipleObject(...)
    • 支持线程池
  • Java(利用 Windows API 或者 pthreads 来实现);

    • 由 JVM 管理,通常使用底层操作系统提供的线程模型实现

    • Java 线程可以通过以下方式创建:

      • 扩展线程类
      • 实现可运行接口
      • 标准实践是实现可运行接口
    • 允许围绕 Executor 接口创建线程,典型的线程池

      • static ExecutorService newSingleThreadExecutor()
      • static ExecutorService newFixedThreadPool (int size)
      • static ExecutorService newCachedThreadPool()

# Linux 线程

Linux 将它们称为任务(task)而不是线程

线程创建是通过 clone() 系统调用完成的(Linux 上用 pthread 库的创建线程也是使用这个系统调用)

clone() 允许子任务共享父任务 (进程) 的地址空间

标记控件行为...

结构 task_struct 指向流程数据结构 (共享或唯一)

# 隐式多线程

随着线程数量的增加,程序员来控制多线程程序变得越来越困难,于是诞生了由编译器和运行时库而不是程序员创建和管理线程的隐式多线程

探索了五种方法

  • 线程池

  • Fork-Join

    • 适用于超算、高性能计算场景,利用嵌套创建子线程可以短时间创建数百万子线程
  • OpenMP

    • 让编译器实现程序的多线程并行化
    • 指令指定代码编译为多线程并行程序
      • #pragma omp parallel {...}
      • #pragma omp for ...
  • 中央大调度 (GCD) (eg: Apple...)

    • 目标是自动识别程序的并行部分并实现并行化
    • C、C++ 和 Obj-C 语言、API 和运行库的扩展
  • 英特尔线程构件 (TBB)

    • 设计并行 C++ 程序的模板库
    • parallel_forfor 的并行化版本

# 多线程引入的问题

  • fork()exec() 系统调用的语义
    • fork() 是只复制调用线程,还是复制该进程的所有线程?
      • 有些 UNIX 有 2 种 fork 版本
    • exec() 通常正常工作,替换正在运行的进程,包括所有线程

UNIX 中的信号 —— 用于通知进程某个特定事件已发生。

信号处理器用于处理信号

  1. 信号由特定事件产生

  2. 信号被传送到进程

  3. 信号由两个信号处理程序之一处理:

    • 缺省的信号处理程序
    • 用户定义

每个信号都有内核在处理信号时运行的默认处理程序

  • 用户定义的信号处理程序可以覆盖默认值
  • 对于单线程,信号传输到进程
  • 信号处理

    • 同步 / 异步
    • 多线程的信号应该在哪里传递?
      • 将信号传递到应用该信号的线程(一对一)
      • 将信号传递给进程中的每个线程(一对多)
      • 将信号传递给进程中的某些线程(一对一)
      • 指定一个特定线程来接收进程的所有信号(多对一)
  • 线程取消(要终止的线程一般叫做目标线程)

    • 异步 —— 立即终止目标线程
    • 延迟 —— 允许目标线程定期 —— 也就是执行到代码中的 “取消点” 的时候 —— 检查是否应该取消,缺省情况下都是这种情况
    • Linux 由信号处理,而且应该是一对一的
    • Java 用 interrupt 方法
  • 线程本地存储

    • 线程本地存储 (TLS) 允许每个线程拥有自己的数据副本,有这些好处:

      • 当无法控制线程创建过程时 (即,当使用线程池时),此功能非常有用
      • 可以避免不同线程之间访问同一互斥变量带来的性能损失
    • 与局部变量不同

      • 局部变量仅在单个函数调用期间可见
      • TLS 在函数调用中可见
    • 类似于静态数据

      • TLS 对于每个线程都是唯一的
  • 调度程序激活

    • 多对多模型和一对一模型都需要通信来维护分配给应用程序的适当数量的内核线程

    • 通常在用户线程和内核线程之间使用中间数据结构 —— 轻量级进程 (LWP, Light Weight Process)

      • 似乎是一个虚拟处理器,进程可以 在该处理器上调度用户线程运行
      • 每个 LWP 都连接到内核线程
      • 要创建多少 LWP?
    • 调度器激活提供了 upcall —— 一种从内核到线程库中 upcall 处理程序的通信机制

    • 这种通信允许应用程序保持正确的内核线程数

Edited on Views times
\ No newline at end of file diff --git a/cs/os/ysosv2/lab0/index.html b/cs/os/ysosv2/lab0/index.html index 12d5ffd0..ed61329e 100644 --- a/cs/os/ysosv2/lab0/index.html +++ b/cs/os/ysosv2/lab0/index.html @@ -1 +1 @@ -YSOSv2: lab0 实验报告 - YSOSv2 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
Edited on Views times
\ No newline at end of file +YSOSv2: lab0 实验报告 - YSOSv2 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
Edited on Views times
\ No newline at end of file diff --git a/cs/os/ysosv2/lab1/index.html b/cs/os/ysosv2/lab1/index.html index ca0ace32..88b9cf98 100644 --- a/cs/os/ysosv2/lab1/index.html +++ b/cs/os/ysosv2/lab1/index.html @@ -1 +1 @@ -YSOSv2: lab1 实验报告 - YSOSv2 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
Edited on Views times
\ No newline at end of file +YSOSv2: lab1 实验报告 - YSOSv2 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
Edited on Views times
\ No newline at end of file diff --git a/cs/os/ysosv2/lab2/index.html b/cs/os/ysosv2/lab2/index.html index 0b7bdb0c..f944580c 100644 --- a/cs/os/ysosv2/lab2/index.html +++ b/cs/os/ysosv2/lab2/index.html @@ -1 +1 @@ -YSOSv2: lab2 实验报告 - YSOSv2 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
Edited on Views times
\ No newline at end of file +YSOSv2: lab2 实验报告 - YSOSv2 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
Edited on Views times
\ No newline at end of file diff --git a/cs/os/ysosv2/lab3/index.html b/cs/os/ysosv2/lab3/index.html index f165e3a8..188abc83 100644 --- a/cs/os/ysosv2/lab3/index.html +++ b/cs/os/ysosv2/lab3/index.html @@ -1 +1 @@ -YSOSv2: lab3 实验报告 - YSOSv2 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
Edited on Views times
\ No newline at end of file +YSOSv2: lab3 实验报告 - YSOSv2 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
Edited on Views times
\ No newline at end of file diff --git a/cs/os/ysosv2/lab4/index.html b/cs/os/ysosv2/lab4/index.html index 12be4b6f..35981cbb 100644 --- a/cs/os/ysosv2/lab4/index.html +++ b/cs/os/ysosv2/lab4/index.html @@ -1 +1 @@ -YSOSv2: lab4 实验报告 - YSOSv2 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
Edited on Views times
\ No newline at end of file +YSOSv2: lab4 实验报告 - YSOSv2 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
Edited on Views times
\ No newline at end of file diff --git a/cs/os/ysosv2/lab5/index.html b/cs/os/ysosv2/lab5/index.html index 52175acb..dc8f528b 100644 --- a/cs/os/ysosv2/lab5/index.html +++ b/cs/os/ysosv2/lab5/index.html @@ -1 +1 @@ -YSOSv2: lab5 实验报告 - YSOSv2 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
Edited on Views times
\ No newline at end of file +YSOSv2: lab5 实验报告 - YSOSv2 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
Edited on Views times
\ No newline at end of file diff --git a/cs/os/ysosv2/lab6/index.html b/cs/os/ysosv2/lab6/index.html index 7e036409..f263022d 100644 --- a/cs/os/ysosv2/lab6/index.html +++ b/cs/os/ysosv2/lab6/index.html @@ -1 +1 @@ -YSOSv2: lab6 实验报告 - YSOSv2 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
Edited on Views times
\ No newline at end of file +YSOSv2: lab6 实验报告 - YSOSv2 - 操作系统 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
Edited on Views times
\ No newline at end of file diff --git a/cs/parallel-programing/pthread/index.html b/cs/parallel-programing/pthread/index.html index feca4a21..5c5b89a9 100644 --- a/cs/parallel-programing/pthread/index.html +++ b/cs/parallel-programing/pthread/index.html @@ -1 +1 @@ -线程 - 并行程序设计 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# pthread 库

# 简介

pthread 是 POSIX 线程库,它是一种跨平台的线程库,可以在不同的操作系统上使用。它是 C 语言的标准库,提供了一组函数来创建、管理和同步线程。"pthread" 库相对于 "thread" 库来说,更加底层和与操作系统紧密相关。

thread 是 C11 标准提供的线程库,它是 C 的一部分。它提供了一种面向对象的方式来创建、管理和同步线程。"thread" 库提供了 std::thread 类,可以用于创建和管理线程,并提供了一些成员函数和工具函数来操作线程。

pthread 相关函数需要引入标准库头文件: #include<pthread.h>

# 参考资料

开源教程:https://hpc-tutorials.llnl.gov/posix/

pthread 库在不同的操作系统上有不同的实现,因此,官方的 pthread 库文档可能由各个操作系统的文档或开发者文档提供。以下是一些常见操作系统的 pthread 官方文档链接:

  • Linux: 在 Linux 系统上,pthread 库的官方文档可以在 GNU C 库(glibc)的文档中找到。您可以访问以下链接获取详细的 pthread 文档:https://www.gnu.org/software/libc/manual/html_node/Threads.html

  • macOS: 在 macOS 上,pthread 库的官方文档可以在 Apple 开发者文档中找到。您可以访问以下链接获取有关 pthread 的详细信息:https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/Introduction/Introduction.html

  • Windows: 在 Windows 操作系统上,Microsoft 提供了一种名为 "Windows Threads" 的线程库,它是 Windows 对 POSIX 线程的实现。您可以在 Microsoft 的官方文档中找到有关 "Windows Threads" 的详细信息:https://docs.microsoft.com/en-us/windows/win32/procthread/creating-threads

  • IBM:

    • z/OS:

      z/OS V2R4 POSIX Threads Programming: https://www.ibm.com/docs/en/zos/3.1.0?topic=programming-posix-threads-programming

    • IBM i:

      IBM i 7.4 PASE Programming and Reference: https://www.ibm.com/docs/en/i/7.4?topic=programming-pase-programming-reference

    • AIX:

      AIX 7.2 Library Reference - Threads and Concurrency: https://www.ibm.com/docs/en/aix/7.2?topic=library-threads-concurrency

不同操作系统上的 pthread 库在语法和使用方式上可能会有一些差异。这是因为 pthread 库是根据 POSIX 线程标准实现的,而各个操作系统可能会在标准的基础上进行一些定制和扩展。

# 多线程程序举例分析

# 线程间接执行的函数

c
float *func1(float a, float b) {
    int i;
    float *result;
    result = (float *)malloc(sizeof(float) * 2);
    for (i = 0; i < 1000000000; ++i) {
        result[0] = a + b;
        result[1] = a - b;
    }
    return result;
}
float *func2(float a, float b) {
    int i;
    float *result;
    result = (float *)malloc(sizeof(float) * 2);
    for (i = 0; i < 1000000000; ++i) {
        result[0] = a * b;
        result[1] = a / b;
    }
    return result;
}

# 给间接函数传递参数用的结构体

传递给子线程的将是这个结构体变量的地址,这个地址对父线程和子线程都是一样的,可见的,所以其内容是共享的,互相可以看到对方的修改。

c
typedef struct {
    float a;
    float b;
} Args;

# 线程直接执行的函数

只能返回 void 指针类型,即返回 void*

return 返回的地址内容将被 pthread_join 读出

c
void *thread_func1(void *arg) {
    Args *args = (Args *)arg; // 传递参数结构体变量的地址
    return func1(args->a, args->b);
}
void *thread_func2(void *arg) {
    Args *args = (Args *)arg; // 传递参数结构体变量的地址
    return func2(args->a, args->b);
}

# pthread_exit 结束线程

除了 return 返回数据,还可以用 pthread_exit 函数返回数据并直接结束线程,而不必等到主线程 pthread_join 连接该线程。提前结束进程可以释放进程占用的内存、处理器,节省计算机资源 (真的能吗?)

线程终止函数 pthread_exit 传入 1 个参数

  • void * 类型:非 void 类型指针,指向返回数据的地址
c
void *thread_func1(void *arg) {
    Args *args = (Args *)arg;
    pthread_exit(func1(args->a, args->b));
}
void *thread_func2(void *arg) {
    Args *args = (Args *)arg;
    pthread_exit(func1(args->a, args->b));
}

# 线程返回数据存储的有类型地址

应当是数据的类型

c
result1 = (float *)malloc(sizeof(float) * 2);
result2 = (float *)malloc(sizeof(float) * 2);

# 线程返回数据直接存储的无类型地址

只能是 void 指针类型

c
void *r1, *r2;

# 定义 pthread_t 类型变量

pthread_t 类型变量用于存储线程句柄 (TID) , t 表示数据类型 (type)

c
pthread_t tid1, tid2;

# pthread_create 创建线程

线程创建函数 pthread_create 传入 4 个参数:

  • pthread_t 类型:新线程的线程句柄 (TID) 要存储的地址 (pthread_t 变量指针)
  • const pthread_attr_t * 类型:属性
  • 执行函数 (只能是 void 类型,即无返回)
  • 传给执行函数的参数 (一次只能传一个参数,所以一般用结构体传参数)
c
pthread_create(&tid1, NULL, thread_func1, &ab);
pthread_create(&tid2, NULL, thread_func2, &ab);

函数返回结果:代表线程连接的状态,成功返回 0 ,否则返回错误码

错误码:

  • EAGAIN : The system lacks the necessary resources to create another thread.
  • EINVAL : The value specified by thread is null.
  • ELEMULTITHREADFORK : pthread_create() was invoked from a child process created by calling fork() from a multi-threaded process. This child process is restricted from becoming multi-threaded.
  • ENOMEM : There is not enough memory to create the thread.

# ⚠️区别进程的创建

c
for(i = 0; i < 5; i++)
    pthread_join(tid[i], NULL);

这里与 Linux 创建进程(线程)的 fork 不同,后者会创建 252^5 个进程(线程),而这里是 5 个线程!因为子线程、父线程是并行的!

# pthread_join 连接并读出线程执行结果

线程数据读出函数 pthread_join 传入 2 个参数:

  • pthread_t 类型:线程句柄,即 TID
  • void ** 类型:执行函数的返回数据要存储的地址 (地址只能是 void 类型,一次只能返回一个地址)
c
pthread_join(tid1, &r1);
pthread_join(tid2, &r2);

函数返回结果:代表线程连接的状态,成功返回 0 ,否则返回错误码

错误码:

  • EDEADLK : A deadlock was detected (e.g., two threads tried to join with each other); or thread specifies the calling thread.
  • EINVAL : hread is not a joinable thread.
  • EINVAL : Another thread is already waiting to join with this thread.
  • ESRCH : No thread with the ID thread could be found.

一个线程只能同时连接一个线程,子线程自创建开始执行,若连接子线程时子线程还没结束,主线程会等到子线程执行结束后再读出数据

Windows 中使用的是 WaitForSingleObject(... , ...) / WaitForMultipleObject(... , ...) ,因为 Windows 将所有资源对象命名为 Object

# 无类型地址数据存储到有类型地址

c
result1 = (float *)r1;
result2 = (float *)r2;

# 完整程序

c
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
float *func1(float a, float b) {
    int i;
    float *result;
    result = (float *)malloc(sizeof(float) * 2);
    for (i = 0; i < 1000000000; ++i) {
        result[0] = a + b;
        result[1] = a - b;
    }
    return result;
}
float *func2(float a, float b) {
    int i;
    float *result;
    result = (float *)malloc(sizeof(float) * 2);
    for (i = 0; i < 1000000000; ++i) {
        result[0] = a * b;
        result[1] = a / b;
    }
    return result;
}
typedef struct {
    float a;
    float b;
} Args;
void *thread_func1(void *arg) {
    Args *args = (Args *)arg;
    return func1(args->a, args->b);
}
void *thread_func2(void *arg) {
    Args *args = (Args *)arg;
    return func1(args->a, args->b);
}
int main() {
    float a = 1.14, b = 5.14, *result1, *result2, during;
    Args ab;
    ab.a = a;
    ab.b = b;
    result1 = (float *)malloc(sizeof(float) * 2);
    result2 = (float *)malloc(sizeof(float) * 2);
    struct timeval start, end;
    gettimeofday(&start, NULL);
    void *r1, *r2;
    pthread_t tid1, tid2;
    pthread_create(&tid1, NULL, thread_func1, &ab);
    pthread_create(&tid2, NULL, thread_func2, &ab);
    pthread_join(tid1, &r1);
    pthread_join(tid2, &r2);
    result1 = (float *)r1;
    result2 = (float *)r2;
    gettimeofday(&end, NULL);
    during = (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec) / 1000000.0;
    printf("result1[0] = %f\nresult1[1] = %f\n", result1[0], result1[1]);
    printf("result2[0] = %f\nresult2[1] = %f\n", result2[0], result2[1]);
    printf("during time = %f s\n", during);
    free(result1);
    free(result2);
    return 0;
}

# 线程间互动

# 互斥锁 pthread_mutex

对应数据类型 (type) 为 pthred_mutex_t ,以及相关函数 pthread_mutex_function

互斥锁的作用主要是每个线程都可以在进入某个区域时 把这个区域锁起来, 不让其他的线程进入。 当自己的工作完成时或者达成某种条件时,则打开互斥锁。互斥锁存在的目的就是为了避免很多线程同时进入一个事件时发生冲突。

# pthread_cond 条件变量

对应数据类型 (type) 为 pthred_cond_t ,以及相关函数 pthread_cond_function

条件变量主要和互斥锁一同使用,也就是当满足某一个条件时打开互斥锁。这个条件可以通过 pthread_cond_signal 或者是 pthread_cond_broadcast 发出

# pthread_cond_signal

  • 一次只能激活一个条件变量
  • 不容易出现 “线程打架”

# pthread_cond_broadcast

  • 一次性激活所有等待的条件变量
  • 容易出现 “线程打架”,造成 “死锁”

# 线程互动程序举例分析

# 初始化锁 pthread_mutex_t

c
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

# 初始化条件变量 pthread_cond_t

c
pthread_cond_t cond_catchfish_finish = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond_eatfish_finish = PTHREAD_COND_INITIALIZER;

# 线程函数

# pthread_mutex_lock 上锁

c
pthread_mutex_lock (&mutex) ;

上锁之后线程将无法收到来自其他线程的信号

# 输入

c
int pthread_mutex_lock(pthread_mutex_t *mutex);
//SUSv3:
int pthread_mutex_lock(pthread_mutex_t *mutex);

# 返回值

  • If successful, pthread_mutex_lock() returns 0.

  • If unsuccessful, pthread_mutex_lock() returns -1 and sets errno to one of the following values:

    • Error Code

      • Description*
    • EAGAIN

      • The mutex could not be acquired because the maximum number of recursive locks for mutex has been exceeded. This errno will only occur in the shared path.
    • EDEADLK

      • The current thread already owns the mutex, and the mutex has a kind attribute of __MUTEX_NONRECURSIVE.
    • EINVAL

      • The value specified by mutex is not valid.

Special behavior for Single UNIX Specification, Version 3: If unsuccessful, pthread_mutex_lock () returns an error number to indicate the error. SUSv3 操作系统可以直接返回错误码

# pthred_cond_wait 使线程进入等待状态

c
pthread_cond_wait(&cond_eatfish_finish, &mutex);

会原子地释放之前获取的互斥锁,使当前线程进入等待状态,并等待条件变量满足特定的条件

# 输入

c
int pthread_cond_wait(pthread_cond_t *cond,
                      pthread_mutex_t *mutex);
//SUSv3:
int pthread_cond_wait(pthread_cond_t * __restrict__cond, 
                      pthread_mutex_t * __restrict__mutex);

# 返回值

  • If successful, pthread_cond_wait() returns 0.

  • If unsuccessful, pthread_cond_wait() returns -1 and sets errno to one of the following values:

    • Error Code

      • Description
    • EINVAL

      • Different mutexes were specified for concurrent operations on the same condition variable.
    • EPERM

      • The mutex was not owned by the current thread at the time of the call.

Special behavior for Single UNIX Specification, Version 3: If unsuccessful, pthread_cond_wait () returns an error number to indicate the error. SUSv3 操作系统可以直接返回错误码

# 完整程序

c
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
int countFish = 0;// 计数器,记录容器内鱼的数量
const int numFish = 10;// 一筐鱼的数量
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;// 初始化一把叫做 mutex 的锁
pthread_cond_t cond_catchfish_finish = PTHREAD_COND_INITIALIZER;// 初始化一个条件变量,这个条件变量为捕鱼操作是否完成
pthread_cond_t cond_eatfish_finish = PTHREAD_COND_INITIALIZER;// 初始化一个条件变量,这个条件变量为吃鱼操作是否完成
void* fishman (){
    int i, j, k;
    for(i= 0;i < numFish * 2; i++){
        pthread_mutex_lock (&mutex) ;
        // 渔夫在捕鱼时,先加一把锁,防止猫咪把容器抢走
        while (countFish == numFish){
            pthread_cond_wait(&cond_eatfish_finish, &mutex);
            // 如果容器中鱼满了,渔夫就等待猫咪吃完鱼,然后再继续捕鱼
            // 当没有接收到 cond_eatfish_finish 信号时,就会一直等待,并且会释放 mutex 锁
        }
        countFish++;
        // 捕到一条鱼
        printf("Catching Fish! Now there are %d fish, total fish are %d\n", countFish, i + 1);
        pthread_cond_signal (&cond_catchfish_finish);
        // 发送信号,告诉猫咪可以吃鱼了,但是如果没有捕够鱼,猫咪还是会等待,因为锁还没有释放
        pthread_mutex_unlock(&mutex) ;
        // 解锁
    }
    pthread_exit (NULL);
}
// 渔夫函数
void* cat (){
    int i,j,k;
    for(i= 0; i < numFish * 2; i++){
        pthread_mutex_lock (&mutex) ;
        // 猫咪在吃鱼时,先加一把锁,防止渔夫把容器抢走
        while (countFish == 0){
            pthread_cond_wait (&cond_catchfish_finish, &mutex);
            // 如果容器中鱼没有了,猫咪就等待渔夫捕鱼的操作完成,然后继续吃鱼
            // 当没有接收到 cond_catchfish_finish 信号时,就会一直等待,并且会释放 mutex 锁
        }
        countFish--;
        // 吃掉一只鱼
        printf("Eating Fish! Now there are %d fish\n", countFish);
        pthread_cond_signal (&cond_eatfish_finish);
        // 发送信号,告诉渔夫可以继续捕鱼了,但是如果没有吃完鱼,渔夫还是会等待,因为锁没有释放
        pthread_mutex_unlock(&mutex) ;
        // 解锁
    }
    pthread_exit (NULL);
}
int main() {
    pthread_t fishmanThread, catThread;
    pthread_create(&fishmanThread, NULL, fishman, NULL);
    pthread_create (&catThread, NULL, cat, NULL);
    pthread_join (fishmanThread, NULL);
    pthread_join (catThread, NULL);
    printf ("The cat is full!\n");
    return 0;
}
\ No newline at end of file +线程 - 并行程序设计 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# pthread 库

# 简介

pthread 是 POSIX 线程库,它是一种跨平台的线程库,可以在不同的操作系统上使用。它是 C 语言的标准库,提供了一组函数来创建、管理和同步线程。"pthread" 库相对于 "thread" 库来说,更加底层和与操作系统紧密相关。

thread 是 C11 标准提供的线程库,它是 C 的一部分。它提供了一种面向对象的方式来创建、管理和同步线程。"thread" 库提供了 std::thread 类,可以用于创建和管理线程,并提供了一些成员函数和工具函数来操作线程。

pthread 相关函数需要引入标准库头文件: #include<pthread.h>

# 参考资料

开源教程:https://hpc-tutorials.llnl.gov/posix/

pthread 库在不同的操作系统上有不同的实现,因此,官方的 pthread 库文档可能由各个操作系统的文档或开发者文档提供。以下是一些常见操作系统的 pthread 官方文档链接:

  • Linux: 在 Linux 系统上,pthread 库的官方文档可以在 GNU C 库(glibc)的文档中找到。您可以访问以下链接获取详细的 pthread 文档:https://www.gnu.org/software/libc/manual/html_node/Threads.html

  • macOS: 在 macOS 上,pthread 库的官方文档可以在 Apple 开发者文档中找到。您可以访问以下链接获取有关 pthread 的详细信息:https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/Introduction/Introduction.html

  • Windows: 在 Windows 操作系统上,Microsoft 提供了一种名为 "Windows Threads" 的线程库,它是 Windows 对 POSIX 线程的实现。您可以在 Microsoft 的官方文档中找到有关 "Windows Threads" 的详细信息:https://docs.microsoft.com/en-us/windows/win32/procthread/creating-threads

  • IBM:

    • z/OS:

      z/OS V2R4 POSIX Threads Programming: https://www.ibm.com/docs/en/zos/3.1.0?topic=programming-posix-threads-programming

    • IBM i:

      IBM i 7.4 PASE Programming and Reference: https://www.ibm.com/docs/en/i/7.4?topic=programming-pase-programming-reference

    • AIX:

      AIX 7.2 Library Reference - Threads and Concurrency: https://www.ibm.com/docs/en/aix/7.2?topic=library-threads-concurrency

不同操作系统上的 pthread 库在语法和使用方式上可能会有一些差异。这是因为 pthread 库是根据 POSIX 线程标准实现的,而各个操作系统可能会在标准的基础上进行一些定制和扩展。

# 多线程程序举例分析

# 线程间接执行的函数

c
float *func1(float a, float b) {
    int i;
    float *result;
    result = (float *)malloc(sizeof(float) * 2);
    for (i = 0; i < 1000000000; ++i) {
        result[0] = a + b;
        result[1] = a - b;
    }
    return result;
}
float *func2(float a, float b) {
    int i;
    float *result;
    result = (float *)malloc(sizeof(float) * 2);
    for (i = 0; i < 1000000000; ++i) {
        result[0] = a * b;
        result[1] = a / b;
    }
    return result;
}

# 给间接函数传递参数用的结构体

传递给子线程的将是这个结构体变量的地址,这个地址对父线程和子线程都是一样的,可见的,所以其内容是共享的,互相可以看到对方的修改。

c
typedef struct {
    float a;
    float b;
} Args;

# 线程直接执行的函数

只能返回 void 指针类型,即返回 void*

return 返回的地址内容将被 pthread_join 读出

c
void *thread_func1(void *arg) {
    Args *args = (Args *)arg; // 传递参数结构体变量的地址
    return func1(args->a, args->b);
}
void *thread_func2(void *arg) {
    Args *args = (Args *)arg; // 传递参数结构体变量的地址
    return func2(args->a, args->b);
}

# pthread_exit 结束线程

除了 return 返回数据,还可以用 pthread_exit 函数返回数据并直接结束线程,而不必等到主线程 pthread_join 连接该线程。提前结束进程可以释放进程占用的内存、处理器,节省计算机资源 (真的能吗?)

线程终止函数 pthread_exit 传入 1 个参数

  • void * 类型:非 void 类型指针,指向返回数据的地址
c
void *thread_func1(void *arg) {
    Args *args = (Args *)arg;
    pthread_exit(func1(args->a, args->b));
}
void *thread_func2(void *arg) {
    Args *args = (Args *)arg;
    pthread_exit(func1(args->a, args->b));
}

# 线程返回数据存储的有类型地址

应当是数据的类型

c
result1 = (float *)malloc(sizeof(float) * 2);
result2 = (float *)malloc(sizeof(float) * 2);

# 线程返回数据直接存储的无类型地址

只能是 void 指针类型

c
void *r1, *r2;

# 定义 pthread_t 类型变量

pthread_t 类型变量用于存储线程句柄 (TID) , t 表示数据类型 (type)

c
pthread_t tid1, tid2;

# pthread_create 创建线程

线程创建函数 pthread_create 传入 4 个参数:

  • pthread_t 类型:新线程的线程句柄 (TID) 要存储的地址 (pthread_t 变量指针)
  • const pthread_attr_t * 类型:属性
  • 执行函数 (只能是 void 类型,即无返回)
  • 传给执行函数的参数 (一次只能传一个参数,所以一般用结构体传参数)
c
pthread_create(&tid1, NULL, thread_func1, &ab);
pthread_create(&tid2, NULL, thread_func2, &ab);

函数返回结果:代表线程连接的状态,成功返回 0 ,否则返回错误码

错误码:

  • EAGAIN : The system lacks the necessary resources to create another thread.
  • EINVAL : The value specified by thread is null.
  • ELEMULTITHREADFORK : pthread_create() was invoked from a child process created by calling fork() from a multi-threaded process. This child process is restricted from becoming multi-threaded.
  • ENOMEM : There is not enough memory to create the thread.

# ⚠️区别进程的创建

c
for(i = 0; i < 5; i++)
    pthread_join(tid[i], NULL);

这里与 Linux 创建进程(线程)的 fork 不同,后者会创建 252^5 个进程(线程),而这里是 5 个线程!因为子线程、父线程是并行的!

# pthread_join 连接并读出线程执行结果

线程数据读出函数 pthread_join 传入 2 个参数:

  • pthread_t 类型:线程句柄,即 TID
  • void ** 类型:执行函数的返回数据要存储的地址 (地址只能是 void 类型,一次只能返回一个地址)
c
pthread_join(tid1, &r1);
pthread_join(tid2, &r2);

函数返回结果:代表线程连接的状态,成功返回 0 ,否则返回错误码

错误码:

  • EDEADLK : A deadlock was detected (e.g., two threads tried to join with each other); or thread specifies the calling thread.
  • EINVAL : hread is not a joinable thread.
  • EINVAL : Another thread is already waiting to join with this thread.
  • ESRCH : No thread with the ID thread could be found.

一个线程只能同时连接一个线程,子线程自创建开始执行,若连接子线程时子线程还没结束,主线程会等到子线程执行结束后再读出数据

Windows 中使用的是 WaitForSingleObject(... , ...) / WaitForMultipleObject(... , ...) ,因为 Windows 将所有资源对象命名为 Object

# 无类型地址数据存储到有类型地址

c
result1 = (float *)r1;
result2 = (float *)r2;

# 完整程序

c
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
float *func1(float a, float b) {
    int i;
    float *result;
    result = (float *)malloc(sizeof(float) * 2);
    for (i = 0; i < 1000000000; ++i) {
        result[0] = a + b;
        result[1] = a - b;
    }
    return result;
}
float *func2(float a, float b) {
    int i;
    float *result;
    result = (float *)malloc(sizeof(float) * 2);
    for (i = 0; i < 1000000000; ++i) {
        result[0] = a * b;
        result[1] = a / b;
    }
    return result;
}
typedef struct {
    float a;
    float b;
} Args;
void *thread_func1(void *arg) {
    Args *args = (Args *)arg;
    return func1(args->a, args->b);
}
void *thread_func2(void *arg) {
    Args *args = (Args *)arg;
    return func1(args->a, args->b);
}
int main() {
    float a = 1.14, b = 5.14, *result1, *result2, during;
    Args ab;
    ab.a = a;
    ab.b = b;
    result1 = (float *)malloc(sizeof(float) * 2);
    result2 = (float *)malloc(sizeof(float) * 2);
    struct timeval start, end;
    gettimeofday(&start, NULL);
    void *r1, *r2;
    pthread_t tid1, tid2;
    pthread_create(&tid1, NULL, thread_func1, &ab);
    pthread_create(&tid2, NULL, thread_func2, &ab);
    pthread_join(tid1, &r1);
    pthread_join(tid2, &r2);
    result1 = (float *)r1;
    result2 = (float *)r2;
    gettimeofday(&end, NULL);
    during = (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec) / 1000000.0;
    printf("result1[0] = %f\nresult1[1] = %f\n", result1[0], result1[1]);
    printf("result2[0] = %f\nresult2[1] = %f\n", result2[0], result2[1]);
    printf("during time = %f s\n", during);
    free(result1);
    free(result2);
    return 0;
}

# 线程间互动

# 互斥锁 pthread_mutex

对应数据类型 (type) 为 pthred_mutex_t ,以及相关函数 pthread_mutex_function

互斥锁的作用主要是每个线程都可以在进入某个区域时 把这个区域锁起来, 不让其他的线程进入。 当自己的工作完成时或者达成某种条件时,则打开互斥锁。互斥锁存在的目的就是为了避免很多线程同时进入一个事件时发生冲突。

# pthread_cond 条件变量

对应数据类型 (type) 为 pthred_cond_t ,以及相关函数 pthread_cond_function

条件变量主要和互斥锁一同使用,也就是当满足某一个条件时打开互斥锁。这个条件可以通过 pthread_cond_signal 或者是 pthread_cond_broadcast 发出

# pthread_cond_signal

  • 一次只能激活一个条件变量
  • 不容易出现 “线程打架”

# pthread_cond_broadcast

  • 一次性激活所有等待的条件变量
  • 容易出现 “线程打架”,造成 “死锁”

# 线程互动程序举例分析

# 初始化锁 pthread_mutex_t

c
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

# 初始化条件变量 pthread_cond_t

c
pthread_cond_t cond_catchfish_finish = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond_eatfish_finish = PTHREAD_COND_INITIALIZER;

# 线程函数

# pthread_mutex_lock 上锁

c
pthread_mutex_lock (&mutex) ;

上锁之后线程将无法收到来自其他线程的信号

# 输入

c
int pthread_mutex_lock(pthread_mutex_t *mutex);
//SUSv3:
int pthread_mutex_lock(pthread_mutex_t *mutex);

# 返回值

  • If successful, pthread_mutex_lock() returns 0.

  • If unsuccessful, pthread_mutex_lock() returns -1 and sets errno to one of the following values:

    • Error Code

      • Description*
    • EAGAIN

      • The mutex could not be acquired because the maximum number of recursive locks for mutex has been exceeded. This errno will only occur in the shared path.
    • EDEADLK

      • The current thread already owns the mutex, and the mutex has a kind attribute of __MUTEX_NONRECURSIVE.
    • EINVAL

      • The value specified by mutex is not valid.

Special behavior for Single UNIX Specification, Version 3: If unsuccessful, pthread_mutex_lock () returns an error number to indicate the error. SUSv3 操作系统可以直接返回错误码

# pthred_cond_wait 使线程进入等待状态

c
pthread_cond_wait(&cond_eatfish_finish, &mutex);

会原子地释放之前获取的互斥锁,使当前线程进入等待状态,并等待条件变量满足特定的条件

# 输入

c
int pthread_cond_wait(pthread_cond_t *cond,
                      pthread_mutex_t *mutex);
//SUSv3:
int pthread_cond_wait(pthread_cond_t * __restrict__cond, 
                      pthread_mutex_t * __restrict__mutex);

# 返回值

  • If successful, pthread_cond_wait() returns 0.

  • If unsuccessful, pthread_cond_wait() returns -1 and sets errno to one of the following values:

    • Error Code

      • Description
    • EINVAL

      • Different mutexes were specified for concurrent operations on the same condition variable.
    • EPERM

      • The mutex was not owned by the current thread at the time of the call.

Special behavior for Single UNIX Specification, Version 3: If unsuccessful, pthread_cond_wait () returns an error number to indicate the error. SUSv3 操作系统可以直接返回错误码

# 完整程序

c
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
int countFish = 0;// 计数器,记录容器内鱼的数量
const int numFish = 10;// 一筐鱼的数量
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;// 初始化一把叫做 mutex 的锁
pthread_cond_t cond_catchfish_finish = PTHREAD_COND_INITIALIZER;// 初始化一个条件变量,这个条件变量为捕鱼操作是否完成
pthread_cond_t cond_eatfish_finish = PTHREAD_COND_INITIALIZER;// 初始化一个条件变量,这个条件变量为吃鱼操作是否完成
void* fishman (){
    int i, j, k;
    for(i= 0;i < numFish * 2; i++){
        pthread_mutex_lock (&mutex) ;
        // 渔夫在捕鱼时,先加一把锁,防止猫咪把容器抢走
        while (countFish == numFish){
            pthread_cond_wait(&cond_eatfish_finish, &mutex);
            // 如果容器中鱼满了,渔夫就等待猫咪吃完鱼,然后再继续捕鱼
            // 当没有接收到 cond_eatfish_finish 信号时,就会一直等待,并且会释放 mutex 锁
        }
        countFish++;
        // 捕到一条鱼
        printf("Catching Fish! Now there are %d fish, total fish are %d\n", countFish, i + 1);
        pthread_cond_signal (&cond_catchfish_finish);
        // 发送信号,告诉猫咪可以吃鱼了,但是如果没有捕够鱼,猫咪还是会等待,因为锁还没有释放
        pthread_mutex_unlock(&mutex) ;
        // 解锁
    }
    pthread_exit (NULL);
}
// 渔夫函数
void* cat (){
    int i,j,k;
    for(i= 0; i < numFish * 2; i++){
        pthread_mutex_lock (&mutex) ;
        // 猫咪在吃鱼时,先加一把锁,防止渔夫把容器抢走
        while (countFish == 0){
            pthread_cond_wait (&cond_catchfish_finish, &mutex);
            // 如果容器中鱼没有了,猫咪就等待渔夫捕鱼的操作完成,然后继续吃鱼
            // 当没有接收到 cond_catchfish_finish 信号时,就会一直等待,并且会释放 mutex 锁
        }
        countFish--;
        // 吃掉一只鱼
        printf("Eating Fish! Now there are %d fish\n", countFish);
        pthread_cond_signal (&cond_eatfish_finish);
        // 发送信号,告诉渔夫可以继续捕鱼了,但是如果没有吃完鱼,渔夫还是会等待,因为锁没有释放
        pthread_mutex_unlock(&mutex) ;
        // 解锁
    }
    pthread_exit (NULL);
}
int main() {
    pthread_t fishmanThread, catThread;
    pthread_create(&fishmanThread, NULL, fishman, NULL);
    pthread_create (&catThread, NULL, cat, NULL);
    pthread_join (fishmanThread, NULL);
    pthread_join (catThread, NULL);
    printf ("The cat is full!\n");
    return 0;
}
\ No newline at end of file diff --git a/cs/principles-of-computer-composition/basic-indicators-of-computer-performance/index.html b/cs/principles-of-computer-composition/basic-indicators-of-computer-performance/index.html index db1d9f1a..a7d52e92 100644 --- a/cs/principles-of-computer-composition/basic-indicators-of-computer-performance/index.html +++ b/cs/principles-of-computer-composition/basic-indicators-of-computer-performance/index.html @@ -1,4 +1,4 @@ -计算机性能的基本指标 - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 思维导图

计算机性能的基本指标

# 完成单个任务的时间

# 响应时间 (response time):

完成单个任务所需的总时间,由 2 部分组成

  • 响应时间短的场合:
    事务处理系统 (存 / 取款的速度要快)

  • CPU 执行时间 (CPU time)
    执行时间 (Execution time)
    CPU 真正花费在程序执行上的时间

    • 用户 CPU 时间:
      用来运行用户代码的时间

    • 系统 CPU 时间:
      为执行用户程序而需运行一些操作系统代码的时间

  • 其他时间

    • 等待 I/O 操作完成

    • CPU 花在其他用户程序的时间

# 单位时间完成的任务量

# 吞吐率 (throughput)

  • 吞吐率高的场合:
    多媒体应用 (音 / 视频播放要流畅)

  • 不同层次上对吞吐率性能的度量

    • ISA

      • MIPS
        Million Instructions Per Seconds
        因为每条指令执行时间不同,所以 MIPS 是一个平均值,
        指令使用的频度动态变化

        • MIPS
          = Instruction Counts / ( Execution Time ×10^6 )
          = Clock Rate / ( CPI × 10^6 )
          = 1 / ( Clock Cycle × CPI × 10^6 )

        • 用 MIPS 数表示性能有局限

          • 不同机器的指令集不同

          • 程序由不同的指令混合而成

          • 指令使用的频度动态变化

      • MFLOPS
        Million Floating-point Operations Per Second

        • MFLOPS
          = FP Operations / ( Execution Time × 10^6 )

          • Peak MIPS
            取一组指令组合,使得得到的平均 CPI 最小,由此得到的 MIPS 就是峰值 MIPS (Peak MIPS)
            (不实用)
      • Datapath Control

        • Megabytes per second (带宽)
      • Function Units

        • Transistors

        • Wires

        • Pins

        • Cycles per second (频率)

# 带宽 (bandwidth)

# 系统性能

(System performance)
表示系统响应时间,与 CPU 之外的其他部分都有关系

# 影响系统性能的硬件技术指标

  • 主频

    • 定义

      • CPU 的工作节拍是由时钟控制的,时钟不断产生固定频率的时钟脉冲,这个时钟的频率就是 CPU 的主频
    • 主频越高,CPU 的工作节拍就越快,运算速度就越高

    • 主频通常用一秒钟内处理器所能发出电子脉冲数来表示,单位一般为 GHz

    • 芯片的功耗与频率成正比

  • 运算速度

    • 定义

      • 每秒钟所能执行的指令条数
    • 计量单位

      • MIPS

      • MFLOPS

    • 计算方法

      • 吉布森混合法:各类指令根据出现频率加权求平均

      • 计算各种指令的执行速度

      • 计算典型程序的运算速度

      • 模型分析和模拟等其他方法

  • 运算精度

    • 定义

      • 计算机能直接处理的二进制位数
    • 一般和 CPU 中存储的数据寄存器的位数是相同。位数越多,精度越高

    • 参与运算的操作数的基本位数称之为基本字长 。早期的微机字长为 8 位或 16 位,现为 32 位或 64 位

  • 存储容量

    • 主存容量

      • 存储单元个数 × 存储字长

      • 主存越大,处理问题的速度越快

      • 与辅存交换次数越少,访存效率越高

    • 辅存容量

# CPU 性能

(CPU performance)
表示用户 CPU 时间
衡量指标是: CPU time

# 一个程序的 CPU 执行时间 (CPU time)

执行时间 (Execution time)
= 一个程序的 CPU 时钟周期数 × 时钟周期时间
= 一个程序的 CPU 时钟周期数 ÷ 时钟频率
= 程序的指令数 × CPI × 时钟周期时间
= 程序的指令数 × CPI ÷ 时钟频率
= Instruction Counts / (MIPS × 10^6)

  • 一个程序的 CPU 时钟周期数
    =程序的指令数 × CPI

Clock Cycle Counts = Instructions Counts × CPI

- CPI (avg. clock Cycles Per Instruction)
+计算机性能的基本指标 - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 思维导图

计算机性能的基本指标

# 完成单个任务的时间

# 响应时间 (response time):

完成单个任务所需的总时间,由 2 部分组成

  • 响应时间短的场合:
    事务处理系统 (存 / 取款的速度要快)

  • CPU 执行时间 (CPU time)
    执行时间 (Execution time)
    CPU 真正花费在程序执行上的时间

    • 用户 CPU 时间:
      用来运行用户代码的时间

    • 系统 CPU 时间:
      为执行用户程序而需运行一些操作系统代码的时间

  • 其他时间

    • 等待 I/O 操作完成

    • CPU 花在其他用户程序的时间

# 单位时间完成的任务量

# 吞吐率 (throughput)

  • 吞吐率高的场合:
    多媒体应用 (音 / 视频播放要流畅)

  • 不同层次上对吞吐率性能的度量

    • ISA

      • MIPS
        Million Instructions Per Seconds
        因为每条指令执行时间不同,所以 MIPS 是一个平均值,
        指令使用的频度动态变化

        • MIPS
          = Instruction Counts / ( Execution Time ×10^6 )
          = Clock Rate / ( CPI × 10^6 )
          = 1 / ( Clock Cycle × CPI × 10^6 )

        • 用 MIPS 数表示性能有局限

          • 不同机器的指令集不同

          • 程序由不同的指令混合而成

          • 指令使用的频度动态变化

      • MFLOPS
        Million Floating-point Operations Per Second

        • MFLOPS
          = FP Operations / ( Execution Time × 10^6 )

          • Peak MIPS
            取一组指令组合,使得得到的平均 CPI 最小,由此得到的 MIPS 就是峰值 MIPS (Peak MIPS)
            (不实用)
      • Datapath Control

        • Megabytes per second (带宽)
      • Function Units

        • Transistors

        • Wires

        • Pins

        • Cycles per second (频率)

# 带宽 (bandwidth)

# 系统性能

(System performance)
表示系统响应时间,与 CPU 之外的其他部分都有关系

# 影响系统性能的硬件技术指标

  • 主频

    • 定义

      • CPU 的工作节拍是由时钟控制的,时钟不断产生固定频率的时钟脉冲,这个时钟的频率就是 CPU 的主频
    • 主频越高,CPU 的工作节拍就越快,运算速度就越高

    • 主频通常用一秒钟内处理器所能发出电子脉冲数来表示,单位一般为 GHz

    • 芯片的功耗与频率成正比

  • 运算速度

    • 定义

      • 每秒钟所能执行的指令条数
    • 计量单位

      • MIPS

      • MFLOPS

    • 计算方法

      • 吉布森混合法:各类指令根据出现频率加权求平均

      • 计算各种指令的执行速度

      • 计算典型程序的运算速度

      • 模型分析和模拟等其他方法

  • 运算精度

    • 定义

      • 计算机能直接处理的二进制位数
    • 一般和 CPU 中存储的数据寄存器的位数是相同。位数越多,精度越高

    • 参与运算的操作数的基本位数称之为基本字长 。早期的微机字长为 8 位或 16 位,现为 32 位或 64 位

  • 存储容量

    • 主存容量

      • 存储单元个数 × 存储字长

      • 主存越大,处理问题的速度越快

      • 与辅存交换次数越少,访存效率越高

    • 辅存容量

# CPU 性能

(CPU performance)
表示用户 CPU 时间
衡量指标是: CPU time

# 一个程序的 CPU 执行时间 (CPU time)

执行时间 (Execution time)
= 一个程序的 CPU 时钟周期数 × 时钟周期时间
= 一个程序的 CPU 时钟周期数 ÷ 时钟频率
= 程序的指令数 × CPI × 时钟周期时间
= 程序的指令数 × CPI ÷ 时钟频率
= Instruction Counts / (MIPS × 10^6)

  • 一个程序的 CPU 时钟周期数
    =程序的指令数 × CPI

Clock Cycle Counts = Instructions Counts × CPI

- CPI (avg. clock Cycles Per Instruction)
 

每条指令的平均时钟周期数

	- 对于某一条特定的指令而言,其CPI是一个确定的值 
 						
 	- 对于某一类指令、或一个程序、或一台机器而言,其CPI是一个平均值 
@@ -6,4 +6,4 @@
 - 程序包含的指令数量 (Instruction Counts) 
 						
 - CPI
-
  • 时钟周期 × 时钟频率 = 1

    • 时钟周期 (Clock Cycle)

    • 时钟频率 (Clock Rate)

# 改善性能的措施

  • 采用更复杂的指令

    • 减少指令数

    • 可能导致 CPI 升高

    • 可能导致时钟周期增大

  • 采用更简单的指令

    • 可降低 CPI

    • 可能导致指令数增加

    • 可能缩短时钟周期

  • 减少每个指令执行的周期数

    • 可降低 CPI

    • 每个时钟周期需完成的操作更多,时钟周期可能需要增大

  • 缩短时钟周期

    • 每个周期内完成的操作有限,可能导致 CPI 提高

# 影响因素

  • 算法

    • 指令数

      • 算法决定源程序的指令条数,因此决定了处理器执行的指令条数
    • CPI

      • 算法由于对慢速或快速指令的不同倾向性而同样影响了 CPI
  • 编程语言

    • 指令数

      • 由于编程语言中的语句被翻译成 CPU 指令,而后者决定了指令条数,因此编程语言势必会影响指令条数
    • CPI

      • 由于编程语言的自身特点,它可能同样影响 CPI。例:强支持数据抽象的语言 (如 Java) 要求间接调用,而这往往会用到具有高 CPI 的指令
  • 编译器

    • 指令数

    • CPI

  • IS / 指令集 / 体系结构
    / ISA

    • 指令数

    • CPI

    • 时钟频率 / 时钟周期

# Amdahl 定律

#

# 吞吐率高且响应时间短的场合:

ATM、文件服务器、Web 服务器等

\ No newline at end of file +
  • 时钟周期 × 时钟频率 = 1

    • 时钟周期 (Clock Cycle)

    • 时钟频率 (Clock Rate)

# 改善性能的措施

  • 采用更复杂的指令

    • 减少指令数

    • 可能导致 CPI 升高

    • 可能导致时钟周期增大

  • 采用更简单的指令

    • 可降低 CPI

    • 可能导致指令数增加

    • 可能缩短时钟周期

  • 减少每个指令执行的周期数

    • 可降低 CPI

    • 每个时钟周期需完成的操作更多,时钟周期可能需要增大

  • 缩短时钟周期

    • 每个周期内完成的操作有限,可能导致 CPI 提高

# 影响因素

  • 算法

    • 指令数

      • 算法决定源程序的指令条数,因此决定了处理器执行的指令条数
    • CPI

      • 算法由于对慢速或快速指令的不同倾向性而同样影响了 CPI
  • 编程语言

    • 指令数

      • 由于编程语言中的语句被翻译成 CPU 指令,而后者决定了指令条数,因此编程语言势必会影响指令条数
    • CPI

      • 由于编程语言的自身特点,它可能同样影响 CPI。例:强支持数据抽象的语言 (如 Java) 要求间接调用,而这往往会用到具有高 CPI 的指令
  • 编译器

    • 指令数

    • CPI

  • IS / 指令集 / 体系结构
    / ISA

    • 指令数

    • CPI

    • 时钟频率 / 时钟周期

# Amdahl 定律

#

# 吞吐率高且响应时间短的场合:

ATM、文件服务器、Web 服务器等

\ No newline at end of file diff --git a/cs/principles-of-computer-composition/cache/index.html b/cs/principles-of-computer-composition/cache/index.html index 004f3adb..7cca2180 100644 --- a/cs/principles-of-computer-composition/cache/index.html +++ b/cs/principles-of-computer-composition/cache/index.html @@ -1 +1 @@ -Cache - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 思维导图

Cache

# Cache 的结构

# Cache 是小容量、高速缓冲存储器,由 SRAM 组成

# 一般将 Cache 和主存的存储空间都划分为若干大小相同的块并映射

  • 把主存划分成大小相等的主存块 (Block)

  • Cache 中存放一个主存块的对应单位称为行 (line) 或槽 (Slot) 或项 (Entry) 或块 (Block),一段 Cache 行包括:

    • Valid 位,1 位

    • LRU 位

    • Dirty 位,1 位,采用 Write Back (写回、一次性写、回写) 时需要

    • Tag 位

    • Data 数据

  • 主存块 (Block) 与 Cache 中的 行 / 槽 / 项 / 块 映射

# Cache 中存放最近访问的数据

# Cache 工作原理

# 程序运行时,CPU 使用的一部分数据 / 指令会预先成批拷贝到 Cache 中,Cache 的内容是主存储器中部分内容的映象 (副本)

# 当 CPU 需从主存读 (写) 数据或指令时,先查看 Cache

  • 失效或缺失 (miss)
    若被访问信息不在 cache 中,则直接从 Cache 中取,不用访问主存

  • 命中 (hit)
    若被访问信息在 cache 中,则直接访问主存

# Cache 对程序员 (编译器) 是透明的

# 对操作系统程序员也是基本透明的

# 对一些内核高级程序员不是透明的

# 程序访问局部性

# 时间局部性 (Temporal Locality) :

刚被访问过的存储单元很可能不久又被访问
所以让最近被访问过的信息保留在靠近 CPU 的存储器中

# 空间局部性 (Spatial Locality) :

刚被访问过的存储单元的邻近单元很可能不久被访问,单个数据不考虑空间局部性
所以将刚被访问过的存储单元的邻近单元调到靠近 CPU 的存储器中

# 块大小的设置需利用空间局部性

  • 块太小,无法利用空间局部性,发生缺失的概率增大

# Cache 在计算机存储层次结构中的位置

#

# Cache 位于 CPU 内,速度几乎与 CPU 一样快

# 块 (Block) 是一个定长块,是两层存储器之间存储信息的最小单元。Cache 是主存一部分的副本

# Cache 替换算法 / 淘汰策略问题

# 当一个新的主存块需要复制到 Cache 中时,如果 Cache 中的对应行已经全部被占满,如何选择被替换掉的 Cache 行?

  • 直接映射(Direct Mapped)Cache
    映射唯一,无条件用新信息替换老信息

  • N 路组相联(N-way Set Associative)Cache
    每个主存数据有 N 个 Cache 行可选择,需考虑替换哪一行

  • 全相联(Fully Associative)Cache
    每个主存数据可存放到 Cache 任意行中,需考虑替换哪一行

# 先进先出(First In First Out,FIFO)

总是把最近最少用的那一块淘汰掉,利用时间局部性

  • 加一位标记位标记当前哪一行是最先进入的

  • 替换掉之后按顺序将下一行标记为最先进入的,最后一行被替换掉则标记第一行

# 最近最少用(Least Recently Used,LRU)

总是把最近最少用的那一块淘汰掉,利用时间局部性

  • 具体实现:通过给每个 Cache 行设定一个计数器,根据计数值来记录这些主存块的使用情况。这个计数值称为 LRU 位。

    • 组相联每组 n 行时,LRU 位长度 = log_2 (n)

    • 全相联相当于组相联只有一组,LRU 位长度 = log_2 (Cache 的行数)

    • 命中时,被访问行的 LRU 位置 0,其他行 LRU 位加 1,其余不变

    • 未命中且该组未满时,新行 LRU 位置为 0,其余全加 1

    • 未命中且该组已满时,LRU 位最大的那一行中的主存块被淘汰,新行 LRU 位置为 0,其余加 1

    • LRU 位的最大值 = n-1 (从 0 开始计数)

  • LRU 算法的命中率随组中行数的增大而提高

# 随机替换(Random)

  • 随机地从候选的槽中选取一个淘汰,与使用情况无关

  • 模拟试验表明,随机替换算法在性能上只稍逊于 LRU 算法,而且代价低!

# 最不经常使用 LFU

# 相关指标与术语

# 命中(Hit):要访问的信息在 Cache 中

  • Hit Rate (命中率 p): 在 Cache 中的概率

  • Hit Time (命中时间 Tc) :访问 Cache 所需时间,包括:判断时间 + Cache 访问

# 失效(Miss):要访问的信息不在 Cache 中

  • Miss Rate (缺失率 / 失效率) = 1 - (Hit Rate) = 1-p

  • Miss Penalty (失效损失 Tm):从主存将一块数据读取到 Cache 所需时间,包括访问主存块,向上逐层传输块直至将数据块放入发生缺失的那一层所需时间。

# 平均访问时间 = p × Tc + (1-p) × (Tm + Tc) = Tc + (1-p) × Tm

【失效损失 Tm】 不包括 【命中时间 Tc】!考点

# Cache 抖动

由于内存中不同主存块都映射到 Cache 同一行,某些块在主存和 Cache 之间频繁传送,产生了频繁的 Cache 替换,称之为 Cache 抖动

  • 可能引起 Cache 抖动的 Cache 失效类型

    • 容量失效

    • 冲突失效

  • 增加容量和相联性,有助于缓解这种现象

# 逻辑地址

CPU 给出的虚拟地址

# 物理地址 / 主存地址

在 Cache 和主存中查询所用的地址

  • Tag 位,与 Cache 中的 Tag 位比较,相等则命中

  • Index 位,组号位,只有组相联才有

  • Offset 位,在 Cache 行或主存块中的偏移量,即最低位块内地址

# 关联度

主存块映射到 Cache 时,可能存放的位置个数

  • 关联度最低?直接映射(关联度为 1)

  • 关联度居中?N - 路组相联映射(关联度为 N)

  • 关联度最高?全相联映射(为 Cache 行数)

  • Cache 大小和块大小一定的情况下直观结论

    • 提高关联度通常能够降低缺失率 (miss rate)

    • 提高关联度通常会增加命中时间

# Cache 的失效率(Miss Rate)

# Miss Rate 与 Cache 大小、Block 大小、映射方式、Cache 级数等有关

  • Cache 大小:

    • Cache 越大,Miss Rate 越低

    • 但成本越高!

  • Block 大小:

    • Block 越大,Miss Rate 越低,因为空间局部性充分发掘

    • Block 大小在 Cache 大小中所占的比例增加到一定程度时, Miss Rate 也会随之增加

    • Cache 不扩大时 Cache Block 的总数变少了,冲突变大

  • Cache 映射方式

    • Cache 容量小时, Cache 映射方式对 Miss Rate 有影响

    • Cache 容量大时,Cache 映射方式对 Miss Rate 影响不大

      • 映射到同一组的概率降低

# Cache 失效类型

  • 强制失效 (Compulsory misses)

    • 首次访问某数据块时,必然引起的 Cache 失效

    • 增加 Block 大小,有利于减少此类不命中

  • 容量失效 (Capacity misses)

    • Cache 不能存放程序运行所需的所有块,替换后再次被使用所引起的 Cache 失效

    • 增加 Cache 大小,有利于减少此类不命中

  • 冲突失效 (Conflict misses)

    • 映射到同一组的数据块个数超过组内可容纳的块时,竞争所引起的 Cache 失效

    • 全相联没有此类失效,但价格贵且访问速度慢

# Cache 的一致性问题

# 导致 Cache 和主存数据不一致的情况

  • 情况 1:当 Cache 中的内容进行更新时,而没有改变主存中的相应内容时,Cache 和主存之间产生了不一致 (inconsistent)

  • 情况 2:当多个设备都允许访问主存时

    • 例:I/O 设备可通过 DMA 方式直接读写内存时,如果 Cache 中的内容被修改,则 I/O 设备读出的对应主存单元的内容无效;若 I/O 设备修改了主存单元的内容,则对应 Cache 行中的内容无效。
  • 情况 3:当多个 CPU 都有各自私有的 Cache 并且共享主存时

    • 例:某个 CPU 修改了自身 Cache 中的内容,则对应的主存单元和其他 CPU 中对应的 Cache 行的内容都要变为无效。

# Cache 写机制

  • 写命中 (Write Hit)
    要写的单元已经在 Cache 中时

    • Write Through (写直达、写通过、直写、写穿透)
      当一个写操作产生时,无论写的是 Cache 还是主存,新值同时写到 Cache 和主存的块中

      • 问题:内存速度太慢,所以会导致 CPU “被拖累”,CPU 性能降低

      • 一种改进措施:在 Cache 和主存之间使用写缓冲 (Write Buffer)

        • 当一个数据等待被写入主存时,先将其存入写缓冲;

        • 在把数据写入 Cache 和写缓冲后,处理器继续执行命令;

        • 当写主存操作结束后,写缓冲里的数据释放

      • 写穿透 / 直达 Cache 可用写分配或写不分配

    • Write Back (写回、一次性写、回写)
      当一个写操作产生时,新值仅被写到 Cache 中,而不被写入主存

      • 特点

        • 大大降低主存带宽需求

        • 提高系统性能

        • 控制可能很复杂

      • 每个 Cache 行都设置一个修改位 (“dirty bit - 脏位”)

        • 如果修改位为 “0”,则说明对应主存块没有被修改过

        • 如果对应 Cache 行中的主存块被修改,就同时置修改位为 “1”

        • 只有当修改位为 “1” 的块从 cache 中替换出去时,才把它写回主存
          (写不命中时 Cache 里没有有效的对应块,即使写分配也不需要考虑 Cache 中的数据。但是写分配写入 Cache 新的行时,被替换掉的行不能忘了考虑写回)

        • 修改位为 “0” 的块从 cache 中替换出去时,不写回主存

      • 写回 Cache 通常用写分配

  • 写不命中 (Write Miss)
    要写的单元不在 Cache 中时

    • Allocate-on-miss (写分配)

      • 更新主存块中相应单元,再将该主存块装入 Cache;

      • 试图利用空间局部性,但增加了从主存读入一个块的开销

    • No-allocate-on-write (写不分配)

      • 直接写主存,不把被写数据放入 Cache,同时将 Cache 中该行 Valid 位置 0;

      • 减少了从主存读一个块的开销,但没有利用空间局部性

# Cache 和主存之间的映射

# 直接映射 / 模映射 (Direct Mapped)

  • 原理:

    • 把主存的每一块映射到一个固定的 Cache 行中。
      Cache 总行数为 N,将存储空间总块数为 M 的主存分成 K = M/N 个组群,每个组群有 N 个块;
      即每个主存地址对应于高速缓存中唯一的地址,也称模映射(本质是哈希)
  • 映射关系为:Cache 行号 = 主存块号 mod Cache 行数

  • 物理地址

    • Tag 位,标记位
      长度 = log _2 (主存中 块 的 数量 / Cache 中 块 的 数量) =log_2 (K)

    • Index 位,Cache 槽号
      长度 = log _2 (Cache 中 块 的 数量) = Log_2 (N)

    • Offset 位,块内地址
      长度 = log _2 (块 的 大小) (按编址单位算)

  • 特点

    • 关联度 = 1

    • 易实现 (求低地址就行了) 电路简单,命中时间短

    • 淘汰 / 替换策略简单

    • 不灵活,Cache 存储空间得不到充分利用,命中率低,抖动多

# 全相联映射(Fully Associative)

  • 原理:
    主存块可装到 Cache 任一行 / 槽中,称为全相联映射
    Cache 有几个 slot 就最多需要查找多少次 slot,查找时需要一个 slot 一个 slot 比较 Tag 位查找(除非并行同时比较所有 Cache 行的 Tag,硬件实现更复杂)

  • 物理地址

    • Tag 位,标记位
      长度 = log _2 (主存中 块 的 数量)

    • Offset 位,块内地址
      长度 = log _2 (块 的 大小) (按编址单位算)

  • 特点:

    • 关联度 = Cache 的行的数量

    • 块冲突概率低:只要有空闲 Cache 块,都不会发生冲突

    • 实现复杂 (比较逻辑的硬件代价大)、速度慢

# 组相联映射(N-way Set Associative)

  • n - 路组相联将总行数为 N 的 Cache 分成 S = N/n 组,每一组有 n 行;
    将存储空间总块数为 M 的主存分成 K = M/S = M*n/N 个组群,每个组群有 S 个块;
    把主存块映射到 Cache 固定组的任一行中。即:组间模映射、组内全映射

  • 物理地址

    • Tag 位,标记位
      长度 = log _2 (主存中 块 的 数量 / 组的数量) = log _2 (K)

    • 组号位
      长度 = log _2 (组 的 数量) = log _2 (S)

    • Offset 位,块内地址
      长度 = log _2 (块 的 大小) (按编址单位算)

  • 特点

    • 关联度 = n

    • 结合直接映射和全相联映射的优点。当 Cache 的组数为 1 时,则为全相联映射;

    • 每组两个行(2 路组相联)较常用。在较大容量的 L2 Cahce 和 L3 Cahce 中使用 4 路以上

    • 当每组只有一行时,则为直接映射

    • 当只有一组时,则为全相联映射

\ No newline at end of file +Cache - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 思维导图

Cache

# Cache 的结构

# Cache 是小容量、高速缓冲存储器,由 SRAM 组成

# 一般将 Cache 和主存的存储空间都划分为若干大小相同的块并映射

  • 把主存划分成大小相等的主存块 (Block)

  • Cache 中存放一个主存块的对应单位称为行 (line) 或槽 (Slot) 或项 (Entry) 或块 (Block),一段 Cache 行包括:

    • Valid 位,1 位

    • LRU 位

    • Dirty 位,1 位,采用 Write Back (写回、一次性写、回写) 时需要

    • Tag 位

    • Data 数据

  • 主存块 (Block) 与 Cache 中的 行 / 槽 / 项 / 块 映射

# Cache 中存放最近访问的数据

# Cache 工作原理

# 程序运行时,CPU 使用的一部分数据 / 指令会预先成批拷贝到 Cache 中,Cache 的内容是主存储器中部分内容的映象 (副本)

# 当 CPU 需从主存读 (写) 数据或指令时,先查看 Cache

  • 失效或缺失 (miss)
    若被访问信息不在 cache 中,则直接从 Cache 中取,不用访问主存

  • 命中 (hit)
    若被访问信息在 cache 中,则直接访问主存

# Cache 对程序员 (编译器) 是透明的

# 对操作系统程序员也是基本透明的

# 对一些内核高级程序员不是透明的

# 程序访问局部性

# 时间局部性 (Temporal Locality) :

刚被访问过的存储单元很可能不久又被访问
所以让最近被访问过的信息保留在靠近 CPU 的存储器中

# 空间局部性 (Spatial Locality) :

刚被访问过的存储单元的邻近单元很可能不久被访问,单个数据不考虑空间局部性
所以将刚被访问过的存储单元的邻近单元调到靠近 CPU 的存储器中

# 块大小的设置需利用空间局部性

  • 块太小,无法利用空间局部性,发生缺失的概率增大

# Cache 在计算机存储层次结构中的位置

#

# Cache 位于 CPU 内,速度几乎与 CPU 一样快

# 块 (Block) 是一个定长块,是两层存储器之间存储信息的最小单元。Cache 是主存一部分的副本

# Cache 替换算法 / 淘汰策略问题

# 当一个新的主存块需要复制到 Cache 中时,如果 Cache 中的对应行已经全部被占满,如何选择被替换掉的 Cache 行?

  • 直接映射(Direct Mapped)Cache
    映射唯一,无条件用新信息替换老信息

  • N 路组相联(N-way Set Associative)Cache
    每个主存数据有 N 个 Cache 行可选择,需考虑替换哪一行

  • 全相联(Fully Associative)Cache
    每个主存数据可存放到 Cache 任意行中,需考虑替换哪一行

# 先进先出(First In First Out,FIFO)

总是把最近最少用的那一块淘汰掉,利用时间局部性

  • 加一位标记位标记当前哪一行是最先进入的

  • 替换掉之后按顺序将下一行标记为最先进入的,最后一行被替换掉则标记第一行

# 最近最少用(Least Recently Used,LRU)

总是把最近最少用的那一块淘汰掉,利用时间局部性

  • 具体实现:通过给每个 Cache 行设定一个计数器,根据计数值来记录这些主存块的使用情况。这个计数值称为 LRU 位。

    • 组相联每组 n 行时,LRU 位长度 = log_2 (n)

    • 全相联相当于组相联只有一组,LRU 位长度 = log_2 (Cache 的行数)

    • 命中时,被访问行的 LRU 位置 0,其他行 LRU 位加 1,其余不变

    • 未命中且该组未满时,新行 LRU 位置为 0,其余全加 1

    • 未命中且该组已满时,LRU 位最大的那一行中的主存块被淘汰,新行 LRU 位置为 0,其余加 1

    • LRU 位的最大值 = n-1 (从 0 开始计数)

  • LRU 算法的命中率随组中行数的增大而提高

# 随机替换(Random)

  • 随机地从候选的槽中选取一个淘汰,与使用情况无关

  • 模拟试验表明,随机替换算法在性能上只稍逊于 LRU 算法,而且代价低!

# 最不经常使用 LFU

# 相关指标与术语

# 命中(Hit):要访问的信息在 Cache 中

  • Hit Rate (命中率 p): 在 Cache 中的概率

  • Hit Time (命中时间 Tc) :访问 Cache 所需时间,包括:判断时间 + Cache 访问

# 失效(Miss):要访问的信息不在 Cache 中

  • Miss Rate (缺失率 / 失效率) = 1 - (Hit Rate) = 1-p

  • Miss Penalty (失效损失 Tm):从主存将一块数据读取到 Cache 所需时间,包括访问主存块,向上逐层传输块直至将数据块放入发生缺失的那一层所需时间。

# 平均访问时间 = p × Tc + (1-p) × (Tm + Tc) = Tc + (1-p) × Tm

【失效损失 Tm】 不包括 【命中时间 Tc】!考点

# Cache 抖动

由于内存中不同主存块都映射到 Cache 同一行,某些块在主存和 Cache 之间频繁传送,产生了频繁的 Cache 替换,称之为 Cache 抖动

  • 可能引起 Cache 抖动的 Cache 失效类型

    • 容量失效

    • 冲突失效

  • 增加容量和相联性,有助于缓解这种现象

# 逻辑地址

CPU 给出的虚拟地址

# 物理地址 / 主存地址

在 Cache 和主存中查询所用的地址

  • Tag 位,与 Cache 中的 Tag 位比较,相等则命中

  • Index 位,组号位,只有组相联才有

  • Offset 位,在 Cache 行或主存块中的偏移量,即最低位块内地址

# 关联度

主存块映射到 Cache 时,可能存放的位置个数

  • 关联度最低?直接映射(关联度为 1)

  • 关联度居中?N - 路组相联映射(关联度为 N)

  • 关联度最高?全相联映射(为 Cache 行数)

  • Cache 大小和块大小一定的情况下直观结论

    • 提高关联度通常能够降低缺失率 (miss rate)

    • 提高关联度通常会增加命中时间

# Cache 的失效率(Miss Rate)

# Miss Rate 与 Cache 大小、Block 大小、映射方式、Cache 级数等有关

  • Cache 大小:

    • Cache 越大,Miss Rate 越低

    • 但成本越高!

  • Block 大小:

    • Block 越大,Miss Rate 越低,因为空间局部性充分发掘

    • Block 大小在 Cache 大小中所占的比例增加到一定程度时, Miss Rate 也会随之增加

    • Cache 不扩大时 Cache Block 的总数变少了,冲突变大

  • Cache 映射方式

    • Cache 容量小时, Cache 映射方式对 Miss Rate 有影响

    • Cache 容量大时,Cache 映射方式对 Miss Rate 影响不大

      • 映射到同一组的概率降低

# Cache 失效类型

  • 强制失效 (Compulsory misses)

    • 首次访问某数据块时,必然引起的 Cache 失效

    • 增加 Block 大小,有利于减少此类不命中

  • 容量失效 (Capacity misses)

    • Cache 不能存放程序运行所需的所有块,替换后再次被使用所引起的 Cache 失效

    • 增加 Cache 大小,有利于减少此类不命中

  • 冲突失效 (Conflict misses)

    • 映射到同一组的数据块个数超过组内可容纳的块时,竞争所引起的 Cache 失效

    • 全相联没有此类失效,但价格贵且访问速度慢

# Cache 的一致性问题

# 导致 Cache 和主存数据不一致的情况

  • 情况 1:当 Cache 中的内容进行更新时,而没有改变主存中的相应内容时,Cache 和主存之间产生了不一致 (inconsistent)

  • 情况 2:当多个设备都允许访问主存时

    • 例:I/O 设备可通过 DMA 方式直接读写内存时,如果 Cache 中的内容被修改,则 I/O 设备读出的对应主存单元的内容无效;若 I/O 设备修改了主存单元的内容,则对应 Cache 行中的内容无效。
  • 情况 3:当多个 CPU 都有各自私有的 Cache 并且共享主存时

    • 例:某个 CPU 修改了自身 Cache 中的内容,则对应的主存单元和其他 CPU 中对应的 Cache 行的内容都要变为无效。

# Cache 写机制

  • 写命中 (Write Hit)
    要写的单元已经在 Cache 中时

    • Write Through (写直达、写通过、直写、写穿透)
      当一个写操作产生时,无论写的是 Cache 还是主存,新值同时写到 Cache 和主存的块中

      • 问题:内存速度太慢,所以会导致 CPU “被拖累”,CPU 性能降低

      • 一种改进措施:在 Cache 和主存之间使用写缓冲 (Write Buffer)

        • 当一个数据等待被写入主存时,先将其存入写缓冲;

        • 在把数据写入 Cache 和写缓冲后,处理器继续执行命令;

        • 当写主存操作结束后,写缓冲里的数据释放

      • 写穿透 / 直达 Cache 可用写分配或写不分配

    • Write Back (写回、一次性写、回写)
      当一个写操作产生时,新值仅被写到 Cache 中,而不被写入主存

      • 特点

        • 大大降低主存带宽需求

        • 提高系统性能

        • 控制可能很复杂

      • 每个 Cache 行都设置一个修改位 (“dirty bit - 脏位”)

        • 如果修改位为 “0”,则说明对应主存块没有被修改过

        • 如果对应 Cache 行中的主存块被修改,就同时置修改位为 “1”

        • 只有当修改位为 “1” 的块从 cache 中替换出去时,才把它写回主存
          (写不命中时 Cache 里没有有效的对应块,即使写分配也不需要考虑 Cache 中的数据。但是写分配写入 Cache 新的行时,被替换掉的行不能忘了考虑写回)

        • 修改位为 “0” 的块从 cache 中替换出去时,不写回主存

      • 写回 Cache 通常用写分配

  • 写不命中 (Write Miss)
    要写的单元不在 Cache 中时

    • Allocate-on-miss (写分配)

      • 更新主存块中相应单元,再将该主存块装入 Cache;

      • 试图利用空间局部性,但增加了从主存读入一个块的开销

    • No-allocate-on-write (写不分配)

      • 直接写主存,不把被写数据放入 Cache,同时将 Cache 中该行 Valid 位置 0;

      • 减少了从主存读一个块的开销,但没有利用空间局部性

# Cache 和主存之间的映射

# 直接映射 / 模映射 (Direct Mapped)

  • 原理:

    • 把主存的每一块映射到一个固定的 Cache 行中。
      Cache 总行数为 N,将存储空间总块数为 M 的主存分成 K = M/N 个组群,每个组群有 N 个块;
      即每个主存地址对应于高速缓存中唯一的地址,也称模映射(本质是哈希)
  • 映射关系为:Cache 行号 = 主存块号 mod Cache 行数

  • 物理地址

    • Tag 位,标记位
      长度 = log _2 (主存中 块 的 数量 / Cache 中 块 的 数量) =log_2 (K)

    • Index 位,Cache 槽号
      长度 = log _2 (Cache 中 块 的 数量) = Log_2 (N)

    • Offset 位,块内地址
      长度 = log _2 (块 的 大小) (按编址单位算)

  • 特点

    • 关联度 = 1

    • 易实现 (求低地址就行了) 电路简单,命中时间短

    • 淘汰 / 替换策略简单

    • 不灵活,Cache 存储空间得不到充分利用,命中率低,抖动多

# 全相联映射(Fully Associative)

  • 原理:
    主存块可装到 Cache 任一行 / 槽中,称为全相联映射
    Cache 有几个 slot 就最多需要查找多少次 slot,查找时需要一个 slot 一个 slot 比较 Tag 位查找(除非并行同时比较所有 Cache 行的 Tag,硬件实现更复杂)

  • 物理地址

    • Tag 位,标记位
      长度 = log _2 (主存中 块 的 数量)

    • Offset 位,块内地址
      长度 = log _2 (块 的 大小) (按编址单位算)

  • 特点:

    • 关联度 = Cache 的行的数量

    • 块冲突概率低:只要有空闲 Cache 块,都不会发生冲突

    • 实现复杂 (比较逻辑的硬件代价大)、速度慢

# 组相联映射(N-way Set Associative)

  • n - 路组相联将总行数为 N 的 Cache 分成 S = N/n 组,每一组有 n 行;
    将存储空间总块数为 M 的主存分成 K = M/S = M*n/N 个组群,每个组群有 S 个块;
    把主存块映射到 Cache 固定组的任一行中。即:组间模映射、组内全映射

  • 物理地址

    • Tag 位,标记位
      长度 = log _2 (主存中 块 的 数量 / 组的数量) = log _2 (K)

    • 组号位
      长度 = log _2 (组 的 数量) = log _2 (S)

    • Offset 位,块内地址
      长度 = log _2 (块 的 大小) (按编址单位算)

  • 特点

    • 关联度 = n

    • 结合直接映射和全相联映射的优点。当 Cache 的组数为 1 时,则为全相联映射;

    • 每组两个行(2 路组相联)较常用。在较大容量的 L2 Cahce 和 L3 Cahce 中使用 4 路以上

    • 当每组只有一行时,则为直接映射

    • 当只有一组时,则为全相联映射

\ No newline at end of file diff --git a/cs/principles-of-computer-composition/cpu/index.html b/cs/principles-of-computer-composition/cpu/index.html index 26f09e28..780ad3a0 100644 --- a/cs/principles-of-computer-composition/cpu/index.html +++ b/cs/principles-of-computer-composition/cpu/index.html @@ -1 +1 @@ -CPU - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 思维导图

CPU

CPU

# 单周期 CPU

# 单周期控制器

  • 控制信号在整个指令执行过程中保持不变

  • 真值表反映了指令和控制信号的关系

  • 按照真值表就可以实现控制器!

# 多周期 CPU

# 多周期控制器功能描述方式

  • 有限状态机
    采用组合逻辑设计方法用硬连线路 (PLA) 实现

  • 微程序
    用 ROM 存放微程序实现

# MIPS 各指令的周期数:

划分关键是:

  1. 所有指令均需要 IF,ID,EX 这三个周期
  2. 需要访存的指令额外需要一个周期 MEM(ID 内的访存不算,所以只有 Load/Store)
  3. 需要写回寄存器的指令额外需要一个周期 WB
  • R-Type (寄存器之间操作):4
    包含 IF,ID,EX,WB 共 4 个周期

  • I-Type

    • 运算指令 (一个寄存器、一个立即数) 如:4
      包含 IF,ID,EX,WB 共 4 个周期

    • Load 指令:4
      包含 IF,ID,EX,WB 共 4 个周期

    • Store 指令:5
      包含 IF,ID,EX,MEM,WB 共 5 个周期

    • 条件分支指令:3
      包含 IF,ID,EX 共 3 个周期

  • J-Type:3
    包含 IF,ID,EX 共 3 个周期

# 竞争 race :在组合电路中,信号经由不同的路径到达某一会合点的时间有先有后的现象

# ?冒险:竞争而引起电路输出发生瞬间错误。表现为输出端出现原设计中没有的毛刺

# 如何避免竞争问题:

确认地址和数据在第 N 周期结束时已稳定

  • 数据:就绪的早,撤的晚
    在 “写使能” 信号无效前地址和数据保持不变

  • 写使能:就绪的晚,撤的早
    使 “写使能” 信号在一个周期后 (即:第 N+1 周期) 有效

# 竞争冒险:因为信号传输延迟时间不同,而引起输出逻辑错误的现象

# 流水线 CPU

# 特点

  • 适合于大量重复的时序过程

  • 时空图是流水线分析的最好表示方法

  • 单个任务执行时,所需总执行时间没有缩短

  • 多个任务执行时,所有工作可以并行处理:单位时间内完成的工作量大大增加。在不改变单个任务执行时间的前提下,流水线提高了整个执行过程的吞吐率

  • 最大加速比 <流水栈数 (深度)

  • 流水线控制器的数据通路与单周期控制器十分类似

# 按级划分

  • 三级 CPU 划分:

      1. 取指 IF
      1. 译码 ID
      1. 执行 EX
  • 五级 CPU 划分:

      1. 取指 IF
      1. 译码 ID
      1. 执行 EX
      1. 访存 MEM
      1. 写回 WB

# 流水线越深(栈数越多)不一定提升性能:

  • (1)每两个相邻阶段之间都需要增加寄存器,因此会增大电路的复杂度,占用芯片的电路面积也就越大,容易增加成本、功耗。

  • (2)增加的寄存器也会使数据的传输时间变得更长,增加了执行指令的额外时间。复杂机制的影响(转移猜测、指令相关性等)。

  • 这些负面影响有可能会抵消增加流水线级数带来的正面影响。

# n 级流水线 CPU 完成 k 条指令需要周期为:

n + k -1 (最后一天条指令取指令后还需执行 k-1 个周期)

# 具有什么特征的指令集有利于流水线执行呢?

  • 指令长度尽量一致:有利于简化取指令和指令译码操作,不一致则需要取一次判断一次要不要再取

    • MIPS 指令都是 32 位,每次取 4 字节的指令,下址计算方便 (PC+4)

    • X86 指令从 1 字节到 17 字节不等,使取指部件极其复杂

  • 指令格式少,且源寄存器位置相同:有利于在指令未知时预取操作数

    • MIPS 指令的 Rs 和 Rt 位置一定,指令译码时就可读 Rs 和 Rt 的值

    • 若位置随指令不同而变,需先译码确定指令后才能取寄存器编号

  • 只有 load / Store 指令才能访问存储器,有利于减少操作步骤,规整流水线

    • MIPS 把 lw/sw 指令地址计算和运算指令执行步骤规整在同一个周期

    • X86 运算类指令操作数有内存数据,需计算地址、访存、执行

  • 数据和指令在内存中需要 “对齐” 存放,有利于减少访存次数和流水线的规整

# 冒险(Hazards)

指流水线遇到了无法正确执行后续指令或执行了不该执行的指令的现象

  • 结构冒险 (Struture Hazard)
    一个功能部件同时被多条指令使用的现象,或称为资源冲突,解决策略:

    • 在流水线中插入 “Bubble”(气泡)

      • 控制逻辑复杂

      • 使 n 级流水线中的每条指令都有相同的 n 个阶段,实际上没有执行的阶段(例如 5 级流水线中的 MEM 和 WB)为 NOP (空操作)

      • 设置多个部件,以避免冲突

  • 控制冒险 (Control Hazard)
    分支指令 (Branch) 引起的,亦称为分支冒险或转移冒险 (Branch Hazard),解决策略:

    • 硬件层面解决:
      流水线阻塞 (stall),也称为延迟和 “气泡 Bubble”,控制相当复杂,需要改数据通路

      • 编译器(软件)层面解决:

        • 分支预测 (Predict)

          • 简单 (静态) 预测 (statistic predictor):

            • 总是预测条件不满足,即:继续执行分支指令的后续指令

            • 可加启发式规则:在特定情况下总是预测满足 (taken),其他情况总是预测不满足。如:循环顶 (底) 部分支总是预测为不满足 (满足)。预测准确率可达 65%-85%

          • 动态预测 (dynamic predictor) :

            • 根据程序执行的历史情况,进行动态预测调整,能达 90% 的预测准确率

            • 利用分支历史记录表 BHT(或 BTB、BPB)

            • 现在几乎所有的处理器都采用动态预测

            • 预测器总结

              • 简单的 2 位预测器

                • 根据 2 位饱和计数器的值选择 Taken 和 ¬Taken

                • 连续错误两次则改变预测结果

              • 相关预测器

                • 为每个分支设置 2n 个 2 位的预测器

                • 根据最近全局发生的 n 次分支从 2n 个 2 位的预测器中选出一个

              • 局部预测器

                • 为每个分支设置 2n 个 2 位的预测器

                • 根据最近本身发生的 n 次分支从 2n 个 2 位的预测器中选出一个

              • 竞赛预测器(Tournament Predictor)

                • 在局部预测器和相关预测器之间动态选择

                • 采用一个饱和计数器(如 2 位计数器),在两者之间选择

                  • 计数器值为 00、01,选择局部预测器

                  • 计数器值为 10、11,选择相关预测器

          • 注:采用分支预测时,流水线控制必须确保错误预测指令的执行结果不能生效,能从正确的分支地址处重新启动流水线工作

        • 指令静态调度:编译优化指令顺序 / 延迟分支 (Delayed branch)

          • 延迟分支:把分支指令前面与分支指令无关的指令调到分支指令后面执行,也称之为延迟转移

          • 区分:分支延迟
            分支延迟是由于分支指令引起的延迟

          • 减少分支延迟的方法

            • 在流水线中尽早判断出分支转移是否成功

            • 尽早计算出分支目标地址

        • 插入三条 “NOP” 指令

  • 数据冒险 (Data Hazard)
    装入指令 (Load) 引起的,亦称为数据相关 (Data Dependency),解决策略:

    • 采用转发 / 旁路 (Forwarding/Bypassing)(技术现代常用):

      • 可以解决所有 R 指令后间隔的 lw 指令或 R 指令 的数据冒险问题
        任何运算指令总是在 ALU 阶段(EX 执行阶段)产生数据(第 3 个时钟)
        对于同一个 ALU 时,ALU 输出端直接输出到自己的输入端
        或把数据从流水段寄存器中直接取到 ALU 的输入端
        寄存器写 / 读口分别在前 / 后半周期
        使写入被直接读出

      • lw 指令在第 4 个时钟才产生数据,所以 lw 指令后紧接着 R 指令或 lw 指令转发无法解决,只能阻塞

      • 硬件层面解决:

      流水线阻塞 (stall),也称为延迟和 “气泡 Bubble”,控制相当复杂,需要改数据通路

      • 编译器(软件)层面解决:

        • 指令静态调度:编译优化指令顺序,拉大具有数据冒险指令的距离,减少流水线可能产生的停顿

        • 插入 NOP 指令
          最糟糕的做法,没有其他无关指令可以插入了

\ No newline at end of file +CPU - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 思维导图

CPU

CPU

# 单周期 CPU

# 单周期控制器

  • 控制信号在整个指令执行过程中保持不变

  • 真值表反映了指令和控制信号的关系

  • 按照真值表就可以实现控制器!

# 多周期 CPU

# 多周期控制器功能描述方式

  • 有限状态机
    采用组合逻辑设计方法用硬连线路 (PLA) 实现

  • 微程序
    用 ROM 存放微程序实现

# MIPS 各指令的周期数:

划分关键是:

  1. 所有指令均需要 IF,ID,EX 这三个周期
  2. 需要访存的指令额外需要一个周期 MEM(ID 内的访存不算,所以只有 Load/Store)
  3. 需要写回寄存器的指令额外需要一个周期 WB
  • R-Type (寄存器之间操作):4
    包含 IF,ID,EX,WB 共 4 个周期

  • I-Type

    • 运算指令 (一个寄存器、一个立即数) 如:4
      包含 IF,ID,EX,WB 共 4 个周期

    • Load 指令:4
      包含 IF,ID,EX,WB 共 4 个周期

    • Store 指令:5
      包含 IF,ID,EX,MEM,WB 共 5 个周期

    • 条件分支指令:3
      包含 IF,ID,EX 共 3 个周期

  • J-Type:3
    包含 IF,ID,EX 共 3 个周期

# 竞争 race :在组合电路中,信号经由不同的路径到达某一会合点的时间有先有后的现象

# ?冒险:竞争而引起电路输出发生瞬间错误。表现为输出端出现原设计中没有的毛刺

# 如何避免竞争问题:

确认地址和数据在第 N 周期结束时已稳定

  • 数据:就绪的早,撤的晚
    在 “写使能” 信号无效前地址和数据保持不变

  • 写使能:就绪的晚,撤的早
    使 “写使能” 信号在一个周期后 (即:第 N+1 周期) 有效

# 竞争冒险:因为信号传输延迟时间不同,而引起输出逻辑错误的现象

# 流水线 CPU

# 特点

  • 适合于大量重复的时序过程

  • 时空图是流水线分析的最好表示方法

  • 单个任务执行时,所需总执行时间没有缩短

  • 多个任务执行时,所有工作可以并行处理:单位时间内完成的工作量大大增加。在不改变单个任务执行时间的前提下,流水线提高了整个执行过程的吞吐率

  • 最大加速比 <流水栈数 (深度)

  • 流水线控制器的数据通路与单周期控制器十分类似

# 按级划分

  • 三级 CPU 划分:

      1. 取指 IF
      1. 译码 ID
      1. 执行 EX
  • 五级 CPU 划分:

      1. 取指 IF
      1. 译码 ID
      1. 执行 EX
      1. 访存 MEM
      1. 写回 WB

# 流水线越深(栈数越多)不一定提升性能:

  • (1)每两个相邻阶段之间都需要增加寄存器,因此会增大电路的复杂度,占用芯片的电路面积也就越大,容易增加成本、功耗。

  • (2)增加的寄存器也会使数据的传输时间变得更长,增加了执行指令的额外时间。复杂机制的影响(转移猜测、指令相关性等)。

  • 这些负面影响有可能会抵消增加流水线级数带来的正面影响。

# n 级流水线 CPU 完成 k 条指令需要周期为:

n + k -1 (最后一天条指令取指令后还需执行 k-1 个周期)

# 具有什么特征的指令集有利于流水线执行呢?

  • 指令长度尽量一致:有利于简化取指令和指令译码操作,不一致则需要取一次判断一次要不要再取

    • MIPS 指令都是 32 位,每次取 4 字节的指令,下址计算方便 (PC+4)

    • X86 指令从 1 字节到 17 字节不等,使取指部件极其复杂

  • 指令格式少,且源寄存器位置相同:有利于在指令未知时预取操作数

    • MIPS 指令的 Rs 和 Rt 位置一定,指令译码时就可读 Rs 和 Rt 的值

    • 若位置随指令不同而变,需先译码确定指令后才能取寄存器编号

  • 只有 load / Store 指令才能访问存储器,有利于减少操作步骤,规整流水线

    • MIPS 把 lw/sw 指令地址计算和运算指令执行步骤规整在同一个周期

    • X86 运算类指令操作数有内存数据,需计算地址、访存、执行

  • 数据和指令在内存中需要 “对齐” 存放,有利于减少访存次数和流水线的规整

# 冒险(Hazards)

指流水线遇到了无法正确执行后续指令或执行了不该执行的指令的现象

  • 结构冒险 (Struture Hazard)
    一个功能部件同时被多条指令使用的现象,或称为资源冲突,解决策略:

    • 在流水线中插入 “Bubble”(气泡)

      • 控制逻辑复杂

      • 使 n 级流水线中的每条指令都有相同的 n 个阶段,实际上没有执行的阶段(例如 5 级流水线中的 MEM 和 WB)为 NOP (空操作)

      • 设置多个部件,以避免冲突

  • 控制冒险 (Control Hazard)
    分支指令 (Branch) 引起的,亦称为分支冒险或转移冒险 (Branch Hazard),解决策略:

    • 硬件层面解决:
      流水线阻塞 (stall),也称为延迟和 “气泡 Bubble”,控制相当复杂,需要改数据通路

      • 编译器(软件)层面解决:

        • 分支预测 (Predict)

          • 简单 (静态) 预测 (statistic predictor):

            • 总是预测条件不满足,即:继续执行分支指令的后续指令

            • 可加启发式规则:在特定情况下总是预测满足 (taken),其他情况总是预测不满足。如:循环顶 (底) 部分支总是预测为不满足 (满足)。预测准确率可达 65%-85%

          • 动态预测 (dynamic predictor) :

            • 根据程序执行的历史情况,进行动态预测调整,能达 90% 的预测准确率

            • 利用分支历史记录表 BHT(或 BTB、BPB)

            • 现在几乎所有的处理器都采用动态预测

            • 预测器总结

              • 简单的 2 位预测器

                • 根据 2 位饱和计数器的值选择 Taken 和 ¬Taken

                • 连续错误两次则改变预测结果

              • 相关预测器

                • 为每个分支设置 2n 个 2 位的预测器

                • 根据最近全局发生的 n 次分支从 2n 个 2 位的预测器中选出一个

              • 局部预测器

                • 为每个分支设置 2n 个 2 位的预测器

                • 根据最近本身发生的 n 次分支从 2n 个 2 位的预测器中选出一个

              • 竞赛预测器(Tournament Predictor)

                • 在局部预测器和相关预测器之间动态选择

                • 采用一个饱和计数器(如 2 位计数器),在两者之间选择

                  • 计数器值为 00、01,选择局部预测器

                  • 计数器值为 10、11,选择相关预测器

          • 注:采用分支预测时,流水线控制必须确保错误预测指令的执行结果不能生效,能从正确的分支地址处重新启动流水线工作

        • 指令静态调度:编译优化指令顺序 / 延迟分支 (Delayed branch)

          • 延迟分支:把分支指令前面与分支指令无关的指令调到分支指令后面执行,也称之为延迟转移

          • 区分:分支延迟
            分支延迟是由于分支指令引起的延迟

          • 减少分支延迟的方法

            • 在流水线中尽早判断出分支转移是否成功

            • 尽早计算出分支目标地址

        • 插入三条 “NOP” 指令

  • 数据冒险 (Data Hazard)
    装入指令 (Load) 引起的,亦称为数据相关 (Data Dependency),解决策略:

    • 采用转发 / 旁路 (Forwarding/Bypassing)(技术现代常用):

      • 可以解决所有 R 指令后间隔的 lw 指令或 R 指令 的数据冒险问题
        任何运算指令总是在 ALU 阶段(EX 执行阶段)产生数据(第 3 个时钟)
        对于同一个 ALU 时,ALU 输出端直接输出到自己的输入端
        或把数据从流水段寄存器中直接取到 ALU 的输入端
        寄存器写 / 读口分别在前 / 后半周期
        使写入被直接读出

      • lw 指令在第 4 个时钟才产生数据,所以 lw 指令后紧接着 R 指令或 lw 指令转发无法解决,只能阻塞

      • 硬件层面解决:

      流水线阻塞 (stall),也称为延迟和 “气泡 Bubble”,控制相当复杂,需要改数据通路

      • 编译器(软件)层面解决:

        • 指令静态调度:编译优化指令顺序,拉大具有数据冒险指令的距离,减少流水线可能产生的停顿

        • 插入 NOP 指令
          最糟糕的做法,没有其他无关指令可以插入了

\ No newline at end of file diff --git a/cs/principles-of-computer-composition/data-path/index.html b/cs/principles-of-computer-composition/data-path/index.html index e3f06bb3..95c98361 100644 --- a/cs/principles-of-computer-composition/data-path/index.html +++ b/cs/principles-of-computer-composition/data-path/index.html @@ -1 +1 @@ -数据通路 - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 思维导图

数据通路

# CPU (Processor)

# Control 控制器

指令执行过程中,数据所经过的路径 (包括路径中的部件)—— 指令的执行部件

  • 控制器的基本功能

    • 取指令 (控制指令流出 — PC)

    • 分析指令 (控制指令分析 — IR)

    • 执行指令,发出各种操作命令
      (控制指令执行 — REGs 和 ALU)

    • 确定下一条指令的地址
      (控制指令流向 —PC)

    • 执行环境的建立与保护 (控制执行环境的维护 —FLAGs/PSW)

# Datapath 数据通路

对指令进行译码,生成指令对应的控制信号,控制数据通路的动作,能对指令的执行部件发出控制信号 —— 指令的控制部件

  • 数据通路的构成
    由 “操作元件” 和 “存储元件” 通过总线或分散方式连接而成

  • 数据通路的功能
    进行数据存储、处理、传送

# 数据通路由两类部件组成

# 组合逻辑元件 or 操作元件

  • 组合逻辑元件的特点:

    • 其输出只取决于当前的输入

    • 所有输入到达后,经过一定的逻辑门延时,输出端改变,并保持到下次改变,不需要时钟信号来定时

  • 包括:

    • 译码器 (Decoder)

      • 多路选择器 (MUX)

      • 加法器 (Adder)

      • 算术逻辑部件 (ALU)

# 存储元件 or 状态元件

  • 状态 (存储) 元件的特点

    • 具有存储功能,在时钟控制下输入状态被写到电路中,直到下一个时钟到达

    • 输入端状态由时钟决定何时写入,输出端状态随时可读出

  • 定时方式:规定信号何时写入状态元件或何时从状态元件读出

    • 边沿触发 (edge-triggered) 方式:状态单元中的值只在时钟边沿改变。每个时钟周期改变一次

      • 上升沿 (rising edge) 触发:在时钟正跳变时进行读 / 写

      • 下降沿 (falling edge) 触发:在时钟负跳变时进行读 / 写

  • 包括

    • 寄存器 (组)

      • 寄存器 (Register)

        • 写使能 (Write Enable-WE) 信号

          • 0: 时钟边沿到时,输出不变

          • 1: 时钟边沿到时,输出开始变为输入

        • 若每个时钟边沿都写入,则不需 WE 信号

      • 寄存器组 (Register File)

        • 两个读口 (组合逻辑操作):busA 和 busB
          不需要 “读使能”

          • 分别由 RA 和 RB 给出地址。地址 RA 或 RB 有效后,经一个 “取数时间 (AccessTime)”,busA 和 busB 有效
      • 一个写口 (时序逻辑操作):写使能

        • 为 1 且时钟边沿到时,busW 传来的值开始被写入 RW 指定的寄存器中
    • 存储器(理想存储器)
      按存储内容分为:指令存储器 和 数据存储器

      • Data Out:32/64 位读出数据

      • Data In: 32/64 位写入数据

      • Address:读写共用一个 32/64 位地址

      • 读 (组合逻辑操作):地址 Address 有效后,经一个 “取数时间 (AccessTime)”,Data Out 上数据有效

      • 写 (时序逻辑操作):写使能为 1 且时钟 Clk 边沿到来,Data In 传来的值开始被写入 Address 指定的存储单元

# 元件之间的连接方式

# 总线式连接

  • 单总线数据通路

  • 三总线数据通路

    • 总线 A、B 分别传送两个源操作数,

    • 总线 C 传送结果

    • 采用双口寄存器

# 分散式连接

# 早期累加器型指令数据通路

\ No newline at end of file +数据通路 - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 思维导图

数据通路

# CPU (Processor)

# Control 控制器

指令执行过程中,数据所经过的路径 (包括路径中的部件)—— 指令的执行部件

  • 控制器的基本功能

    • 取指令 (控制指令流出 — PC)

    • 分析指令 (控制指令分析 — IR)

    • 执行指令,发出各种操作命令
      (控制指令执行 — REGs 和 ALU)

    • 确定下一条指令的地址
      (控制指令流向 —PC)

    • 执行环境的建立与保护 (控制执行环境的维护 —FLAGs/PSW)

# Datapath 数据通路

对指令进行译码,生成指令对应的控制信号,控制数据通路的动作,能对指令的执行部件发出控制信号 —— 指令的控制部件

  • 数据通路的构成
    由 “操作元件” 和 “存储元件” 通过总线或分散方式连接而成

  • 数据通路的功能
    进行数据存储、处理、传送

# 数据通路由两类部件组成

# 组合逻辑元件 or 操作元件

  • 组合逻辑元件的特点:

    • 其输出只取决于当前的输入

    • 所有输入到达后,经过一定的逻辑门延时,输出端改变,并保持到下次改变,不需要时钟信号来定时

  • 包括:

    • 译码器 (Decoder)

      • 多路选择器 (MUX)

      • 加法器 (Adder)

      • 算术逻辑部件 (ALU)

# 存储元件 or 状态元件

  • 状态 (存储) 元件的特点

    • 具有存储功能,在时钟控制下输入状态被写到电路中,直到下一个时钟到达

    • 输入端状态由时钟决定何时写入,输出端状态随时可读出

  • 定时方式:规定信号何时写入状态元件或何时从状态元件读出

    • 边沿触发 (edge-triggered) 方式:状态单元中的值只在时钟边沿改变。每个时钟周期改变一次

      • 上升沿 (rising edge) 触发:在时钟正跳变时进行读 / 写

      • 下降沿 (falling edge) 触发:在时钟负跳变时进行读 / 写

  • 包括

    • 寄存器 (组)

      • 寄存器 (Register)

        • 写使能 (Write Enable-WE) 信号

          • 0: 时钟边沿到时,输出不变

          • 1: 时钟边沿到时,输出开始变为输入

        • 若每个时钟边沿都写入,则不需 WE 信号

      • 寄存器组 (Register File)

        • 两个读口 (组合逻辑操作):busA 和 busB
          不需要 “读使能”

          • 分别由 RA 和 RB 给出地址。地址 RA 或 RB 有效后,经一个 “取数时间 (AccessTime)”,busA 和 busB 有效
      • 一个写口 (时序逻辑操作):写使能

        • 为 1 且时钟边沿到时,busW 传来的值开始被写入 RW 指定的寄存器中
    • 存储器(理想存储器)
      按存储内容分为:指令存储器 和 数据存储器

      • Data Out:32/64 位读出数据

      • Data In: 32/64 位写入数据

      • Address:读写共用一个 32/64 位地址

      • 读 (组合逻辑操作):地址 Address 有效后,经一个 “取数时间 (AccessTime)”,Data Out 上数据有效

      • 写 (时序逻辑操作):写使能为 1 且时钟 Clk 边沿到来,Data In 传来的值开始被写入 Address 指定的存储单元

# 元件之间的连接方式

# 总线式连接

  • 单总线数据通路

  • 三总线数据通路

    • 总线 A、B 分别传送两个源操作数,

    • 总线 C 传送结果

    • 采用双口寄存器

# 分散式连接

# 早期累加器型指令数据通路

\ No newline at end of file diff --git a/cs/principles-of-computer-composition/dram-refresh/index.html b/cs/principles-of-computer-composition/dram-refresh/index.html index 9f3f5bfd..756455d9 100644 --- a/cs/principles-of-computer-composition/dram-refresh/index.html +++ b/cs/principles-of-computer-composition/dram-refresh/index.html @@ -1 +1 @@ -DRAM 刷新 - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 思维导图

DRAM刷新

# 为什么要刷新?

# DRAM 存储位元的特点

# 靠电容上的电荷存储效应记忆信息,虽然有 MOS 高电阻 (10121015Ω10^{12} \sim 10^{15} \Omega),仍会泄漏电荷

# 为保证所存信息的正确性,需要用充电的方法及时使所有位元的电容上电荷恢复到泄漏前的状态

# DRAM 刷新的有关参数

# 刷新周期 Trc (refresh cycle)

  • 对同一存储位元连续两次刷新,仍能保证鉴别出原存信息的最大允许间隔时间,即在 Trc 内必须对每个单元刷新一遍

  • 一般为 ms 级,亦称为刷新间隔时间

  • 在 Trc 时间内,应刷新存储芯片中的所有存储位

  • 在 DRAM 芯片的主要性能参数中,都给出 Trc。通常为 2ms、4ms、8ms

  • Trc < Tref

# 刷新操作周期 Troc (refresh operating cycle)

刷新一行存储位元所需时间,通常和 DRAM 读写周期 tRC /tWC 相同

# 刷新操作周期数 Nr (Number of refresh operating cycle)

存储芯片所有位元刷新一遍所需的刷新操作周期个数。它与芯片的内部结构有关。
即每次可以刷新一行, Nr 决定于存储矩阵的行数

# 信息保持时间 Tref (不太重要)

从信息以电荷形式存入电容,到电荷经过一段时间泄漏,读放仍能鉴别出原存信息的时间

# 按刷新操作周期的分配方式分类

# 集中式刷新

也叫 “批刷新”,从刷新周期 Trc 中抽出连续一段长度的访存周期作为刷新操作周期集中进行刷新

  • 缺点:集中式刷新使 98.976% 的时间用于访存,这期间存储器的效能得以充分发挥,但有 1.024% 的时间,即在 8ms 中有 81.92μs 不允许访存,CPU 要处于等待状态,影响了计算机的工作效率

  • 优点:控制逻辑简单,设计容易实现

# 分散式刷新

把集中到一起的不允许访存的刷新时间分散开,每个等分的最后一个访存周期用作刷新操作周期,以完成一行存储位元的刷新,其余时间则用于访存

  • 优点:降低了访存的阻塞时间,提高了计算机的工作效率

  • 缺点:控制逻辑复杂,设计不易实现

# 透明式刷新

设一个系统的访存周期是存储器实际访存周期的两倍,并令系统访存周期的前半周期用于访存,后半周期用于刷新

  • 优点:控制简单、设计容易,不需增加多少器件

  • 缺点:存储器的效能仅利用 50%,仅用于低速系统

\ No newline at end of file +DRAM 刷新 - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 思维导图

DRAM刷新

# 为什么要刷新?

# DRAM 存储位元的特点

# 靠电容上的电荷存储效应记忆信息,虽然有 MOS 高电阻 (10121015Ω10^{12} \sim 10^{15} \Omega),仍会泄漏电荷

# 为保证所存信息的正确性,需要用充电的方法及时使所有位元的电容上电荷恢复到泄漏前的状态

# DRAM 刷新的有关参数

# 刷新周期 Trc (refresh cycle)

  • 对同一存储位元连续两次刷新,仍能保证鉴别出原存信息的最大允许间隔时间,即在 Trc 内必须对每个单元刷新一遍

  • 一般为 ms 级,亦称为刷新间隔时间

  • 在 Trc 时间内,应刷新存储芯片中的所有存储位

  • 在 DRAM 芯片的主要性能参数中,都给出 Trc。通常为 2ms、4ms、8ms

  • Trc < Tref

# 刷新操作周期 Troc (refresh operating cycle)

刷新一行存储位元所需时间,通常和 DRAM 读写周期 tRC /tWC 相同

# 刷新操作周期数 Nr (Number of refresh operating cycle)

存储芯片所有位元刷新一遍所需的刷新操作周期个数。它与芯片的内部结构有关。
即每次可以刷新一行, Nr 决定于存储矩阵的行数

# 信息保持时间 Tref (不太重要)

从信息以电荷形式存入电容,到电荷经过一段时间泄漏,读放仍能鉴别出原存信息的时间

# 按刷新操作周期的分配方式分类

# 集中式刷新

也叫 “批刷新”,从刷新周期 Trc 中抽出连续一段长度的访存周期作为刷新操作周期集中进行刷新

  • 缺点:集中式刷新使 98.976% 的时间用于访存,这期间存储器的效能得以充分发挥,但有 1.024% 的时间,即在 8ms 中有 81.92μs 不允许访存,CPU 要处于等待状态,影响了计算机的工作效率

  • 优点:控制逻辑简单,设计容易实现

# 分散式刷新

把集中到一起的不允许访存的刷新时间分散开,每个等分的最后一个访存周期用作刷新操作周期,以完成一行存储位元的刷新,其余时间则用于访存

  • 优点:降低了访存的阻塞时间,提高了计算机的工作效率

  • 缺点:控制逻辑复杂,设计不易实现

# 透明式刷新

设一个系统的访存周期是存储器实际访存周期的两倍,并令系统访存周期的前半周期用于访存,后半周期用于刷新

  • 优点:控制简单、设计容易,不需增加多少器件

  • 缺点:存储器的效能仅利用 50%,仅用于低速系统

\ No newline at end of file diff --git a/cs/principles-of-computer-composition/exception-and-interruption/index.html b/cs/principles-of-computer-composition/exception-and-interruption/index.html index 00c7892b..0e9685b5 100644 --- a/cs/principles-of-computer-composition/exception-and-interruption/index.html +++ b/cs/principles-of-computer-composition/exception-and-interruption/index.html @@ -1 +1 @@ -异常和中断 - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 思维导图

异常和中断

# 异常和中断的概念

# 异常:

异常来自于 cpu 内部的正在执行的指令本身

# 中断:

中断来自于 cpu 外部的硬件触发

# 统称为 “中断”:

  • 内中断 (内部异常)
    CPU 自己产生而不通过中断请求线请求,皆为不可屏蔽中断

  • 外中断 (外部中断)
    通过中断请求线 INTR 和 NMI 来实现

# 内部 “异常”:CPU 内发生的意外事件或特殊事件

# 按发生原因分为硬故障中断和程序性中断两类

  • 硬故障中断:如电源掉电、硬件线路故障等

  • 程序性中断:执行某条指令时发生的 “异常 (Exception)”,如

    • 溢出

    • 缺页

    • 越界

    • 越权

    • 非法指令

    • 除数为 0

    • 断点

    • 单步跟踪

    • 系统调用

# 按处理方式分 故障 (fault)、自陷 (Trap) 和终止 (Abort) 三类

  • 故障:执行指令引起的异常事件,如 溢出 / 缺页 / 访问超时
    属于程序性中断

  • 自陷:预先安排的事件,如 单步跟踪、系统调用等 (自愿中断)
    属于程序性中断

  • 终止:硬故障事件,机器将终止,调出中断程序重启操作系统
    属于硬故障中断

# 外部 “中断”:

# INTR(Interrupt Require):

可屏蔽中断 (外设中断源引起的中断)
CPU 可以响应、也可以不响应
响应与否受两个控制:

  • 本身的屏蔽位

  • CPU 标志寄存器中的中断允许位 (IF)

    • 置 IF=1:指令 STI—— 开中断

    • 清 IF=0:指令 CLI—— 关中断

# NMI(Nonmaskable Interrupt):

不可屏蔽中断 (重要或紧急的硬件故障),属于类型 2 中断
CPU 必须无条件响应
如电源掉电、存储器读写出错、总线奇偶位出错等

# 处理器中的异常处理机制

# 关中断:

使处理器处于 “禁止中断” 状态,以防止新异常 (或中断) 破坏断点和现场

# 保护断点和程序状态:

将断点和程序状态保存到堆栈或特殊寄存器中

  • PC→堆栈 或 EPC (专门存放断点的寄存器)

  • PSWR →堆栈 或 EPSWR (专门保存程序状态的寄存器)

    • PSW—Program Status Word:程序状态字,包括条件码、中断码、状态位等

    • PSWR (PSW 寄存器):用于存放程序状态字寄存器。如 X86 的 FLAGS

# 识别异常事件:软件识别和硬件识别

  • 软件识别 (非向量中断、MIPS 采用)
    设置一个异常状态寄存器 (如 MIPS 中为 Cause 寄存器),用于记录异常原因。操作系统用一个异常处理程序,按优先级顺序查询异常状态寄存器,识别出异常事件,转入相应的中断服务程序执行

    • 数据通路中需增加两个寄存器

      • EPC:32 位,用于存放断点 (异常处理后返回到的指令的地址)

        • 写入 EPC 的断点可能是正在执行的指令 (故障 时):把 PC 的值减 4 后送到 EPC

        • 写入 EPC 的断点可能是下条指令 (自陷 和 中断 时):直接送 PC 到 EPC

      • Cause:32 位,记录异常原因

        • 处理的异常类型:例如未定义指令 (Cause=10)、算术溢出 (Cause=12)
    • 需要加入两个寄存器的 “写使能” 控制信号

      • EPCWr:在保存断点时该信号有效,使断点 PC 写入 EPC

      • CauseWr:在处理器发现异常 (如非法指令等) 时,该信号有效,使异常类型被写到 Cause 寄存器

    • 需要一个控制信号 IntCause:选择正确的值写入到 Cause 中

    • 需要将异常查询程序的入口地址 (MIPS 为 0x8000 0180) 写入 PC:在原来 PCSource 控制的多路复用器中再增加一路,其输入为 0x8000 0180

  • 硬件识别 (向量中断、80x86 采用)
    用专门的硬件查询电路按优先级顺序识别异常,得到 “中断类型号”,到中断向量表中读取对应的中断服务程序的入口地址

    • 中断向量表(中断入口地址表),位于 0000H~03FFH

    • 含 256 个中断向量,每一项就是对应的中断服务程序的入口地址,每个向量长度为四个字节 (CS:IP)
      256 = 41616/4

      • 中断向量地址 = 中断类型号 ×4

      • 若已知一个中断类型码,需要通过两次地址转换:

        • 中断类型码到中断向量表地址

        • 中断向量表地址到中断处理程序地址

# 流水线方式下的异常和中断处理

# 异常和中断都会改变程序的执行顺序

# 某条指令发现异常时,后面多条指令已被取到流水线中执行

处理时需要首先清除当前指令以及后面的所有已在流水线中的指令

# 如果是内部异常,n 级流水线中同时有 n 条指令,哪一条发生异常?

根据异常发生的流水段可确定是哪条指令,因为各类异常发生的流水段不同

  • “溢出” 在 EX 段检出

  • “无效指令” 在 ID 段检出

  • “除数为 0” 在 ID 段检出

  • “无效指令地址” 在 IF 段检出

  • “无效数据地址” 在 Load/Store 指令的 EX 段检出

# 如果是外部中断,外部中断与特定指令无关,如何确定处理点?

  • 可在 IF 段或 WB 段中进行中断查询,需要保证当前 WB 段的指令能正确完成,并在有中断发生时,确保下个时钟开始执行中断服务程序

# 检测到异常时,指令已经取出多条,当前 PC 的值已不是断点,怎么办?

  • 指令地址存放在流水段寄存器中,把这个地址送到 EPC 保存,以实现精确中断

  • 精确中断 (precise interrupt) 或精确异常 (precise exception)

    • 对于发生中断或者异常的单条指令,中断被称为 “精确” 当且仅当满足:
      所有该指令之前的指令都已经提交其状态;
      所有后继指令 (包括中断的指令) 没有改变任何机器的状态

    • 在流水线计算机中,异常或中断与其产生的指令始终能精确地关联起来

\ No newline at end of file +异常和中断 - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 思维导图

异常和中断

# 异常和中断的概念

# 异常:

异常来自于 cpu 内部的正在执行的指令本身

# 中断:

中断来自于 cpu 外部的硬件触发

# 统称为 “中断”:

  • 内中断 (内部异常)
    CPU 自己产生而不通过中断请求线请求,皆为不可屏蔽中断

  • 外中断 (外部中断)
    通过中断请求线 INTR 和 NMI 来实现

# 内部 “异常”:CPU 内发生的意外事件或特殊事件

# 按发生原因分为硬故障中断和程序性中断两类

  • 硬故障中断:如电源掉电、硬件线路故障等

  • 程序性中断:执行某条指令时发生的 “异常 (Exception)”,如

    • 溢出

    • 缺页

    • 越界

    • 越权

    • 非法指令

    • 除数为 0

    • 断点

    • 单步跟踪

    • 系统调用

# 按处理方式分 故障 (fault)、自陷 (Trap) 和终止 (Abort) 三类

  • 故障:执行指令引起的异常事件,如 溢出 / 缺页 / 访问超时
    属于程序性中断

  • 自陷:预先安排的事件,如 单步跟踪、系统调用等 (自愿中断)
    属于程序性中断

  • 终止:硬故障事件,机器将终止,调出中断程序重启操作系统
    属于硬故障中断

# 外部 “中断”:

# INTR(Interrupt Require):

可屏蔽中断 (外设中断源引起的中断)
CPU 可以响应、也可以不响应
响应与否受两个控制:

  • 本身的屏蔽位

  • CPU 标志寄存器中的中断允许位 (IF)

    • 置 IF=1:指令 STI—— 开中断

    • 清 IF=0:指令 CLI—— 关中断

# NMI(Nonmaskable Interrupt):

不可屏蔽中断 (重要或紧急的硬件故障),属于类型 2 中断
CPU 必须无条件响应
如电源掉电、存储器读写出错、总线奇偶位出错等

# 处理器中的异常处理机制

# 关中断:

使处理器处于 “禁止中断” 状态,以防止新异常 (或中断) 破坏断点和现场

# 保护断点和程序状态:

将断点和程序状态保存到堆栈或特殊寄存器中

  • PC→堆栈 或 EPC (专门存放断点的寄存器)

  • PSWR →堆栈 或 EPSWR (专门保存程序状态的寄存器)

    • PSW—Program Status Word:程序状态字,包括条件码、中断码、状态位等

    • PSWR (PSW 寄存器):用于存放程序状态字寄存器。如 X86 的 FLAGS

# 识别异常事件:软件识别和硬件识别

  • 软件识别 (非向量中断、MIPS 采用)
    设置一个异常状态寄存器 (如 MIPS 中为 Cause 寄存器),用于记录异常原因。操作系统用一个异常处理程序,按优先级顺序查询异常状态寄存器,识别出异常事件,转入相应的中断服务程序执行

    • 数据通路中需增加两个寄存器

      • EPC:32 位,用于存放断点 (异常处理后返回到的指令的地址)

        • 写入 EPC 的断点可能是正在执行的指令 (故障 时):把 PC 的值减 4 后送到 EPC

        • 写入 EPC 的断点可能是下条指令 (自陷 和 中断 时):直接送 PC 到 EPC

      • Cause:32 位,记录异常原因

        • 处理的异常类型:例如未定义指令 (Cause=10)、算术溢出 (Cause=12)
    • 需要加入两个寄存器的 “写使能” 控制信号

      • EPCWr:在保存断点时该信号有效,使断点 PC 写入 EPC

      • CauseWr:在处理器发现异常 (如非法指令等) 时,该信号有效,使异常类型被写到 Cause 寄存器

    • 需要一个控制信号 IntCause:选择正确的值写入到 Cause 中

    • 需要将异常查询程序的入口地址 (MIPS 为 0x8000 0180) 写入 PC:在原来 PCSource 控制的多路复用器中再增加一路,其输入为 0x8000 0180

  • 硬件识别 (向量中断、80x86 采用)
    用专门的硬件查询电路按优先级顺序识别异常,得到 “中断类型号”,到中断向量表中读取对应的中断服务程序的入口地址

    • 中断向量表(中断入口地址表),位于 0000H~03FFH

    • 含 256 个中断向量,每一项就是对应的中断服务程序的入口地址,每个向量长度为四个字节 (CS:IP)
      256 = 41616/4

      • 中断向量地址 = 中断类型号 ×4

      • 若已知一个中断类型码,需要通过两次地址转换:

        • 中断类型码到中断向量表地址

        • 中断向量表地址到中断处理程序地址

# 流水线方式下的异常和中断处理

# 异常和中断都会改变程序的执行顺序

# 某条指令发现异常时,后面多条指令已被取到流水线中执行

处理时需要首先清除当前指令以及后面的所有已在流水线中的指令

# 如果是内部异常,n 级流水线中同时有 n 条指令,哪一条发生异常?

根据异常发生的流水段可确定是哪条指令,因为各类异常发生的流水段不同

  • “溢出” 在 EX 段检出

  • “无效指令” 在 ID 段检出

  • “除数为 0” 在 ID 段检出

  • “无效指令地址” 在 IF 段检出

  • “无效数据地址” 在 Load/Store 指令的 EX 段检出

# 如果是外部中断,外部中断与特定指令无关,如何确定处理点?

  • 可在 IF 段或 WB 段中进行中断查询,需要保证当前 WB 段的指令能正确完成,并在有中断发生时,确保下个时钟开始执行中断服务程序

# 检测到异常时,指令已经取出多条,当前 PC 的值已不是断点,怎么办?

  • 指令地址存放在流水段寄存器中,把这个地址送到 EPC 保存,以实现精确中断

  • 精确中断 (precise interrupt) 或精确异常 (precise exception)

    • 对于发生中断或者异常的单条指令,中断被称为 “精确” 当且仅当满足:
      所有该指令之前的指令都已经提交其状态;
      所有后继指令 (包括中断的指令) 没有改变任何机器的状态

    • 在流水线计算机中,异常或中断与其产生的指令始终能精确地关联起来

\ No newline at end of file diff --git a/cs/principles-of-computer-composition/instruction-system/index.html b/cs/principles-of-computer-composition/instruction-system/index.html index 716bcb6d..05e40afe 100644 --- a/cs/principles-of-computer-composition/instruction-system/index.html +++ b/cs/principles-of-computer-composition/instruction-system/index.html @@ -1 +1 @@ -指令系统 - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 思维导图

指令系统

# 两大类型

# CISC

  • (1) 指令系统复杂
  • (2) 指令周期长
  • (3) 各种指令都能访问存储器
  • (4) 有专用寄存器(寻址快)
  • (5) 采用微程序控制
  • (6) 难以进行编译优化生成高效目标代码
  • (7) 指令长度不等长,
    变长指令字 (Expanding Opcodes)

# RISC

  • (1) 简化的指令系统
  • (2) 指令周期短
  • (3) 有专门的访存指令如 load、store,
    以寄存器 - 寄存器方式工作 (三地址指令是 RISC 风格)
  • (4) 采用大量通用寄存器,以减少访存次数
  • (5) 采用组合逻辑电路控制,不用或少用微程序控制
  • (6) 采用优化的编译系统,力求有效地支持高级语言程序
  • (7) 指令长度几乎全部相等,
    定长指令字 (Fixed Length Opcodes)

# 设计原则

# 完备性

# 有效性

  • 每条指令的操作码只能是一个

# 规整性

# 兼容性

  • 向上兼容
  • 向下兼容

# 指令系统的结构

# 堆栈结构:零地址指令

# 累加器结构:一地址指令

# 通用寄存器结构:二、三地址指令

# 指令 Command

指令是指挥计算机实现某个基本操作的命令

# MIPS 三种指令类型

  • R-Type (用于寄存器 Register)
    两个操作数都是寄存器的运算指令。如:sub rd, rs, rt

  • I-Type

    • 运算指令:一个寄存器、一个立即数。如:
      ori rt, rs, imm16
    • Load 和 Store 指令。如:
      lw rt, rs, imm16
    • 条件分支指令。如:
      beq rs, rt, imm16
  • J-Type
    无条件跳转指令。如:j target

注意:J 指令是绝对寻址 (伪直接寻址),不是相对寻址!

# 一条指令

  • 操作码

  • 地址码

    • 寻址方式码
    • 操作数

# 地址码结构

  • 零地址指令

    • (1) 无需操作数。如:空操作/停机等
    • (2) 所需操作数为默认的。如:堆栈等
  • 一地址指令
    其地址既是源操作数地址,也是存放结果地址

    • (1) 单目运算:如:取反/取负等
    • (2) 双目运算:另一操作数为默认的 如:累加器等
  • 二地址指令 (最常用)
    分别存放双目运算中两个源操作数地址,并将其中一个地址作为存放结果地址

  • 三地址指令 (RISC 风格)
    三个地址分别为双目运算中两个源操作数地址和一个结果地址

  • 多地址指令
    用于成批数据处理的指令,如:向量指令 等

# 一个较完善的指令系统应该包括

# 数据传送指令

# 输入输出指令

# 算术运算指令

  • 单目运算
  • 双面运算

# 逻辑运算指令

  • 单目运算
  • 双面运算

# 系统控制指令

# 程序控制指令

# 寻址

# 寻址方式出现的目的

  • 扩大访存范围

  • 提高访问数据的灵活性和有效性

  • 支持软件技术的发展:多道程序设计

# 指令系统中的两类寻址

  • 寻找操作数
    较复杂

    • 操作数的来源:

      • 寄存器
      • 外设端口
      • 主 (虚) 存
      • 堆栈
    • 操作数的数据结构:

      • 字节
      • 半字
      • 双字
      • 一维表
  • 寻找 (下一条) 指令
    较简单

    • 顺序寻址
      PC 增值

    • 跳跃寻址
      跳转 :操作数就是目标语句块第一条指令的地址
      相对寻址

      • jump
      • branch
      • call
      • return

# 寻址方式的确定

  • 在操作码中隐含寻址方式
  • 专门的寻址方式位显式给出

# 基本寻址方式

# 一、立即数寻址

“不寻址”,源操作数直接在指令中

  • 1. 指令执行时间很短,无需访存
  • 2. 操作数的大小受地址字段长度的限制
  • 3. 广泛使用

# 二、存储器直接寻址

操作数在存储器中,指令地址字段直接给出操作数在存储器中的地址
无括号包围

  • 1. 处理简单、直接
  • 2. 寻址空间受到指令的地址字段长度限制
  • 3. 较少使用,8 位计算机和一些 16 位计算机

# 三、寄存器直接寻址

操作数在寄存器中,指令地址字段直接给出存放操作数的寄存器编号
汇编语言:一个括号包围一个寄存器 (编号)

  • 1. 只需要很短的地址字段
  • 2. 无需访存,指令执行速度快
  • 3. 地址范围有限,可以编程使用的通用寄存器不多
  • 4. 使用最多,是提高性能的常用手段

# 四、存储器间接寻址

操作数和操作数地址都在存储器中指令地址字段直接给出操作数地址在存储器中的地址
汇编语言:双重括号包围一个主存地址

  • 1. 寻址空间大,灵活,便于编程
  • 2. 至少需要两次访存才能取到操作数
  • 3. 执行速度慢
  • 4. 用的非常少

# 五、寄存器间接寻址

汇编语言:双重括号包围一个寄存器 (编号)

  • 操作数在存储器中
  • 操作数地址在寄存器中
  • 指令地址字段给出的寄存器的内容是操作数在存储器中的地址
  • 1. 比存储器间接寻址少访问存储器一次
  • 2. 寻址空间大,使用比较普遍

# 六、偏移寻址

EA = (R) + A
A 由立即数的形式在指令中给出
EA (Effective Address):操作数实际地址

  • 相对寻址:EA = (PC) + A
    相对于当前指令处位移量为 A 的单元

  • 基址寻址:EA = (B) + A
    相对于基址 (B) 处位移量为 A 的单元

    • 对于一道程序,基址是不变的,程序中的所有地址都是相对于基址变化的
    • 在基址寻址中,偏移量位数较短
    • 基址寻址立足于面向系统,主要是解决程序逻辑空间与存储器物理空间的无关性
    • 例如:实现程序重定位
  • 变址寻址:EA = A + (I)
    相对于形式地址 A 处位移量为 (I) 的单元

    • 对于变址寻址,形式地址给出的是一个存储器地址基准,变址寄存器存放的是相对于该基准地址的偏移量
    • 而在变址寻址中,偏移量位数足以表示整个存储空间
    • 而变址寻址立足于用户,主要是为编写高效访问一片存储空间的程序
    • 例如:实现线性表元素 (数组) 的存取

# 七、堆栈寻址

EA = 栈顶

  • 堆栈的结构:

    • 一段连续的内存区域
    • 栈底
    • 栈顶
  • 堆栈指针 (SP):一个特殊寄存器,指向栈顶

  • 堆栈操作

    • PUSH (从寄存器到堆栈)
    • POP (从堆栈到寄存器)

# 混合寻址方式

也会出现多个括号包围

\ No newline at end of file +指令系统 - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 思维导图

指令系统

# 两大类型

# CISC

  • (1) 指令系统复杂
  • (2) 指令周期长
  • (3) 各种指令都能访问存储器
  • (4) 有专用寄存器(寻址快)
  • (5) 采用微程序控制
  • (6) 难以进行编译优化生成高效目标代码
  • (7) 指令长度不等长,
    变长指令字 (Expanding Opcodes)

# RISC

  • (1) 简化的指令系统
  • (2) 指令周期短
  • (3) 有专门的访存指令如 load、store,
    以寄存器 - 寄存器方式工作 (三地址指令是 RISC 风格)
  • (4) 采用大量通用寄存器,以减少访存次数
  • (5) 采用组合逻辑电路控制,不用或少用微程序控制
  • (6) 采用优化的编译系统,力求有效地支持高级语言程序
  • (7) 指令长度几乎全部相等,
    定长指令字 (Fixed Length Opcodes)

# 设计原则

# 完备性

# 有效性

  • 每条指令的操作码只能是一个

# 规整性

# 兼容性

  • 向上兼容
  • 向下兼容

# 指令系统的结构

# 堆栈结构:零地址指令

# 累加器结构:一地址指令

# 通用寄存器结构:二、三地址指令

# 指令 Command

指令是指挥计算机实现某个基本操作的命令

# MIPS 三种指令类型

  • R-Type (用于寄存器 Register)
    两个操作数都是寄存器的运算指令。如:sub rd, rs, rt

  • I-Type

    • 运算指令:一个寄存器、一个立即数。如:
      ori rt, rs, imm16
    • Load 和 Store 指令。如:
      lw rt, rs, imm16
    • 条件分支指令。如:
      beq rs, rt, imm16
  • J-Type
    无条件跳转指令。如:j target

注意:J 指令是绝对寻址 (伪直接寻址),不是相对寻址!

# 一条指令

  • 操作码

  • 地址码

    • 寻址方式码
    • 操作数

# 地址码结构

  • 零地址指令

    • (1) 无需操作数。如:空操作/停机等
    • (2) 所需操作数为默认的。如:堆栈等
  • 一地址指令
    其地址既是源操作数地址,也是存放结果地址

    • (1) 单目运算:如:取反/取负等
    • (2) 双目运算:另一操作数为默认的 如:累加器等
  • 二地址指令 (最常用)
    分别存放双目运算中两个源操作数地址,并将其中一个地址作为存放结果地址

  • 三地址指令 (RISC 风格)
    三个地址分别为双目运算中两个源操作数地址和一个结果地址

  • 多地址指令
    用于成批数据处理的指令,如:向量指令 等

# 一个较完善的指令系统应该包括

# 数据传送指令

# 输入输出指令

# 算术运算指令

  • 单目运算
  • 双面运算

# 逻辑运算指令

  • 单目运算
  • 双面运算

# 系统控制指令

# 程序控制指令

# 寻址

# 寻址方式出现的目的

  • 扩大访存范围

  • 提高访问数据的灵活性和有效性

  • 支持软件技术的发展:多道程序设计

# 指令系统中的两类寻址

  • 寻找操作数
    较复杂

    • 操作数的来源:

      • 寄存器
      • 外设端口
      • 主 (虚) 存
      • 堆栈
    • 操作数的数据结构:

      • 字节
      • 半字
      • 双字
      • 一维表
  • 寻找 (下一条) 指令
    较简单

    • 顺序寻址
      PC 增值

    • 跳跃寻址
      跳转 :操作数就是目标语句块第一条指令的地址
      相对寻址

      • jump
      • branch
      • call
      • return

# 寻址方式的确定

  • 在操作码中隐含寻址方式
  • 专门的寻址方式位显式给出

# 基本寻址方式

# 一、立即数寻址

“不寻址”,源操作数直接在指令中

  • 1. 指令执行时间很短,无需访存
  • 2. 操作数的大小受地址字段长度的限制
  • 3. 广泛使用

# 二、存储器直接寻址

操作数在存储器中,指令地址字段直接给出操作数在存储器中的地址
无括号包围

  • 1. 处理简单、直接
  • 2. 寻址空间受到指令的地址字段长度限制
  • 3. 较少使用,8 位计算机和一些 16 位计算机

# 三、寄存器直接寻址

操作数在寄存器中,指令地址字段直接给出存放操作数的寄存器编号
汇编语言:一个括号包围一个寄存器 (编号)

  • 1. 只需要很短的地址字段
  • 2. 无需访存,指令执行速度快
  • 3. 地址范围有限,可以编程使用的通用寄存器不多
  • 4. 使用最多,是提高性能的常用手段

# 四、存储器间接寻址

操作数和操作数地址都在存储器中指令地址字段直接给出操作数地址在存储器中的地址
汇编语言:双重括号包围一个主存地址

  • 1. 寻址空间大,灵活,便于编程
  • 2. 至少需要两次访存才能取到操作数
  • 3. 执行速度慢
  • 4. 用的非常少

# 五、寄存器间接寻址

汇编语言:双重括号包围一个寄存器 (编号)

  • 操作数在存储器中
  • 操作数地址在寄存器中
  • 指令地址字段给出的寄存器的内容是操作数在存储器中的地址
  • 1. 比存储器间接寻址少访问存储器一次
  • 2. 寻址空间大,使用比较普遍

# 六、偏移寻址

EA = (R) + A
A 由立即数的形式在指令中给出
EA (Effective Address):操作数实际地址

  • 相对寻址:EA = (PC) + A
    相对于当前指令处位移量为 A 的单元

  • 基址寻址:EA = (B) + A
    相对于基址 (B) 处位移量为 A 的单元

    • 对于一道程序,基址是不变的,程序中的所有地址都是相对于基址变化的
    • 在基址寻址中,偏移量位数较短
    • 基址寻址立足于面向系统,主要是解决程序逻辑空间与存储器物理空间的无关性
    • 例如:实现程序重定位
  • 变址寻址:EA = A + (I)
    相对于形式地址 A 处位移量为 (I) 的单元

    • 对于变址寻址,形式地址给出的是一个存储器地址基准,变址寄存器存放的是相对于该基准地址的偏移量
    • 而在变址寻址中,偏移量位数足以表示整个存储空间
    • 而变址寻址立足于用户,主要是为编写高效访问一片存储空间的程序
    • 例如:实现线性表元素 (数组) 的存取

# 七、堆栈寻址

EA = 栈顶

  • 堆栈的结构:

    • 一段连续的内存区域
    • 栈底
    • 栈顶
  • 堆栈指针 (SP):一个特殊寄存器,指向栈顶

  • 堆栈操作

    • PUSH (从寄存器到堆栈)
    • POP (从堆栈到寄存器)

# 混合寻址方式

也会出现多个括号包围

\ No newline at end of file diff --git a/cs/principles-of-computer-composition/memory/index.html b/cs/principles-of-computer-composition/memory/index.html index 507508b8..ec1db6ac 100644 --- a/cs/principles-of-computer-composition/memory/index.html +++ b/cs/principles-of-computer-composition/memory/index.html @@ -1 +1 @@ -存储器 - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 思维导图

存储器

# 基本术语

# 记忆单元 / 存储位元 / 位元 (Cell)

具有两种稳态的能够表示二进制数 0 和 1 的物理器件

# 存储单元 / 编址单位 / 寻址单位 (Addressing Unit)

存储器中具有相同地址的那些位构成一个存储单元,又称为一个编址单位

# 存储体 / 存储矩阵 / 存储阵列 (Bank)

所有存储单元构成一个存储阵列

# 存储器地址寄存器 (Memory Address Register – MAR)

用于存放主存单元地址的寄存器

# 存储器数据寄存器 (Memory Data Register – MDR)

用于存放主存单元中数据的寄存器

# 机器字长

运算器中参加运算的寄存器的位数,即:数据通路的宽度

# 存储字

存储芯片中一个读写单位,一般等于存储器的数据线宽度
32bit 系统是 32 位,64 位系统是 64 位……

# 编址方式 (Addressing Mode):对存储体中各存储单元进行编号的方法

  • 按字节编址 (现代计算机基本上都按字节编址)

  • 按字编址 (早期有机器按字编址)

# 传输单位:一次读写存储器的数据单位

  • 对主存而言,指一次从主存读出或写入的数据位数

  • 对辅存而言,数据通常按块传输,传输单位为块

# 计算机存储层次结构

#

# 从上到下一级一级查找,找到后再从下往上一级一级存

  • CPU 运行时,需要的操作数大部分来自寄存器

  • 需从 (向) 存储器中取 (存) 数时,先访问 cache;若在,取自 cache

  • 若不在 cache,则访问 RAM;若在,则取自 RAM (还会保存到 cache 上)

  • 若不在 RAM,则访问磁盘,操作数从磁盘中读出→RAM →cache

# 按存储器中信息的可保存性分类

# 断电后是否丢失数据

  • 挥发性存储器 (易失性存储器)
    特点:断电后,信息即丢失
    SRAM、DRAM

  • 非挥发性存储器 (非易失性 / 永久性存储器)
    特点:断电后,信息不丢失
    ROM、磁盘、闪存

# 读出后是否保持数据

  • 破坏性存储器
    特点:读出时原存信息被破坏,需重写
    DRAM

  • 非破坏性存储器
    特点:读出时,原存信息不被破坏
    SRAM

# 存储器技术指标

# 存取时间 TA 与 存储周期 TS

  • 存取时间 TA:启动一次存储器操作到完成该操作所用时间

    • 读:从启动读命令到读出的数据送 MDR 所需的时间

    • 写:从启动到将 MDR 内容写入指定存储单元的时间
      亦称访问时间,是反映存储器速度的指标,决定了 CPU 发出读 / 写命令后必须等待的时间

  • 存储周期 TS:亦称存取周期或访问周期
    两连续两次启动同一存储器进行存取操作所需的最小时间间隔次启动包括:两次读,两次写,一次读或一次写

  • TA<TS :
    TA、TS 的差别依赖于存储信息的器件和电路,存储介质和控制线路需要恢复时间
    破坏性读出须重写;非破坏性读出不须重写

# 存取宽度 与 存储带宽

  • 存取宽度:一次访存操作可存取的数据位数或字节数 (银河 - I 的存取宽度是 64 位)

  • 存储带宽:每秒传输的最大数据量 (位 / 秒)

# MTBF(Mean Time Between Failure)

  • MTBF 表示两次故障之间的平均时间间隔

  • 采用纠错编码技术进行容错处理

# 主存和 CPU 之间的两种通信方式

# 异步方式过程 (需握手信号)

  • 读操作

  • CPU 送地址到地址线,主存进行地址译码

  • CPU 发读命令,然后等待存储器发回 “完成” 信号

  • 主存收到读命令后开始读数,完成后发 “完成” 信号给 CPU

  • CPU 接收到 “完成” 信号,从数据线取数

# 同步方式的特点

  • CPU 和主存由统一时钟信号控制,无需应答信号

  • 主存总是在确定的时间内准备好数据

  • CPU 送出地址和读命令后,总是在确定的时间取数据

  • 存储器芯片必须支持同步方式

# 主存和 CPU 的连接

#

# 地址线的连接

  • CPU 地址线数决定了整个主存空间的寻址范围

  • CPU 地址线数 > 存储芯片地址引脚线

  • 通常将 CPU 地址线的低位和存储芯片地址线相连,高位用作字扩展时的片选信号的译码

# 数据线的连接

  • CPU 数据线数决定了一次可读写的最大数据宽度

  • CPU 数据线数 > 存储芯片数据引脚线

  • 通常将 CPU 数据线连到多个位扩展的芯片中,使扩展后的位数与 CPU 数据线数相等

# 控制线的连接

  • 若 CPU 读 / 写命令线和存储芯片的读 / 写控制线是一根,且电平信号一致,则可直接相连

  • 若 CPU 读 / 写命令线分开,则需分别进行连接

  • ROM read only 不需要连接写使能 WR

# 按在计算机中的作用分类

# 寄存器型存储器

  • 亦称便笺式存储器,由寄存器构成,封装在 CPU 内

  • 用于存放当前正在执行的指令和使用的数据

  • 用触发器实现,速度快,容量小 O (KB)

# 高速缓冲存储器 (Cache)

  • 位于 CPU 内部或位于主存和 CPU 之间

  • 用来存放当前正在执行的局部程序段和数据

  • 用 SRAM 实现,速度 O (ns)、容量 O (MB)

# 主存储器

  • 位于 CPU 之外

  • 用来存放已被启动的程序及所用数据

  • 用 DRAM 实现,速度 O (ns)、容量 O (GB)

# 辅助存储器

  • 不能由 CPU 的指令直接访问

  • 用来存放暂不运行的程序、数据或存档文件

  • 用磁、光等存储器件实现,容量大,但速度慢 O (ms)

# 其它功能的存储器

  • 控存 CM:存储微程序代码

  • 表格存储器:为加快 CPU 处理而设置 (倒数表、函数表)

  • 字库和数据缓冲存储器:显示和印刷输出设备中

# 按存储介质分类

# 半导体存储器 (SCM)

  • 速度快,用作内存

  • 记忆原理:双稳态触发器、电容 (静态、动态)

# 磁表面存储器 MSM

  • 用陶瓷、非磁性金属或塑料作载磁体,磁化后具有两种不同的剩磁状态记录信息 “1” 和 “0”

  • 非易失,容量大并且每位价格低 。用作外存

# 光盘存储器 ODM

  • 有机玻璃作载磁体,利用磁化、晶态 / 非晶态表示信息

  • 非易失,可靠性高,保存时间长,容量大且易于更换

  • 存储速度比硬盘低一个数量级

# 铁电存储器 FeM (FRAM)、相变存储器 PCM、阻变存储器 ReRAM、……

  • 掉电数据不丢失 (non-volatile),速度快

# 按存储方式分类

# 随机访问存储器 (RAM)

  • 存储器任意单元可随时访问且访问所需时间基本相同

  • 访问时间与存储单元所处的物理位置无关

  • 速度快 (ns)

  • 主存和 Cache

# 只读存储器 (ROM)(Read Only Memory)

  • 只读是指正常工作时只读,能随机读出,不能随机写入

  • MROM:只能读,不能修改

  • PROM:只能修改一次,修改后只读

  • 可多次改写 ROM:

    • 光擦除电可编程只读存储器,亦称 UV EPROM
      ——s 级别

    • 电擦除电可编程只读存储器 E2PROM
      ——s 级别

    • 块擦除电可编程的快擦写存储器 Flash Memory
      ——ms 级别(闪存)

# 顺序存储器 (SAS)(Sequential Access Memory)

  • 存储时以数据块为单位存储,顺序地记录在存储介质上

  • 数据按顺序从存储载体的始端读出或写入,存取时间的长短与数据所在位置有关

  • 速度慢、容量大、成本低,用作后援外存

# 磁带、电荷耦合器件 CCD、VCD

# 常用半导体存储器(常考)

# 随机存取存储器 (RAM)

  • SRAM 静态随机存取存储器 (—— 用作 Cache)

    • 特点

      • 只要加上电源,信息就能一直保持

      • 对电气干扰相对不很敏感

      • 比 DRAM 更快,也更贵

    • 六管静态 MOS 管电路

      • SRAM 数据保存在一对正负反馈门电路中,只要供电,数据就一直保持,不是破环性读出,也不需要重写数据来保持数据不变。即:无需刷新!
  • DRAM 动态随机存取存储器 (—— 用作主存储器)

    • 特点

      • 每隔一段时间必须刷新一次

      • 对电气干扰比较敏感

      • 比 SRAM 慢,但便宜

      • DRAM 读比写稍微快一点,因为读需要等行列地址就绪?

    • 动态单管 MOS 电路

      • 优点

        • 电路元件少

        • 工作功耗小

        • 集成度高,广泛用于大容量主存储器中

      • 缺点

        • 速度慢

        • 破坏性读出 (读后状态改变,需重写)

        • 需要定时刷新

  • 随机存储器的地址译码

    • 线选法 (一维地址译码) 存储矩阵

    • 位片式 (二维双译码) 存储矩阵

    • 地址引脚复用

      • RAS 有效时送行地址

      • CAS 有效时送列地址

# 只读存储器 (ROM)

  • 不可在线改写内容的 ROM (—— 用作 BIOS)

  • 闪存 (Flash Memory)(——U 盘、SSD 等)

# 划分为主存空间包 ROM 和 RAM 区

# ROM 区用来存放系统程序、标准子程序等,选 ROM 芯片构造

# RAM 区用来存放用户程序,选 RAM 芯片构造

# 存储容量的扩展

默认使用同一种芯片扩展

# 位扩展

存储芯片 (mk×n 位 / 片) 构成存储器 (mk×N 位)

  • 特点:

    • 字数不变 (存储单元个数不变),位数扩展 (字长加长)
      芯片地址码位数 = 存储器的地址码位数
      芯片存储单元中所含位元数 < 存储器存储单元中所含位元数

    • 给出地址后,该存储单元中所有芯片同时工作

    • 所有芯片地址范围相同

  • 需存储芯片数:ceil (N /n) 片

# 字扩展

存储芯片 (mk×n 位 / 片) 构成存储器 (Mk×n 位)

  • 特点:

    • 位数不变 (字长不变)、扩充容量 (存储单元个数增加)
      芯片地址码位数 < 存储器的地址码位数
      芯片存储单元中所含位元数 = 存储器存储单元中所含位元数

    • 给出地址后,选中芯片工作

    • 每个芯片地址范围不同

  • 需存储芯片数:ceil (M /m) 片

  • 片选 依据 增加的高位地址码
    增加的高位地址码 = 存储器地址码位数 - 每片芯片的地址码位数

# 字位同时扩展

存储芯片 (mk×n 位) 构成存储器 (Mk×N 位)

  • 特点:

    • 存储单元个数,字长同时增加
      芯片地址码位数 < 存储器的地址码位数
      芯片存储单元中所含位元数 < 存储器存储单元中所含位元数

    • 给出地址后,同行芯片均工作

  • 需存储芯片数: ceil (M /m) * ceil ( N /n ) 片

\ No newline at end of file +存储器 - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 思维导图

存储器

# 基本术语

# 记忆单元 / 存储位元 / 位元 (Cell)

具有两种稳态的能够表示二进制数 0 和 1 的物理器件

# 存储单元 / 编址单位 / 寻址单位 (Addressing Unit)

存储器中具有相同地址的那些位构成一个存储单元,又称为一个编址单位

# 存储体 / 存储矩阵 / 存储阵列 (Bank)

所有存储单元构成一个存储阵列

# 存储器地址寄存器 (Memory Address Register – MAR)

用于存放主存单元地址的寄存器

# 存储器数据寄存器 (Memory Data Register – MDR)

用于存放主存单元中数据的寄存器

# 机器字长

运算器中参加运算的寄存器的位数,即:数据通路的宽度

# 存储字

存储芯片中一个读写单位,一般等于存储器的数据线宽度
32bit 系统是 32 位,64 位系统是 64 位……

# 编址方式 (Addressing Mode):对存储体中各存储单元进行编号的方法

  • 按字节编址 (现代计算机基本上都按字节编址)

  • 按字编址 (早期有机器按字编址)

# 传输单位:一次读写存储器的数据单位

  • 对主存而言,指一次从主存读出或写入的数据位数

  • 对辅存而言,数据通常按块传输,传输单位为块

# 计算机存储层次结构

#

# 从上到下一级一级查找,找到后再从下往上一级一级存

  • CPU 运行时,需要的操作数大部分来自寄存器

  • 需从 (向) 存储器中取 (存) 数时,先访问 cache;若在,取自 cache

  • 若不在 cache,则访问 RAM;若在,则取自 RAM (还会保存到 cache 上)

  • 若不在 RAM,则访问磁盘,操作数从磁盘中读出→RAM →cache

# 按存储器中信息的可保存性分类

# 断电后是否丢失数据

  • 挥发性存储器 (易失性存储器)
    特点:断电后,信息即丢失
    SRAM、DRAM

  • 非挥发性存储器 (非易失性 / 永久性存储器)
    特点:断电后,信息不丢失
    ROM、磁盘、闪存

# 读出后是否保持数据

  • 破坏性存储器
    特点:读出时原存信息被破坏,需重写
    DRAM

  • 非破坏性存储器
    特点:读出时,原存信息不被破坏
    SRAM

# 存储器技术指标

# 存取时间 TA 与 存储周期 TS

  • 存取时间 TA:启动一次存储器操作到完成该操作所用时间

    • 读:从启动读命令到读出的数据送 MDR 所需的时间

    • 写:从启动到将 MDR 内容写入指定存储单元的时间
      亦称访问时间,是反映存储器速度的指标,决定了 CPU 发出读 / 写命令后必须等待的时间

  • 存储周期 TS:亦称存取周期或访问周期
    两连续两次启动同一存储器进行存取操作所需的最小时间间隔次启动包括:两次读,两次写,一次读或一次写

  • TA<TS :
    TA、TS 的差别依赖于存储信息的器件和电路,存储介质和控制线路需要恢复时间
    破坏性读出须重写;非破坏性读出不须重写

# 存取宽度 与 存储带宽

  • 存取宽度:一次访存操作可存取的数据位数或字节数 (银河 - I 的存取宽度是 64 位)

  • 存储带宽:每秒传输的最大数据量 (位 / 秒)

# MTBF(Mean Time Between Failure)

  • MTBF 表示两次故障之间的平均时间间隔

  • 采用纠错编码技术进行容错处理

# 主存和 CPU 之间的两种通信方式

# 异步方式过程 (需握手信号)

  • 读操作

  • CPU 送地址到地址线,主存进行地址译码

  • CPU 发读命令,然后等待存储器发回 “完成” 信号

  • 主存收到读命令后开始读数,完成后发 “完成” 信号给 CPU

  • CPU 接收到 “完成” 信号,从数据线取数

# 同步方式的特点

  • CPU 和主存由统一时钟信号控制,无需应答信号

  • 主存总是在确定的时间内准备好数据

  • CPU 送出地址和读命令后,总是在确定的时间取数据

  • 存储器芯片必须支持同步方式

# 主存和 CPU 的连接

#

# 地址线的连接

  • CPU 地址线数决定了整个主存空间的寻址范围

  • CPU 地址线数 > 存储芯片地址引脚线

  • 通常将 CPU 地址线的低位和存储芯片地址线相连,高位用作字扩展时的片选信号的译码

# 数据线的连接

  • CPU 数据线数决定了一次可读写的最大数据宽度

  • CPU 数据线数 > 存储芯片数据引脚线

  • 通常将 CPU 数据线连到多个位扩展的芯片中,使扩展后的位数与 CPU 数据线数相等

# 控制线的连接

  • 若 CPU 读 / 写命令线和存储芯片的读 / 写控制线是一根,且电平信号一致,则可直接相连

  • 若 CPU 读 / 写命令线分开,则需分别进行连接

  • ROM read only 不需要连接写使能 WR

# 按在计算机中的作用分类

# 寄存器型存储器

  • 亦称便笺式存储器,由寄存器构成,封装在 CPU 内

  • 用于存放当前正在执行的指令和使用的数据

  • 用触发器实现,速度快,容量小 O (KB)

# 高速缓冲存储器 (Cache)

  • 位于 CPU 内部或位于主存和 CPU 之间

  • 用来存放当前正在执行的局部程序段和数据

  • 用 SRAM 实现,速度 O (ns)、容量 O (MB)

# 主存储器

  • 位于 CPU 之外

  • 用来存放已被启动的程序及所用数据

  • 用 DRAM 实现,速度 O (ns)、容量 O (GB)

# 辅助存储器

  • 不能由 CPU 的指令直接访问

  • 用来存放暂不运行的程序、数据或存档文件

  • 用磁、光等存储器件实现,容量大,但速度慢 O (ms)

# 其它功能的存储器

  • 控存 CM:存储微程序代码

  • 表格存储器:为加快 CPU 处理而设置 (倒数表、函数表)

  • 字库和数据缓冲存储器:显示和印刷输出设备中

# 按存储介质分类

# 半导体存储器 (SCM)

  • 速度快,用作内存

  • 记忆原理:双稳态触发器、电容 (静态、动态)

# 磁表面存储器 MSM

  • 用陶瓷、非磁性金属或塑料作载磁体,磁化后具有两种不同的剩磁状态记录信息 “1” 和 “0”

  • 非易失,容量大并且每位价格低 。用作外存

# 光盘存储器 ODM

  • 有机玻璃作载磁体,利用磁化、晶态 / 非晶态表示信息

  • 非易失,可靠性高,保存时间长,容量大且易于更换

  • 存储速度比硬盘低一个数量级

# 铁电存储器 FeM (FRAM)、相变存储器 PCM、阻变存储器 ReRAM、……

  • 掉电数据不丢失 (non-volatile),速度快

# 按存储方式分类

# 随机访问存储器 (RAM)

  • 存储器任意单元可随时访问且访问所需时间基本相同

  • 访问时间与存储单元所处的物理位置无关

  • 速度快 (ns)

  • 主存和 Cache

# 只读存储器 (ROM)(Read Only Memory)

  • 只读是指正常工作时只读,能随机读出,不能随机写入

  • MROM:只能读,不能修改

  • PROM:只能修改一次,修改后只读

  • 可多次改写 ROM:

    • 光擦除电可编程只读存储器,亦称 UV EPROM
      ——s 级别

    • 电擦除电可编程只读存储器 E2PROM
      ——s 级别

    • 块擦除电可编程的快擦写存储器 Flash Memory
      ——ms 级别(闪存)

# 顺序存储器 (SAS)(Sequential Access Memory)

  • 存储时以数据块为单位存储,顺序地记录在存储介质上

  • 数据按顺序从存储载体的始端读出或写入,存取时间的长短与数据所在位置有关

  • 速度慢、容量大、成本低,用作后援外存

# 磁带、电荷耦合器件 CCD、VCD

# 常用半导体存储器(常考)

# 随机存取存储器 (RAM)

  • SRAM 静态随机存取存储器 (—— 用作 Cache)

    • 特点

      • 只要加上电源,信息就能一直保持

      • 对电气干扰相对不很敏感

      • 比 DRAM 更快,也更贵

    • 六管静态 MOS 管电路

      • SRAM 数据保存在一对正负反馈门电路中,只要供电,数据就一直保持,不是破环性读出,也不需要重写数据来保持数据不变。即:无需刷新!
  • DRAM 动态随机存取存储器 (—— 用作主存储器)

    • 特点

      • 每隔一段时间必须刷新一次

      • 对电气干扰比较敏感

      • 比 SRAM 慢,但便宜

      • DRAM 读比写稍微快一点,因为读需要等行列地址就绪?

    • 动态单管 MOS 电路

      • 优点

        • 电路元件少

        • 工作功耗小

        • 集成度高,广泛用于大容量主存储器中

      • 缺点

        • 速度慢

        • 破坏性读出 (读后状态改变,需重写)

        • 需要定时刷新

  • 随机存储器的地址译码

    • 线选法 (一维地址译码) 存储矩阵

    • 位片式 (二维双译码) 存储矩阵

    • 地址引脚复用

      • RAS 有效时送行地址

      • CAS 有效时送列地址

# 只读存储器 (ROM)

  • 不可在线改写内容的 ROM (—— 用作 BIOS)

  • 闪存 (Flash Memory)(——U 盘、SSD 等)

# 划分为主存空间包 ROM 和 RAM 区

# ROM 区用来存放系统程序、标准子程序等,选 ROM 芯片构造

# RAM 区用来存放用户程序,选 RAM 芯片构造

# 存储容量的扩展

默认使用同一种芯片扩展

# 位扩展

存储芯片 (mk×n 位 / 片) 构成存储器 (mk×N 位)

  • 特点:

    • 字数不变 (存储单元个数不变),位数扩展 (字长加长)
      芯片地址码位数 = 存储器的地址码位数
      芯片存储单元中所含位元数 < 存储器存储单元中所含位元数

    • 给出地址后,该存储单元中所有芯片同时工作

    • 所有芯片地址范围相同

  • 需存储芯片数:ceil (N /n) 片

# 字扩展

存储芯片 (mk×n 位 / 片) 构成存储器 (Mk×n 位)

  • 特点:

    • 位数不变 (字长不变)、扩充容量 (存储单元个数增加)
      芯片地址码位数 < 存储器的地址码位数
      芯片存储单元中所含位元数 = 存储器存储单元中所含位元数

    • 给出地址后,选中芯片工作

    • 每个芯片地址范围不同

  • 需存储芯片数:ceil (M /m) 片

  • 片选 依据 增加的高位地址码
    增加的高位地址码 = 存储器地址码位数 - 每片芯片的地址码位数

# 字位同时扩展

存储芯片 (mk×n 位) 构成存储器 (Mk×N 位)

  • 特点:

    • 存储单元个数,字长同时增加
      芯片地址码位数 < 存储器的地址码位数
      芯片存储单元中所含位元数 < 存储器存储单元中所含位元数

    • 给出地址后,同行芯片均工作

  • 需存储芯片数: ceil (M /m) * ceil ( N /n ) 片

\ No newline at end of file diff --git a/cs/principles-of-computer-composition/operation/index.html b/cs/principles-of-computer-composition/operation/index.html index 3040828a..688bc53e 100644 --- a/cs/principles-of-computer-composition/operation/index.html +++ b/cs/principles-of-computer-composition/operation/index.html @@ -1 +1 @@ -运算 - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 思维导图

运算

# 补码

# 符号部分同原码

  • 数的最高位为符号位,0 表示正数,1 表示负数

# 数字部分与它的符号位有关

  • 对于正数,补码数值部分与原码数值部分相同

  • 对于负数,补码数值部分是将原码数值部分按位取反再加 1 ,即在反码数值部分基础上加 1

# 阶码

# 补码和移码的关系:符号位相反、数值位相同

  • 阶码用移码表示,阶码加减运算后得到补码,再将符号位取反即可得到运算后的阶码

  • 移码的和、差 = 真值的和、差的补码

# 补码 E_1 的 (mod 2^n) n 位移码:

[E_1] 移 = 2^(n-1) + E_1

# 补码 E_1 的 (mod 2^n) n 位补码:

[E_1] 补 = 2^n + E_1

# 浮点数(IEEE754 标准)

# 单精度浮点数

  • 31:1 位符号位

  • 30~23:8 位阶码

  • 22~0:23 位尾数

# 双精度浮点数

  • 63:1 位符号位

  • 62~52:11 位阶码

  • 51~0:52 位尾数

# 阶码全部为 0:

  • 尾数不为 0:表示非规格化数

  • 尾数为 0:表示数字 0

# 阶码全部为 1:

  • 尾数不为 0:NaN(非数)

  • 尾数为 0:

    • 符号位为 0:表示正无穷

    • 符号位为 1:表示负无穷

# 状态标志位

# CF—— 进位标志位

  • 加法

  • 减法

# OF—— 溢出标志位

# ZF

# 计算机运算部件 (ALU) 的硬件组织

# 1 位全加器 / 普通进位加法器 CPA

# 存储进位加法器 CSA

  • n 位串行加法器
    分 n 步实现,每步只求一位和

    • 进位按串行方式传递,速度慢

    • 进位延时较长,关键路径延时 O (n)

    • 实现复杂度 O (n)

  • n 位并行加法器

    • 同时产生进位

    • 加法延时缩短,关键路径延时 O (log n)

    • 实现相对复杂,复杂度 O (n2)

    • 完全大规模并行进位实现困难,因为高位的进位形成逻辑涉及输入变量过多,将受到器件扇入系数的限制

  • 分组并行进位加法器

    • 组内并行,组间串行

# 快速乘法器

  • 柱形乘法器

  • 阵列乘法器

# 快速除法器

  • 阵列除法器

# 定点整数阶码运算器和定点小数尾数运算器组成浮点运算器

# 与其他寄存器组构成完整的运算部件 (ALU)

# 移位

# 算术左移

# 逻辑左移

# 算术右移

# 逻辑右移

# 注意易错

  • 对于整数,左移指令相当于将原数与 2 的幂次方相乘;右移指令则相当于将原来的整数除以 2 的幂次方。正数没啥问题,负数不行!

# 位扩展

短数转为长数

# 0 扩展:无符号数,即:前面补 “0”,

# 符号扩展:有符号整数,即:前面补 “数符

# 应用

  • 强制类型转换

  • 无符号数加入寄存器时用这种方式填补寄存器左侧多余位置

# 位截断

长数转为短数

# 强行将一个长数的高位丢弃

# 可能会发生数据 “溢出” 或者数据不正确

# 数据语义上的高位截断,与大小端存储方式无关

# 应用

  • 强制类型转换

  • 有符号数加入寄存器时用这种方式填补寄存器左侧多余位置

# 加减法

# 有符号原码加减法

符号位和数值部分分别处理
减法转化为加法处理

  • 同号:

    • 数值位直接相加

    • 和的符号取被加数的符号

    • 若最高位产生进位,则结果溢出

  • 异号:负数取补码,与正数相加,分二种情况讨论:

    • 最高数值位产生进位,符号位为 0,表明加法结果为正,所得数值位正确。

    • 最高数值位没有产生进位,符号位为 1,表明加法结果为负,得到的是数值位的补码形式,需对结果求补,得到原码结果

# 无符号原码加减法

# 补码加减法

补码可以化简加法运算
还可以将减法运算转化为加法运算

  • 溢出
    同符号数相加或异符号数相减才可能溢出

    • 补码中采用两位符号位 (变形补码),符号位仍然参与运算,结果中的两位符号位标示溢出状态

      • 11、00:正常

      • 01:正溢出

      • 10:负溢出

    • C 语言不考虑溢出的异常处理

      • 对于 unsigned 整型溢出:做模运算

      • 对于 signed 整型的溢出,C 的规范定义是 “undefined behavior”

    • MIPS:

      • MIPS 上的 C 编译器会选用无符号的算术运算指令 (如 addu、addiu、subu)

      • MIPS 上的 Fortran 编译器则会根据操作数的不同类型选用合适的算术运算指令 (如 add、addi、sub)

      • MIPS 检测到有符号数运算溢出时,产生一个异常(exception/interrupt)

      • 造成溢出的那条指令的地址被存放在一个特定寄存器 —— 异常程序计数器 (EPC)

      • mfc0 指令将 EPC 中的地址复制到某个寄存器 (k0/k0/k1),用 jr 指令返回到溢出而中断的代码处

# 移码加减法

  • ① 加法:直接将 [E1] 移 和 [E2] 移进行模 2n 相加,对结果符号取反得到结果的阶码

  • ② 减法:先将减数 [E2] 移 求补 (各位取反,末位加 1),再与被减数 [E1] 移进行模 2n 相加,对结果的符号取反

  • ③ 溢出判断:进行模 2n 相加时,如果两个加数的符号相同,且与和数的符号也相同,则发生溢出

# 乘法

“加” + “右移”

# 原码一位乘法

  • 符号位和数值位分开运算,数值部分用无符号数乘法实现

  • 用于浮点数尾数乘法运算

# 补码乘法

  • 用于定点整数乘法法运算

  • 现在主流乘法器是 3 位乘法,甚至 4 位,都是基于两位判断位

  • Booth 一位乘法

    • 被乘数 A 和部分积 P 均取两位符号位即变形码,乘数取一位符号位,符号位参与运算

    • 乘数末尾增设附加位 Bn+1 ,其初始值为 0

    • Bn 和 Bn+1 构成各步运算的乘数判断位

    • 按补码移位规则:部分积为正 (第 1 符号位为 0),右移时有效位最高位补 0;部分积为负,右移时有效位最高位补 1

    • 按 Booth 乘法表算法进行到第 n+1 步,但第 n+1 步的部分积不再移位

  • Booth 二位乘法

    • 两位两位看,从右往左看,但每次 [A] 补的 “数量级” 不一样
  • (-1) X (-1) 是定点小数补码乘法唯一溢出情况

# 使用伪加器构成柱形乘法器

  • 三个数的求和由两次普通加法变成了:一次伪加,一次普通加

  • 四个数的求和,通过两次伪加,一次普通加

  • 求和加的数越多,普通加仍是一次,伪加增多,伪加器相比全加器效率更高

# 利用实现多位乘的专用芯片构成阵列乘法器

# 除法

“加 / 减”+“左移”

# 原码除法

  • 符号位和数值位分开,数值部分用无符号数除法实现

  • 用于浮点数尾数除法运算

  • 有恢复余数和加减交替法两种

# 补码除法

  • 符号位和数值位一起运算

  • 用于定点整数除法运算

# 快速除法器:阵列除法器

# 浮点数加减法

# 求阶差

# 对阶

# 尾数相加减

# 规格化并判断溢出

  • 尾数规格化范围:1 ≤ 尾数真值 < 2

  • 阶码不溢出的范围:127 ≥ 阶码真值 ≥ -126

  • 阶码上溢:结果发生溢出,一般将其认为是+∞和-∞

  • 阶码下溢:结果为 0

  • 尾数上溢:

    • 不一定浮点数溢出,即不一定会发生 “异常”

    • 右归:将尾数右移,阶码增 1 来重新对齐

  • 尾数下溢:

    • 进行舍入处理

    • 在运算过程中,添加保护位

# 舍入

  • 就近舍入,舍入为最近可表示的数

  • 附加位为:

    • 11:入

    • 01:舍

    • 10(强制结果为偶数)

    • 00:保持结果不变

# 置 0

  • 尾数为 0 说明结果也为 0,根据 IEEE754,阶码和尾数全为 0,需要将阶码置零

# 注意易错

  • 浮点数加减法不满足结合律

# 浮点数乘除法

# 尾数用定点原码乘 / 除运算实现

# 阶码用定点数加 / 减运算实现

# 规格化

  • 乘法

    • 1≤尾数 1 × 尾数 2<4

    • 不需左规、最多右规 (➗2) 一次

  • 除法

    • 0.5 < 尾数 1 ÷ 尾数 2<2

    • 不需右规、最多左规 (✖️2) 一次

# 符号确定

  • 同号:结果为正

  • 异号:结果为负

\ No newline at end of file +运算 - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 思维导图

运算

# 补码

# 符号部分同原码

  • 数的最高位为符号位,0 表示正数,1 表示负数

# 数字部分与它的符号位有关

  • 对于正数,补码数值部分与原码数值部分相同

  • 对于负数,补码数值部分是将原码数值部分按位取反再加 1 ,即在反码数值部分基础上加 1

# 阶码

# 补码和移码的关系:符号位相反、数值位相同

  • 阶码用移码表示,阶码加减运算后得到补码,再将符号位取反即可得到运算后的阶码

  • 移码的和、差 = 真值的和、差的补码

# 补码 E_1 的 (mod 2^n) n 位移码:

[E_1] 移 = 2^(n-1) + E_1

# 补码 E_1 的 (mod 2^n) n 位补码:

[E_1] 补 = 2^n + E_1

# 浮点数(IEEE754 标准)

# 单精度浮点数

  • 31:1 位符号位

  • 30~23:8 位阶码

  • 22~0:23 位尾数

# 双精度浮点数

  • 63:1 位符号位

  • 62~52:11 位阶码

  • 51~0:52 位尾数

# 阶码全部为 0:

  • 尾数不为 0:表示非规格化数

  • 尾数为 0:表示数字 0

# 阶码全部为 1:

  • 尾数不为 0:NaN(非数)

  • 尾数为 0:

    • 符号位为 0:表示正无穷

    • 符号位为 1:表示负无穷

# 状态标志位

# CF—— 进位标志位

  • 加法

  • 减法

# OF—— 溢出标志位

# ZF

# 计算机运算部件 (ALU) 的硬件组织

# 1 位全加器 / 普通进位加法器 CPA

# 存储进位加法器 CSA

  • n 位串行加法器
    分 n 步实现,每步只求一位和

    • 进位按串行方式传递,速度慢

    • 进位延时较长,关键路径延时 O (n)

    • 实现复杂度 O (n)

  • n 位并行加法器

    • 同时产生进位

    • 加法延时缩短,关键路径延时 O (log n)

    • 实现相对复杂,复杂度 O (n2)

    • 完全大规模并行进位实现困难,因为高位的进位形成逻辑涉及输入变量过多,将受到器件扇入系数的限制

  • 分组并行进位加法器

    • 组内并行,组间串行

# 快速乘法器

  • 柱形乘法器

  • 阵列乘法器

# 快速除法器

  • 阵列除法器

# 定点整数阶码运算器和定点小数尾数运算器组成浮点运算器

# 与其他寄存器组构成完整的运算部件 (ALU)

# 移位

# 算术左移

# 逻辑左移

# 算术右移

# 逻辑右移

# 注意易错

  • 对于整数,左移指令相当于将原数与 2 的幂次方相乘;右移指令则相当于将原来的整数除以 2 的幂次方。正数没啥问题,负数不行!

# 位扩展

短数转为长数

# 0 扩展:无符号数,即:前面补 “0”,

# 符号扩展:有符号整数,即:前面补 “数符

# 应用

  • 强制类型转换

  • 无符号数加入寄存器时用这种方式填补寄存器左侧多余位置

# 位截断

长数转为短数

# 强行将一个长数的高位丢弃

# 可能会发生数据 “溢出” 或者数据不正确

# 数据语义上的高位截断,与大小端存储方式无关

# 应用

  • 强制类型转换

  • 有符号数加入寄存器时用这种方式填补寄存器左侧多余位置

# 加减法

# 有符号原码加减法

符号位和数值部分分别处理
减法转化为加法处理

  • 同号:

    • 数值位直接相加

    • 和的符号取被加数的符号

    • 若最高位产生进位,则结果溢出

  • 异号:负数取补码,与正数相加,分二种情况讨论:

    • 最高数值位产生进位,符号位为 0,表明加法结果为正,所得数值位正确。

    • 最高数值位没有产生进位,符号位为 1,表明加法结果为负,得到的是数值位的补码形式,需对结果求补,得到原码结果

# 无符号原码加减法

# 补码加减法

补码可以化简加法运算
还可以将减法运算转化为加法运算

  • 溢出
    同符号数相加或异符号数相减才可能溢出

    • 补码中采用两位符号位 (变形补码),符号位仍然参与运算,结果中的两位符号位标示溢出状态

      • 11、00:正常

      • 01:正溢出

      • 10:负溢出

    • C 语言不考虑溢出的异常处理

      • 对于 unsigned 整型溢出:做模运算

      • 对于 signed 整型的溢出,C 的规范定义是 “undefined behavior”

    • MIPS:

      • MIPS 上的 C 编译器会选用无符号的算术运算指令 (如 addu、addiu、subu)

      • MIPS 上的 Fortran 编译器则会根据操作数的不同类型选用合适的算术运算指令 (如 add、addi、sub)

      • MIPS 检测到有符号数运算溢出时,产生一个异常(exception/interrupt)

      • 造成溢出的那条指令的地址被存放在一个特定寄存器 —— 异常程序计数器 (EPC)

      • mfc0 指令将 EPC 中的地址复制到某个寄存器 (k0/k0/k1),用 jr 指令返回到溢出而中断的代码处

# 移码加减法

  • ① 加法:直接将 [E1] 移 和 [E2] 移进行模 2n 相加,对结果符号取反得到结果的阶码

  • ② 减法:先将减数 [E2] 移 求补 (各位取反,末位加 1),再与被减数 [E1] 移进行模 2n 相加,对结果的符号取反

  • ③ 溢出判断:进行模 2n 相加时,如果两个加数的符号相同,且与和数的符号也相同,则发生溢出

# 乘法

“加” + “右移”

# 原码一位乘法

  • 符号位和数值位分开运算,数值部分用无符号数乘法实现

  • 用于浮点数尾数乘法运算

# 补码乘法

  • 用于定点整数乘法法运算

  • 现在主流乘法器是 3 位乘法,甚至 4 位,都是基于两位判断位

  • Booth 一位乘法

    • 被乘数 A 和部分积 P 均取两位符号位即变形码,乘数取一位符号位,符号位参与运算

    • 乘数末尾增设附加位 Bn+1 ,其初始值为 0

    • Bn 和 Bn+1 构成各步运算的乘数判断位

    • 按补码移位规则:部分积为正 (第 1 符号位为 0),右移时有效位最高位补 0;部分积为负,右移时有效位最高位补 1

    • 按 Booth 乘法表算法进行到第 n+1 步,但第 n+1 步的部分积不再移位

  • Booth 二位乘法

    • 两位两位看,从右往左看,但每次 [A] 补的 “数量级” 不一样
  • (-1) X (-1) 是定点小数补码乘法唯一溢出情况

# 使用伪加器构成柱形乘法器

  • 三个数的求和由两次普通加法变成了:一次伪加,一次普通加

  • 四个数的求和,通过两次伪加,一次普通加

  • 求和加的数越多,普通加仍是一次,伪加增多,伪加器相比全加器效率更高

# 利用实现多位乘的专用芯片构成阵列乘法器

# 除法

“加 / 减”+“左移”

# 原码除法

  • 符号位和数值位分开,数值部分用无符号数除法实现

  • 用于浮点数尾数除法运算

  • 有恢复余数和加减交替法两种

# 补码除法

  • 符号位和数值位一起运算

  • 用于定点整数除法运算

# 快速除法器:阵列除法器

# 浮点数加减法

# 求阶差

# 对阶

# 尾数相加减

# 规格化并判断溢出

  • 尾数规格化范围:1 ≤ 尾数真值 < 2

  • 阶码不溢出的范围:127 ≥ 阶码真值 ≥ -126

  • 阶码上溢:结果发生溢出,一般将其认为是+∞和-∞

  • 阶码下溢:结果为 0

  • 尾数上溢:

    • 不一定浮点数溢出,即不一定会发生 “异常”

    • 右归:将尾数右移,阶码增 1 来重新对齐

  • 尾数下溢:

    • 进行舍入处理

    • 在运算过程中,添加保护位

# 舍入

  • 就近舍入,舍入为最近可表示的数

  • 附加位为:

    • 11:入

    • 01:舍

    • 10(强制结果为偶数)

    • 00:保持结果不变

# 置 0

  • 尾数为 0 说明结果也为 0,根据 IEEE754,阶码和尾数全为 0,需要将阶码置零

# 注意易错

  • 浮点数加减法不满足结合律

# 浮点数乘除法

# 尾数用定点原码乘 / 除运算实现

# 阶码用定点数加 / 减运算实现

# 规格化

  • 乘法

    • 1≤尾数 1 × 尾数 2<4

    • 不需左规、最多右规 (➗2) 一次

  • 除法

    • 0.5 < 尾数 1 ÷ 尾数 2<2

    • 不需右规、最多左规 (✖️2) 一次

# 符号确定

  • 同号:结果为正

  • 异号:结果为负

\ No newline at end of file diff --git a/cs/principles-of-computer-composition/virtual-memory/index.html b/cs/principles-of-computer-composition/virtual-memory/index.html index f0f29557..b85a1a5a 100644 --- a/cs/principles-of-computer-composition/virtual-memory/index.html +++ b/cs/principles-of-computer-composition/virtual-memory/index.html @@ -1 +1 @@ -虚拟存储器 - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 思维导图

虚拟存储器

# 分区方案

# 简单分区:

  • 原理:使用长度不等的固定长分区,当一个进程调入主存时,分配给它一个能容纳的最小分区

  • 缺点:固定长度的分区,可能会浪费 主存空间。多数情况下,进程对分区大小的需求不可能和提供的分区大小一样

# 可变长分区(Partitioning)

  • 原理:分配的分区大小与进程所需大小一样

  • 特点:开始较好 ,但到最后存储器中会有许多碎片。时间越长,存储器的碎片会越来越多,存储器的利用率下降

  • 程序员自己手动管理内存,可以改善内存碎片化问题(例如一次性 malloc 或 new、stl 新建容器好几 kb 大小……

# 分页(Paging)

  • 基本思想

    • 内存分成固定长且较小的存储块 (页框 /page frame)

    • 每个进程也划分成固定长的程序块 (页 /page)

    • 程序块 (页 /page) 可装到内存可用的存储块 (页框 /page frame) 中

    • 无需用连续页框来存放一个进程

    • 操作系统为每个进程生成一个页表:页和页框一一对应的关系表

      • 通过页表 (page table) 实现逻辑地址向物理地址转换 (Address Mapping)

# 虚存技术的实质

# 程序员在比实际主存空间大得多的逻辑地址空间编写程序

# 程序执行时,把当前需要的程序段和相应的数据块调入主存,其他暂不用的部分存放在磁盘上

# 指令执行时,通过硬件将逻辑地址 (亦称虚拟地址或虚地址) 转化为物理地址 (亦称主存地址或实地址)// 分页查表

# 在发生指令或数据访问失效时,由操作系统进行主存和磁盘之间的信息交换

# 每个进程都有专属于自己的从 0 到 FFFFFFFFH 的地址空间

# 快表 / 转换后备缓冲器 / TLB (Translation Lookaside Buffer)

# 原理:

  • 使用 Cache 来存储页表项,称为 TLB,它包含最近使用的那些页表项,加速虚实地址转换

  • 多用全相联:命中率高,小、成本不高

  • 采用随机替换策略:降低替换算法开销

  • 采用回写策略:减少访问内存的次数

# TLB 页表项

  • Tag 位

  • Index 位,组相联时才有

  • Physical Adress,对应物理页框号

  • 其他标志位

    • Valid 位,1 位

    • Dirty 位,1 位

    • Ref

    • Access

# TLB 缺失

# 基本概念

# 主存分配

  • 操作系统:固定(ROM)

  • 用户区:分区(RAM)

# 三种地址空间:

  • 虚拟地址空间

  • 主存地址空间

  • 辅存地址空间

# 地址映射:把虚拟地址空间映射到主存地址空间

# 地址变换:程序运行时,把虚拟地址变换成主存物理地址

# 为什么需要虚存

# 同时运行更多进程,内存需求增大

# 允许多个程序有效而安全地共享存储器,消除内存因小而有限的存储器容量给程序设计造成的障碍

  • 可以更有效的共享处理器和主存

  • 虚拟存储器实现程序地址空间到物理空间的转换,加强了各个程序地址空间之间的保护

# 允许单用户程序大小超过主存储器的容量

  • 虚拟存储器自动管理主存和辅存组成的两级层次结构

# 虚存组织方式

# 页式

  • 原理:

    • 虚存地址空间和主存地址空间按统一大小分成若干页,虚存称为虚页,主存称为实页

    • 程序按页从磁盘调入主存 (某一虚页调入某一实页)

    • 指令给出虚拟地址 / 逻辑地址

    • 每个页表项记录对应的虚页情况

    • Valid 为 0 说明 “miss”(称为 page fault / 缺页)

    • CPU 执行指令时,先将逻辑地址转换为物理地址

    • 地址转换由 MMU 实现

    • 页大小比 Cache 中 Block 大得多

    • 采用全相联映射

    • 通过软件来处理 “缺页”

    • 采用 Write Back 写策略

  • 地址格式

    • 虚存的地址格式 (逻辑地址格式):

      • 直接映射虚拟地址

        • 高位,虚拟地址比物理地址长的位数,算在 Tag 位里

        • Tag 位,标记位
          长度 = log _2 (主存中 页 的 数量 / TLB 中 页表项 的 数量)

        • Index 位,Cache 槽号
          长度 = log _2 (TLB 中 页表项 的 数量)

        • Offset 位,页内地址
          长度 = log _2 (页 的 大小) (按编址单位算)

      • 全相联虚拟地址

        • 高位,虚拟地址比物理地址长的位数,算在 Tag 位里

        • Tag 位,标记位
          长度 = log _2 (主存中 页 的 数量)

        • Offset 位,页内地址
          长度 = log _2 (页 的 大小) (按编址单位算)

      • n 路组相联虚拟地址

        • 高位,虚拟地址比物理地址长的位数,算在 Tag 位里

        • Tag 位,标记位
          长度 = log _2 (主存中 页 的 数量 / 组的数量)

        • 组号位
          长度 = log _2 (组 的 数量)

        • Offset 位,页内地址
          长度 = log _2 (页 的 大小) (按编址单位算)

    • 主存的地址格式 (物理地址格式):

      • 实页号 / 物理页号

      • 页内地址

  • 页表 (Page Table)
    建立一个映射关系表来存放虚拟地址与物理地址之间的映射关系,该映射关系表被称为页表,用来实现虚实地址的转换

    • 建立在主存中,操作系统为每道程序建立一个页表

    • 设置页表基址寄存器:保存页表在主存中的起始地址

    • 页表项

      • 装入位

      • 修改 (Dirty) 位

      • 替换控制位

      • 访问权限位

      • 禁止缓存位

      • 实页号

    • 页表的项数 = 页表的容量 = 最大页表项 = 虚存大小 / 页大小

    • 页表大小 = 页表的项数 * 页表项大小

  • 异常情况

    • 缺页 (page fault)

      • 产生条件:当 Valid (有效位 / 装入位) 为 0 时

      • 相应处理:从磁盘中读信息到内存,若内存没有空间,则还要从内存选择一页替换到磁盘上,替换算法类似于 Cache,采用回写法,页面淘汰时,根据 “dirty” 位确定是否要写磁盘

      • 异常处理结束后:缺页发生时,当前指令的执行被阻塞,当前进程挂起;缺页处理结束后,回到原指令继续执行

    • 保护违例 (protection_violation_fault)

      • 产生条件: 当 Access Rights (存取权限) 与所指定的具体操作不相符时

      • 相应处理:在屏幕上显示 “内存保护错” 信息

      • 异常处理结束后:当前指令执行被阻塞,当前进程终止

      • Access Rights (存取权限) 可能的取值有哪些?

        • R = Read-only

        • R/W = read/write

        • X = execute only

  • 特点

    • 优点:实现简单,开销少。因为只有进程的最后一个零头(内部碎片)不能利用,故浪费很小

    • 缺点:由于页不是逻辑上独立的实体,可能会出现如 “一条指令跨页” 等情况(CISC),使处理、管理、保护和共享都不方便

# 段式

# 段页式

\ No newline at end of file +虚拟存储器 - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 思维导图

虚拟存储器

# 分区方案

# 简单分区:

  • 原理:使用长度不等的固定长分区,当一个进程调入主存时,分配给它一个能容纳的最小分区

  • 缺点:固定长度的分区,可能会浪费 主存空间。多数情况下,进程对分区大小的需求不可能和提供的分区大小一样

# 可变长分区(Partitioning)

  • 原理:分配的分区大小与进程所需大小一样

  • 特点:开始较好 ,但到最后存储器中会有许多碎片。时间越长,存储器的碎片会越来越多,存储器的利用率下降

  • 程序员自己手动管理内存,可以改善内存碎片化问题(例如一次性 malloc 或 new、stl 新建容器好几 kb 大小……

# 分页(Paging)

  • 基本思想

    • 内存分成固定长且较小的存储块 (页框 /page frame)

    • 每个进程也划分成固定长的程序块 (页 /page)

    • 程序块 (页 /page) 可装到内存可用的存储块 (页框 /page frame) 中

    • 无需用连续页框来存放一个进程

    • 操作系统为每个进程生成一个页表:页和页框一一对应的关系表

      • 通过页表 (page table) 实现逻辑地址向物理地址转换 (Address Mapping)

# 虚存技术的实质

# 程序员在比实际主存空间大得多的逻辑地址空间编写程序

# 程序执行时,把当前需要的程序段和相应的数据块调入主存,其他暂不用的部分存放在磁盘上

# 指令执行时,通过硬件将逻辑地址 (亦称虚拟地址或虚地址) 转化为物理地址 (亦称主存地址或实地址)// 分页查表

# 在发生指令或数据访问失效时,由操作系统进行主存和磁盘之间的信息交换

# 每个进程都有专属于自己的从 0 到 FFFFFFFFH 的地址空间

# 快表 / 转换后备缓冲器 / TLB (Translation Lookaside Buffer)

# 原理:

  • 使用 Cache 来存储页表项,称为 TLB,它包含最近使用的那些页表项,加速虚实地址转换

  • 多用全相联:命中率高,小、成本不高

  • 采用随机替换策略:降低替换算法开销

  • 采用回写策略:减少访问内存的次数

# TLB 页表项

  • Tag 位

  • Index 位,组相联时才有

  • Physical Adress,对应物理页框号

  • 其他标志位

    • Valid 位,1 位

    • Dirty 位,1 位

    • Ref

    • Access

# TLB 缺失

# 基本概念

# 主存分配

  • 操作系统:固定(ROM)

  • 用户区:分区(RAM)

# 三种地址空间:

  • 虚拟地址空间

  • 主存地址空间

  • 辅存地址空间

# 地址映射:把虚拟地址空间映射到主存地址空间

# 地址变换:程序运行时,把虚拟地址变换成主存物理地址

# 为什么需要虚存

# 同时运行更多进程,内存需求增大

# 允许多个程序有效而安全地共享存储器,消除内存因小而有限的存储器容量给程序设计造成的障碍

  • 可以更有效的共享处理器和主存

  • 虚拟存储器实现程序地址空间到物理空间的转换,加强了各个程序地址空间之间的保护

# 允许单用户程序大小超过主存储器的容量

  • 虚拟存储器自动管理主存和辅存组成的两级层次结构

# 虚存组织方式

# 页式

  • 原理:

    • 虚存地址空间和主存地址空间按统一大小分成若干页,虚存称为虚页,主存称为实页

    • 程序按页从磁盘调入主存 (某一虚页调入某一实页)

    • 指令给出虚拟地址 / 逻辑地址

    • 每个页表项记录对应的虚页情况

    • Valid 为 0 说明 “miss”(称为 page fault / 缺页)

    • CPU 执行指令时,先将逻辑地址转换为物理地址

    • 地址转换由 MMU 实现

    • 页大小比 Cache 中 Block 大得多

    • 采用全相联映射

    • 通过软件来处理 “缺页”

    • 采用 Write Back 写策略

  • 地址格式

    • 虚存的地址格式 (逻辑地址格式):

      • 直接映射虚拟地址

        • 高位,虚拟地址比物理地址长的位数,算在 Tag 位里

        • Tag 位,标记位
          长度 = log _2 (主存中 页 的 数量 / TLB 中 页表项 的 数量)

        • Index 位,Cache 槽号
          长度 = log _2 (TLB 中 页表项 的 数量)

        • Offset 位,页内地址
          长度 = log _2 (页 的 大小) (按编址单位算)

      • 全相联虚拟地址

        • 高位,虚拟地址比物理地址长的位数,算在 Tag 位里

        • Tag 位,标记位
          长度 = log _2 (主存中 页 的 数量)

        • Offset 位,页内地址
          长度 = log _2 (页 的 大小) (按编址单位算)

      • n 路组相联虚拟地址

        • 高位,虚拟地址比物理地址长的位数,算在 Tag 位里

        • Tag 位,标记位
          长度 = log _2 (主存中 页 的 数量 / 组的数量)

        • 组号位
          长度 = log _2 (组 的 数量)

        • Offset 位,页内地址
          长度 = log _2 (页 的 大小) (按编址单位算)

    • 主存的地址格式 (物理地址格式):

      • 实页号 / 物理页号

      • 页内地址

  • 页表 (Page Table)
    建立一个映射关系表来存放虚拟地址与物理地址之间的映射关系,该映射关系表被称为页表,用来实现虚实地址的转换

    • 建立在主存中,操作系统为每道程序建立一个页表

    • 设置页表基址寄存器:保存页表在主存中的起始地址

    • 页表项

      • 装入位

      • 修改 (Dirty) 位

      • 替换控制位

      • 访问权限位

      • 禁止缓存位

      • 实页号

    • 页表的项数 = 页表的容量 = 最大页表项 = 虚存大小 / 页大小

    • 页表大小 = 页表的项数 * 页表项大小

  • 异常情况

    • 缺页 (page fault)

      • 产生条件:当 Valid (有效位 / 装入位) 为 0 时

      • 相应处理:从磁盘中读信息到内存,若内存没有空间,则还要从内存选择一页替换到磁盘上,替换算法类似于 Cache,采用回写法,页面淘汰时,根据 “dirty” 位确定是否要写磁盘

      • 异常处理结束后:缺页发生时,当前指令的执行被阻塞,当前进程挂起;缺页处理结束后,回到原指令继续执行

    • 保护违例 (protection_violation_fault)

      • 产生条件: 当 Access Rights (存取权限) 与所指定的具体操作不相符时

      • 相应处理:在屏幕上显示 “内存保护错” 信息

      • 异常处理结束后:当前指令执行被阻塞,当前进程终止

      • Access Rights (存取权限) 可能的取值有哪些?

        • R = Read-only

        • R/W = read/write

        • X = execute only

  • 特点

    • 优点:实现简单,开销少。因为只有进程的最后一个零头(内部碎片)不能利用,故浪费很小

    • 缺点:由于页不是逻辑上独立的实体,可能会出现如 “一条指令跨页” 等情况(CISC),使处理、管理、保护和共享都不方便

# 段式

# 段页式

\ No newline at end of file diff --git a/cs/principles-of-computer-composition/von-neumann-architecture/index.html b/cs/principles-of-computer-composition/von-neumann-architecture/index.html index 63dd26fc..d92e51c1 100644 --- a/cs/principles-of-computer-composition/von-neumann-architecture/index.html +++ b/cs/principles-of-computer-composition/von-neumann-architecture/index.html @@ -1 +1 @@ -冯・诺伊曼体系结构 - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +冯・诺伊曼体系结构 - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/cs/principles-of-computer-composition/yatcpu/chisel/index.html b/cs/principles-of-computer-composition/yatcpu/chisel/index.html index 7948203d..7747caed 100644 --- a/cs/principles-of-computer-composition/yatcpu/chisel/index.html +++ b/cs/principles-of-computer-composition/yatcpu/chisel/index.html @@ -1,4 +1,4 @@ -Chisel - YatCPU - 计算机组成原理 - 编程语言 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# Scala

# import

在 Scala 中,import 语句用于引入其他类、对象或特质,以便在当前作用域中可以直接访问它们的成员。下面是一些关于 Scala 中 import 的常见用法:

  1. 基本用法
a
// 导入单个类
import scala.collection.mutable.ListBuffer
// 导入整个包
import scala.collection.mutable._
// 重命名导入的类 / 对象 / 特质
import java.util.{ArrayList => JArrayList, HashMap => JHashMap}
// 隐藏某个成员
import java.util.{Random => _, _} // 隐藏 java.util.Random
  1. 导入对象的成员
a
import java.awt.Color._
val c = RED // 直接访问 Color 对象的成员 RED
  1. 静态导入
a
import java.lang.Math._
val maxNum = max(5, 10) // 直接使用 Math 类的静态方法 max

# 测试

# ScalaTest

要使用 ScalaTest 进行测试可以按照以下基本步骤进行操作:

导入必要的包和类:

a
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

创建测试类并扩展相应的测试风格特质:

a
class MyTest extends AnyFlatSpec with Matchers {
  // 在这里编写测试代码
}

在这个例子中,我们创建了一个名为 "MyTest" 的测试类,并将其扩展为 AnyFlatSpec 和 Matchers。AnyFlatSpec 是 ScalaTest 提供的一种测试规范风格,而 Matchers 允许你使用自然语言风格编写断言。

编写测试代码:
在测试类中,你可以编写各种测试方法来验证你的代码行为是否符合预期,例如:

a
it should "return the correct result" in {
  // 编写测试代码来验证某个函数或者方法的行为
  val result = myFunction()
  result should equal (expectedResult)
}

在这个例子中,我们使用 "it should" 来描述测试的行为,然后使用 "in" 关键字定义测试代码块。在测试代码块中,我们调用了一个名为 "myFunction" 的函数,并使用 "should equal" 断言来验证其返回值是否等于 "expectedResult"。

运行测试:
使用构建工具(如 sbt)来运行测试。在 sbt 中,你可以执行以下命令来运行测试:

sbt test

这将会执行所有的测试,并输出测试结果。

# Chisel

在 Scala 中,Chisel 是一个常用于硬件设计的领域特定语言(DSL),它提供了许多有用的库和工具,一些常用的库包括:

  1. chisel3:这是 Chisel 的核心库,它定义了 Chisel 的语法和 API。
  2. firrtl:这是 Chisel 的前端,用于将 Chisel 代码转换为可执行的 RTL 代码。
  3. chisel-iotesters:这是一个用于测试 Chisel 模块的库,它提供了一些常见的测试工具和模拟器。
  4. treadle:这是一个开源的 Verilog 仿真器,可以与 Chisel 代码一起使用进行仿真和调试。
  5. chisel-testers2:这是一个测试框架,用于编写和运行 Chisel 测试。
  6. chisel-formal:这是一个用于形式验证的库,可用于对 Chisel 模块进行形式化验证。
  7. chisel-fluent:这是一个用于创建可重用组件库的库,使得在不同的项目中可以轻松地重用 Chisel 模块。

在 chisel3 库中,常用的一些子库包括:

  1. chisel3:Chisel3 核心库,定义了 Chisel 的语法和 API。
  2. chisel3.util:提供了一些常见的工具和实用函数,如位宽转换、数据选择器、优先级编码器等。
  3. chisel3.experimental:包含一些实验性质的功能和模块,可能还处于开发或测试阶段。
  4. chisel3.testers:提供了对 Chisel 模块进行测试的相关工具和框架,用于验证设计的正确性。
  5. chisel3.tester:一个用于编写和运行 Chisel 测试的测试框架,支持生成测试向量、执行仿真等操作。
  6. chisel3.stage:用于将 Chisel 生成的硬件描述转换为 Verilog 或 FIRRTL 格式的工具。
  7. chisel3.formal:用于形式验证的库,可以对 Chisel 模块进行形式化验证。

有的时候不知道为什么 import chisel._ 了还是有些函数或运算符编译反馈 not found 或者 warnning,解决办法是 “更具体地 import”,比如:
遇到编译报错: not found value Cat
可以在文件开头加上 import chisel.util.Cat 来解决

# 数据类型

# Seq

Seq (Sequence) 是一个表示序列的数据类型。它用于定义一系列连续的元素,并提供了一些方法来操作和访问这些元素。

Seq 可以包含任意类型的元素,例如整数、布尔值或自定义的 Chisel 数据类型。通过使用 Seq.apply 方法或使用逗号分隔的元素列表,可以创建一个 Seq 实例

以下是一个使用 Seq 的示例:

import chisel3._
+Chisel - YatCPU - 计算机组成原理 - 编程语言 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# Scala

# import

在 Scala 中,import 语句用于引入其他类、对象或特质,以便在当前作用域中可以直接访问它们的成员。下面是一些关于 Scala 中 import 的常见用法:

  1. 基本用法
a
// 导入单个类
import scala.collection.mutable.ListBuffer
// 导入整个包
import scala.collection.mutable._
// 重命名导入的类 / 对象 / 特质
import java.util.{ArrayList => JArrayList, HashMap => JHashMap}
// 隐藏某个成员
import java.util.{Random => _, _} // 隐藏 java.util.Random
  1. 导入对象的成员
a
import java.awt.Color._
val c = RED // 直接访问 Color 对象的成员 RED
  1. 静态导入
a
import java.lang.Math._
val maxNum = max(5, 10) // 直接使用 Math 类的静态方法 max

# 测试

# ScalaTest

要使用 ScalaTest 进行测试可以按照以下基本步骤进行操作:

导入必要的包和类:

a
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

创建测试类并扩展相应的测试风格特质:

a
class MyTest extends AnyFlatSpec with Matchers {
  // 在这里编写测试代码
}

在这个例子中,我们创建了一个名为 "MyTest" 的测试类,并将其扩展为 AnyFlatSpec 和 Matchers。AnyFlatSpec 是 ScalaTest 提供的一种测试规范风格,而 Matchers 允许你使用自然语言风格编写断言。

编写测试代码:
在测试类中,你可以编写各种测试方法来验证你的代码行为是否符合预期,例如:

a
it should "return the correct result" in {
  // 编写测试代码来验证某个函数或者方法的行为
  val result = myFunction()
  result should equal (expectedResult)
}

在这个例子中,我们使用 "it should" 来描述测试的行为,然后使用 "in" 关键字定义测试代码块。在测试代码块中,我们调用了一个名为 "myFunction" 的函数,并使用 "should equal" 断言来验证其返回值是否等于 "expectedResult"。

运行测试:
使用构建工具(如 sbt)来运行测试。在 sbt 中,你可以执行以下命令来运行测试:

sbt test

这将会执行所有的测试,并输出测试结果。

# Chisel

在 Scala 中,Chisel 是一个常用于硬件设计的领域特定语言(DSL),它提供了许多有用的库和工具,一些常用的库包括:

  1. chisel3:这是 Chisel 的核心库,它定义了 Chisel 的语法和 API。
  2. firrtl:这是 Chisel 的前端,用于将 Chisel 代码转换为可执行的 RTL 代码。
  3. chisel-iotesters:这是一个用于测试 Chisel 模块的库,它提供了一些常见的测试工具和模拟器。
  4. treadle:这是一个开源的 Verilog 仿真器,可以与 Chisel 代码一起使用进行仿真和调试。
  5. chisel-testers2:这是一个测试框架,用于编写和运行 Chisel 测试。
  6. chisel-formal:这是一个用于形式验证的库,可用于对 Chisel 模块进行形式化验证。
  7. chisel-fluent:这是一个用于创建可重用组件库的库,使得在不同的项目中可以轻松地重用 Chisel 模块。

在 chisel3 库中,常用的一些子库包括:

  1. chisel3:Chisel3 核心库,定义了 Chisel 的语法和 API。
  2. chisel3.util:提供了一些常见的工具和实用函数,如位宽转换、数据选择器、优先级编码器等。
  3. chisel3.experimental:包含一些实验性质的功能和模块,可能还处于开发或测试阶段。
  4. chisel3.testers:提供了对 Chisel 模块进行测试的相关工具和框架,用于验证设计的正确性。
  5. chisel3.tester:一个用于编写和运行 Chisel 测试的测试框架,支持生成测试向量、执行仿真等操作。
  6. chisel3.stage:用于将 Chisel 生成的硬件描述转换为 Verilog 或 FIRRTL 格式的工具。
  7. chisel3.formal:用于形式验证的库,可以对 Chisel 模块进行形式化验证。

有的时候不知道为什么 import chisel._ 了还是有些函数或运算符编译反馈 not found 或者 warnning,解决办法是 “更具体地 import”,比如:
遇到编译报错: not found value Cat
可以在文件开头加上 import chisel.util.Cat 来解决

# 数据类型

# Seq

Seq (Sequence) 是一个表示序列的数据类型。它用于定义一系列连续的元素,并提供了一些方法来操作和访问这些元素。

Seq 可以包含任意类型的元素,例如整数、布尔值或自定义的 Chisel 数据类型。通过使用 Seq.apply 方法或使用逗号分隔的元素列表,可以创建一个 Seq 实例

以下是一个使用 Seq 的示例:

import chisel3._
 
 class MyModule extends Module {
   val io = IO(new Bundle {
@@ -217,4 +217,4 @@
     true
   }
 }
-

在这个例子中,我们定义了一个名为 performSomeOperation 的独立函数,并在测试用例中调用它。这种方式可以使测试代码更加清晰,同时也方便测试用例的复用。

\ No newline at end of file +

在这个例子中,我们定义了一个名为 performSomeOperation 的独立函数,并在测试用例中调用它。这种方式可以使测试代码更加清晰,同时也方便测试用例的复用。

\ No newline at end of file diff --git a/cs/principles-of-computer-composition/yatcpu/lab-reports/lab1/index.html b/cs/principles-of-computer-composition/yatcpu/lab-reports/lab1/index.html index 2432fb8c..f791007d 100644 --- a/cs/principles-of-computer-composition/yatcpu/lab-reports/lab1/index.html +++ b/cs/principles-of-computer-composition/yatcpu/lab-reports/lab1/index.html @@ -1 +1 @@ -lab1 - YatCPU - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

YatCPU - - - lab1 - - - lab2 - - - lab3 - - - lab4

# 测试用例及其波形图分析

# SayGoodbyeTest

src/test/scala/riscv/BoardTest.scala

avatar

其中 Top 模块来自:

avatar

# 测试用例的功能

用于烧板验证,但由于 CPU 还未能实现中断,该程序只能通过 LED 灯闪烁判断 CPU 能否正常工作

在 lab1 中该测试用例可以用于检查 CPU 及其内部各个模块、模块内的端口信号是否有完整地实现、初始化,即 "Fully initialized"。若有信号定义后没有完整实现,则该项会测试后报错: Reference xxx is not fully initialized. 则表明可能该处有代码空缺没有填补完整。

# 从什么层面测试 CPU

从完整性的层面测试 CPU,CPU 能否正常工作

但测试程序并没有测试 CPU 的正确性,只是进行了 pokestep ,没有对任何信号进行 expect 检查。

# 加载测试程序的方法

利用定义在 ssrc/main/scala/board/z710/Top.scala 中的模块 Top ,用 RISC-V 程序 src/main/resources/say_goodbye.asmbin 初始化进行仿真

# 测试用例的执行结果

avatar

# 输出波形图

avatar

该测试只向波形文件写入了 Top 模块的信号

# 执行不同指令时候对应的部件的关键信号的变化情况

由 clock 信号变化可以看出时钟周期为 2 ps

测试中循环执行了 50000 次 step(5) ,即 250000 个时钟周期,输出的波形图总时长为 500001 ps ,除去半个用于 reset 的时钟周期之外恰好 250000 个时钟周期。

可以看到波形图中除了 clock 信号有规律的周期性变化之外, io_rx 也在周期性地在 0 和 1 之间变化。从波形图也可以看出每 10 ps 即 5 个时钟周期 io_rx 变化一次,符合 step(5) 一次 c.io.rx.poke((i % 2).U) 一次的变化规律。

# ExecuteTest

src/test/scala/riscv/singlecycle/ExecuteTest.scala

avatar

# 测试用例的功能

该测试用例用于检查 Execute 模块的正确性,包括:

# 执行 ALU 加法运算

测试程序循环执行了 100 次两个随机生成的 int 整型操作数 op1 和 op2 的求和运算,检查 R 型指令 add 的正确性。

同时检查跳转信号是否始终保持 0 (fasle),确保 CPU 在非跳转指令下不跳转

# 处理 beq 指令是否跳转

测试程序按顺序测试了两个情况:

跳转,即 op1 等于 op2 ,此时跳转信号应该为 1 (true),原指令地址 (PC):2 应该与立即数 2 相加得到新的指令地址 (PC):4

不跳转,即 op1 不等于 op2 ,此时跳转信号应该为 0 (false),指令地址 (PC) 保持 4 不变

# 从什么层面测试 CPU

从 CPU 运算处理的层面测试 CPU ,即能否正确控制 ALU 的输入输出,以及输入输出结果对指令跳转的控制

# 加载测试程序的方法

利用定义在 src/main/scala/riscv/core/Execute.scala 中的模块 Execute ,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

# ALU 加法运算

总共执行了 102 个时钟周期,测试了 101 次随机样例 (循环从 i=0 到 i=100 执行了 101 次)。

avatar

# io_funct3[2:0]

该信号始终保持 000B 不变,与 io_opcode 一起指示 ALU 执行 R 类型指令 add 的加法运算

# io_opcode[6:0]

该信号始终保持 0110011B 不变,与 io_funct3 一起指示 ALU 执行 R 类型指令 add 的加法运算

avatar

# io_alu_funct[3:0]

按照 src/main/scala/riscv/core/ALU.scala 定义的 ChiselEnum 枚举类型如下:

avatar

由于总共有 11 种取值,默认从 0 开始计数直到 10 ,需要二进制 4 位数才能表示,因此对应的 io_alu_funct 为 4 位二进制数

在加法运算时该信号始终保持 0001B 不变,对应 ChiselEnu 类型定义的 ALUFunctions 中从 0 开始计数的第二个 add,指示 ALU 执行加法运算

# io_op1[31:0]

该信号来自 c.io.reg1_data.poke(op1.U) ,在 add 指令中 ALU 的运算操作数 op1 来自寄存器,因此 Execute 模块的 io_reg1_data 直接传递给 ALU 模块的 io_op1

每隔一个时钟周期 (2 ps) 变化一次,每次均为一个新的随机 int 型整数

# io_op2[31:0]

该信号来自 c.io.reg2_data.poke(op1.U) ,在 add 指令中 ALU 的运算操作数 op2 来自寄存器,因此 Execute 模块的 io_reg2_data 直接传递给 ALU 模块的 io_op2

每隔一个时钟周期 (2 ps) 变化一次,每次均为一个新的随机 int 型整数

# io_result[31:0]

每隔一个时钟周期 (2 ps) 变化一次,每次均为当前 io_op1 与 io_op2 的算术和,同时该值直接传递给 Execute 模块的 mem_alu_result

# 指令

总共执行 3 个时钟周期,先后测试了成功跳转和不成功跳转两种情况。

avatar

# io_funct3[2:0]

该信号始终保持 000B 不变,与 io_opcode 一起指示 ALU 执行 B 类型指令 beq 的加法运算计算跳转目标地址,以及控制跳转信号 io_if_jump 的产生

# io_opcode[6:0]

该信号始终保持 1100011B 不变,与 io_funct3 一起指示 ALU 执行 B 类型指令 beq 的加法运算计算跳转目标地址,以及控制跳转信号 io_if_jump 的产生

avatar

# io_reg1_data[31:0]

该信号表示所读取的来自寄存器的数据,在 beq 指令中直接将两个寄存器的值进行比较得到跳转信号 io_if_jump

在测试的后 2 个时钟周期内其值均为 9 ,来自测试程序中的 c.io.reg1_data.poke(9.U)

# io_reg2_data[31:0]

该信号表示所读取的来自寄存器的数据,在 beq 指令中直接将两个寄存器的值进行比较得到跳转信号 io_if_jump

在第 2 个时钟周期内其值为 9 ,来自测试程序中的 c.io.reg2_data.poke(9.U)

在第 3 个时钟周期内其值为 19 ,来自测试程序中的 c.io.reg2_data.poke(19.U)

# io_if_jump

该信号表示 PC 下一条指令是否要跳转,是则 io_if_jump = 1 ,否则 io_if_jump = 0

在第 2 个时钟周期其值为 1 ,因为此时 io_reg1_data = 9 = io_reg2_data

在第 3 个时钟周期其值为 0 ,因为此时 io_reg1_data = 9 , io_reg2_data = 19

# io_alu_funct[3:0]

在 beq 指令中,ALU 执行加法运算,io_alu_funct = 1

# alu_io_op1[31:0]

由于 c.io.aluop1_source.poke(1.U) ,aluop1_source = 1 指示该信号 alu_io_op1 来自 instruction_address ,同时 c.io.instruction_address.poke(2.U) ,因此 alu_io_op1 = 2

# alu_io_op2[31:0]

由于 c.io.aluop2_source.poke(1.U) ,aluop2_source = 1 指示该信号 alu_io_op2 来自立即数 io_immediate ,同时 c.io.immediate.poke(2.U) ,因此 alu_io_op2 = 2

# io_if_jump_address[31:0]

表示跳转成功时 PC 跳转的目标指令地址,在 beq 指令中等于 ALU 计算出来的结果 alu_io_result

在 2 个时钟周期内均为 4 ,即 alu_io_op1 与 alu_io_op2 的和

# InstructionDecoderTest

src/test/scala/riscv/singlecycle/InstructionDecoderTest.scala

avatar

# 测试用例的功能

测试了 InstructionDecode 模块的正确性,包括:

# S 型指令

测试了对 S 型指令 sw 翻译的正确性,包括读取正确的寄存器并且将正确的操作数传递给 ALU。

在 S 型指令中,存储的数据来自寄存器,存储目标的内存地址由另一寄存器中的数据和指令中的立即数作为偏移量共同决定。

# lui 指令

测试了对高位加载立即数指令 lui 翻译的正确性,包括读取正确的寄存器并且将正确的操作数传递给 ALU

在 lui 指令中,符号位扩展的 20 位立即数左移 12 位后,将低 12 位置零,传入 ALU,同时 ALU 另一个操作数设置为 0 号寄存器 (内容始终为 0) 的值,即另一个操作数为 0,ALU 做加法运算,相当于将位扩展后的结果直接作为写入的值,写入目标寄存器中

# add 指令

测试了对 R 型指令 add 翻译的正确性,主要测试了是否控制选择寄存器作为 ALU 操作数

# 从什么层面测试 CPU

从指令的翻译、分析层面,指导 CPU 如何根据当前指令进行工作,包括立即数的提取、各个控制信号的取值等

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/core/InstructionDecode.scala 中的模块 InstructionDecode ,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

# S 型指令

总共执行了一个时钟周期 (2 ~ 4 ps),测试了 S 型指令 sw 在 ID 阶段的信号输出

avatar

# io_instruction[31:0]

该信号直接来自 c.io.instruction.poke(00a02223L.U) ,对应二进制码为:0000000 0

avatar

# io_ex_immediate[31:0]

该信号由 io_instruction 的 [11:5] 部分 0000000B 和 [11:7] 部分 00100B 组成 004H ,再位扩展后得到 00000004H = 4,作为立即数传入 ALU

# io_regs_reg1_read_address[4:0]

该信号来自 io_instruction 的 [19:15] 部分,为 00000B,对应 0 号寄存器

# io_regs_reg2_read_address[4:0]

该信号来自 io_instruction 的 [24:20] 部分,为 01010B,对应 10 号寄存器

# io_ex_aluop1_source

在 S 型指令中, io_ex_aluop1_source = 0 ,指示读取寄存器的数据传给 ALU 作为其中一个操作数

# io_ex_aluop2_source

在 S 型指令中, io_ex_aluop2_source = 1 ,指示将立即数 io_ex_immediate 传给 ALU 作为其中一个操作数

# io_memory_read_enable

S 型指令没有读取内存,所以 io_memory_read_enable = 0

# io_memory_write_enable

S 型指令需要写内存,所以 io_memory_write_enable = 1

# lui 指令

总共执行了一个时钟周期 (4 ~ 6 ps),测试了 lui 指令在 ID 阶段的信号输出

avatar

# io_instruction[31:0]

该信号直接来自 c.io.instruction.poke(000022b7L.U) ,对应二进制码为:00000000000000000010 00101 01

avatar

# io_ex_immediate[31:0]

该信号由 io_instruction 的 [31:12] 部分 00002H 位扩展后得到 00002000H = 2,作为立即数传入 ALU

# io_reg_write_address[4:0]

该信号来自 io_instruction 的 [11:7] 部分,其值为 00101 ,对应 5 号寄存器,即结果要写入 5 号寄存器

# io_ex_aluop1_source

在 lui 指令中, io_ex_aluop1_source = 0 ,指示读取寄存器 (0 号寄存器) 的数据 ( 0 ) 传给 ALU 作为其中一个操作数

# io_ex_aluop2_source

在 lui 指令中, io_ex_aluop1_source = 1 ,指示将立即数 io_ex_immediate 传给 ALU 作为其中一个操作数

# io_regs_reg1_read_address[4:0]

在 lui 指令中, 该值被设置为 00000 ,对应 0 号寄存器

# io_reg_write_enable

在 lui 指令中,需要写入寄存器,所以 io_reg_write_enable = 1

# io_wb_reg_write_source[1:0]

在 lui 指令中,写入寄存器的值为 ALU 计算结果,所以 io_wb_reg_write_source 的值为 00 ,指示选择 ALU 输出结果作为写入寄存器的数据源

# io_memory_write_enable

lui 指令没有写内存,所以 io_memory_write_enable = 0 ,避免误写内存

# 指令

总共执行了一个时钟周期 (4 ~ 6 ps),测试了 lui 指令在 ID 阶段的信号输出

avatar

# io_instruction[31:0]

该信号直接来自 c.io.instruction.poke(002081b3L.U) ,对应二进制码为:= 0000000 00010 00001 000 00011 0110011 B ,其中 [6:0] 部分、 [14:12] 部分和 [31:25] 部分一起决定了当前指令为 add 指令;[19:15] 部分和 [24:20] 部分分别为操作数寄存器地址,对应信号 io_regs_reg1_read_address 和 io_regs_reg2_read_address ;[11:7] 部分作为目标寄存器的地址,对应 io_reg_write_address

avatar

# io_reg_write_address[4:0]

该信号来自 io_instruction 的 [11:7] 部分,其值为 00011 ,对应 3 号寄存器,即结果要写入 3 号寄存器

# io_regs_reg1_read_address[4:0]

该信号来自 io_instruction 的 [19:15] 部分,为 00001B,对应 1 号寄存器

# io_regs_reg2_read_address[4:0]

该信号来自 io_instruction 的 [24:20] 部分,为 00010B,对应 2 号寄存器

# io_ex_aluop1_source

在 add 指令中, io_ex_aluop1_source = 0 ,指示读取寄存器的数据传给 ALU 作为其中一个操作数

# io_ex_aluop2_source

在 add 指令中, io_ex_aluop1_source = 0 ,指示读取寄存器的数据传给 ALU 作为其中一个操作数

# io_reg_write_enable

在 add 指令中,需要写入寄存器,所以 io_reg_write_enable = 1

# io_wb_reg_write_source[1:0]

在 add 指令中,写入寄存器的值为 ALU 计算结果,所以 io_wb_reg_write_source 的值为 00 ,指示选择 ALU 输出结果作为写入寄存器的数据源

# io_memory_write_enable

R 型指令 add 没有写内存,所以 io_memory_write_enable = 0 ,避免误写内存

# InstructionFetchTest

src/test/scala/riscv/singlecycle/InstructionFetchTest.scala

avatar

# 测试用例的功能

模拟了 CPU 执行连续的 100 条随机指令时 InstructionFetch 模块能否正确顺序执行指令或跳转

# 从什么层面测试 CPU

从指令取指层面测试 CPU 的正确性

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/core/InstructionFetch.scala 中的模块 InstructionFetch ,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

# 不跳转

avatar

此时 io_jump_flag = 0,指示不跳转,pc 的值每隔一个时钟周期 (2 ps) 就递增 4 ,指令顺序执行

# 跳转

avatar

io_jump_flag = 1 时指示 pc 跳转,pc 的值在 io_jump_flag = 1 出现后的第二个时钟周期被置为跳转目标地址 io_jump_address_id = 00001000H,实现指令跳转

# RegisterFileTest 1 : read the writing content

src/test/scala/riscv/singlecycle/RegisterFileTest.scala

avatar

# 测试用例的功能

测试了写入寄存器操作的时钟周期内目标寄存器内容的变化,即测试了写寄存器功能的正确性

# 从什么层面测试 CPU

从寄存器的读写层面测试了 CPU ,测试了寄存器模块

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/core/RegisterFile.scala 中的模块 RegisterFile ,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

测试总共执行了 2 个时钟周期,第 1 个时钟周期内检测了 2 号寄存器内的值是否为 0 ,即是否为初始状态,同时测试程序模拟了一次写寄存器操作,向 2 号寄存器写入数据 DEADBEEFLH 。在第 2 个时钟周期再次检测 2 号寄存器的值,看其内容是否已经变为写入的数据。在这个过程中始终检测读取 2 号寄存器,所以信号 io_read_address 的内容始终为 2 ;第 1 个时钟周期模拟写入 2 号寄存器的过程,第 2 个时钟周期没有再写入过,所以信号 io_write_address 的内容始终为 2 且 io_write_data 的内容始终为 DEADBEEFLH ;在写寄存器操作后的下一个时钟周期上升沿到来时 register_2 [31:0] 的内容变为 DEADBEEFLH ,表明写寄存器操作正确执行;io_read_data_1 [31:0] 的值在第 2 个时钟周期上升沿到来前为 0 ,在第 2 个时钟周期上升沿到来时变为 DEADBEEFLH

# RegisterFileTest 2 : read the written content

src/test/scala/riscv/singlecycle/RegisterFileTest.scala

avatar

# 测试用例的功能

测试了写入寄存器操作后的下一个时钟周期能否在目标寄存器读出写入的数据,即测试了写寄存器功能的正确性

# 从什么层面测试 CPU

从寄存器的读写层面测试了 CPU ,测试了寄存器模块

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/core/RegisterFile.scala 中的模块 RegisterFile ,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

测试执行了一个时钟周期,测试程序在一个 timescope 内模拟了一次写入寄存器的操作,将数据 DEADBEEFLH 写入 1 号寄存器,这个过程将 io_write_enable 打开;将 io_write_address 赋值为 1 ,即写入 1 号寄存器;将 io_write_data 赋值为 DEADBEEFLH 。然后在下一个时钟周期模拟测试了能否从 1 号寄存器读出正确的数据,这个测试过程由于没有 clock.step() 所以没有显示在波形图中。但在波形图中可以看到第一个时钟周期后在下一个时钟上升沿到来之前,1 号寄存器的内容 register_1 [31:0] 以及变为了 DEADBEEFLH ,表明写入寄存器操作正确执行。

# RegisterFileTest 3 : x0 always be zero

src/test/scala/riscv/singlecycle/RegisterFileTest.scala

avatar

# 测试用例的功能

测试了写入 0 号寄存器后 0 号寄存器的内容是否保持 0 不变

# 从什么层面测试 CPU

从寄存器的读写层面测试了 CPU ,测试了寄存器模块

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/core/RegisterFile.scala 中的模块 RegisterFile ,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

测试总共执行了一个时钟周期,模拟了将写入目标寄存器设置为 0 号寄存器 x0 时的写寄存器操作。io_write_address = 0 ,表示写入 0 号寄存器;io_write_data = DEADBEEFH ,输入为要写入的数据;io_write_enable = 1 ,打开寄存器写使能;register_0 = 0 始终不变,表明测试成功,0 号寄存器的内容没有被改变始终为 0

# FibonacciTest

src/test/scala/riscv/singlecycle/CPUTest.scala

avatar

csrc/fibonacci.c

avatar

# 测试用例的功能

测试了利用递归方法计算斐波那契数列第 10 项的程序能否在 CPU 上正常执行,并计算出结果存储到内存目标地址上

# 从什么层面测试 CPU

从最终完整执行一个程序的层面测试 CPU ,包括除了中断处理、与外设通信以外的所有 CPU 功能

# 加载测试程序指令的方法

利用定义在 src/test/scala/riscv/singlecycle/CPUTest.scala 中的模块 TestTopModule ,模拟一个简单的计算机,连接了 CPU 、Memory、InstructionRom 、ROMLoader几个模块。用 RISC-V 程序 src/main/resources/fibonacci.asmbin``` 初始化 instruction_rom 模块作为运行程序进行仿真

# 测试用例的执行结果

avatar

# 输出波形图

avatar

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

# 程序指令的执行

为了保证程序完整执行完毕,测试程序循环执行了 50 次 c.clock.step(1000) ,总共执行了 50000 个时钟周期。其中大约前 20 ns 的时间内 CPU 各个信号不断变化,表明程序在执行。此后所有信号稳定,表明程序执行已经结束。

avatar

avatar

从第 279 ps 开始 CPU 的信号开始发生变化,计算斐波那契数列的程序开始执行,到 22299 ps 为止 CPU 的所以信号稳定,表明 CPU 已经执行完毕。

在执行过程中可以看到 io_instruction 信号以 8 ps 为周期变化一次,即 CPU 周期为 8 ps ,相当于 4 个时钟周期。

avatar

寄存器信号中可以发现,在程序运行过程中只有 1、2、8、10、11 号寄存器不断发生变化,也即程序只使用了除 0 号寄存器以外 5 个寄存器。

# 程序结果的检测

在 csrc/fibonacci.c 程序中可以看到,最终计算结果为斐波那契数列第 10 项,结果存储在地址为 4 的内存空间里。程序结果的检测执行了一个时钟周期

avatar

# io_mem_debug_read_address[31:0]

该信号直接来自 c.io.mem_debug_read_address.poke(4.U) ,表示检测读取的内存地址为 4

# io_mem_debug_read_data[31:0]

一个时钟周期后读取内存地址为 4 的内容得到该信号的值为 00000037H = 55 ,表明程序结果正确

# QuicksortTest

src/test/scala/riscv/singlecycle/CPUTest.scala

avatar

csrc/quicksort.c

avatar

# 测试用例的功能

测试程序给出了一个由 10 个阿拉伯数字组成的数组: {6,2,4,5,3,1,0,9,7,8} ,利用递归实现的 quicksort 函数对该数组进行排序,检测是否得到一个正确的有序数组

# 从什么层面测试 CPU

从最终完整执行一个程序的层面测试 CPU ,包括除了中断处理、与外设通信以外的所有 CPU 功能

# 加载测试程序指令的方法

利用定义在 src/test/scala/riscv/singlecycle/CPUTest.scala 中的模块 TestTopModule ,模拟一个简单的计算机,连接了 CPU 、Memory、InstructionRom 、ROMLoader 几个模块。用 RISC-V 程序 src/main/resources/quicksort.asmbin 初始化进行仿真

# 测试用例的执行结果

avatar

# 输出波形图

avatar

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

# 程序指令的执行

为了保证程序完整执行完毕,测试程序循环执行了 50 次 c.clock.step(1000) ,总共执行了 50000 个时钟周期。其中大约前 15 ns 的时间内 CPU 各个信号不断变化,表明程序在执行。此后所有信号稳定,表明程序执行已经结束。

avatar

avatar

从第 525 ps 开始 CPU 的信号开始发生变化,快排程序开始执行,到 13931 ps 为止 CPU 的所以信号稳定,表明 CPU 已经执行完毕。

在执行过程中可以看到 io_instruction 信号以 8 ps 为周期变化一次,即 CPU 周期为 8 ps ,相当于 4 个时钟周期。

avatar

寄存器信号中可以发现,在程序运行过程中只有 1、2、8、10、11 、12 号寄存器不断发生变化,也即程序只使用了除 0 号寄存器以外 6 个寄存器。其中 1、2、8、12 号寄存器的变化呈现较同步的规律,说明这 4 个寄存器中的数据与递归有关;而 10、11 号寄存器的内容总是在频繁变化,说明这两个寄存器主要用来存储 ALU 运算的操作数

# 程序结果的检测

在 csrc/quicksort.c 程序中可以看到,排列得到的结果,结果存储在起始地址为 4 ,长度为 10 个 int 类型大小的内存空间里。程序结果的检测执行了 10 个时钟周期,利用循环程序对检测的内存地址递增,逐个访问目标内存,看所存储的内容是否上是从 0 到 9 的升序排列数组

avatar

# io_mem_debug_read_address[31:0]

该信号直接来自 c.io.mem_debug_read_address.poke((4*i).U)i 从 1 到 10 递增, 4*i 从 4 到 40 变化,即检测读取的内存地址从 00000004H 到 00000028H 变化

# io_mem_debug_read_data[31:0]

内存地址从 00000004H 到 00000028H 变化的同时 io_mem_debug_read_data 读取内存的内容也从 0 到 9 变化,表明程序结果正确

# ByteAccessTest

src/test/scala/riscv/singlecycle/CPUTest.scala

avatar

csrc/sb.S

avatar

# 测试用例的功能

在 RISCV 手册第 30 页可以查到寄存器编号即助记名如下:

avatar

对测试使用的 RISCV 汇编代码具体解释如下:

RISCV汇编
.globl _start 			;声明_start为全局符号
	_start:         	;程序从这里开始执行
	li a0, 0x4      	;将立即数 0x4 加载到寄存器 a0 (x10)
	li t0, 0xDEADBEEF ;将立即数 0xDEADBEEF 加载到寄存器 t0(x5)
	sb t0, 0(a0)    	;将寄存器 t0(x5) 的值存储到地址为 a0(x10) 的内存位置中
	lw t1, 0(a0)    	;将地址为 a0(x10) 的内存位置中的值加载到寄存器 t1(x6)
	li s2, 0x15    		;将立即数 0x15 加载到寄存器 s2(x18)
	sb s2, 1(a0)   		;将寄存器 s2(x18) 的值存储到地址为 (a0+1) 的内存位置中
	lw ra, 0(a0)    	;将地址为 a0(x10) 的内存位置中的值加载到寄存器 ra(x1)
loop:           		;循环的标签
	j loop          	;无条件地跳转到标签 loop,实现无限循环

# 从什么层面测试 CPU

从指令的层面测试 CPU ,测试了 CPU 对若干连续的 S 型和 L 型指令能否正确执行。主要检测了执行指令读写寄存器功能是否正确

# 加载测试程序指令的方法

利用定义在 src/test/scala/riscv/singlecycle/CPUTest.scala 中的模块 TestTopModule ,模拟一个简单的计算机,连接了 CPU 、Memory、InstructionRom 、ROMLoader 几个模块。用 RISC-V 程序 src/main/resources/sb.asmbin 初始化进行仿真

# 测试用例的执行结果

avatar

# 输出波形图

avatar

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

上图中可以看到有 5 个寄存器的值发生了变化:

register_10 [31:0] 即 10 号寄存器 x10 或 a0 ,由 li a0, 0x4 赋值后信号稳定为 4

register_5 [31:0] 即 5 号寄存器 x5 或 t0 ,由 li t0, 0xDEADBEEF 赋值时,由于寄存器写使能信号 io_reg_write_enable 此时仍保持打开的,因为上一条指令 li a0, 0x4 执行时也打开了寄存器写使能,所以此时写入目标寄存器 5 号寄存器的内容出现了毛刺 DEADC000H ,但在下一个时钟周期恢复正确值 DEADBEEFH 并稳定

register_6 [31:0] 即 6 号寄存器 x6 或 t1 ,由 lw t1, 0(a0) 赋值后信号稳定。内存地址 DEADBEEFH 的内容由 sb t0, 0(a0) 赋值,而 sb 指令存储时只存低位字节,且 RISCV 为小端存储模式,所以存入内存的只有 EFH ,读取内存时 EFH 即为最低位字节,存到 6 号寄存器的内容为 000000EFH

register_18 [31:0] 即 18 号寄存器 x18 或 s2 ,由 li s2, 0x15 赋值后信号稳定为 15H

register_1 [31:0] 即 1 号寄存器 x1 或 ra,由 lw ra, 0(a0) 赋值后信号稳定。内存地址 DEADBEEFH 的内容原本只有只有 EFH ,sb s2, 1 (a0) 再次对该地址赋值,而 sb 指令存储时只存低位字节,按照 RISCV 的小端存储模式,此时存入内存的只有 15H ,且存到 DEADBEEFH +1 的地址,即存到 EFH 的下一个地址。读取内存时字节从低到高为 EFH、15H ,存到 1 号寄存器的内容为 000015EFH

测试程序检测了 ,与波形图对应寄存器内容的信号最后稳定的值相同,表明指令正确执行

# 填空涉及到的信号分析

(src/main/scala/riscv/)

# core/InstructionFetch.scala

# io.jump_flag_id

该控制信号告诉 CPU 取指阶段下一条指令是否需要跳转,如果是则将 PC 设置为跳转目标指令地址,否则 PC+4,下一个时钟周期顺序读取下一条指令

# core/InstructionDecode.scala

# io.ex_aluop2_source

改控制信号控制 ALU 输入端的第二个输入源,分别有以下两种:

avatar

ALUOp2Source.Immediate:
将 io.ex_aluop2_source 设置为该值后 ALU 输入端端第二个输入源是来自指令的立即数

ALUOp2Source.Register:
将 io.ex_aluop2_source 设置为该值后 ALU 输入端端第二个输入源是读取寄存器得到的数据

avatar

根据以上 RISC-V 手册第 25 页指令译码过程可以知道,需要使用到立即数的指令有:

  • U 型指令
    • lui
    • auipc
  • J 型指令
    • jal
    • jalr
  • I 型指令
  • L 型指令
  • B 型指令
  • 其他
    • fence 同步内存和 I/O
    • CSR 型指令
    • nop 伪指令

因此当执行上述指令时,将 io.ex_aluop2_source 设置为 ALUOp2Source.Immediate

# io.memory_read_enable

RISCV 中只有 L 型指令需要读取内存,所以执行 L 型指令时将 io.memory_read_enable 设置为 1,否则均设置为 0

# io.memory_write_enable

RISCV 中只有 S 型指令需要写内存,所以执行 S 型指令时将 io.memory_write_enable 设置为 1,否则均设置为 0

# io.wb_reg_write_source

查阅手册各个指令的功能可知,需要写回寄存器的指令及其对应写入数据源如下:

  • R 型指令:ALU 计算结果
  • U 型指令
    • lui:ALU 计算结果
    • auipc:ALU 计算结果
  • I 型指令:ALU 计算结果
  • L 型指令:内存
  • 其他
    • nop 伪指令:ALU 计算结果

不考虑中断的 CSR 作为写入数据源,其余指令均可设置 io.wb_reg_write_source 为 NextInstructionAddress (作为默认值)

# core/Execute.scala

# alu.io.func

该信号传给 ALU ,决定 ALU 执行何种运算,实际上该信号的取值为 src/main/scala/riscv/core/ALU.scala 定义的 ChiselEnum 枚举类型,在 “ alu.io.func

# alu.io.op1

该信号传给 ALU,决定 ALU 的第一个操作数的数据源为 PC 还是寄存器。其控制已在 InstructionDecode 模块实现,其传入 Execute 模块的信号为 io.aluop1_source ,根据该信号即可确定 alu.io.op1

# alu.io.op2

该信号传给 ALU,决定 ALU 的第一个操作数的数据源为立即数还是寄存器。其控制已在 InstructionDecode 模块实现,其传入 Execute 模块的信号为 io.aluop2_source ,根据该信号即可确定 alu.io.op2

# core/CPU.scala

所填代码主要涉及传递给 Execute 模块的信号,各个赋值语句对应了连线图的控制信号连线、模块之间的端口的连接

# ex.io.instruction := inst_fetch.io.instruction

取指阶段得到的指令传递给 Execute 模块

# ex.io.instruction_address := inst_fetch.io.instruction_address

取指阶段得到的指令地址传递给 Execute 模块

# ex.io.reg1_data := regs.io.read_data1

寄存器组将读取的第 1 个数据传递给 Execute 模块

# ex.io.reg2_data := regs.io.read_data2

寄存器组将读取的第 2 个数据传递给 Execute 模块

# ex.io.immediate := id.io.ex_immediate

译码阶段得到的立即数传递给 Execute 模块

# ex.io.aluop1_source := id.io.ex_aluop1_source

译码阶段得到的 ALU 第 1 个操作数的数据源的控制信号传递给 Execute 模块

# ex.io.aluop2_source := id.io.ex_aluop2_source

译码阶段得到的 ALU 第 2 个操作数的数据源的控制信号传递给 Execute 模块

# 在完成实验的过程中,遇到的关于实验指导不明确或者其他问题,或者改进的建议。

使用实验板上的数码管、视频输出等外设,输出一个完整程序的运行结果,或者参考硬件调试一节的内容,用硬件波形的方法捕获程序运行结果。给出你的 CPU 可以正确在实验板上运行程序的照片或者硬件调试器波形截图。

\ No newline at end of file +lab1 - YatCPU - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

YatCPU - - - lab1 - - - lab2 - - - lab3 - - - lab4

# 测试用例及其波形图分析

# SayGoodbyeTest

src/test/scala/riscv/BoardTest.scala

avatar

其中 Top 模块来自:

avatar

# 测试用例的功能

用于烧板验证,但由于 CPU 还未能实现中断,该程序只能通过 LED 灯闪烁判断 CPU 能否正常工作

在 lab1 中该测试用例可以用于检查 CPU 及其内部各个模块、模块内的端口信号是否有完整地实现、初始化,即 "Fully initialized"。若有信号定义后没有完整实现,则该项会测试后报错: Reference xxx is not fully initialized. 则表明可能该处有代码空缺没有填补完整。

# 从什么层面测试 CPU

从完整性的层面测试 CPU,CPU 能否正常工作

但测试程序并没有测试 CPU 的正确性,只是进行了 pokestep ,没有对任何信号进行 expect 检查。

# 加载测试程序的方法

利用定义在 ssrc/main/scala/board/z710/Top.scala 中的模块 Top ,用 RISC-V 程序 src/main/resources/say_goodbye.asmbin 初始化进行仿真

# 测试用例的执行结果

avatar

# 输出波形图

avatar

该测试只向波形文件写入了 Top 模块的信号

# 执行不同指令时候对应的部件的关键信号的变化情况

由 clock 信号变化可以看出时钟周期为 2 ps

测试中循环执行了 50000 次 step(5) ,即 250000 个时钟周期,输出的波形图总时长为 500001 ps ,除去半个用于 reset 的时钟周期之外恰好 250000 个时钟周期。

可以看到波形图中除了 clock 信号有规律的周期性变化之外, io_rx 也在周期性地在 0 和 1 之间变化。从波形图也可以看出每 10 ps 即 5 个时钟周期 io_rx 变化一次,符合 step(5) 一次 c.io.rx.poke((i % 2).U) 一次的变化规律。

# ExecuteTest

src/test/scala/riscv/singlecycle/ExecuteTest.scala

avatar

# 测试用例的功能

该测试用例用于检查 Execute 模块的正确性,包括:

# 执行 ALU 加法运算

测试程序循环执行了 100 次两个随机生成的 int 整型操作数 op1 和 op2 的求和运算,检查 R 型指令 add 的正确性。

同时检查跳转信号是否始终保持 0 (fasle),确保 CPU 在非跳转指令下不跳转

# 处理 beq 指令是否跳转

测试程序按顺序测试了两个情况:

跳转,即 op1 等于 op2 ,此时跳转信号应该为 1 (true),原指令地址 (PC):2 应该与立即数 2 相加得到新的指令地址 (PC):4

不跳转,即 op1 不等于 op2 ,此时跳转信号应该为 0 (false),指令地址 (PC) 保持 4 不变

# 从什么层面测试 CPU

从 CPU 运算处理的层面测试 CPU ,即能否正确控制 ALU 的输入输出,以及输入输出结果对指令跳转的控制

# 加载测试程序的方法

利用定义在 src/main/scala/riscv/core/Execute.scala 中的模块 Execute ,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

# ALU 加法运算

总共执行了 102 个时钟周期,测试了 101 次随机样例 (循环从 i=0 到 i=100 执行了 101 次)。

avatar

# io_funct3[2:0]

该信号始终保持 000B 不变,与 io_opcode 一起指示 ALU 执行 R 类型指令 add 的加法运算

# io_opcode[6:0]

该信号始终保持 0110011B 不变,与 io_funct3 一起指示 ALU 执行 R 类型指令 add 的加法运算

avatar

# io_alu_funct[3:0]

按照 src/main/scala/riscv/core/ALU.scala 定义的 ChiselEnum 枚举类型如下:

avatar

由于总共有 11 种取值,默认从 0 开始计数直到 10 ,需要二进制 4 位数才能表示,因此对应的 io_alu_funct 为 4 位二进制数

在加法运算时该信号始终保持 0001B 不变,对应 ChiselEnu 类型定义的 ALUFunctions 中从 0 开始计数的第二个 add,指示 ALU 执行加法运算

# io_op1[31:0]

该信号来自 c.io.reg1_data.poke(op1.U) ,在 add 指令中 ALU 的运算操作数 op1 来自寄存器,因此 Execute 模块的 io_reg1_data 直接传递给 ALU 模块的 io_op1

每隔一个时钟周期 (2 ps) 变化一次,每次均为一个新的随机 int 型整数

# io_op2[31:0]

该信号来自 c.io.reg2_data.poke(op1.U) ,在 add 指令中 ALU 的运算操作数 op2 来自寄存器,因此 Execute 模块的 io_reg2_data 直接传递给 ALU 模块的 io_op2

每隔一个时钟周期 (2 ps) 变化一次,每次均为一个新的随机 int 型整数

# io_result[31:0]

每隔一个时钟周期 (2 ps) 变化一次,每次均为当前 io_op1 与 io_op2 的算术和,同时该值直接传递给 Execute 模块的 mem_alu_result

# 指令

总共执行 3 个时钟周期,先后测试了成功跳转和不成功跳转两种情况。

avatar

# io_funct3[2:0]

该信号始终保持 000B 不变,与 io_opcode 一起指示 ALU 执行 B 类型指令 beq 的加法运算计算跳转目标地址,以及控制跳转信号 io_if_jump 的产生

# io_opcode[6:0]

该信号始终保持 1100011B 不变,与 io_funct3 一起指示 ALU 执行 B 类型指令 beq 的加法运算计算跳转目标地址,以及控制跳转信号 io_if_jump 的产生

avatar

# io_reg1_data[31:0]

该信号表示所读取的来自寄存器的数据,在 beq 指令中直接将两个寄存器的值进行比较得到跳转信号 io_if_jump

在测试的后 2 个时钟周期内其值均为 9 ,来自测试程序中的 c.io.reg1_data.poke(9.U)

# io_reg2_data[31:0]

该信号表示所读取的来自寄存器的数据,在 beq 指令中直接将两个寄存器的值进行比较得到跳转信号 io_if_jump

在第 2 个时钟周期内其值为 9 ,来自测试程序中的 c.io.reg2_data.poke(9.U)

在第 3 个时钟周期内其值为 19 ,来自测试程序中的 c.io.reg2_data.poke(19.U)

# io_if_jump

该信号表示 PC 下一条指令是否要跳转,是则 io_if_jump = 1 ,否则 io_if_jump = 0

在第 2 个时钟周期其值为 1 ,因为此时 io_reg1_data = 9 = io_reg2_data

在第 3 个时钟周期其值为 0 ,因为此时 io_reg1_data = 9 , io_reg2_data = 19

# io_alu_funct[3:0]

在 beq 指令中,ALU 执行加法运算,io_alu_funct = 1

# alu_io_op1[31:0]

由于 c.io.aluop1_source.poke(1.U) ,aluop1_source = 1 指示该信号 alu_io_op1 来自 instruction_address ,同时 c.io.instruction_address.poke(2.U) ,因此 alu_io_op1 = 2

# alu_io_op2[31:0]

由于 c.io.aluop2_source.poke(1.U) ,aluop2_source = 1 指示该信号 alu_io_op2 来自立即数 io_immediate ,同时 c.io.immediate.poke(2.U) ,因此 alu_io_op2 = 2

# io_if_jump_address[31:0]

表示跳转成功时 PC 跳转的目标指令地址,在 beq 指令中等于 ALU 计算出来的结果 alu_io_result

在 2 个时钟周期内均为 4 ,即 alu_io_op1 与 alu_io_op2 的和

# InstructionDecoderTest

src/test/scala/riscv/singlecycle/InstructionDecoderTest.scala

avatar

# 测试用例的功能

测试了 InstructionDecode 模块的正确性,包括:

# S 型指令

测试了对 S 型指令 sw 翻译的正确性,包括读取正确的寄存器并且将正确的操作数传递给 ALU。

在 S 型指令中,存储的数据来自寄存器,存储目标的内存地址由另一寄存器中的数据和指令中的立即数作为偏移量共同决定。

# lui 指令

测试了对高位加载立即数指令 lui 翻译的正确性,包括读取正确的寄存器并且将正确的操作数传递给 ALU

在 lui 指令中,符号位扩展的 20 位立即数左移 12 位后,将低 12 位置零,传入 ALU,同时 ALU 另一个操作数设置为 0 号寄存器 (内容始终为 0) 的值,即另一个操作数为 0,ALU 做加法运算,相当于将位扩展后的结果直接作为写入的值,写入目标寄存器中

# add 指令

测试了对 R 型指令 add 翻译的正确性,主要测试了是否控制选择寄存器作为 ALU 操作数

# 从什么层面测试 CPU

从指令的翻译、分析层面,指导 CPU 如何根据当前指令进行工作,包括立即数的提取、各个控制信号的取值等

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/core/InstructionDecode.scala 中的模块 InstructionDecode ,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

# S 型指令

总共执行了一个时钟周期 (2 ~ 4 ps),测试了 S 型指令 sw 在 ID 阶段的信号输出

avatar

# io_instruction[31:0]

该信号直接来自 c.io.instruction.poke(00a02223L.U) ,对应二进制码为:0000000 0

avatar

# io_ex_immediate[31:0]

该信号由 io_instruction 的 [11:5] 部分 0000000B 和 [11:7] 部分 00100B 组成 004H ,再位扩展后得到 00000004H = 4,作为立即数传入 ALU

# io_regs_reg1_read_address[4:0]

该信号来自 io_instruction 的 [19:15] 部分,为 00000B,对应 0 号寄存器

# io_regs_reg2_read_address[4:0]

该信号来自 io_instruction 的 [24:20] 部分,为 01010B,对应 10 号寄存器

# io_ex_aluop1_source

在 S 型指令中, io_ex_aluop1_source = 0 ,指示读取寄存器的数据传给 ALU 作为其中一个操作数

# io_ex_aluop2_source

在 S 型指令中, io_ex_aluop2_source = 1 ,指示将立即数 io_ex_immediate 传给 ALU 作为其中一个操作数

# io_memory_read_enable

S 型指令没有读取内存,所以 io_memory_read_enable = 0

# io_memory_write_enable

S 型指令需要写内存,所以 io_memory_write_enable = 1

# lui 指令

总共执行了一个时钟周期 (4 ~ 6 ps),测试了 lui 指令在 ID 阶段的信号输出

avatar

# io_instruction[31:0]

该信号直接来自 c.io.instruction.poke(000022b7L.U) ,对应二进制码为:00000000000000000010 00101 01

avatar

# io_ex_immediate[31:0]

该信号由 io_instruction 的 [31:12] 部分 00002H 位扩展后得到 00002000H = 2,作为立即数传入 ALU

# io_reg_write_address[4:0]

该信号来自 io_instruction 的 [11:7] 部分,其值为 00101 ,对应 5 号寄存器,即结果要写入 5 号寄存器

# io_ex_aluop1_source

在 lui 指令中, io_ex_aluop1_source = 0 ,指示读取寄存器 (0 号寄存器) 的数据 ( 0 ) 传给 ALU 作为其中一个操作数

# io_ex_aluop2_source

在 lui 指令中, io_ex_aluop1_source = 1 ,指示将立即数 io_ex_immediate 传给 ALU 作为其中一个操作数

# io_regs_reg1_read_address[4:0]

在 lui 指令中, 该值被设置为 00000 ,对应 0 号寄存器

# io_reg_write_enable

在 lui 指令中,需要写入寄存器,所以 io_reg_write_enable = 1

# io_wb_reg_write_source[1:0]

在 lui 指令中,写入寄存器的值为 ALU 计算结果,所以 io_wb_reg_write_source 的值为 00 ,指示选择 ALU 输出结果作为写入寄存器的数据源

# io_memory_write_enable

lui 指令没有写内存,所以 io_memory_write_enable = 0 ,避免误写内存

# 指令

总共执行了一个时钟周期 (4 ~ 6 ps),测试了 lui 指令在 ID 阶段的信号输出

avatar

# io_instruction[31:0]

该信号直接来自 c.io.instruction.poke(002081b3L.U) ,对应二进制码为:= 0000000 00010 00001 000 00011 0110011 B ,其中 [6:0] 部分、 [14:12] 部分和 [31:25] 部分一起决定了当前指令为 add 指令;[19:15] 部分和 [24:20] 部分分别为操作数寄存器地址,对应信号 io_regs_reg1_read_address 和 io_regs_reg2_read_address ;[11:7] 部分作为目标寄存器的地址,对应 io_reg_write_address

avatar

# io_reg_write_address[4:0]

该信号来自 io_instruction 的 [11:7] 部分,其值为 00011 ,对应 3 号寄存器,即结果要写入 3 号寄存器

# io_regs_reg1_read_address[4:0]

该信号来自 io_instruction 的 [19:15] 部分,为 00001B,对应 1 号寄存器

# io_regs_reg2_read_address[4:0]

该信号来自 io_instruction 的 [24:20] 部分,为 00010B,对应 2 号寄存器

# io_ex_aluop1_source

在 add 指令中, io_ex_aluop1_source = 0 ,指示读取寄存器的数据传给 ALU 作为其中一个操作数

# io_ex_aluop2_source

在 add 指令中, io_ex_aluop1_source = 0 ,指示读取寄存器的数据传给 ALU 作为其中一个操作数

# io_reg_write_enable

在 add 指令中,需要写入寄存器,所以 io_reg_write_enable = 1

# io_wb_reg_write_source[1:0]

在 add 指令中,写入寄存器的值为 ALU 计算结果,所以 io_wb_reg_write_source 的值为 00 ,指示选择 ALU 输出结果作为写入寄存器的数据源

# io_memory_write_enable

R 型指令 add 没有写内存,所以 io_memory_write_enable = 0 ,避免误写内存

# InstructionFetchTest

src/test/scala/riscv/singlecycle/InstructionFetchTest.scala

avatar

# 测试用例的功能

模拟了 CPU 执行连续的 100 条随机指令时 InstructionFetch 模块能否正确顺序执行指令或跳转

# 从什么层面测试 CPU

从指令取指层面测试 CPU 的正确性

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/core/InstructionFetch.scala 中的模块 InstructionFetch ,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

# 不跳转

avatar

此时 io_jump_flag = 0,指示不跳转,pc 的值每隔一个时钟周期 (2 ps) 就递增 4 ,指令顺序执行

# 跳转

avatar

io_jump_flag = 1 时指示 pc 跳转,pc 的值在 io_jump_flag = 1 出现后的第二个时钟周期被置为跳转目标地址 io_jump_address_id = 00001000H,实现指令跳转

# RegisterFileTest 1 : read the writing content

src/test/scala/riscv/singlecycle/RegisterFileTest.scala

avatar

# 测试用例的功能

测试了写入寄存器操作的时钟周期内目标寄存器内容的变化,即测试了写寄存器功能的正确性

# 从什么层面测试 CPU

从寄存器的读写层面测试了 CPU ,测试了寄存器模块

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/core/RegisterFile.scala 中的模块 RegisterFile ,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

测试总共执行了 2 个时钟周期,第 1 个时钟周期内检测了 2 号寄存器内的值是否为 0 ,即是否为初始状态,同时测试程序模拟了一次写寄存器操作,向 2 号寄存器写入数据 DEADBEEFLH 。在第 2 个时钟周期再次检测 2 号寄存器的值,看其内容是否已经变为写入的数据。在这个过程中始终检测读取 2 号寄存器,所以信号 io_read_address 的内容始终为 2 ;第 1 个时钟周期模拟写入 2 号寄存器的过程,第 2 个时钟周期没有再写入过,所以信号 io_write_address 的内容始终为 2 且 io_write_data 的内容始终为 DEADBEEFLH ;在写寄存器操作后的下一个时钟周期上升沿到来时 register_2 [31:0] 的内容变为 DEADBEEFLH ,表明写寄存器操作正确执行;io_read_data_1 [31:0] 的值在第 2 个时钟周期上升沿到来前为 0 ,在第 2 个时钟周期上升沿到来时变为 DEADBEEFLH

# RegisterFileTest 2 : read the written content

src/test/scala/riscv/singlecycle/RegisterFileTest.scala

avatar

# 测试用例的功能

测试了写入寄存器操作后的下一个时钟周期能否在目标寄存器读出写入的数据,即测试了写寄存器功能的正确性

# 从什么层面测试 CPU

从寄存器的读写层面测试了 CPU ,测试了寄存器模块

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/core/RegisterFile.scala 中的模块 RegisterFile ,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

测试执行了一个时钟周期,测试程序在一个 timescope 内模拟了一次写入寄存器的操作,将数据 DEADBEEFLH 写入 1 号寄存器,这个过程将 io_write_enable 打开;将 io_write_address 赋值为 1 ,即写入 1 号寄存器;将 io_write_data 赋值为 DEADBEEFLH 。然后在下一个时钟周期模拟测试了能否从 1 号寄存器读出正确的数据,这个测试过程由于没有 clock.step() 所以没有显示在波形图中。但在波形图中可以看到第一个时钟周期后在下一个时钟上升沿到来之前,1 号寄存器的内容 register_1 [31:0] 以及变为了 DEADBEEFLH ,表明写入寄存器操作正确执行。

# RegisterFileTest 3 : x0 always be zero

src/test/scala/riscv/singlecycle/RegisterFileTest.scala

avatar

# 测试用例的功能

测试了写入 0 号寄存器后 0 号寄存器的内容是否保持 0 不变

# 从什么层面测试 CPU

从寄存器的读写层面测试了 CPU ,测试了寄存器模块

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/core/RegisterFile.scala 中的模块 RegisterFile ,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

测试总共执行了一个时钟周期,模拟了将写入目标寄存器设置为 0 号寄存器 x0 时的写寄存器操作。io_write_address = 0 ,表示写入 0 号寄存器;io_write_data = DEADBEEFH ,输入为要写入的数据;io_write_enable = 1 ,打开寄存器写使能;register_0 = 0 始终不变,表明测试成功,0 号寄存器的内容没有被改变始终为 0

# FibonacciTest

src/test/scala/riscv/singlecycle/CPUTest.scala

avatar

csrc/fibonacci.c

avatar

# 测试用例的功能

测试了利用递归方法计算斐波那契数列第 10 项的程序能否在 CPU 上正常执行,并计算出结果存储到内存目标地址上

# 从什么层面测试 CPU

从最终完整执行一个程序的层面测试 CPU ,包括除了中断处理、与外设通信以外的所有 CPU 功能

# 加载测试程序指令的方法

利用定义在 src/test/scala/riscv/singlecycle/CPUTest.scala 中的模块 TestTopModule ,模拟一个简单的计算机,连接了 CPU 、Memory、InstructionRom 、ROMLoader几个模块。用 RISC-V 程序 src/main/resources/fibonacci.asmbin``` 初始化 instruction_rom 模块作为运行程序进行仿真

# 测试用例的执行结果

avatar

# 输出波形图

avatar

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

# 程序指令的执行

为了保证程序完整执行完毕,测试程序循环执行了 50 次 c.clock.step(1000) ,总共执行了 50000 个时钟周期。其中大约前 20 ns 的时间内 CPU 各个信号不断变化,表明程序在执行。此后所有信号稳定,表明程序执行已经结束。

avatar

avatar

从第 279 ps 开始 CPU 的信号开始发生变化,计算斐波那契数列的程序开始执行,到 22299 ps 为止 CPU 的所以信号稳定,表明 CPU 已经执行完毕。

在执行过程中可以看到 io_instruction 信号以 8 ps 为周期变化一次,即 CPU 周期为 8 ps ,相当于 4 个时钟周期。

avatar

寄存器信号中可以发现,在程序运行过程中只有 1、2、8、10、11 号寄存器不断发生变化,也即程序只使用了除 0 号寄存器以外 5 个寄存器。

# 程序结果的检测

在 csrc/fibonacci.c 程序中可以看到,最终计算结果为斐波那契数列第 10 项,结果存储在地址为 4 的内存空间里。程序结果的检测执行了一个时钟周期

avatar

# io_mem_debug_read_address[31:0]

该信号直接来自 c.io.mem_debug_read_address.poke(4.U) ,表示检测读取的内存地址为 4

# io_mem_debug_read_data[31:0]

一个时钟周期后读取内存地址为 4 的内容得到该信号的值为 00000037H = 55 ,表明程序结果正确

# QuicksortTest

src/test/scala/riscv/singlecycle/CPUTest.scala

avatar

csrc/quicksort.c

avatar

# 测试用例的功能

测试程序给出了一个由 10 个阿拉伯数字组成的数组: {6,2,4,5,3,1,0,9,7,8} ,利用递归实现的 quicksort 函数对该数组进行排序,检测是否得到一个正确的有序数组

# 从什么层面测试 CPU

从最终完整执行一个程序的层面测试 CPU ,包括除了中断处理、与外设通信以外的所有 CPU 功能

# 加载测试程序指令的方法

利用定义在 src/test/scala/riscv/singlecycle/CPUTest.scala 中的模块 TestTopModule ,模拟一个简单的计算机,连接了 CPU 、Memory、InstructionRom 、ROMLoader 几个模块。用 RISC-V 程序 src/main/resources/quicksort.asmbin 初始化进行仿真

# 测试用例的执行结果

avatar

# 输出波形图

avatar

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

# 程序指令的执行

为了保证程序完整执行完毕,测试程序循环执行了 50 次 c.clock.step(1000) ,总共执行了 50000 个时钟周期。其中大约前 15 ns 的时间内 CPU 各个信号不断变化,表明程序在执行。此后所有信号稳定,表明程序执行已经结束。

avatar

avatar

从第 525 ps 开始 CPU 的信号开始发生变化,快排程序开始执行,到 13931 ps 为止 CPU 的所以信号稳定,表明 CPU 已经执行完毕。

在执行过程中可以看到 io_instruction 信号以 8 ps 为周期变化一次,即 CPU 周期为 8 ps ,相当于 4 个时钟周期。

avatar

寄存器信号中可以发现,在程序运行过程中只有 1、2、8、10、11 、12 号寄存器不断发生变化,也即程序只使用了除 0 号寄存器以外 6 个寄存器。其中 1、2、8、12 号寄存器的变化呈现较同步的规律,说明这 4 个寄存器中的数据与递归有关;而 10、11 号寄存器的内容总是在频繁变化,说明这两个寄存器主要用来存储 ALU 运算的操作数

# 程序结果的检测

在 csrc/quicksort.c 程序中可以看到,排列得到的结果,结果存储在起始地址为 4 ,长度为 10 个 int 类型大小的内存空间里。程序结果的检测执行了 10 个时钟周期,利用循环程序对检测的内存地址递增,逐个访问目标内存,看所存储的内容是否上是从 0 到 9 的升序排列数组

avatar

# io_mem_debug_read_address[31:0]

该信号直接来自 c.io.mem_debug_read_address.poke((4*i).U)i 从 1 到 10 递增, 4*i 从 4 到 40 变化,即检测读取的内存地址从 00000004H 到 00000028H 变化

# io_mem_debug_read_data[31:0]

内存地址从 00000004H 到 00000028H 变化的同时 io_mem_debug_read_data 读取内存的内容也从 0 到 9 变化,表明程序结果正确

# ByteAccessTest

src/test/scala/riscv/singlecycle/CPUTest.scala

avatar

csrc/sb.S

avatar

# 测试用例的功能

在 RISCV 手册第 30 页可以查到寄存器编号即助记名如下:

avatar

对测试使用的 RISCV 汇编代码具体解释如下:

RISCV汇编
.globl _start 			;声明_start为全局符号
	_start:         	;程序从这里开始执行
	li a0, 0x4      	;将立即数 0x4 加载到寄存器 a0 (x10)
	li t0, 0xDEADBEEF ;将立即数 0xDEADBEEF 加载到寄存器 t0(x5)
	sb t0, 0(a0)    	;将寄存器 t0(x5) 的值存储到地址为 a0(x10) 的内存位置中
	lw t1, 0(a0)    	;将地址为 a0(x10) 的内存位置中的值加载到寄存器 t1(x6)
	li s2, 0x15    		;将立即数 0x15 加载到寄存器 s2(x18)
	sb s2, 1(a0)   		;将寄存器 s2(x18) 的值存储到地址为 (a0+1) 的内存位置中
	lw ra, 0(a0)    	;将地址为 a0(x10) 的内存位置中的值加载到寄存器 ra(x1)
loop:           		;循环的标签
	j loop          	;无条件地跳转到标签 loop,实现无限循环

# 从什么层面测试 CPU

从指令的层面测试 CPU ,测试了 CPU 对若干连续的 S 型和 L 型指令能否正确执行。主要检测了执行指令读写寄存器功能是否正确

# 加载测试程序指令的方法

利用定义在 src/test/scala/riscv/singlecycle/CPUTest.scala 中的模块 TestTopModule ,模拟一个简单的计算机,连接了 CPU 、Memory、InstructionRom 、ROMLoader 几个模块。用 RISC-V 程序 src/main/resources/sb.asmbin 初始化进行仿真

# 测试用例的执行结果

avatar

# 输出波形图

avatar

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

上图中可以看到有 5 个寄存器的值发生了变化:

register_10 [31:0] 即 10 号寄存器 x10 或 a0 ,由 li a0, 0x4 赋值后信号稳定为 4

register_5 [31:0] 即 5 号寄存器 x5 或 t0 ,由 li t0, 0xDEADBEEF 赋值时,由于寄存器写使能信号 io_reg_write_enable 此时仍保持打开的,因为上一条指令 li a0, 0x4 执行时也打开了寄存器写使能,所以此时写入目标寄存器 5 号寄存器的内容出现了毛刺 DEADC000H ,但在下一个时钟周期恢复正确值 DEADBEEFH 并稳定

register_6 [31:0] 即 6 号寄存器 x6 或 t1 ,由 lw t1, 0(a0) 赋值后信号稳定。内存地址 DEADBEEFH 的内容由 sb t0, 0(a0) 赋值,而 sb 指令存储时只存低位字节,且 RISCV 为小端存储模式,所以存入内存的只有 EFH ,读取内存时 EFH 即为最低位字节,存到 6 号寄存器的内容为 000000EFH

register_18 [31:0] 即 18 号寄存器 x18 或 s2 ,由 li s2, 0x15 赋值后信号稳定为 15H

register_1 [31:0] 即 1 号寄存器 x1 或 ra,由 lw ra, 0(a0) 赋值后信号稳定。内存地址 DEADBEEFH 的内容原本只有只有 EFH ,sb s2, 1 (a0) 再次对该地址赋值,而 sb 指令存储时只存低位字节,按照 RISCV 的小端存储模式,此时存入内存的只有 15H ,且存到 DEADBEEFH +1 的地址,即存到 EFH 的下一个地址。读取内存时字节从低到高为 EFH、15H ,存到 1 号寄存器的内容为 000015EFH

测试程序检测了 ,与波形图对应寄存器内容的信号最后稳定的值相同,表明指令正确执行

# 填空涉及到的信号分析

(src/main/scala/riscv/)

# core/InstructionFetch.scala

# io.jump_flag_id

该控制信号告诉 CPU 取指阶段下一条指令是否需要跳转,如果是则将 PC 设置为跳转目标指令地址,否则 PC+4,下一个时钟周期顺序读取下一条指令

# core/InstructionDecode.scala

# io.ex_aluop2_source

改控制信号控制 ALU 输入端的第二个输入源,分别有以下两种:

avatar

ALUOp2Source.Immediate:
将 io.ex_aluop2_source 设置为该值后 ALU 输入端端第二个输入源是来自指令的立即数

ALUOp2Source.Register:
将 io.ex_aluop2_source 设置为该值后 ALU 输入端端第二个输入源是读取寄存器得到的数据

avatar

根据以上 RISC-V 手册第 25 页指令译码过程可以知道,需要使用到立即数的指令有:

  • U 型指令
    • lui
    • auipc
  • J 型指令
    • jal
    • jalr
  • I 型指令
  • L 型指令
  • B 型指令
  • 其他
    • fence 同步内存和 I/O
    • CSR 型指令
    • nop 伪指令

因此当执行上述指令时,将 io.ex_aluop2_source 设置为 ALUOp2Source.Immediate

# io.memory_read_enable

RISCV 中只有 L 型指令需要读取内存,所以执行 L 型指令时将 io.memory_read_enable 设置为 1,否则均设置为 0

# io.memory_write_enable

RISCV 中只有 S 型指令需要写内存,所以执行 S 型指令时将 io.memory_write_enable 设置为 1,否则均设置为 0

# io.wb_reg_write_source

查阅手册各个指令的功能可知,需要写回寄存器的指令及其对应写入数据源如下:

  • R 型指令:ALU 计算结果
  • U 型指令
    • lui:ALU 计算结果
    • auipc:ALU 计算结果
  • I 型指令:ALU 计算结果
  • L 型指令:内存
  • 其他
    • nop 伪指令:ALU 计算结果

不考虑中断的 CSR 作为写入数据源,其余指令均可设置 io.wb_reg_write_source 为 NextInstructionAddress (作为默认值)

# core/Execute.scala

# alu.io.func

该信号传给 ALU ,决定 ALU 执行何种运算,实际上该信号的取值为 src/main/scala/riscv/core/ALU.scala 定义的 ChiselEnum 枚举类型,在 “ alu.io.func

# alu.io.op1

该信号传给 ALU,决定 ALU 的第一个操作数的数据源为 PC 还是寄存器。其控制已在 InstructionDecode 模块实现,其传入 Execute 模块的信号为 io.aluop1_source ,根据该信号即可确定 alu.io.op1

# alu.io.op2

该信号传给 ALU,决定 ALU 的第一个操作数的数据源为立即数还是寄存器。其控制已在 InstructionDecode 模块实现,其传入 Execute 模块的信号为 io.aluop2_source ,根据该信号即可确定 alu.io.op2

# core/CPU.scala

所填代码主要涉及传递给 Execute 模块的信号,各个赋值语句对应了连线图的控制信号连线、模块之间的端口的连接

# ex.io.instruction := inst_fetch.io.instruction

取指阶段得到的指令传递给 Execute 模块

# ex.io.instruction_address := inst_fetch.io.instruction_address

取指阶段得到的指令地址传递给 Execute 模块

# ex.io.reg1_data := regs.io.read_data1

寄存器组将读取的第 1 个数据传递给 Execute 模块

# ex.io.reg2_data := regs.io.read_data2

寄存器组将读取的第 2 个数据传递给 Execute 模块

# ex.io.immediate := id.io.ex_immediate

译码阶段得到的立即数传递给 Execute 模块

# ex.io.aluop1_source := id.io.ex_aluop1_source

译码阶段得到的 ALU 第 1 个操作数的数据源的控制信号传递给 Execute 模块

# ex.io.aluop2_source := id.io.ex_aluop2_source

译码阶段得到的 ALU 第 2 个操作数的数据源的控制信号传递给 Execute 模块

# 在完成实验的过程中,遇到的关于实验指导不明确或者其他问题,或者改进的建议。

使用实验板上的数码管、视频输出等外设,输出一个完整程序的运行结果,或者参考硬件调试一节的内容,用硬件波形的方法捕获程序运行结果。给出你的 CPU 可以正确在实验板上运行程序的照片或者硬件调试器波形截图。

\ No newline at end of file diff --git a/cs/principles-of-computer-composition/yatcpu/lab-reports/lab2/index.html b/cs/principles-of-computer-composition/yatcpu/lab-reports/lab2/index.html index cf4f953a..72133271 100644 --- a/cs/principles-of-computer-composition/yatcpu/lab-reports/lab2/index.html +++ b/cs/principles-of-computer-composition/yatcpu/lab-reports/lab2/index.html @@ -1 +1 @@ -lab2 - YatCPU - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

YatCPU - - - lab1 - - - lab2 - - - lab3 - - - lab4

# 测试用例及其波形图分析

# BoardSayGoodbyeTest

src/test/scala/riscv/BoardTest.scala

avatar

其中 Top 模块来自:

avatar

测试执行程序来自 csrc/say_goodbye.c :

avatar

# 测试用例的功能

测试能否正常执行打印 "Never gonna give you up~ Never gonna let you down~\nNever gonna run around and~ desert you~" ,用于烧板后测试能否实现打印,即测试 CPU 包括 lab1 的功能以及能否实现中断处理

# 从什么层面测试 CPU

从完整性的层面测试 CPU ,若 CPU 可以打印,说明 CPU 具备了中断处理的能力

但并没有测试 CPU 的正确性,只是进行了 pokestep ,但没有对任何信号进行 expect 检查。实际验证需要烧板手动测试能否打印。

# 加载测试程序的方法

利用定义在 src/main/scala/board/z710/Top.scala 中的模块 Top ,用 RISC-V 程序 src/main/resources/say_goodbye.asmbin 初始化进行仿真

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

由 clock 信号变化可以看出时钟周期为 2 ps

测试中循环执行了 200 次 step(1000) ,即 200000 个时钟周期,输出的波形图总时长为 400001 ps ,除去半个用于 reset 的时钟周期之外恰好 200000 个时钟周期。

波形图中 CPU 内信号一直在不断变化,且按照一定序列无限循环周期变化,说明程序进入了死循环

Timer 模块中的 count 不断自增,但到仿真结束为止页没达到 limit 信号的值 05F5E100H ,所以一直没有进入中断

# ExecuteTest

src/test/scala/riscv/singlecycle/ExecuteTest.scala

avatar

# 测试用例的功能

该测试用例用于检查 Execute 模块的正确性,包括:

# 执行 csrrci 指令

测试指令 csrci ,即立即数读后清除控制状态寄存器 (csr) 指令,测试其是否将控制状态寄存器 csr 的值与按位取反后的 5 位的零扩展立即数 zimm 按位与的结果写入 csr

# 执行 csrrsi 指令

测试指令 csrrsi ,即立即数读后设置控制状态寄存器 (csr) 指令,测试其是否将控制状态寄存器 csr 的值与 5 位的零扩展立即数 zimm 按位或的结果写入 csr

# 执行 csrrw 指令

测试指令 csrrw ,即读后写控制状态寄存器 (csr) 指令,测试其是否将对应寄存器中的值写入 csr

# 执行 csrrs 指令

测试指令 csrrs ,即读后置位控制状态寄存器 (csr) 指令,测试其是否将控制状态寄存器 csr 的值与对应寄存器中的值按位或的结果写入 csr

# 从什么层面测试 CPU

从 CPU 执行处理层面测试了 CPU,主要测试这个阶段对中断相关的 csr 指令的执行处理

# 加载测试程序的方法

利用定义在 src/main/scala/riscv/core/Execute.scala 中的模块 Execute ,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

测试主要使用了下图中的指令:

avatar

# 指令

测试执行了 1 个时钟周期

# io_funct3[2:0]

该信号为 111B ,与 io_opcode 一起指示 ALU 执行 CPU 执行 csr 类型指令 csrrci

# io_opcode[6:0]

该信号为 1110011B ,与 io_funct3 一起指示 CPU 执行 csr 类型指令 csrrci

# zimm[31:0]

零扩展的 5 位立即数,来自指令,值为 8

# io_reg1_data[31:0]

从寄存器读取的值,直接来自 c.io.reg1_data.poke(0x1880L.U) ,值为 1880H

# io_csr_reg_read_data[31:0]

从 csr 寄存器读取的值,直接来自 c.io.csr_reg_data.poke(0x1888L.U) ,值为 1888H

# io_csr_reg_write_data[31:0]

写入 csr 寄存器的值,在 csrrci 指令中该值等于 io_csr_reg_read_data & ~zimm ,结果为 1880H ,与波形图结果一致,说明执行正确

# 指令

测试执行了 1 个时钟周期

# io_funct3[2:0]

该信号为 110B ,与 io_opcode 一起指示 ALU 执行 CPU 执行 csr 类型指令 csrrsi

# io_opcode[6:0]

该信号为 1110011B ,与 io_funct3 一起指示 CPU 执行 csr 类型指令 csrrsi

# zimm[31:0]

零扩展的 5 位立即数,来自指令,值为 8

# io_reg1_data[31:0]

从寄存器读取的值,直接来自 c.io.reg1_data.poke(0x1880L.U) ,值为 1880H

# io_csr_reg_read_data[31:0]

从 csr 寄存器读取的值,直接来自 c.io.csr_reg_data.poke(0x1880L.U) ,值为 1880H

# io_csr_reg_write_data[31:0]

写入 csr 寄存器的值,在 csrrsi 指令中该值等于 io_csr_reg_read_data | zimm ,结果为 1880H ,与波形图结果一致,说明执行正确

# 指令

测试执行了 1 个时钟周期

# io_funct3[2:0]

该信号为 001B ,与 io_opcode 一起指示 ALU 执行 CPU 执行 csr 类型指令 csrrsw

# io_opcode[6:0]

该信号为 1110011B ,与 io_funct3 一起指示 CPU 执行 csr 类型指令 csrrsw

# zimm[31:0]

零扩展的 5 位立即数,来自指令,值为 AH

# io_reg1_data[31:0]

从寄存器读取的值,直接来自 c.io.reg1_data.poke(0x1888L.U) ,值为 1888H

# io_csr_reg_read_data[31:0]

从 csr 寄存器读取的值,直接来自 c.io.csr_reg_data.poke(0.U) ,值为 0

# io_csr_reg_write_data[31:0]

写入 csr 寄存器的值,在 csrrsi 指令中该值等于 io_reg1_data ,结果为 1888H ,与波形图结果一致,说明执行正确

# 指令

测试执行了 1 个时钟周期

# io_funct3[2:0]

该信号为 010B ,与 io_opcode 一起指示 ALU 执行 CPU 执行 csr 类型指令 csrrs

# io_opcode[6:0]

该信号为 1110011B ,与 io_funct3 一起指示 CPU 执行 csr 类型指令 csrrs

# zimm[31:0]

零扩展的 5 位立即数,来自指令,值为 0

# io_reg1_data[31:0]

从寄存器读取的值,直接来自 c.io.reg1_data.poke(0.U) ,值为 0

# io_csr_reg_read_data[31:0]

从 csr 寄存器读取的值,直接来自 c.io.csr_reg_data.poke(0x1888L.U) ,值为 1888H

# io_csr_reg_write_data[31:0]

写入 csr 寄存器的值,在 csrrs 指令中该值等于 io_csr_reg_read_data | io_reg1_data ,结果为 1888H ,与波形图结果一致,说明执行正确

# CLINTCSRTest

src/test/scala/riscv/singlecycle/CLINTCSRTest.scala

avatar

avatar

# 测试用例的功能

测试了 CLINT 模块和 CSR 模块的正确性,测试了以下几种情况:

# 无跳转的情况下处理中断请求

此时应该进入中断:

  • 将 PC 设为中断处理程序入口
  • 写入 CSR 寄存器
    • 将 MIE 置 0
    • 将 PC 的值存入 MEPC ,实际上为中断发生的指令的下一条指令的地址
    • 写入恰当的中断原因存入 MCAUSE

# 跳转的情况下处理中断请求

此时应该进入中断,处理与上一种情况相同,但是存入 MEPC 的值不是 PC 而是跳转目标地址

# 退出中断

  • 将 PC 设为 MEPC
  • 写入 CSR 寄存器
    • 将 MIE 置为 MPIE

# 不响应中断

当 MPIE 位为 0 时,禁用中断

# 从什么层面测试 CPU

从中断处理层面测试,主要测试对不同情况 CPU 能否正确决定是否响应中断、响应中断时是否正确处理中断、能否正确退出中断

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/core/CLINT.scala 中的模块 CLINT 和定义在 src/main/scala/riscv/core/CSR.scala 中的模块 CSR ,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

# 无跳转的情况下处理中断请求

avatar

# io_interrupt_assert

该信号决定 PC 是否跳转,在输入的 interrupt_flag 信号拉高的同时也拉高,表示进入中断,跳转到中断处理程序

# io_interrupt_handler_address[31:0]

该信号在输入的 interrupt_flag 信号拉高的同时变为 00001144H ,表示中断处理程序入口地址,从下一条指令开始进入中断

# mepc[31:0]

该信号在进入中断后的下一时钟周期变为 1904H ,等于原 PC 值 1900H + 4 ,表示原本 PC 所在指令的下一条指令地址

# mcause[31:0]

该信号主要由引起中断的 io.interrupt_flag 信号决定,在进入中断后的下一时钟周期变为 80000007H ,表示 timer 引起中断

# mstatus[31:0]

该信号在进入中断后的下一时钟周期由 00001888H 变为 00001880H ,表示 MPIE 被置 0 ,禁用中断

# 退出中断

avatar

# io_interrupt_assert

该信号决定 PC 是否跳转,在输入的 io_instruction 变为 30200073H 的同时拉高,即遇到 mret 信号拉高,表示退出中断,跳转到中断前原程序

# io_interrupt_handler_address[31:0]

该信号在退出中断的同时保持 00001904H 不变,为 PC 跳转提供目标地址

# mstatus[31:0]

该信号在退出中断后的下一时钟周期由 00001880H 变为 00001888H ,表示 MPIE 被置 1 ,启用中断

# 跳转的情况下处理中断请求

avatar

# io_interrupt_assert

在输入的 interrupt_flag 信号拉高的同时也高,表示进入中断,跳转到中断处理程序

由于上一个时钟周期控制器在退出中断,所以上一个时钟周期 PC 也发生跳转,该信号也为 1 ,所以波形图中表现为连续高电位

# io_interrupt_handler_address[31:0]

该信号在输入的 interrupt_flag 信号拉高的同时变为 00001144H ,表示中断处理程序入口地址,从下一条指令开始进入中断

# mepc[31:0]

该信号在进入中断后的下一时钟周期变为 1990H ,等于原跳转指令对应的跳转目标地址,表示原本 PC 所在指令所要跳转的指令地址

# mcause[31:0]

该信号主要由引起中断的 io.interrupt_flag 信号决定,在进入中断后的下一时钟周期变为 8000000BH ,表示外部引起中断

# mstatus[31:0]

该信号在进入中断后的下一时钟周期由 00001888H 变为 00001880H ,表示 MPIE 被置 0 ,禁用中断

# 退出中断

再次退出中断,与 情况一致

# 不响应中断

原本测试程序无法显示该处波形,需要加一条 c.clock.step() 才能显示出波形

avatar

# io_clint_access_bundle_mstatus[31:0]

该信号由 c.io.csr_regs_write_data.poke(0x1880L.U) 输入,表示写入 mstatus 的值。其中低位第三位为 0 ,即 MPIE = 0 ,禁用中断

# interrupt_enable

在输入的 io_clint_access_bundle_mstatus 信号变为 1880H 的同时拉低,表示禁用中断

# io_interrupt_flag[31:0]

由输入 c.io.interrupt_flag.poke(1.U) 拉高该信号,表示中断请求

# io_interrupt_assert

io_interrupt_flag 拉高的同时,该信号为低电位,表示拒绝中断请求

# TimerTest

src/test/scala/riscv/singlecycle/TimerTest.scala

avatar

# 测试用例的功能

测试了 Timer 模块能否正确处理信号

# 写 limit

检测 Timer 模块能否实现正确的写入到 limit 变量操作

# 写 enabled

检测 Timer 模块能否实现正确的写入到 enabled 变量操作,以及根据变量输出正确的中断信号

# 从什么层面测试 CPU

从外围设备层面测试 CPU 的正确性,准确来说测试 peripheral 设备 Timer 的正确性

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/core/peripheral/Timer.scala 中的模块 Timer,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

# limit

io_bundle_write_data 变为 00990315H 时,io_bundkle_address 值为 4,表示写入 limit 的地址,写入数据为 00990315 , limit 的值也在写入操作的下一个时钟周期由初始值变为 00990315H ,可见写操作正确执行

# enabled

io_bundle_write_data 变为 0 时,io_bundkle_address 值为 8,表示写入 enable 的地址,写入数据为 0 ,enabled 信号关闭不允许启用中断,enabled 的值也在写入操作的下一个时钟周期由 1 变为 0 ,可见写操作正确执行

# SimpleTrapTest

src/test/scala/riscv/singlecycle/SimpleTrapTest.scala

avatar

csrc/simpletest.c

avatar

# 测试用例的功能

测试了 CPU 能否完整的运行一个中断处理程序,并退出中断

# 从什么层面测试 CPU

从 CPU 整体功能层面测试了 CPU ,测试了 CPU 处理自陷的功能

# 加载测试程序指令的方法

利用定义在 src/test/scala/riscv/singlecycle/CPUTest.scala 中的模块 TestTopModule ,模拟一个简单的计算机,连接了 CPU 、Memory、InstructionRom 、ROMLoader 几个模块。用 RISC-V 程序 src/main/resources/simpletest.asmbin 初始化进行仿真

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

测试总共执行了 2007 个时钟周期,在前 1000 多个时钟周期测试了 simpletest.asmbin 的程序,即将数据 DEADBEEFH 存到内存地址为 4 的内存空间。后 1000 多个时钟周期产生了一个中断请求信号,完整执行了一遍 simpletest.asmbin 自定义的中断处理程序。中断处理程序将数据 2022 重新写入内存地址为 4 的内存空间覆盖原来的数据,因此测试程序最后从该地址读取的数据为 2022 ,表明中断处理程序正确执行

波形图表现为前后两段信号不断变化的区间,分别代表 simpletest.asmbin 的 main 函数程序和中断处理程序 trap_handler 的执行。由波形图可见中断处理程序结束后顺利退出了中断

# 填空涉及到的信号分析

(src/main/scala/riscv/)

主要在填空代码处以注释的形式进行了分析

# 在完成实验的过程中,遇到的关于实验指导不明确或者其他问题,或者改进的建议。

使用实验板上的数码管、视频输出等外设,输出一个完整程序的运行结果,或者参考硬件调试一节的内容,用硬件波形的方法捕获程序运行结果。给出你的 CPU 可以正确在实验板上运行程序的照片或者硬件调试器波形截图。

\ No newline at end of file +lab2 - YatCPU - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

YatCPU - - - lab1 - - - lab2 - - - lab3 - - - lab4

# 测试用例及其波形图分析

# BoardSayGoodbyeTest

src/test/scala/riscv/BoardTest.scala

avatar

其中 Top 模块来自:

avatar

测试执行程序来自 csrc/say_goodbye.c :

avatar

# 测试用例的功能

测试能否正常执行打印 "Never gonna give you up~ Never gonna let you down~\nNever gonna run around and~ desert you~" ,用于烧板后测试能否实现打印,即测试 CPU 包括 lab1 的功能以及能否实现中断处理

# 从什么层面测试 CPU

从完整性的层面测试 CPU ,若 CPU 可以打印,说明 CPU 具备了中断处理的能力

但并没有测试 CPU 的正确性,只是进行了 pokestep ,但没有对任何信号进行 expect 检查。实际验证需要烧板手动测试能否打印。

# 加载测试程序的方法

利用定义在 src/main/scala/board/z710/Top.scala 中的模块 Top ,用 RISC-V 程序 src/main/resources/say_goodbye.asmbin 初始化进行仿真

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

由 clock 信号变化可以看出时钟周期为 2 ps

测试中循环执行了 200 次 step(1000) ,即 200000 个时钟周期,输出的波形图总时长为 400001 ps ,除去半个用于 reset 的时钟周期之外恰好 200000 个时钟周期。

波形图中 CPU 内信号一直在不断变化,且按照一定序列无限循环周期变化,说明程序进入了死循环

Timer 模块中的 count 不断自增,但到仿真结束为止页没达到 limit 信号的值 05F5E100H ,所以一直没有进入中断

# ExecuteTest

src/test/scala/riscv/singlecycle/ExecuteTest.scala

avatar

# 测试用例的功能

该测试用例用于检查 Execute 模块的正确性,包括:

# 执行 csrrci 指令

测试指令 csrci ,即立即数读后清除控制状态寄存器 (csr) 指令,测试其是否将控制状态寄存器 csr 的值与按位取反后的 5 位的零扩展立即数 zimm 按位与的结果写入 csr

# 执行 csrrsi 指令

测试指令 csrrsi ,即立即数读后设置控制状态寄存器 (csr) 指令,测试其是否将控制状态寄存器 csr 的值与 5 位的零扩展立即数 zimm 按位或的结果写入 csr

# 执行 csrrw 指令

测试指令 csrrw ,即读后写控制状态寄存器 (csr) 指令,测试其是否将对应寄存器中的值写入 csr

# 执行 csrrs 指令

测试指令 csrrs ,即读后置位控制状态寄存器 (csr) 指令,测试其是否将控制状态寄存器 csr 的值与对应寄存器中的值按位或的结果写入 csr

# 从什么层面测试 CPU

从 CPU 执行处理层面测试了 CPU,主要测试这个阶段对中断相关的 csr 指令的执行处理

# 加载测试程序的方法

利用定义在 src/main/scala/riscv/core/Execute.scala 中的模块 Execute ,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

测试主要使用了下图中的指令:

avatar

# 指令

测试执行了 1 个时钟周期

# io_funct3[2:0]

该信号为 111B ,与 io_opcode 一起指示 ALU 执行 CPU 执行 csr 类型指令 csrrci

# io_opcode[6:0]

该信号为 1110011B ,与 io_funct3 一起指示 CPU 执行 csr 类型指令 csrrci

# zimm[31:0]

零扩展的 5 位立即数,来自指令,值为 8

# io_reg1_data[31:0]

从寄存器读取的值,直接来自 c.io.reg1_data.poke(0x1880L.U) ,值为 1880H

# io_csr_reg_read_data[31:0]

从 csr 寄存器读取的值,直接来自 c.io.csr_reg_data.poke(0x1888L.U) ,值为 1888H

# io_csr_reg_write_data[31:0]

写入 csr 寄存器的值,在 csrrci 指令中该值等于 io_csr_reg_read_data & ~zimm ,结果为 1880H ,与波形图结果一致,说明执行正确

# 指令

测试执行了 1 个时钟周期

# io_funct3[2:0]

该信号为 110B ,与 io_opcode 一起指示 ALU 执行 CPU 执行 csr 类型指令 csrrsi

# io_opcode[6:0]

该信号为 1110011B ,与 io_funct3 一起指示 CPU 执行 csr 类型指令 csrrsi

# zimm[31:0]

零扩展的 5 位立即数,来自指令,值为 8

# io_reg1_data[31:0]

从寄存器读取的值,直接来自 c.io.reg1_data.poke(0x1880L.U) ,值为 1880H

# io_csr_reg_read_data[31:0]

从 csr 寄存器读取的值,直接来自 c.io.csr_reg_data.poke(0x1880L.U) ,值为 1880H

# io_csr_reg_write_data[31:0]

写入 csr 寄存器的值,在 csrrsi 指令中该值等于 io_csr_reg_read_data | zimm ,结果为 1880H ,与波形图结果一致,说明执行正确

# 指令

测试执行了 1 个时钟周期

# io_funct3[2:0]

该信号为 001B ,与 io_opcode 一起指示 ALU 执行 CPU 执行 csr 类型指令 csrrsw

# io_opcode[6:0]

该信号为 1110011B ,与 io_funct3 一起指示 CPU 执行 csr 类型指令 csrrsw

# zimm[31:0]

零扩展的 5 位立即数,来自指令,值为 AH

# io_reg1_data[31:0]

从寄存器读取的值,直接来自 c.io.reg1_data.poke(0x1888L.U) ,值为 1888H

# io_csr_reg_read_data[31:0]

从 csr 寄存器读取的值,直接来自 c.io.csr_reg_data.poke(0.U) ,值为 0

# io_csr_reg_write_data[31:0]

写入 csr 寄存器的值,在 csrrsi 指令中该值等于 io_reg1_data ,结果为 1888H ,与波形图结果一致,说明执行正确

# 指令

测试执行了 1 个时钟周期

# io_funct3[2:0]

该信号为 010B ,与 io_opcode 一起指示 ALU 执行 CPU 执行 csr 类型指令 csrrs

# io_opcode[6:0]

该信号为 1110011B ,与 io_funct3 一起指示 CPU 执行 csr 类型指令 csrrs

# zimm[31:0]

零扩展的 5 位立即数,来自指令,值为 0

# io_reg1_data[31:0]

从寄存器读取的值,直接来自 c.io.reg1_data.poke(0.U) ,值为 0

# io_csr_reg_read_data[31:0]

从 csr 寄存器读取的值,直接来自 c.io.csr_reg_data.poke(0x1888L.U) ,值为 1888H

# io_csr_reg_write_data[31:0]

写入 csr 寄存器的值,在 csrrs 指令中该值等于 io_csr_reg_read_data | io_reg1_data ,结果为 1888H ,与波形图结果一致,说明执行正确

# CLINTCSRTest

src/test/scala/riscv/singlecycle/CLINTCSRTest.scala

avatar

avatar

# 测试用例的功能

测试了 CLINT 模块和 CSR 模块的正确性,测试了以下几种情况:

# 无跳转的情况下处理中断请求

此时应该进入中断:

  • 将 PC 设为中断处理程序入口
  • 写入 CSR 寄存器
    • 将 MIE 置 0
    • 将 PC 的值存入 MEPC ,实际上为中断发生的指令的下一条指令的地址
    • 写入恰当的中断原因存入 MCAUSE

# 跳转的情况下处理中断请求

此时应该进入中断,处理与上一种情况相同,但是存入 MEPC 的值不是 PC 而是跳转目标地址

# 退出中断

  • 将 PC 设为 MEPC
  • 写入 CSR 寄存器
    • 将 MIE 置为 MPIE

# 不响应中断

当 MPIE 位为 0 时,禁用中断

# 从什么层面测试 CPU

从中断处理层面测试,主要测试对不同情况 CPU 能否正确决定是否响应中断、响应中断时是否正确处理中断、能否正确退出中断

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/core/CLINT.scala 中的模块 CLINT 和定义在 src/main/scala/riscv/core/CSR.scala 中的模块 CSR ,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

# 无跳转的情况下处理中断请求

avatar

# io_interrupt_assert

该信号决定 PC 是否跳转,在输入的 interrupt_flag 信号拉高的同时也拉高,表示进入中断,跳转到中断处理程序

# io_interrupt_handler_address[31:0]

该信号在输入的 interrupt_flag 信号拉高的同时变为 00001144H ,表示中断处理程序入口地址,从下一条指令开始进入中断

# mepc[31:0]

该信号在进入中断后的下一时钟周期变为 1904H ,等于原 PC 值 1900H + 4 ,表示原本 PC 所在指令的下一条指令地址

# mcause[31:0]

该信号主要由引起中断的 io.interrupt_flag 信号决定,在进入中断后的下一时钟周期变为 80000007H ,表示 timer 引起中断

# mstatus[31:0]

该信号在进入中断后的下一时钟周期由 00001888H 变为 00001880H ,表示 MPIE 被置 0 ,禁用中断

# 退出中断

avatar

# io_interrupt_assert

该信号决定 PC 是否跳转,在输入的 io_instruction 变为 30200073H 的同时拉高,即遇到 mret 信号拉高,表示退出中断,跳转到中断前原程序

# io_interrupt_handler_address[31:0]

该信号在退出中断的同时保持 00001904H 不变,为 PC 跳转提供目标地址

# mstatus[31:0]

该信号在退出中断后的下一时钟周期由 00001880H 变为 00001888H ,表示 MPIE 被置 1 ,启用中断

# 跳转的情况下处理中断请求

avatar

# io_interrupt_assert

在输入的 interrupt_flag 信号拉高的同时也高,表示进入中断,跳转到中断处理程序

由于上一个时钟周期控制器在退出中断,所以上一个时钟周期 PC 也发生跳转,该信号也为 1 ,所以波形图中表现为连续高电位

# io_interrupt_handler_address[31:0]

该信号在输入的 interrupt_flag 信号拉高的同时变为 00001144H ,表示中断处理程序入口地址,从下一条指令开始进入中断

# mepc[31:0]

该信号在进入中断后的下一时钟周期变为 1990H ,等于原跳转指令对应的跳转目标地址,表示原本 PC 所在指令所要跳转的指令地址

# mcause[31:0]

该信号主要由引起中断的 io.interrupt_flag 信号决定,在进入中断后的下一时钟周期变为 8000000BH ,表示外部引起中断

# mstatus[31:0]

该信号在进入中断后的下一时钟周期由 00001888H 变为 00001880H ,表示 MPIE 被置 0 ,禁用中断

# 退出中断

再次退出中断,与 情况一致

# 不响应中断

原本测试程序无法显示该处波形,需要加一条 c.clock.step() 才能显示出波形

avatar

# io_clint_access_bundle_mstatus[31:0]

该信号由 c.io.csr_regs_write_data.poke(0x1880L.U) 输入,表示写入 mstatus 的值。其中低位第三位为 0 ,即 MPIE = 0 ,禁用中断

# interrupt_enable

在输入的 io_clint_access_bundle_mstatus 信号变为 1880H 的同时拉低,表示禁用中断

# io_interrupt_flag[31:0]

由输入 c.io.interrupt_flag.poke(1.U) 拉高该信号,表示中断请求

# io_interrupt_assert

io_interrupt_flag 拉高的同时,该信号为低电位,表示拒绝中断请求

# TimerTest

src/test/scala/riscv/singlecycle/TimerTest.scala

avatar

# 测试用例的功能

测试了 Timer 模块能否正确处理信号

# 写 limit

检测 Timer 模块能否实现正确的写入到 limit 变量操作

# 写 enabled

检测 Timer 模块能否实现正确的写入到 enabled 变量操作,以及根据变量输出正确的中断信号

# 从什么层面测试 CPU

从外围设备层面测试 CPU 的正确性,准确来说测试 peripheral 设备 Timer 的正确性

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/core/peripheral/Timer.scala 中的模块 Timer,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

# limit

io_bundle_write_data 变为 00990315H 时,io_bundkle_address 值为 4,表示写入 limit 的地址,写入数据为 00990315 , limit 的值也在写入操作的下一个时钟周期由初始值变为 00990315H ,可见写操作正确执行

# enabled

io_bundle_write_data 变为 0 时,io_bundkle_address 值为 8,表示写入 enable 的地址,写入数据为 0 ,enabled 信号关闭不允许启用中断,enabled 的值也在写入操作的下一个时钟周期由 1 变为 0 ,可见写操作正确执行

# SimpleTrapTest

src/test/scala/riscv/singlecycle/SimpleTrapTest.scala

avatar

csrc/simpletest.c

avatar

# 测试用例的功能

测试了 CPU 能否完整的运行一个中断处理程序,并退出中断

# 从什么层面测试 CPU

从 CPU 整体功能层面测试了 CPU ,测试了 CPU 处理自陷的功能

# 加载测试程序指令的方法

利用定义在 src/test/scala/riscv/singlecycle/CPUTest.scala 中的模块 TestTopModule ,模拟一个简单的计算机,连接了 CPU 、Memory、InstructionRom 、ROMLoader 几个模块。用 RISC-V 程序 src/main/resources/simpletest.asmbin 初始化进行仿真

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

测试总共执行了 2007 个时钟周期,在前 1000 多个时钟周期测试了 simpletest.asmbin 的程序,即将数据 DEADBEEFH 存到内存地址为 4 的内存空间。后 1000 多个时钟周期产生了一个中断请求信号,完整执行了一遍 simpletest.asmbin 自定义的中断处理程序。中断处理程序将数据 2022 重新写入内存地址为 4 的内存空间覆盖原来的数据,因此测试程序最后从该地址读取的数据为 2022 ,表明中断处理程序正确执行

波形图表现为前后两段信号不断变化的区间,分别代表 simpletest.asmbin 的 main 函数程序和中断处理程序 trap_handler 的执行。由波形图可见中断处理程序结束后顺利退出了中断

# 填空涉及到的信号分析

(src/main/scala/riscv/)

主要在填空代码处以注释的形式进行了分析

# 在完成实验的过程中,遇到的关于实验指导不明确或者其他问题,或者改进的建议。

使用实验板上的数码管、视频输出等外设,输出一个完整程序的运行结果,或者参考硬件调试一节的内容,用硬件波形的方法捕获程序运行结果。给出你的 CPU 可以正确在实验板上运行程序的照片或者硬件调试器波形截图。

\ No newline at end of file diff --git a/cs/principles-of-computer-composition/yatcpu/lab-reports/lab3/index.html b/cs/principles-of-computer-composition/yatcpu/lab-reports/lab3/index.html index ada612f2..60426f82 100644 --- a/cs/principles-of-computer-composition/yatcpu/lab-reports/lab3/index.html +++ b/cs/principles-of-computer-composition/yatcpu/lab-reports/lab3/index.html @@ -1 +1 @@ -lab3 - YatCPU - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

YatCPU - - - lab1 - - - lab2 - - - lab3 - - - lab4

# 测试用例及其波形图分析

# SayGoodbyeTest

src/test/scala/riscv/BoardTest.scala

avatar

其中 Top 模块来自:

avatar

测试执行程序来自 csrc/say_goodbye.c :

avatar

# 测试用例的功能

与 lab2 中 BoardSayGoodbyeTest 功能相似

测试能否正常执行打印 "Never gonna give you up~ Never gonna let you down~\nNever gonna run around and~ desert you~" ,用于烧板后测试能否实现打印,即测试 CPU 包括 lab1 的功能以及能否实现中断处理

# 从什么层面测试 CPU

从完整性的层面测试 CPU ,若 CPU 可以打印,说明 CPU 具备了中断处理的能力

但并没有测试 CPU 的正确性,只是进行了 pokestep ,但没有对任何信号进行 expect 检查。实际验证需要烧板手动测试能否打印。

# 加载测试程序的方法

利用定义在 src/main/scala/board/z710/Top.scala 中的模块 Top ,用 RISC-V 程序 src/main/resources/say_goodbye.asmbin 初始化进行仿真

# 测试用例的执行结果

avatar

# 输出波形图

avatar

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

测试中循环执行了 50000 次 step(5) ,即 250000 个时钟周期,输出的波形图总时长为 500001 ps ,除去半个用于 reset 的时钟周期之外恰好 250000 个时钟周期。

由 io_jump_flag 、io_id_flush 、io_if_flush 、io_if_stall 、io_pc_stall 几个信号变化可以看出,CPU 在执行程序过程中较频繁地出现了控制冒险和数据冒险,需要通过阻塞、清除、转发等操作处理

# PipelineRegisterTest

src/test/scala/riscv/PipelineRegisterTest.scala

avatar

# 测试用例的功能

该测试用例用于检查 PipelineRegister 模块的正确性,测试程序模拟了 3 种情况:

# 既不清除也不阻塞

在当前指令既不清除也不阻塞的情况,PipelineRegister 模块应该更新内容

# 阻塞

在当前指令需要阻塞的情况,PipelineRegister 模块应该保持原本内容不变,实现 “暂停”

# 清除

在当前指令需要清除的情况,PipelineRegister 模块的内容应该恢复默认值,默认值代表清除时塞入的 “气泡”,例如:

  • instruction 的默认初始值为 nop
  • instruction_address 的默认初始值为程序入口指令地址

# 从什么层面测试 CPU

从辅助寄存器 PipelineRegister 层面测试了 CPU,主要测试流水线 CPU 不同级之间的寄存器能否实现流水线 CPU 所需要的基本功能

# 加载测试程序的方法

利用定义在 src/main/scala/riscv/core/PipelineRegister.scala 中的模块 PipelineRegister ,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

测试程序模拟了 3 中不同情况,并且重复对三种情况中随机一个进行测试,总共测试了 1000 次,执行了 1000 个时钟周期

# 既不清除也不阻塞

avatar

io_flush = 0 且 io_stall = 0 ,表示既不清除也不阻塞的情况,PipelineRegister 模块应该更新内容,所以存储变量 temp 和输出端口的值 io_out 均变为输入寄存器的新的值 io_in = 59111E2DH

# 阻塞

avatar

io_flush = 0 且 io_stall = 1 ,表示阻塞的情况,PipelineRegister 模块应该维持原本内容不变,所以存储变量 temp 和输出端口的值 io_out 均不受输入寄存器的新的值 io_in = 4846D70DH 的影响,维持 7B035A8H 不变

# 清除

avatar

io_flush = 1 且 io_stall = 0 ,表示清除的情况,PipelineRegister 模块应该重制内容为默认初始值,所以存储变量 temp 和输出端口的值 io_out 均不受输入寄存器的新的值 io_in = 4C52A358H 的影响,变为测试程序随机生成的默认初始值 7B035A8H

# hazard.S

后面几个测试都使用了 src/main/resources/hazard.asmbin 进行仿真,其汇编源文件为 csrc/hazard.S ,该文件内容源代码如下

avatar

对这段汇编代码出现的冒险分析如下:

RISCV汇编
.globl _start
_start:
  csrr a0, cycle
  addi t0, zero, 1    # 数据冒险:下一条指令 sub 需要使用 ALU 计算结果 t0 的值
  sub t1, zero, t0    # 数据冒险:需要使用上一条指令 addi 的 ALU 计算结果 t0 的值
                      #          下一条指令 and 需要使用 ALU 计算结果 t1 的值
  and t2, t0, t1      # 数据冒险:需要使用上一条指令 sub 的 ALU 计算结果 t1 的值
                      #          下一条指令 sw 需要使用 ALU 计算结果 t2 的值
  sw t2, 4(zero)      # 数据冒险:需要使用上一条指令 and 的 ALU 计算结果 t2 的值
  j skip1             # 控制冒险:无条件跳转指令,后续指令会被抛弃
  or t2, t0, t1       # 控制冒险:将会无条件跳转到 skip1 标签处,此指令将被抛弃
  xor t2, t0, t1      # 控制冒险:将会无条件跳转到 skip1 标签处,此指令将被抛弃
skip1:
  addi t1, t2, 1      # 数据冒险:下一条指令 add 需要使用 ALU 计算结果 t1 的值
  add t2, t1, t2      # 数据冒险:需要使用上一条指令 addi 的 ALU 计算结果 t1 的值
                      #          下一条指令 and 需要使用 ALU 计算结果 t2 的值
  and t2, t1, t2      # 数据冒险:需要使用上一条指令 and 的 ALU 计算结果 t2 的值
                      #          下一条指令 lw 需要使用 ALU 计算结果 t2 的值
  lw t2, 2(t2)        # 数据冒险:需要使用上一条指令 and 的 ALU 计算结果 t2 的值
  or t3, t1, t2       # 数据冒险:需要使用上一条指令 lw 读取内存得到的 t2 的值
  blt t2, t3, skip2   # 数据冒险:需要使用上一条指令 or 的 ALU 计算结果 t3 的值
                      # 控制冒险:条件分支,后续指令可能会被抛弃
  or t3, t0, t0       # 控制冒险:如果分支条件满足,将会跳转到 skip2 标签处,此指令将被抛弃
  xor t3, t0, t1      # 控制冒险:如果分支条件满足,将会跳转到 skip2 标签处,此指令将被抛弃
skip2:
  addi t4, zero, 3    # 数据冒险:下一条指令 bne 需要使用 ALU 计算结果 t4 的值
  bne t3, t4, skip1   # 数据冒险:需要使用上一条指令 addi 的 ALU 计算结果 t4 的值
                      # 控制冒险:条件分支,后续指令可能会被抛弃
  sw t3, 8(zero)
  auipc t4, 0         # 控制冒险:如果分支条件满足,将会跳转到 skip1 标签处,此指令将被抛弃
                      # 数据冒险:下一条指令 jalr 需要使用扩展立即数结果 t4 的值
  jalr t4, 8(t4)      # 控制冒险:如果分支条件满足,将会跳转到 skip1 标签处,此指令将被抛弃
                      # 数据冒险:需要使用上一条指令 auipc 扩展立即数写入寄存器 t4 的值
                      # 控制冒险:无条件跳转指令,后续指令会被抛弃
  jalr t4, 4(t4)      # 控制冒险:无条件跳转指令,后续指令会被抛弃
  csrr a1, cycle      # 控制冒险:将会无条件跳转到未知地址,此指令可能被抛弃
                      # 数据冒险:下一条指令 sub 需要使用读取计数器得到的 a1 的值
  sub ra, a1, a0      # 控制冒险:将会无条件跳转到未知地址,此指令可能被抛弃
                      # 数据冒险:需要使用上一条指令 csrr 读取计数器得到的 a1 的值
loop:
  j loop

上述分析基于五级流水线 CPU 进行分析,若为三级流水线 CPU,则不存在数据冒险,只存在控制冒险

若所有冒险都能正确处理,则程序应该按照如下过程执行:

RISCV汇编
.globl _start
_start:
  csrr a0, cycle          # 读取计时器的当前值,存入寄存器 a0
  addi t0, zero, 1        # 将 0 加上立即数 1,结果存入寄存器 t0,t0=1
  sub t1, zero, t0        # 将 0 减去寄存器 t0 的值,结果存入寄存器 t1,t1=-1
  and t2, t0, t1          # 将寄存器 t0 和寄存器 t1 进行按位与操作,结果存入寄存器 t2,t2=1
  sw t2, 4(zero)          # 将寄存器 t2 的值存入内存地址 4
  j skip1                # 无条件跳转到标签 skip1
  or t2, t0, t1          # 控制冒险:此指令将被跳过,不会执行
  xor t2, t0, t1         # 控制冒险:此指令将被跳过,不会执行
skip1:
  addi t1, t2, 1          # 将寄存器 t2 的值加上立即数 1,结果存入寄存器 t1,t1=2
  add t2, t1, t2          # 将寄存器 t1 和寄存器 t2 相加,结果存入寄存器 t2,t2=3
  and t2, t1, t2          # 将寄存器 t1 和寄存器 t2 进行按位与操作,结果存入寄存器 t2,t2=2
  lw t2, 2(t2)            # 从内存地址 (t2+2) 处读取值,存入寄存器 t2,t2=1
  or t3, t1, t2           # 将寄存器 t1 和寄存器 t2 进行按位或操作,结果存入寄存器 t3,t3=3
  blt t2, t3, skip2       # t2 < t3,跳转到标签 skip2
  or t3, t0, t0           # 控制冒险:此指令将被跳过,不会执行
  xor t3, t0, t1          # 控制冒险:此指令将被跳过,不会执行
skip2:
  addi t4, zero, 3        # 将 0 加上立即数 3,结果存入寄存器 t4,t4=3
  bne t3, t4, skip1       # t3 和 t4 相等,不跳转,继续执行下面的指令
  sw t3, 8(zero)          # 将寄存器 t3 的值存入内存地址 8
  auipc t4, 0             # 将当前 PC 的高 20 位加上立即数 0 存入寄存器 t4,t4 = 当前指令 PC+4
  jalr t4, 8(t4)          # 跳转到地址 (t4+8),并将返回地址存入寄存器 t4,t4 = 上一条指令 PC+4+8 = 当前指令 PC+8
  jalr t4, 4(t4)          # 控制冒险:此指令将被跳过,不会执行,跳转到下一条指令
  csrr a1, cycle          # 读取计时器的当前值,存入寄存器 a1
  sub ra, a1, a0          # 将寄存器 a1 减去寄存器 a0 的值,结果存入寄存器 ra
loop:
  j loop                  # 无条件跳转到标签 loop,形成一个无限循环

程序结束时,寄存器的值如下:

  • a0 :存储了起始时刻的计时器值
  • a1 :存储了结束时刻的计时器值
  • ra :存储了计时器结束时刻减去起始时刻的差值,即进入死循环前程序运行了多少时钟周期
  • t0、t1、t2、t3、t4 寄存器的值如下:
    • t0 : 1
    • t1 : -1
    • t2 :1
    • t3 :3
    • t4 :指令 csrr a1, cycle 的地址

内存地址中存储的数据如下:

  • 内存地址 4:存储了的值为 1
  • 内存地址 8:存储了的值为 3

后面几个流水线 CPU 测试使用到的斐波那契数列计算、快排、读写单个字节这 3 个测试均已在 lab1 分析过,与单周期 CPU 无异,所以只分析他们对冒险的处理,即只分析他们对上述程序的执行处理过程

# ThreeStageCPUTest

src/test/scala/riscv/ThreeStageCPUTest.scala

avatar

# 测试用例的功能

测试了三级流水线 CPU 的完整功能正确性,检测其是否解决 hazard.asmbin 的所有控制冒险问题

# 从什么层面测试 CPU

从对冒险的处理层面测试三级流水线 CPU

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/TestTopModule.scala 中的模块 TestTopModule ,使用任何 RISC-V 程序 src/main/resources/hazard.asmbin 初始化进行仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

输出波形图中可以看到前面 120 ps 内测试程序执行完毕,此后程序进入死循环,不断重复执行 0000006FH 指令,即 jal 指令,原地循环

# avatar

如上图所示,波形图中自上到下三个信号分别为 IF、ID、EX 阶段的指令信号,当信号连续 2 个周期不发生改变,说明该阶段指令阻塞;当信号变为默认初始值 00000013H ,说明该阶段指令清空。

avatar

当确保程序执行完毕后,测试程序检测结果,读取寄存器和内存的值,看其是否符合预期。

# io_regs_debug_read_data[31:0]

c.io.regs_debug_read_address.poke(1.U) 使信号 io_regs_debug_read_address [4:0] 的值为 1 ,表示读取 1 号寄存器,即读取 ra 寄存器,读取 io_regs_debug_read_data 的值应当为三级流水线 CPU 执行 hazard.asmbin 两次 csrr 指令之间所花费的时钟周期

两次 csrr 指令之间有 18 条指令(包括两条 csrr )在三级流水线执行过程都进入 EX 阶段过,即没有被跳过;且两次 csrr 指令之间经历了 4 次跳转指令控制冒险,从波形图可以看出 EX 阶段发生了 4 次阻塞,每次阻塞 2 个时钟周期。因此两次 csrr 指令之间所花费的时钟周期数为 18+4*2 = 26

波形图可见最后读取到 io_regs_debug_read_data 的值等于 26 ,说明三级流水线 CPU 符合预期正确处理了所有控制冒险

# io_mem_debug_read_data[31:0]

先后两个时钟周期检测了两个地址所存储的内容

c.io.mem_debug_read_address.poke(4.U) 读取内存地址为 4 的内容,结果为 1 ,符合预期;

c.io.mem_debug_read_address.poke(8.U) 读取内存地址为 8 的内容,结果为 3 ,符合预期;

# FiveStageCPUStallTest

src/test/scala/riscv/FiveStageCPUStallTest.scala

avatar

# 测试用例的功能

测试了只使用阻塞解决冒险的五级流水线 CPU 的完整功能正确性,检测其是否解决 hazard.asmbin 的所有控制冒险问题

# 从什么层面测试 CPU

从对冒险的处理层面测试五级流水线 CPU

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/TestTopModule.scala 中的模块 TestTopModule ,使用任何 RISC-V 程序 src/main/resources/hazard.asmbin 初始化进行仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

输出波形图中可以看到前面 450 ps 内测试程序执行完毕,此后程序进入死循环,不断重复执行 0000006FH 指令,即 jal 指令,原地循环

# avatar

如上图所示,波形图中自上到下三个信号分别为 IF、ID、EX 阶段的指令信号,当信号连续 多 个周期不发生改变,说明该阶段指令阻塞;当信号变为默认初始值 00000013H ,说明该阶段指令清空。

avatar

当确保程序执行完毕后,测试程序检测结果,读取寄存器和内存的值,看其是否符合预期。

# io_regs_debug_read_data[31:0]

c.io.regs_debug_read_address.poke(1.U) 使信号 io_regs_debug_read_address [4:0] 的值为 1 ,表示读取 1 号寄存器,即读取 ra 寄存器,读取 io_regs_debug_read_data 的值应当为五级流水线 CPU 执行 hazard.asmbin 两次 csrr 指令之间所花费的时钟周期

两次 csrr 指令之间有 18 条指令(包括第二条 csrr 但不包括第一条 csrr)在五级流水线执行过程都进入 EX 阶段过,即没有被跳过;且两次 csrr 指令之间经历了 4 次跳转指令控制冒险、10 次数据冒险,从波形图可以看出 EX 阶段发生了 14 次阻塞,每次阻塞 2 个时钟周期。因此两次 csrr 指令之间所花费的时钟周期数为 18+14*2 = 46

波形图可见最后读取到 io_regs_debug_read_data 的值等于 46 ,说明五级流水线 CPU 符合预期正确处理了所有冒险

# io_mem_debug_read_data[31:0]

先后两个时钟周期检测了两个地址所存储的内容

c.io.mem_debug_read_address.poke(4.U) 读取内存地址为 4 的内容,结果为 1 ,符合预期;

c.io.mem_debug_read_address.poke(8.U) 读取内存地址为 8 的内容,结果为 3 ,符合预期;

# FiveStageCPUForwardTest

src/test/scala/riscv/FiveStageCPUForwardTest.scala

avatar

# 测试用例的功能

测试了使用阻塞和转发解决冒险的五级流水线 CPU 的完整功能正确性,检测其是否解决 hazard.asmbin 的所有控制冒险问题

# 从什么层面测试 CPU

从对冒险的处理层面测试五级流水线 CPU

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/TestTopModule.scala 中的模块 TestTopModule ,使用任何 RISC-V 程序 src/main/resources/hazard.asmbin 初始化进行仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

输出波形图中可以看到前面 300 ps 内测试程序执行完毕,此后程序进入死循环,不断重复执行 0000006FH 指令,即 jal 指令,原地循环

# avatar

如上图所示,波形图中自上到下三个信号分别为 IF、ID、EX 阶段的指令信号,当信号连续多个周期不发生改变,说明该阶段指令阻塞;当信号变为默认初始值 00000013H ,说明该阶段指令清空。

avatar

当确保程序执行完毕后,测试程序检测结果,读取寄存器和内存的值,看其是否符合预期。

# io_regs_debug_read_data[31:0]

c.io.regs_debug_read_address.poke(1.U) 使信号 io_regs_debug_read_address [4:0] 的值为 1 ,表示读取 1 号寄存器,即读取 ra 寄存器,读取 io_regs_debug_read_data 的值应当为五级流水线 CPU 执行 hazard.asmbin 两次 csrr 指令之间所花费的时钟周期

两次 csrr 指令之间有 18 条指令(包括第二条 csrr 但不包括第一条 csrr)在五级流水线执行过程都进入 EX 阶段过,即没有被跳过;且两次 csrr 指令之间经历了 4 次跳转指令控制冒险、1 次无法用转发解决的数据冒险即 lw t2, 2(t2)or t3, t1, t2 之间的数据冒险,读取内存的数据必须等到下一个周期 MEM 阶段才能得到数据。从波形图可以看出 EX 阶段发生了 4 次阻塞,每次阻塞 2 个时钟周期,同时数据冒险还在 IF 和 ID 阶段阻塞了 1 个时钟周期。因此两次 csrr 指令之间所花费的时钟周期数为 18+4*2+1 = 27

波形图可见最后读取到 io_regs_debug_read_data 的值等于 27 ,说明五级流水线 CPU 符合预期正确处理了所有冒险

# io_mem_debug_read_data[31:0]

先后两个时钟周期检测了两个地址所存储的内容

c.io.mem_debug_read_address.poke(4.U) 读取内存地址为 4 的内容,结果为 1 ,符合预期;

c.io.mem_debug_read_address.poke(8.U) 读取内存地址为 8 的内容,结果为 3 ,符合预期;

# FiveStageCPUFinalTest

src/test/scala/riscv/FiveStageCPUFinalTest.scala

avatar

# 测试用例的功能

测试了使用阻塞、转发以及 ID 阶段判断分支来解决冒险的五级流水线 CPU 的完整功能正确性,检测其是否解决 hazard.asmbin 的所有控制冒险问题

# 从什么层面测试 CPU

从对冒险的处理层面测试五级流水线 CPU

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/TestTopModule.scala 中的模块 TestTopModule ,使用任何 RISC-V 程序 src/main/resources/hazard.asmbin 初始化进行仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

输出波形图中可以看到前面 300 ps 内测试程序执行完毕,此后程序进入死循环,不断重复执行 0000006FH 指令,即 jal 指令,原地循环

# avatar

如上图所示,波形图中自上到下三个信号分别为 IF、ID、EX 阶段的指令信号,当信号连续多个周期不发生改变,说明该阶段指令阻塞;当信号变为默认初始值 00000013H ,说明该阶段指令清空。

avatar

当确保程序执行完毕后,测试程序检测结果,读取寄存器和内存的值,看其是否符合预期。

# io_regs_debug_read_data[31:0]

c.io.regs_debug_read_address.poke(1.U) 使信号 io_regs_debug_read_address [4:0] 的值为 1 ,表示读取 1 号寄存器,即读取 ra 寄存器,读取 io_regs_debug_read_data 的值应当为五级流水线 CPU 执行 hazard.asmbin 两次 csrr 指令之间所花费的时钟周期

两次 csrr 指令之间有 18 条指令(包括第二条 csrr 但不包括第一条 csrr)在五级流水线执行过程都进入 EX 阶段过,即没有被跳过;且两次 csrr 指令之间经历了 4 次跳转指令控制冒险、1 次无法用转发解决的数据冒险即 lw t2, 2(t2)or t3, t1, t2 之间的数据冒险,读取内存的数据必须等到下一个周期 MEM 阶段才能得到数据。其中第一次控制冒险是由无条件跳转指令引起的,可以通过 ID 阶段只阻塞 1 个周期解决;其余 3 个控制冒险都需要阻塞 2 个时钟周期才能解决;同时数据冒险还在 IF 和 ID 阶段阻塞了 1 个时钟周期。因此两次 csrr 指令之间所花费的时钟周期数为 18+1+3*2+1 = 26

波形图可见最后读取到 io_regs_debug_read_data 的值等于 26 ,说明五级流水线 CPU 符合预期正确处理了所有冒险

# io_mem_debug_read_data[31:0]

先后两个时钟周期检测了两个地址所存储的内容

c.io.mem_debug_read_address.poke(4.U) 读取内存地址为 4 的内容,结果为 1 ,符合预期;

c.io.mem_debug_read_address.poke(8.U) 读取内存地址为 8 的内容,结果为 3 ,符合预期;

# 填空涉及到的信号分析

(src/main/scala/riscv/)

主要在填空代码处以注释的形式进行了分析

# 在完成实验的过程中,遇到的关于实验指导不明确或者其他问题,或者改进的建议。

使用实验板上的数码管、视频输出等外设,输出一个完整程序的运行结果,或者参考硬件调试一节的内容,用硬件波形的方法捕获程序运行结果。给出你的 CPU 可以正确在实验板上运行程序的照片或者硬件调试器波形截图。

\ No newline at end of file +lab3 - YatCPU - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

YatCPU - - - lab1 - - - lab2 - - - lab3 - - - lab4

# 测试用例及其波形图分析

# SayGoodbyeTest

src/test/scala/riscv/BoardTest.scala

avatar

其中 Top 模块来自:

avatar

测试执行程序来自 csrc/say_goodbye.c :

avatar

# 测试用例的功能

与 lab2 中 BoardSayGoodbyeTest 功能相似

测试能否正常执行打印 "Never gonna give you up~ Never gonna let you down~\nNever gonna run around and~ desert you~" ,用于烧板后测试能否实现打印,即测试 CPU 包括 lab1 的功能以及能否实现中断处理

# 从什么层面测试 CPU

从完整性的层面测试 CPU ,若 CPU 可以打印,说明 CPU 具备了中断处理的能力

但并没有测试 CPU 的正确性,只是进行了 pokestep ,但没有对任何信号进行 expect 检查。实际验证需要烧板手动测试能否打印。

# 加载测试程序的方法

利用定义在 src/main/scala/board/z710/Top.scala 中的模块 Top ,用 RISC-V 程序 src/main/resources/say_goodbye.asmbin 初始化进行仿真

# 测试用例的执行结果

avatar

# 输出波形图

avatar

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

测试中循环执行了 50000 次 step(5) ,即 250000 个时钟周期,输出的波形图总时长为 500001 ps ,除去半个用于 reset 的时钟周期之外恰好 250000 个时钟周期。

由 io_jump_flag 、io_id_flush 、io_if_flush 、io_if_stall 、io_pc_stall 几个信号变化可以看出,CPU 在执行程序过程中较频繁地出现了控制冒险和数据冒险,需要通过阻塞、清除、转发等操作处理

# PipelineRegisterTest

src/test/scala/riscv/PipelineRegisterTest.scala

avatar

# 测试用例的功能

该测试用例用于检查 PipelineRegister 模块的正确性,测试程序模拟了 3 种情况:

# 既不清除也不阻塞

在当前指令既不清除也不阻塞的情况,PipelineRegister 模块应该更新内容

# 阻塞

在当前指令需要阻塞的情况,PipelineRegister 模块应该保持原本内容不变,实现 “暂停”

# 清除

在当前指令需要清除的情况,PipelineRegister 模块的内容应该恢复默认值,默认值代表清除时塞入的 “气泡”,例如:

  • instruction 的默认初始值为 nop
  • instruction_address 的默认初始值为程序入口指令地址

# 从什么层面测试 CPU

从辅助寄存器 PipelineRegister 层面测试了 CPU,主要测试流水线 CPU 不同级之间的寄存器能否实现流水线 CPU 所需要的基本功能

# 加载测试程序的方法

利用定义在 src/main/scala/riscv/core/PipelineRegister.scala 中的模块 PipelineRegister ,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

测试程序模拟了 3 中不同情况,并且重复对三种情况中随机一个进行测试,总共测试了 1000 次,执行了 1000 个时钟周期

# 既不清除也不阻塞

avatar

io_flush = 0 且 io_stall = 0 ,表示既不清除也不阻塞的情况,PipelineRegister 模块应该更新内容,所以存储变量 temp 和输出端口的值 io_out 均变为输入寄存器的新的值 io_in = 59111E2DH

# 阻塞

avatar

io_flush = 0 且 io_stall = 1 ,表示阻塞的情况,PipelineRegister 模块应该维持原本内容不变,所以存储变量 temp 和输出端口的值 io_out 均不受输入寄存器的新的值 io_in = 4846D70DH 的影响,维持 7B035A8H 不变

# 清除

avatar

io_flush = 1 且 io_stall = 0 ,表示清除的情况,PipelineRegister 模块应该重制内容为默认初始值,所以存储变量 temp 和输出端口的值 io_out 均不受输入寄存器的新的值 io_in = 4C52A358H 的影响,变为测试程序随机生成的默认初始值 7B035A8H

# hazard.S

后面几个测试都使用了 src/main/resources/hazard.asmbin 进行仿真,其汇编源文件为 csrc/hazard.S ,该文件内容源代码如下

avatar

对这段汇编代码出现的冒险分析如下:

RISCV汇编
.globl _start
_start:
  csrr a0, cycle
  addi t0, zero, 1    # 数据冒险:下一条指令 sub 需要使用 ALU 计算结果 t0 的值
  sub t1, zero, t0    # 数据冒险:需要使用上一条指令 addi 的 ALU 计算结果 t0 的值
                      #          下一条指令 and 需要使用 ALU 计算结果 t1 的值
  and t2, t0, t1      # 数据冒险:需要使用上一条指令 sub 的 ALU 计算结果 t1 的值
                      #          下一条指令 sw 需要使用 ALU 计算结果 t2 的值
  sw t2, 4(zero)      # 数据冒险:需要使用上一条指令 and 的 ALU 计算结果 t2 的值
  j skip1             # 控制冒险:无条件跳转指令,后续指令会被抛弃
  or t2, t0, t1       # 控制冒险:将会无条件跳转到 skip1 标签处,此指令将被抛弃
  xor t2, t0, t1      # 控制冒险:将会无条件跳转到 skip1 标签处,此指令将被抛弃
skip1:
  addi t1, t2, 1      # 数据冒险:下一条指令 add 需要使用 ALU 计算结果 t1 的值
  add t2, t1, t2      # 数据冒险:需要使用上一条指令 addi 的 ALU 计算结果 t1 的值
                      #          下一条指令 and 需要使用 ALU 计算结果 t2 的值
  and t2, t1, t2      # 数据冒险:需要使用上一条指令 and 的 ALU 计算结果 t2 的值
                      #          下一条指令 lw 需要使用 ALU 计算结果 t2 的值
  lw t2, 2(t2)        # 数据冒险:需要使用上一条指令 and 的 ALU 计算结果 t2 的值
  or t3, t1, t2       # 数据冒险:需要使用上一条指令 lw 读取内存得到的 t2 的值
  blt t2, t3, skip2   # 数据冒险:需要使用上一条指令 or 的 ALU 计算结果 t3 的值
                      # 控制冒险:条件分支,后续指令可能会被抛弃
  or t3, t0, t0       # 控制冒险:如果分支条件满足,将会跳转到 skip2 标签处,此指令将被抛弃
  xor t3, t0, t1      # 控制冒险:如果分支条件满足,将会跳转到 skip2 标签处,此指令将被抛弃
skip2:
  addi t4, zero, 3    # 数据冒险:下一条指令 bne 需要使用 ALU 计算结果 t4 的值
  bne t3, t4, skip1   # 数据冒险:需要使用上一条指令 addi 的 ALU 计算结果 t4 的值
                      # 控制冒险:条件分支,后续指令可能会被抛弃
  sw t3, 8(zero)
  auipc t4, 0         # 控制冒险:如果分支条件满足,将会跳转到 skip1 标签处,此指令将被抛弃
                      # 数据冒险:下一条指令 jalr 需要使用扩展立即数结果 t4 的值
  jalr t4, 8(t4)      # 控制冒险:如果分支条件满足,将会跳转到 skip1 标签处,此指令将被抛弃
                      # 数据冒险:需要使用上一条指令 auipc 扩展立即数写入寄存器 t4 的值
                      # 控制冒险:无条件跳转指令,后续指令会被抛弃
  jalr t4, 4(t4)      # 控制冒险:无条件跳转指令,后续指令会被抛弃
  csrr a1, cycle      # 控制冒险:将会无条件跳转到未知地址,此指令可能被抛弃
                      # 数据冒险:下一条指令 sub 需要使用读取计数器得到的 a1 的值
  sub ra, a1, a0      # 控制冒险:将会无条件跳转到未知地址,此指令可能被抛弃
                      # 数据冒险:需要使用上一条指令 csrr 读取计数器得到的 a1 的值
loop:
  j loop

上述分析基于五级流水线 CPU 进行分析,若为三级流水线 CPU,则不存在数据冒险,只存在控制冒险

若所有冒险都能正确处理,则程序应该按照如下过程执行:

RISCV汇编
.globl _start
_start:
  csrr a0, cycle          # 读取计时器的当前值,存入寄存器 a0
  addi t0, zero, 1        # 将 0 加上立即数 1,结果存入寄存器 t0,t0=1
  sub t1, zero, t0        # 将 0 减去寄存器 t0 的值,结果存入寄存器 t1,t1=-1
  and t2, t0, t1          # 将寄存器 t0 和寄存器 t1 进行按位与操作,结果存入寄存器 t2,t2=1
  sw t2, 4(zero)          # 将寄存器 t2 的值存入内存地址 4
  j skip1                # 无条件跳转到标签 skip1
  or t2, t0, t1          # 控制冒险:此指令将被跳过,不会执行
  xor t2, t0, t1         # 控制冒险:此指令将被跳过,不会执行
skip1:
  addi t1, t2, 1          # 将寄存器 t2 的值加上立即数 1,结果存入寄存器 t1,t1=2
  add t2, t1, t2          # 将寄存器 t1 和寄存器 t2 相加,结果存入寄存器 t2,t2=3
  and t2, t1, t2          # 将寄存器 t1 和寄存器 t2 进行按位与操作,结果存入寄存器 t2,t2=2
  lw t2, 2(t2)            # 从内存地址 (t2+2) 处读取值,存入寄存器 t2,t2=1
  or t3, t1, t2           # 将寄存器 t1 和寄存器 t2 进行按位或操作,结果存入寄存器 t3,t3=3
  blt t2, t3, skip2       # t2 < t3,跳转到标签 skip2
  or t3, t0, t0           # 控制冒险:此指令将被跳过,不会执行
  xor t3, t0, t1          # 控制冒险:此指令将被跳过,不会执行
skip2:
  addi t4, zero, 3        # 将 0 加上立即数 3,结果存入寄存器 t4,t4=3
  bne t3, t4, skip1       # t3 和 t4 相等,不跳转,继续执行下面的指令
  sw t3, 8(zero)          # 将寄存器 t3 的值存入内存地址 8
  auipc t4, 0             # 将当前 PC 的高 20 位加上立即数 0 存入寄存器 t4,t4 = 当前指令 PC+4
  jalr t4, 8(t4)          # 跳转到地址 (t4+8),并将返回地址存入寄存器 t4,t4 = 上一条指令 PC+4+8 = 当前指令 PC+8
  jalr t4, 4(t4)          # 控制冒险:此指令将被跳过,不会执行,跳转到下一条指令
  csrr a1, cycle          # 读取计时器的当前值,存入寄存器 a1
  sub ra, a1, a0          # 将寄存器 a1 减去寄存器 a0 的值,结果存入寄存器 ra
loop:
  j loop                  # 无条件跳转到标签 loop,形成一个无限循环

程序结束时,寄存器的值如下:

  • a0 :存储了起始时刻的计时器值
  • a1 :存储了结束时刻的计时器值
  • ra :存储了计时器结束时刻减去起始时刻的差值,即进入死循环前程序运行了多少时钟周期
  • t0、t1、t2、t3、t4 寄存器的值如下:
    • t0 : 1
    • t1 : -1
    • t2 :1
    • t3 :3
    • t4 :指令 csrr a1, cycle 的地址

内存地址中存储的数据如下:

  • 内存地址 4:存储了的值为 1
  • 内存地址 8:存储了的值为 3

后面几个流水线 CPU 测试使用到的斐波那契数列计算、快排、读写单个字节这 3 个测试均已在 lab1 分析过,与单周期 CPU 无异,所以只分析他们对冒险的处理,即只分析他们对上述程序的执行处理过程

# ThreeStageCPUTest

src/test/scala/riscv/ThreeStageCPUTest.scala

avatar

# 测试用例的功能

测试了三级流水线 CPU 的完整功能正确性,检测其是否解决 hazard.asmbin 的所有控制冒险问题

# 从什么层面测试 CPU

从对冒险的处理层面测试三级流水线 CPU

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/TestTopModule.scala 中的模块 TestTopModule ,使用任何 RISC-V 程序 src/main/resources/hazard.asmbin 初始化进行仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

输出波形图中可以看到前面 120 ps 内测试程序执行完毕,此后程序进入死循环,不断重复执行 0000006FH 指令,即 jal 指令,原地循环

# avatar

如上图所示,波形图中自上到下三个信号分别为 IF、ID、EX 阶段的指令信号,当信号连续 2 个周期不发生改变,说明该阶段指令阻塞;当信号变为默认初始值 00000013H ,说明该阶段指令清空。

avatar

当确保程序执行完毕后,测试程序检测结果,读取寄存器和内存的值,看其是否符合预期。

# io_regs_debug_read_data[31:0]

c.io.regs_debug_read_address.poke(1.U) 使信号 io_regs_debug_read_address [4:0] 的值为 1 ,表示读取 1 号寄存器,即读取 ra 寄存器,读取 io_regs_debug_read_data 的值应当为三级流水线 CPU 执行 hazard.asmbin 两次 csrr 指令之间所花费的时钟周期

两次 csrr 指令之间有 18 条指令(包括两条 csrr )在三级流水线执行过程都进入 EX 阶段过,即没有被跳过;且两次 csrr 指令之间经历了 4 次跳转指令控制冒险,从波形图可以看出 EX 阶段发生了 4 次阻塞,每次阻塞 2 个时钟周期。因此两次 csrr 指令之间所花费的时钟周期数为 18+4*2 = 26

波形图可见最后读取到 io_regs_debug_read_data 的值等于 26 ,说明三级流水线 CPU 符合预期正确处理了所有控制冒险

# io_mem_debug_read_data[31:0]

先后两个时钟周期检测了两个地址所存储的内容

c.io.mem_debug_read_address.poke(4.U) 读取内存地址为 4 的内容,结果为 1 ,符合预期;

c.io.mem_debug_read_address.poke(8.U) 读取内存地址为 8 的内容,结果为 3 ,符合预期;

# FiveStageCPUStallTest

src/test/scala/riscv/FiveStageCPUStallTest.scala

avatar

# 测试用例的功能

测试了只使用阻塞解决冒险的五级流水线 CPU 的完整功能正确性,检测其是否解决 hazard.asmbin 的所有控制冒险问题

# 从什么层面测试 CPU

从对冒险的处理层面测试五级流水线 CPU

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/TestTopModule.scala 中的模块 TestTopModule ,使用任何 RISC-V 程序 src/main/resources/hazard.asmbin 初始化进行仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

输出波形图中可以看到前面 450 ps 内测试程序执行完毕,此后程序进入死循环,不断重复执行 0000006FH 指令,即 jal 指令,原地循环

# avatar

如上图所示,波形图中自上到下三个信号分别为 IF、ID、EX 阶段的指令信号,当信号连续 多 个周期不发生改变,说明该阶段指令阻塞;当信号变为默认初始值 00000013H ,说明该阶段指令清空。

avatar

当确保程序执行完毕后,测试程序检测结果,读取寄存器和内存的值,看其是否符合预期。

# io_regs_debug_read_data[31:0]

c.io.regs_debug_read_address.poke(1.U) 使信号 io_regs_debug_read_address [4:0] 的值为 1 ,表示读取 1 号寄存器,即读取 ra 寄存器,读取 io_regs_debug_read_data 的值应当为五级流水线 CPU 执行 hazard.asmbin 两次 csrr 指令之间所花费的时钟周期

两次 csrr 指令之间有 18 条指令(包括第二条 csrr 但不包括第一条 csrr)在五级流水线执行过程都进入 EX 阶段过,即没有被跳过;且两次 csrr 指令之间经历了 4 次跳转指令控制冒险、10 次数据冒险,从波形图可以看出 EX 阶段发生了 14 次阻塞,每次阻塞 2 个时钟周期。因此两次 csrr 指令之间所花费的时钟周期数为 18+14*2 = 46

波形图可见最后读取到 io_regs_debug_read_data 的值等于 46 ,说明五级流水线 CPU 符合预期正确处理了所有冒险

# io_mem_debug_read_data[31:0]

先后两个时钟周期检测了两个地址所存储的内容

c.io.mem_debug_read_address.poke(4.U) 读取内存地址为 4 的内容,结果为 1 ,符合预期;

c.io.mem_debug_read_address.poke(8.U) 读取内存地址为 8 的内容,结果为 3 ,符合预期;

# FiveStageCPUForwardTest

src/test/scala/riscv/FiveStageCPUForwardTest.scala

avatar

# 测试用例的功能

测试了使用阻塞和转发解决冒险的五级流水线 CPU 的完整功能正确性,检测其是否解决 hazard.asmbin 的所有控制冒险问题

# 从什么层面测试 CPU

从对冒险的处理层面测试五级流水线 CPU

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/TestTopModule.scala 中的模块 TestTopModule ,使用任何 RISC-V 程序 src/main/resources/hazard.asmbin 初始化进行仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

输出波形图中可以看到前面 300 ps 内测试程序执行完毕,此后程序进入死循环,不断重复执行 0000006FH 指令,即 jal 指令,原地循环

# avatar

如上图所示,波形图中自上到下三个信号分别为 IF、ID、EX 阶段的指令信号,当信号连续多个周期不发生改变,说明该阶段指令阻塞;当信号变为默认初始值 00000013H ,说明该阶段指令清空。

avatar

当确保程序执行完毕后,测试程序检测结果,读取寄存器和内存的值,看其是否符合预期。

# io_regs_debug_read_data[31:0]

c.io.regs_debug_read_address.poke(1.U) 使信号 io_regs_debug_read_address [4:0] 的值为 1 ,表示读取 1 号寄存器,即读取 ra 寄存器,读取 io_regs_debug_read_data 的值应当为五级流水线 CPU 执行 hazard.asmbin 两次 csrr 指令之间所花费的时钟周期

两次 csrr 指令之间有 18 条指令(包括第二条 csrr 但不包括第一条 csrr)在五级流水线执行过程都进入 EX 阶段过,即没有被跳过;且两次 csrr 指令之间经历了 4 次跳转指令控制冒险、1 次无法用转发解决的数据冒险即 lw t2, 2(t2)or t3, t1, t2 之间的数据冒险,读取内存的数据必须等到下一个周期 MEM 阶段才能得到数据。从波形图可以看出 EX 阶段发生了 4 次阻塞,每次阻塞 2 个时钟周期,同时数据冒险还在 IF 和 ID 阶段阻塞了 1 个时钟周期。因此两次 csrr 指令之间所花费的时钟周期数为 18+4*2+1 = 27

波形图可见最后读取到 io_regs_debug_read_data 的值等于 27 ,说明五级流水线 CPU 符合预期正确处理了所有冒险

# io_mem_debug_read_data[31:0]

先后两个时钟周期检测了两个地址所存储的内容

c.io.mem_debug_read_address.poke(4.U) 读取内存地址为 4 的内容,结果为 1 ,符合预期;

c.io.mem_debug_read_address.poke(8.U) 读取内存地址为 8 的内容,结果为 3 ,符合预期;

# FiveStageCPUFinalTest

src/test/scala/riscv/FiveStageCPUFinalTest.scala

avatar

# 测试用例的功能

测试了使用阻塞、转发以及 ID 阶段判断分支来解决冒险的五级流水线 CPU 的完整功能正确性,检测其是否解决 hazard.asmbin 的所有控制冒险问题

# 从什么层面测试 CPU

从对冒险的处理层面测试五级流水线 CPU

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/TestTopModule.scala 中的模块 TestTopModule ,使用任何 RISC-V 程序 src/main/resources/hazard.asmbin 初始化进行仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

输出波形图中可以看到前面 300 ps 内测试程序执行完毕,此后程序进入死循环,不断重复执行 0000006FH 指令,即 jal 指令,原地循环

# avatar

如上图所示,波形图中自上到下三个信号分别为 IF、ID、EX 阶段的指令信号,当信号连续多个周期不发生改变,说明该阶段指令阻塞;当信号变为默认初始值 00000013H ,说明该阶段指令清空。

avatar

当确保程序执行完毕后,测试程序检测结果,读取寄存器和内存的值,看其是否符合预期。

# io_regs_debug_read_data[31:0]

c.io.regs_debug_read_address.poke(1.U) 使信号 io_regs_debug_read_address [4:0] 的值为 1 ,表示读取 1 号寄存器,即读取 ra 寄存器,读取 io_regs_debug_read_data 的值应当为五级流水线 CPU 执行 hazard.asmbin 两次 csrr 指令之间所花费的时钟周期

两次 csrr 指令之间有 18 条指令(包括第二条 csrr 但不包括第一条 csrr)在五级流水线执行过程都进入 EX 阶段过,即没有被跳过;且两次 csrr 指令之间经历了 4 次跳转指令控制冒险、1 次无法用转发解决的数据冒险即 lw t2, 2(t2)or t3, t1, t2 之间的数据冒险,读取内存的数据必须等到下一个周期 MEM 阶段才能得到数据。其中第一次控制冒险是由无条件跳转指令引起的,可以通过 ID 阶段只阻塞 1 个周期解决;其余 3 个控制冒险都需要阻塞 2 个时钟周期才能解决;同时数据冒险还在 IF 和 ID 阶段阻塞了 1 个时钟周期。因此两次 csrr 指令之间所花费的时钟周期数为 18+1+3*2+1 = 26

波形图可见最后读取到 io_regs_debug_read_data 的值等于 26 ,说明五级流水线 CPU 符合预期正确处理了所有冒险

# io_mem_debug_read_data[31:0]

先后两个时钟周期检测了两个地址所存储的内容

c.io.mem_debug_read_address.poke(4.U) 读取内存地址为 4 的内容,结果为 1 ,符合预期;

c.io.mem_debug_read_address.poke(8.U) 读取内存地址为 8 的内容,结果为 3 ,符合预期;

# 填空涉及到的信号分析

(src/main/scala/riscv/)

主要在填空代码处以注释的形式进行了分析

# 在完成实验的过程中,遇到的关于实验指导不明确或者其他问题,或者改进的建议。

使用实验板上的数码管、视频输出等外设,输出一个完整程序的运行结果,或者参考硬件调试一节的内容,用硬件波形的方法捕获程序运行结果。给出你的 CPU 可以正确在实验板上运行程序的照片或者硬件调试器波形截图。

\ No newline at end of file diff --git a/cs/principles-of-computer-composition/yatcpu/lab-reports/lab4/index.html b/cs/principles-of-computer-composition/yatcpu/lab-reports/lab4/index.html index 7eb99fc9..5f0518b1 100644 --- a/cs/principles-of-computer-composition/yatcpu/lab-reports/lab4/index.html +++ b/cs/principles-of-computer-composition/yatcpu/lab-reports/lab4/index.html @@ -1 +1 @@ -lab4 - YatCPU - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

YatCPU - - - lab1 - - - lab2 - - - lab3 - - - lab4

# 测试用例及其波形图分析

# SayGoodbyeTest

src/test/scala/riscv/BoardTest.scala

avatar

其中 Top 模块来自:

avatar

测试执行程序来自 csrc/say_goodbye.c :

avatar

# 测试用例的功能

测试能否正常执行打印 "Never gonna give you up~ Never gonna let you down~\nNever gonna run around and~ desert you~" ,用于烧板后测试能否实现打印,即测试 CPU 包括 lab1 的功能以及能否实现中断处理

此外,测试用例还通过波形图展示了总线连接下各个设备之间的通信

# 从什么层面测试 CPU

从完整性的层面测试 CPU ,若 CPU 可以打印,则说明 CPU 实现了总线以及各个设备通过总线协议的通信

但并没有测试 CPU 的正确性,只是进行了 pokestep ,但没有对任何信号进行 expect 检查。实际验证需要烧板手动测试能否打印

# 加载测试程序的方法

利用定义在 src/main/scala/board/z710/Top.scala 中的模块 Top ,用 RISC-V 程序 src/main/resources/say_goodbye.asmbin 初始化进行仿真

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

所展示波形图里的信号自上而下分别表示:dummy 主设备、CPU、dummy 从设备、instruction_rom 从设备、mem 从设备、timer 从设备、uart 从设备的状态信号 state 变化情况

instruction_rom 设备状态在一开始不断变化的过程即为加载程序的过程,在 ROMLoaderTest 中体现了这一过程

instruction_rom 设备加载结束后,程序被加载到内存,CPU 的状态信号开始不断变化,表示 CPU 开始工作,执行程序

# TimerTest

src/test/scala/riscv/TimerTest.scala

avatar

# 测试用例的功能

该测试用例用于检查总线模块的正确性,利用 Timer 模块作为从设备,与自定义的 master 模块作为主设备进行通信

# 从什么层面测试 CPU

从总线上设备的通信层面测试了 CPU

# 加载测试程序的方法

利用定义在 src/main/scala/riscv/core/peripheral/Timer.scala 中的模块 Timer、定义在 src/main/scala/bus/AXI4Lite.scala 中的模块 AXI4LiteMaster 、AXI4LiteSlave 等模块 ,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

测试程序模拟了先后向 Timer 写数据、读数据的信号变化不同情况:

# 写数据

信号 io_bundle_write = 1 被拉高,向 Timer 内地址为 4 的空间写入数据 io_bundle_write_data = 00990315H ,即向 Timer 的 limit 写入 00990315H 的数据

写入操作开始后 io_bundle_busy 信号变为 1 ,表示 Timer 忙碌,现在正在与主设备通信实现写操作

# 写数据成功

向 Timer 写数据开始的 7 个时钟周期后 Timer 的变量 limit 才变为 00990315H ,此后又花了 1 个时钟周期回复确认,也即 Timer 和主设备之间花了 8 个时钟周期才实现握手、写操作、写回复等。写入 limit 成功后,io_bundle_busy 随即被拉低,表示 Timer 空闲,io_write_valid 被拉高表示写操作请求完成

# 数据

信号 io_bundle_read = 1 被拉高,向 Timer 申请读取地址为 4 的数据 limit = 00990315H

读数据操作开始后 io_bundle_busy 信号变为 1 ,表示 Timer 忙碌,现在正在与主设备通信实现读操作

# 读数据成功

向 Timer 写数据开始的 5 个时钟周期后 io_bundle_read_data 才变为 00990315H ,此后又花了 1 个时钟周期回复确认,也即 Timer 和主设备之间花了 6 个时钟周期才实现握手、读操作等。读取 limit 成功后,io_bundle_busy 随即被拉低,表示 Timer 空闲,io_read_valid 被拉高表示读操作成功执行

# MemoryTest

src/test/scala/riscv/MemoryTest.scala

avatar

# 测试用例的功能

该测试用例用于检查总线模块的正确性,利用 Memory 模块作为从设备,与自定义的 master 模块作为主设备进行通信

# 从什么层面测试 CPU

从总线上设备的通信层面测试了 CPU

# 加载测试程序的方法

利用定义在 src/main/scala/riscv/core/peripheral/Memory.scala 中的模块 Memory、定义在 src/main/scala/bus/AXI4Lite.scala 中的 AXI4LiteMaster 、AXI4LiteSlave 等模块,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

测试程序模拟了先后向 Memory 写数据、读数据的信号变化不同情况:

# 写数据

信号 io_bundle_write = 1 被拉高,向 Memory 内地址为 4 的空间写入数据 io_bundle_write_data = DEADBEEFH

写入操作开始后 io_bundle_busy 信号变为 1 ,表示 Memory 忙碌,现在正在与主设备通信实现写操作

# 写数据成功

向 Memory 写数据开始的 8 个时钟周期后 io_bundle_busy 被拉低,表示 Memory 空闲,io_write_valid 被拉高表示写操作请求完成,也即 Timer 和主设备之间花了 8 个时钟周期才实现握手、写操作、写回复等。

# 数据

信号 io_bundle_read = 1 被拉高,向 Memory 申请读取地址为 4 的数据

读数据操作开始后 io_bundle_busy 信号变为 1 ,表示 Memory 忙碌,现在正在与主设备通信实现读操作

# 读数据成功

向 Timer 写数据开始的 6 个时钟周期后读取 limit 成功,io_bundle_busy 被拉低,表示 Timer 空闲,io_read_valid 被拉高表示读操作成功执行,io_bundle_read_data 信号为 DEADBEEFH ,符合预期

# ROMLoaderTest

src/test/scala/riscv/ROMLoaderTest.scala

avatar

# 测试用例的功能

该测试用例用于检查总线模块的正确性,利用 ROMLoader 模块作为从设备,与自定义的 slave 模块作为主设备进行通信

# 从什么层面测试 CPU

从总线上设备的通信层面测试了 CPU

# 加载测试程序的方法

利用定义在 src/main/scala/peripheral/ROMLoader.scala 中的模块 ROMLoader、定义在 src/main/scala/bus/AXI4Lite.scala 中的 AXI4LiteMaster 、AXI4LiteSlave 等模块,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

测试程序模拟检测了 ROMLoader 加载程序,即将 ROM 数据写入内存 (从设备) 过程的信号变化过程

波形图中最底下 2 个信号从上到下分别表示主设备和从设备的 state 状态变量信号,它们的变化展现了 ROMLoader 加载程序过程的不断

# 写入从设备数据

信号 io_load_start = 1 被拉高,下一个时钟周期开始 ROMLoader 按顺序将数据写入从设备

io_load_address 被设置为 100H ,表示从内存地址 100H 开始写数据

一开始 io_rom_address 的值为 0 ,表示用 rom 内容最开始处的数据写到从设备

# 写入数据成功

写入操作开始后 8 个时钟周期后 io_bundle_write 被拉高,表示成功写入数据

# 加载程序结束

又进行一次写操作后,由于已经遍历了 ROM 的空间为 2 ,达到了测试程序定义的 ROMLoader 模块设置的最大容量 capacity = 2 ,所以加载程序过程停止。此时 io_load_finish 信号拉高变为 1 ,表明程序加载结束,符合预期

# threestage.MMIOTest

src/test/scala/riscv/threestage/CPUTest.scala

avatar

csrc/mmio.S

avatar

对该程序分析如下:

RISCV汇编
.globl _start
_start:
  li a0, 0x80000000   # 将立即数 0x80000000 加载到寄存器 a0 中,a0=80000000H
  lw t0, 4 (a0)        # 从地址 a0+4=80000004H 处加载一个字(32 位)到寄存器 t0 中,t0=05F5E100H(limit 默认初始值)
  li a1, 0xBEEF       # 将立即数 0xBEEF 加载到寄存器 a1 中,a1=BEEFH
  sw a1, 4 (a0)        # 将寄存器 a1 的内容存储到地址 a0+4=80000004H 处,limit=BEEFH
  nop                 # 空指令,不执行任何操作
  lw t1, 4 (a0)        # 从地址 a0+4 处加载一个字(32 位)到寄存器 t1 中,t1=BEEFH
loop:
  j loop              # 无条件跳转到标签 loop 处

可知程序执行结束后,各个寄存器的内容如下:

  • a0:80000000H
  • a1:BEEFH
  • t0:05F5E100H
  • t1:BEEFH

且主存地址为 80000004H 处的 Timer 内部数据 limit 变为 BEEFH

# 测试用例的功能

测试了 CPU 能否与计时器 Timer 通信,并实现 CPU 作为主设备对 Timer 的读写功能

# 从什么层面测试 CPU

从总线上设备的通信层面测试了 CPU

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/TestTopModule.scala 中的模块 TestTopModule ,使用任何 RISC-V 程序 src/main/resources/mmio.asmbin 初始化进行仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

测试程序总共执行了 200 个时钟周期:

  • 前面几乎一半时间用来加载程序,波形图上表现为 ROMLoader 的状态变量 state 在这一段时间不断变化,然后稳定

  • 后面剩余时间用于 CPU 执行程序,波形图上表现为 IF 阶段的 io_id_instruction 变两在这段时间不断变化

当确保程序执行完毕后,测试程序检测结果,读取寄存器和内存的值,看其是否符合预期

# register_5[31:0]

CPU 5 号寄存器的值,即 t0 寄存器的值,最后结果为 05F5E100H,符合预期

# register_6[31:0]

CPU 6 号寄存器的值,即 t1 寄存器的值,最后结果为 BEEFH ,符合预期

# register_10[31:0]

CPU 10 号寄存器的值,即 a0 寄存器的值,最后结果为 80000000H,符合预期

# register_11[31:0]

CPU 11 号寄存器的值,即 a1 寄存器的值,最后结果为 BEEFH,符合预期

# limit[31:0]

计时器 Timer 的变量,即内存地址空间为 80000004H 的值,最后结果为 BEEFH,符合预期

# fivestage.MMIOTest

该测试与 threestage.MMIOTest 基本一致,不再重复分析

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 填空涉及到的信号分析

(src/main/scala/riscv/)

主要在填空代码处以注释的形式进行了分析

状态转移图:

avatar

# 在完成实验的过程中,遇到的关于实验指导不明确或者其他问题,或者改进的建议。

使用实验板上的数码管、视频输出等外设,输出一个完整程序的运行结果,或者参考硬件调试一节的内容,用硬件波形的方法捕获程序运行结果。给出你的 CPU 可以正确在实验板上运行程序的照片或者硬件调试器波形截图。

\ No newline at end of file +lab4 - YatCPU - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

YatCPU - - - lab1 - - - lab2 - - - lab3 - - - lab4

# 测试用例及其波形图分析

# SayGoodbyeTest

src/test/scala/riscv/BoardTest.scala

avatar

其中 Top 模块来自:

avatar

测试执行程序来自 csrc/say_goodbye.c :

avatar

# 测试用例的功能

测试能否正常执行打印 "Never gonna give you up~ Never gonna let you down~\nNever gonna run around and~ desert you~" ,用于烧板后测试能否实现打印,即测试 CPU 包括 lab1 的功能以及能否实现中断处理

此外,测试用例还通过波形图展示了总线连接下各个设备之间的通信

# 从什么层面测试 CPU

从完整性的层面测试 CPU ,若 CPU 可以打印,则说明 CPU 实现了总线以及各个设备通过总线协议的通信

但并没有测试 CPU 的正确性,只是进行了 pokestep ,但没有对任何信号进行 expect 检查。实际验证需要烧板手动测试能否打印

# 加载测试程序的方法

利用定义在 src/main/scala/board/z710/Top.scala 中的模块 Top ,用 RISC-V 程序 src/main/resources/say_goodbye.asmbin 初始化进行仿真

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

所展示波形图里的信号自上而下分别表示:dummy 主设备、CPU、dummy 从设备、instruction_rom 从设备、mem 从设备、timer 从设备、uart 从设备的状态信号 state 变化情况

instruction_rom 设备状态在一开始不断变化的过程即为加载程序的过程,在 ROMLoaderTest 中体现了这一过程

instruction_rom 设备加载结束后,程序被加载到内存,CPU 的状态信号开始不断变化,表示 CPU 开始工作,执行程序

# TimerTest

src/test/scala/riscv/TimerTest.scala

avatar

# 测试用例的功能

该测试用例用于检查总线模块的正确性,利用 Timer 模块作为从设备,与自定义的 master 模块作为主设备进行通信

# 从什么层面测试 CPU

从总线上设备的通信层面测试了 CPU

# 加载测试程序的方法

利用定义在 src/main/scala/riscv/core/peripheral/Timer.scala 中的模块 Timer、定义在 src/main/scala/bus/AXI4Lite.scala 中的模块 AXI4LiteMaster 、AXI4LiteSlave 等模块 ,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

测试程序模拟了先后向 Timer 写数据、读数据的信号变化不同情况:

# 写数据

信号 io_bundle_write = 1 被拉高,向 Timer 内地址为 4 的空间写入数据 io_bundle_write_data = 00990315H ,即向 Timer 的 limit 写入 00990315H 的数据

写入操作开始后 io_bundle_busy 信号变为 1 ,表示 Timer 忙碌,现在正在与主设备通信实现写操作

# 写数据成功

向 Timer 写数据开始的 7 个时钟周期后 Timer 的变量 limit 才变为 00990315H ,此后又花了 1 个时钟周期回复确认,也即 Timer 和主设备之间花了 8 个时钟周期才实现握手、写操作、写回复等。写入 limit 成功后,io_bundle_busy 随即被拉低,表示 Timer 空闲,io_write_valid 被拉高表示写操作请求完成

# 数据

信号 io_bundle_read = 1 被拉高,向 Timer 申请读取地址为 4 的数据 limit = 00990315H

读数据操作开始后 io_bundle_busy 信号变为 1 ,表示 Timer 忙碌,现在正在与主设备通信实现读操作

# 读数据成功

向 Timer 写数据开始的 5 个时钟周期后 io_bundle_read_data 才变为 00990315H ,此后又花了 1 个时钟周期回复确认,也即 Timer 和主设备之间花了 6 个时钟周期才实现握手、读操作等。读取 limit 成功后,io_bundle_busy 随即被拉低,表示 Timer 空闲,io_read_valid 被拉高表示读操作成功执行

# MemoryTest

src/test/scala/riscv/MemoryTest.scala

avatar

# 测试用例的功能

该测试用例用于检查总线模块的正确性,利用 Memory 模块作为从设备,与自定义的 master 模块作为主设备进行通信

# 从什么层面测试 CPU

从总线上设备的通信层面测试了 CPU

# 加载测试程序的方法

利用定义在 src/main/scala/riscv/core/peripheral/Memory.scala 中的模块 Memory、定义在 src/main/scala/bus/AXI4Lite.scala 中的 AXI4LiteMaster 、AXI4LiteSlave 等模块,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

测试程序模拟了先后向 Memory 写数据、读数据的信号变化不同情况:

# 写数据

信号 io_bundle_write = 1 被拉高,向 Memory 内地址为 4 的空间写入数据 io_bundle_write_data = DEADBEEFH

写入操作开始后 io_bundle_busy 信号变为 1 ,表示 Memory 忙碌,现在正在与主设备通信实现写操作

# 写数据成功

向 Memory 写数据开始的 8 个时钟周期后 io_bundle_busy 被拉低,表示 Memory 空闲,io_write_valid 被拉高表示写操作请求完成,也即 Timer 和主设备之间花了 8 个时钟周期才实现握手、写操作、写回复等。

# 数据

信号 io_bundle_read = 1 被拉高,向 Memory 申请读取地址为 4 的数据

读数据操作开始后 io_bundle_busy 信号变为 1 ,表示 Memory 忙碌,现在正在与主设备通信实现读操作

# 读数据成功

向 Timer 写数据开始的 6 个时钟周期后读取 limit 成功,io_bundle_busy 被拉低,表示 Timer 空闲,io_read_valid 被拉高表示读操作成功执行,io_bundle_read_data 信号为 DEADBEEFH ,符合预期

# ROMLoaderTest

src/test/scala/riscv/ROMLoaderTest.scala

avatar

# 测试用例的功能

该测试用例用于检查总线模块的正确性,利用 ROMLoader 模块作为从设备,与自定义的 slave 模块作为主设备进行通信

# 从什么层面测试 CPU

从总线上设备的通信层面测试了 CPU

# 加载测试程序的方法

利用定义在 src/main/scala/peripheral/ROMLoader.scala 中的模块 ROMLoader、定义在 src/main/scala/bus/AXI4Lite.scala 中的 AXI4LiteMaster 、AXI4LiteSlave 等模块,不使用任何 RISC-V 程序初始化进行仿真,直接仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

测试程序模拟检测了 ROMLoader 加载程序,即将 ROM 数据写入内存 (从设备) 过程的信号变化过程

波形图中最底下 2 个信号从上到下分别表示主设备和从设备的 state 状态变量信号,它们的变化展现了 ROMLoader 加载程序过程的不断

# 写入从设备数据

信号 io_load_start = 1 被拉高,下一个时钟周期开始 ROMLoader 按顺序将数据写入从设备

io_load_address 被设置为 100H ,表示从内存地址 100H 开始写数据

一开始 io_rom_address 的值为 0 ,表示用 rom 内容最开始处的数据写到从设备

# 写入数据成功

写入操作开始后 8 个时钟周期后 io_bundle_write 被拉高,表示成功写入数据

# 加载程序结束

又进行一次写操作后,由于已经遍历了 ROM 的空间为 2 ,达到了测试程序定义的 ROMLoader 模块设置的最大容量 capacity = 2 ,所以加载程序过程停止。此时 io_load_finish 信号拉高变为 1 ,表明程序加载结束,符合预期

# threestage.MMIOTest

src/test/scala/riscv/threestage/CPUTest.scala

avatar

csrc/mmio.S

avatar

对该程序分析如下:

RISCV汇编
.globl _start
_start:
  li a0, 0x80000000   # 将立即数 0x80000000 加载到寄存器 a0 中,a0=80000000H
  lw t0, 4 (a0)        # 从地址 a0+4=80000004H 处加载一个字(32 位)到寄存器 t0 中,t0=05F5E100H(limit 默认初始值)
  li a1, 0xBEEF       # 将立即数 0xBEEF 加载到寄存器 a1 中,a1=BEEFH
  sw a1, 4 (a0)        # 将寄存器 a1 的内容存储到地址 a0+4=80000004H 处,limit=BEEFH
  nop                 # 空指令,不执行任何操作
  lw t1, 4 (a0)        # 从地址 a0+4 处加载一个字(32 位)到寄存器 t1 中,t1=BEEFH
loop:
  j loop              # 无条件跳转到标签 loop 处

可知程序执行结束后,各个寄存器的内容如下:

  • a0:80000000H
  • a1:BEEFH
  • t0:05F5E100H
  • t1:BEEFH

且主存地址为 80000004H 处的 Timer 内部数据 limit 变为 BEEFH

# 测试用例的功能

测试了 CPU 能否与计时器 Timer 通信,并实现 CPU 作为主设备对 Timer 的读写功能

# 从什么层面测试 CPU

从总线上设备的通信层面测试了 CPU

# 加载测试程序指令的方法

利用定义在 src/main/scala/riscv/TestTopModule.scala 中的模块 TestTopModule ,使用任何 RISC-V 程序 src/main/resources/mmio.asmbin 初始化进行仿真测试

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 执行不同指令时候对应的部件的关键信号的变化情况

测试程序总共执行了 200 个时钟周期:

  • 前面几乎一半时间用来加载程序,波形图上表现为 ROMLoader 的状态变量 state 在这一段时间不断变化,然后稳定

  • 后面剩余时间用于 CPU 执行程序,波形图上表现为 IF 阶段的 io_id_instruction 变两在这段时间不断变化

当确保程序执行完毕后,测试程序检测结果,读取寄存器和内存的值,看其是否符合预期

# register_5[31:0]

CPU 5 号寄存器的值,即 t0 寄存器的值,最后结果为 05F5E100H,符合预期

# register_6[31:0]

CPU 6 号寄存器的值,即 t1 寄存器的值,最后结果为 BEEFH ,符合预期

# register_10[31:0]

CPU 10 号寄存器的值,即 a0 寄存器的值,最后结果为 80000000H,符合预期

# register_11[31:0]

CPU 11 号寄存器的值,即 a1 寄存器的值,最后结果为 BEEFH,符合预期

# limit[31:0]

计时器 Timer 的变量,即内存地址空间为 80000004H 的值,最后结果为 BEEFH,符合预期

# fivestage.MMIOTest

该测试与 threestage.MMIOTest 基本一致,不再重复分析

# 测试用例的执行结果

avatar

# 输出波形图

avatar

# 填空涉及到的信号分析

(src/main/scala/riscv/)

主要在填空代码处以注释的形式进行了分析

状态转移图:

avatar

# 在完成实验的过程中,遇到的关于实验指导不明确或者其他问题,或者改进的建议。

使用实验板上的数码管、视频输出等外设,输出一个完整程序的运行结果,或者参考硬件调试一节的内容,用硬件波形的方法捕获程序运行结果。给出你的 CPU 可以正确在实验板上运行程序的照片或者硬件调试器波形截图。

\ No newline at end of file diff --git a/cs/principles-of-computer-composition/yatcpu/yatcpu-report/index.html b/cs/principles-of-computer-composition/yatcpu/yatcpu-report/index.html index e4ebd2a4..aff9b72d 100644 --- a/cs/principles-of-computer-composition/yatcpu/yatcpu-report/index.html +++ b/cs/principles-of-computer-composition/yatcpu/yatcpu-report/index.html @@ -1 +1 @@ -YatCPU 实验报告 - YatCPU - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# YatCPU 实验报告

2023 年秋季学期的计算机组成原理实验项目 YatCPU 的实验报告

# YatCPU 相关资料

  • YatCPU 的教学文档仓库

  • 2023 年秋季学期由 Tokisakix 整理的文档仓库,新纳入了 docker 环境搭建脚本、zybo-z710 开发板移植及烧板脚本

# 实验报告

YatCPU - - - lab1 - - - lab2 - - - lab3 - - - lab4

# 关于挑战实验

阅读了 egos-2000 操作系统的文档和仓库,按照其教程实现了操作系统映像文件的编译和写入 microSD 卡的过程

但是 egos-2000 操作系统暂时只支持 Arty A7-35T board、A7-100T board 和 S7-50 board,移植到 z710 上比较困难,所以没能成功

关于开发板移植的问题仓库有人咨询过,作者给出的回答也很有参考价值:

avatar

目前只成功在 qemu 上运行了 egos-2000 操作系统:

avatar

附:我们的板子 z710 上原本有一个 ARM 处理器,在官方网站和文档可以查到官方配套的在 z710 上运行 linux 操作系统的方法和工具。但是这个方法使用的是已有的 ARM 处理器

\ No newline at end of file +YatCPU 实验报告 - YatCPU - 计算机组成原理 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# YatCPU 实验报告

2023 年秋季学期的计算机组成原理实验项目 YatCPU 的实验报告

# YatCPU 相关资料

  • YatCPU 的教学文档仓库

  • 2023 年秋季学期由 Tokisakix 整理的文档仓库,新纳入了 docker 环境搭建脚本、zybo-z710 开发板移植及烧板脚本

# 实验报告

YatCPU - - - lab1 - - - lab2 - - - lab3 - - - lab4

# 关于挑战实验

阅读了 egos-2000 操作系统的文档和仓库,按照其教程实现了操作系统映像文件的编译和写入 microSD 卡的过程

但是 egos-2000 操作系统暂时只支持 Arty A7-35T board、A7-100T board 和 S7-50 board,移植到 z710 上比较困难,所以没能成功

关于开发板移植的问题仓库有人咨询过,作者给出的回答也很有参考价值:

avatar

目前只成功在 qemu 上运行了 egos-2000 操作系统:

avatar

附:我们的板子 z710 上原本有一个 ARM 处理器,在官方网站和文档可以查到官方配套的在 z710 上运行 linux 操作系统的方法和工具。但是这个方法使用的是已有的 ARM 处理器

\ No newline at end of file diff --git a/cs/raspberrypi/static-ip/index.html b/cs/raspberrypi/static-ip/index.html index 0b0a390a..b8fbeaaa 100644 --- a/cs/raspberrypi/static-ip/index.html +++ b/cs/raspberrypi/static-ip/index.html @@ -1 +1 @@ -树莓派配置静态 ip - 树莓派 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

树莓派配置静态 ip

bash
sudo nano /etc/dhcpcd.conf

文件末尾添加:

bash
interface eth0
static ip_address=192.168.134.32/24
static routers=192.168.134.1
static domain_name_servers=192.168.134.1 8.8.8.8

其中 192.168.134.32 可以直接是路由器给树莓派分配的 ip 地址,作为静态 ip 地址

ctrl+s 保存,ctrl+x 退出,重启树莓派即可

\ No newline at end of file +树莓派配置静态 ip - 树莓派 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

树莓派配置静态 ip

bash
sudo nano /etc/dhcpcd.conf

文件末尾添加:

bash
interface eth0
static ip_address=192.168.134.32/24
static routers=192.168.134.1
static domain_name_servers=192.168.134.1 8.8.8.8

其中 192.168.134.32 可以直接是路由器给树莓派分配的 ip 地址,作为静态 ip 地址

ctrl+s 保存,ctrl+x 退出,重启树莓派即可

\ No newline at end of file diff --git a/cs/tools/cmake/index.html b/cs/tools/cmake/index.html index 3babcf43..b5a053d1 100644 --- a/cs/tools/cmake/index.html +++ b/cs/tools/cmake/index.html @@ -1 +1 @@ -CMake 基础 - 工具 - 编程语言 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# CMake 简介

CMake 官网:https://cmake.org

WIKI:https://en.wikipedia.org/wiki/CMake

CMake 自身也是一种编程语言,可以用它实现基本的程序逻辑,此如循环、条件分支等等,其中最典型的应用是根据工程的配置来选择性编译部分源代码,比如有些功能只有在测试版本中才会开启。

和其它的构建工具一样,CMake 的本质依然是定义各个目标之间的关联,比如您的项目由哪些可执行文件、动态库、资源文件组成,然后它们又是通过哪些源文件编译,用到了哪些外部关联等等,本身并没有编译和链接的功能。

除了基本的构建功能之外,CMake 还允许您添加单元测试、创建安装包、或者将工程拆分成若干个子目录更利于大型项目的管理。

CMake 与 (GNU) Make 类似,不同之处在于 Make 只是一个命令行工具,用于自动化构建和编译软件项目。Make 使用 Makefile 文件来定义构建过程和依赖关系而 CMake 使用 CMakeLists.txt 。Make 最初是为 Unix 系统设计的,但现在也可用于其他操作系统,且不同平台需要编写不同的 Makefile 文件,而 CMake 则支持跨平台,无需为不同平台分别编写 CMakeLists.txt 文件,还可以更好的实现复杂庞大的项目,功能更加强大,更加方便。

# CMakeLists.txt

一个比较完整的 CMakeLists.txt 内容如下:

工程所需最低 cmake 版本

cmake
cmake_minimum_required(VERSION 3.10)

工程名字 Example

cmake
project (Example)

需要的第三方库 example ,其中 REQUIRED 表示这个库是必须的
cmake 会自动在机器中寻找符合要求、支持 cmake 构建的第三方库

cmake
find_package(example REQUIRED)

用 GLOB 指令将所有源文件存到变量 SRC_FILE 中

cmake
File(GLOB SRC_FILES
	"${PROJECT_SOURCE_DIR}/src/*.h"
	"${PROJECT_SOURCE_DIR}/src/*.cpp"
	"${PROJECT_ SOURCE_DIR}/src/*.c"
	"${ PROJECT_SOURCE_DIR}/src/*.cc")	# 用正则表达式匹配所有源文件

构建一个可执行文件,名字为 CMAKE_PROJECT_NAME 即为 Example 工程名字,由 SRC_FILES 里所有文件编译而成

cmake
add_executable(${CMAKE_PROJECT_NAME} ${SRC_FILES})

使用了多个第三方库,需要进行第三方库的链接,否则会出现经典的符号无法解析的报错

cmake
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE imgui::imgui)
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE glfw)
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE GLEW: :GLEW)
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE gim)

打开对 c++17 的语法支持

cmake
target_compile features (${CMAKE_PROJECT_MAME} PRIVATE cxx_std_17)

简单的自动化脚本,在构建结束后复制所有 文件

cmake
add_custom_command(
  TARGET ${CMAKE_ PROJECT_NAME}
  POST_BUILD		# 表示在【构建】完成后执行
  COMMAND ${CMAKE_COMMAND} -E copy_directory
  	"${PROJECT_SOURCE_DIR}/assets"
  	"$<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>/assets")
cmake
add_custom_command (
  TARGET ${CMAKE_PROJECT_NAME}
  POST_BUILD
  COMMAND ${CMAKE_COMMAND}-E copy_directory
    "${PROJECT_SOURCE_DIR) /shader/"
    "$<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>/shader")

# 配置 (Configure)

根据 CMakeLists 文件生成目标平台下的原生工程

bash
cmake -S . -B build

使用了第三方库时,若使用 vcpkg 管理第三方库,则需要:

bash
cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=<vcpkg安装路径:.../vcpkg>/scripts/buildsystems/vcpkg.cmake

使用 VScode 则需在 settings.json 中添加:

json
{
  "make configureSettings":{"MAKE_TOOLCHAIN_FILE": "<vcpkg安装路径:.../vcpkg>/scripts/buildsystems/vcpkg.cmake"
	}
}

# 构建 (Build)

构建生成可执行文件

bash
cmake --build build

# 第三方库

使用微软的跨平台开源工具 vcpkg 可以更方便的安装和管理 c/c++ 第三方库,类似 python 的 pip

Edited on Views times
\ No newline at end of file +CMake 基础 - 工具 - 编程语言 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# CMake 简介

CMake 官网:https://cmake.org

WIKI:https://en.wikipedia.org/wiki/CMake

CMake 自身也是一种编程语言,可以用它实现基本的程序逻辑,此如循环、条件分支等等,其中最典型的应用是根据工程的配置来选择性编译部分源代码,比如有些功能只有在测试版本中才会开启。

和其它的构建工具一样,CMake 的本质依然是定义各个目标之间的关联,比如您的项目由哪些可执行文件、动态库、资源文件组成,然后它们又是通过哪些源文件编译,用到了哪些外部关联等等,本身并没有编译和链接的功能。

除了基本的构建功能之外,CMake 还允许您添加单元测试、创建安装包、或者将工程拆分成若干个子目录更利于大型项目的管理。

CMake 与 (GNU) Make 类似,不同之处在于 Make 只是一个命令行工具,用于自动化构建和编译软件项目。Make 使用 Makefile 文件来定义构建过程和依赖关系而 CMake 使用 CMakeLists.txt 。Make 最初是为 Unix 系统设计的,但现在也可用于其他操作系统,且不同平台需要编写不同的 Makefile 文件,而 CMake 则支持跨平台,无需为不同平台分别编写 CMakeLists.txt 文件,还可以更好的实现复杂庞大的项目,功能更加强大,更加方便。

# CMakeLists.txt

一个比较完整的 CMakeLists.txt 内容如下:

工程所需最低 cmake 版本

cmake
cmake_minimum_required(VERSION 3.10)

工程名字 Example

cmake
project (Example)

需要的第三方库 example ,其中 REQUIRED 表示这个库是必须的
cmake 会自动在机器中寻找符合要求、支持 cmake 构建的第三方库

cmake
find_package(example REQUIRED)

用 GLOB 指令将所有源文件存到变量 SRC_FILE 中

cmake
File(GLOB SRC_FILES
	"${PROJECT_SOURCE_DIR}/src/*.h"
	"${PROJECT_SOURCE_DIR}/src/*.cpp"
	"${PROJECT_ SOURCE_DIR}/src/*.c"
	"${ PROJECT_SOURCE_DIR}/src/*.cc")	# 用正则表达式匹配所有源文件

构建一个可执行文件,名字为 CMAKE_PROJECT_NAME 即为 Example 工程名字,由 SRC_FILES 里所有文件编译而成

cmake
add_executable(${CMAKE_PROJECT_NAME} ${SRC_FILES})

使用了多个第三方库,需要进行第三方库的链接,否则会出现经典的符号无法解析的报错

cmake
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE imgui::imgui)
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE glfw)
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE GLEW: :GLEW)
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE gim)

打开对 c++17 的语法支持

cmake
target_compile features (${CMAKE_PROJECT_MAME} PRIVATE cxx_std_17)

简单的自动化脚本,在构建结束后复制所有 文件

cmake
add_custom_command(
  TARGET ${CMAKE_ PROJECT_NAME}
  POST_BUILD		# 表示在【构建】完成后执行
  COMMAND ${CMAKE_COMMAND} -E copy_directory
  	"${PROJECT_SOURCE_DIR}/assets"
  	"$<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>/assets")
cmake
add_custom_command (
  TARGET ${CMAKE_PROJECT_NAME}
  POST_BUILD
  COMMAND ${CMAKE_COMMAND}-E copy_directory
    "${PROJECT_SOURCE_DIR) /shader/"
    "$<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>/shader")

# 配置 (Configure)

根据 CMakeLists 文件生成目标平台下的原生工程

bash
cmake -S . -B build

使用了第三方库时,若使用 vcpkg 管理第三方库,则需要:

bash
cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=<vcpkg安装路径:.../vcpkg>/scripts/buildsystems/vcpkg.cmake

使用 VScode 则需在 settings.json 中添加:

json
{
  "make configureSettings":{"MAKE_TOOLCHAIN_FILE": "<vcpkg安装路径:.../vcpkg>/scripts/buildsystems/vcpkg.cmake"
	}
}

# 构建 (Build)

构建生成可执行文件

bash
cmake --build build

# 第三方库

使用微软的跨平台开源工具 vcpkg 可以更方便的安装和管理 c/c++ 第三方库,类似 python 的 pip

Edited on Views times
\ No newline at end of file diff --git a/cs/tools/vscode-remote-ssh-login-shell/index.html b/cs/tools/vscode-remote-ssh-login-shell/index.html index b904f8ea..8c622ec0 100644 --- a/cs/tools/vscode-remote-ssh-login-shell/index.html +++ b/cs/tools/vscode-remote-ssh-login-shell/index.html @@ -1 +1 @@ -VSCode 远程 SSH 连接的 shell 相关一个 bug - 工具 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 环境 / 情景

MacOS 14.2 M1 用 VSCode 远程连接 Ubuntu 22.04

# 问题

在虚拟机上安装了 Enviroment Modules ,并按照官方配置文档配置了 bash 启动时自动加载 module 指令,ssh 远程登录虚拟机 'module' 指令可用,但是 VSCode 远程连接虚拟机发现 module 指令使用不了。

# 原因

在 VSCode 的 bash 中检查发现当前 shell 不是登录式的:

shell
shopt login_shell
# 结果为 off 不是登陆式
login_shell    	off

分析发现由于 VSCode 启动 shell 是非登陆式,参考这篇,所以没有加载 /etc/profile 文件,而该文件下包含如下内容:

shell
if [ -d /etc/profile.d ]; then
  for i in /etc/profile.d/*.sh; do
    if [ -r $i ]; then
      . $i
    fi
  done
  unset i
fi

因此也没有加载 /etc/profile.d/ 目录下的文件,自然也没有加载 Enviroment Modules 官方文档配置的 /etc/profile.d/modules.sh/etc/profile.d/modules.csh 这些 Linux Link。导致了 VSCode 的终端无法使用 'module' 指令。

去官方文档搜索找到了一个 open 的 issue :https://github.com/microsoft/vscode-remote-release/issues/8484 ,也是同样的问题,暂时没有解决。

# 临时解决方案

暂时无法从 VSCode 这一远程连接服务端解决,那就只能:

  • 要么从控制端解决,每次 VSCode 打开一个 shell 后手动输指令加载 /etc/profile 文件
  • 要么从受控端解决
    • 在 Ubuntu 里编辑 /etc/bash.bashrc~/.bashrc 让它加载 /etc/profile 等 login shell 才能加载的文件,虽然保证了 VSCode 的 shell 环境能够与 login shell 一致更方便了,但是这么做修改了系统设计可能会导致其他问题。
    • 更安全的做法是单独在 /etc/bash.bashrc~/.bashrc 里添加单独加载指定的需要的配置文件,还可以单独自定义一个目录存放这样的配置文件并用 iffor 加载这个目录所有文件(模仿 /etc/profile 文件里的操作)。
\ No newline at end of file +VSCode 远程 SSH 连接的 shell 相关一个 bug - 工具 - 计算机科学 | Balloon Party = 風船のパーティー = fuusen no party

# 环境 / 情景

MacOS 14.2 M1 用 VSCode 远程连接 Ubuntu 22.04

# 问题

在虚拟机上安装了 Enviroment Modules ,并按照官方配置文档配置了 bash 启动时自动加载 module 指令,ssh 远程登录虚拟机 'module' 指令可用,但是 VSCode 远程连接虚拟机发现 module 指令使用不了。

# 原因

在 VSCode 的 bash 中检查发现当前 shell 不是登录式的:

shell
shopt login_shell
# 结果为 off 不是登陆式
login_shell    	off

分析发现由于 VSCode 启动 shell 是非登陆式,参考这篇,所以没有加载 /etc/profile 文件,而该文件下包含如下内容:

shell
if [ -d /etc/profile.d ]; then
  for i in /etc/profile.d/*.sh; do
    if [ -r $i ]; then
      . $i
    fi
  done
  unset i
fi

因此也没有加载 /etc/profile.d/ 目录下的文件,自然也没有加载 Enviroment Modules 官方文档配置的 /etc/profile.d/modules.sh/etc/profile.d/modules.csh 这些 Linux Link。导致了 VSCode 的终端无法使用 'module' 指令。

去官方文档搜索找到了一个 open 的 issue :https://github.com/microsoft/vscode-remote-release/issues/8484 ,也是同样的问题,暂时没有解决。

# 临时解决方案

暂时无法从 VSCode 这一远程连接服务端解决,那就只能:

  • 要么从控制端解决,每次 VSCode 打开一个 shell 后手动输指令加载 /etc/profile 文件
  • 要么从受控端解决
    • 在 Ubuntu 里编辑 /etc/bash.bashrc~/.bashrc 让它加载 /etc/profile 等 login shell 才能加载的文件,虽然保证了 VSCode 的 shell 环境能够与 login shell 一致更方便了,但是这么做修改了系统设计可能会导致其他问题。
    • 更安全的做法是单独在 /etc/bash.bashrc~/.bashrc 里添加单独加载指定的需要的配置文件,还可以单独自定义一个目录存放这样的配置文件并用 iffor 加载这个目录所有文件(模仿 /etc/profile 文件里的操作)。
\ No newline at end of file diff --git a/css/app.css b/css/app.css index 2ba658c3..69b32f97 100644 --- a/css/app.css +++ b/css/app.css @@ -1,3 +1,3 @@ -/* build time:Wed Aug 14 2024 22:47:41 GMT+0800 (中国标准时间)*/ +/* build time:Wed Aug 14 2024 23:17:33 GMT+0800 (中国标准时间)*/ #nav .menu .item:not(.title) a::before{content:"";position:absolute;width:0;height:.1875rem;bottom:0;border-radius:.125rem;left:50%;transform:translateX(-50%);background-color:currentColor}#nav .menu .submenu .item.active,#nav .menu .submenu .item:hover,#search-pagination .current .page-number,#sidebar .tab .item.active,#sidebar .tab .item:hover,.overview .menu .item.active,.pagination .next:hover,.pagination .page-number.current,.pagination .page-number:hover,.pagination .prev:hover{color:var(--grey-0);background-image:linear-gradient(to right,var(--color-pink) 0,var(--color-orange) 100%);box-shadow:0 0 .75rem var(--color-pink-a3)}#loading,#neko{position:fixed;left:0;right:0;top:0;bottom:0;z-index:9999}:root{--grey-0:#fff;--grey-1:#fdfdfd;--grey-2:#f7f7f7;--grey-3:#eff2f3;--grey-4:#ccc;--grey-5:#999;--grey-6:#666;--grey-7:#333;--grey-8:#222;--grey-9:#000;--grey-1-a0:rgba(253,253,253,0);--grey-1-a7:rgba(253,253,253,0.7);--grey-1-a5:rgba(253,253,253,0.5);--grey-1-a3:rgba(253,253,253,0.3);--grey-9-a1:rgba(0,0,0,0.1);--grey-9-a5:rgba(0,0,0,0.5);--grey-2-a0:rgba(247,247,247,0);--color-pink-light:#ffe6fa;--color-cyan-light:#e3fdf5;--color-red:#e9546b;--color-pink:#ed6ea0;--color-orange:#ec8c69;--color-yellow:#eab700;--color-green:#0a7426;--color-aqua:#3e999f;--color-blue:#38a1db;--color-purple:#9d5b8b;--color-grey:#869194;--color-red-a1:rgba(233,84,107,0.1);--color-red-a3:rgba(233,84,107,0.3);--color-pink-a3:rgba(237,110,160,0.3);--color-pink-light-a3:rgba(255,230,250,0.3);--color-pink-light-a5:rgba(255,230,250,0.5);--color-pink-light-a7:rgba(255,230,250,0.7);--body-bg-shadow:var(--grey-2);--box-bg-shadow:var(--grey-9-a1);--text-color:var(--grey-7);--header-text-color:var(--grey-0);--primary-color:var(--color-red);--nav-bg:linear-gradient(-225deg, var(--color-cyan-light) 0, var(--color-pink-light) 100%)}.primary{--note-border:#cda0c7;--note-bg:#fdf8ff;--note-text:#8a51c0;--note-hover:#935aca}.info{--note-border:#8fa4dc;--note-bg:#f1f9ff;--note-text:#1d4974;--note-hover:#1d5fa0}.success{--note-border:#a3c293;--note-bg:#fcfff5;--note-text:#2c662d;--note-hover:#3b883c}.warning{--note-border:#c9ba9b;--note-bg:#fffbeb;--note-text:#947600;--note-hover:#ccb045}.danger{--note-border:#f4b3c1;--note-bg:#fff2f5;--note-text:#cc0f35;--note-hover:#f14668}[data-theme=dark]:root{--grey-0:#222;--grey-1:#21252b;--grey-2:#363636;--grey-3:#444;--grey-4:#666;--grey-5:#aaa;--grey-6:#ccc;--grey-7:#ddd;--grey-8:#eee;--grey-9:#f7f7f7;--grey-1-a7:rgba(34,34,34,0.7);--grey-1-a5:rgba(34,34,34,0.5);--grey-1-a3:rgba(34,34,34,0.3);--grey-1-a0:rgba(34,34,34,0);--grey-9-a1:rgba(51,51,51,0.1);--grey-2-a0:rgba(54,54,54,0);--color-pink-light:#322d31;--color-cyan-light:#2d3230;--color-red:rgba(237,118,137,0.9);--color-pink:rgba(241,139,179,0.8);--color-orange:rgba(240,163,135,0.8);--color-yellow:#ffe175;--color-green:#86c59d;--color-aqua:#97d3d6;--color-blue:#9cd0ed;--color-purple:#cfacc5;--color-grey:#c3c8ca;--body-bg-shadow:#000;--box-bg-shadow:#000;--text-color:var(--grey-5);--header-text-color:var(--grey-9)}[data-theme=dark] .primary{--note-border:rgba(123,96,119,0.8);--note-bg:rgba(50,49,50,0.8);--note-text:rgba(161,116,205,0.8);--note-hover:rgba(117,72,161,0.8)}[data-theme=dark] .info{--note-border:rgba(85,98,132,0.8);--note-bg:rgba(48,49,50,0.8);--note-text:rgba(109,164,219,0.8);--note-hover:rgba(39,127,214,0.8)}[data-theme=dark] .success{--note-border:rgba(97,116,88,0.8);--note-bg:rgba(50,50,48,0.8);--note-text:rgba(128,200,129,0.8);--note-hover:rgba(41,95,42,0.8)}[data-theme=dark] .warning{--note-border:rgba(120,111,93,0.8);--note-bg:rgba(50,50,46,0.8);--note-text:rgba(220,176,0,0.8);--note-hover:rgba(163,140,55,0.8)}[data-theme=dark] .danger{--note-border:rgba(146,107,115,0.8);--note-bg:rgba(50,48,48,0.8);--note-text:rgba(239,38,79,0.8);--note-hover:rgba(168,49,72,0.8)}[data-theme=dark] .index.wrap .card .message .btn,[data-theme=dark] .overview .menu .item,[data-theme=dark] .sidebar .tab li,[data-theme=dark] [data-background-image],[data-theme=dark] img{transition:all .2s ease-in-out 0s;opacity:.75}[data-theme=dark] .index.wrap .card .message .btn:hover,[data-theme=dark] .overview .menu .item:hover,[data-theme=dark] .sidebar .tab li:hover,[data-theme=dark] [data-background-image]:hover,[data-theme=dark] img:hover{opacity:.9}[data-theme=dark] #imgs::before{background-color:rgba(0,0,0,.5)}.red{color:var(--color-red)}.pink{color:var(--color-pink)}.orange{color:var(--color-orange)}.yellow{color:var(--color-yellow)}.green{color:var(--color-green)}.aqua{color:var(--color-aqua)}.blue{color:var(--color-blue)}.purple{color:var(--color-purple)}.grey{color:var(--color-grey)}.i-bilibili:before{content:"\e652"}.i-volume-off:before,.player-info .volume.off::before{content:"\e61e"}.i-volume-on:before,.player-info .volume.on::before{content:"\e62c"}.i-circle-play:before,.player-info .play-pause::before{content:"\e647"}.i-forward:before,.player-info .forward::before{content:"\e648"}.i-backward:before,.player-info .backward::before{content:"\e649"}.i-circle-pause:before,.playing .player-info .play-pause::before{content:"\e64a"}.i-loop:before,.player-info .mode.loop::before{content:"\e64b"}.i-order:before,.player-info .mode.order::before{content:"\e64c"}.i-random:before,.player-info .mode.random::before{content:"\e64d"}.i-douban:before{content:"\e75f"}.i-linux:before{content:"\f1e8"}.i-opera:before{content:"\f205"}.i-qq:before{content:"\f216"}.i-safari:before{content:"\f229"}.i-snapchat-ghost:before{content:"\f234"}.i-weixin:before{content:"\f262"}.i-windows:before{content:"\f266"}.i-stars:before{content:"\e8c4"}.i-apple:before{content:"\e600"}.i-blackberry:before{content:"\e601"}.i-centos:before{content:"\e602"}.i-fedora:before{content:"\e603"}.i-redhat:before{content:"\e604"}.i-ubuntu:before{content:"\e605"}.i-suse:before{content:"\e606"}.i-mobile-alt:before{content:"\f052"}.i-paw:before{content:"\f06b"}.i-android:before{content:"\f161"}.i-chrome:before{content:"\f178"}.i-edge:before{content:"\f195"}.i-firefox:before{content:"\f1a1"}.i-internet-explorer:before{content:"\f1d4"}.i-markdown:before{content:"\f1eb"}.i-smile:before{content:"\f2a5"}.i-preview:before{content:"\e901"}#copyright .license::before,.i-share:before{content:"\e61b"}#copyright .link::before,.i-link-circle:before{content:"\e67b"}#copyright .author::before,.i-person:before{content:"\e69d"}.i-sun:before{content:"\e6d1"}.i-moon:before{content:"\e71e"}.i-compress:before{content:"\ef82"}.i-expand:before{content:"\efb4"}.i-align-justify:before{content:"\ef13"}.i-align-left:before{content:"\ef14"}.i-eye:before{content:"\efb8"}.i-pen:before{content:"\f071"}.i-clock:before{content:"\ef75"}.i-flag:before{content:"\e680"}.i-at:before{content:"\e619"}.i-file:before{content:"\e68d"}.i-clipboard:before{content:"\e651"}.i-feather:before{content:"\efbd"}#tool .player .music::before,.i-music:before{content:"\f059"}#tool.playing .player .play-pause::before,.i-pause:before{content:"\f06a"}.i-comments:before{content:"\ef7f"}#tool .player .play-pause::before,.i-play:before,.player-info ol>li.current::before{content:"\f07f"}.i-calendar-check:before{content:"\ef5b"}.i-angle-up:before{content:"\ef1b"}.i-facebook:before{content:"\f19d"}.i-instagram:before{content:"\f1d3"}.i-skype:before{content:"\f231"}.i-stack-overflow:before{content:"\f239"}.i-youtube:before{content:"\f274"}.i-list-alt:before{content:"\e6c1"}.i-star:before,.page .body h3 .anchor::before{content:"\f0d4"}.i-link-alt:before{content:"\f037"}.i-paper-plane:before{content:"\f063"}.i-user:before{content:"\f2dd"}.i-link:before{content:"\e8fc"}.i-angle-down:before,details[open] summary::before{content:"\ef1a"}.i-calendar:before{content:"\e812"}#sidebar .tab .item.overview::before,.i-home:before{content:"\e8ed"}.i-magic:before{content:"\f03e"}.i-sakura:before,.page .body h1 .anchor::before{content:"\e695"}.i-tag:before{content:"\e759"}.i-angle-left:before{content:"\ef19"}.i-arrow-circle-right:before,.md .note.default::before{content:"\ef23"}.i-check-circle:before,.md .note.success::before,.md ul li.task-list-item input[type=checkbox]:checked+label::before{content:"\ef66"}.i-exclamation-circle:before,.md .note.warning::before{content:"\efb5"}.i-info-circle:before,.md .note.info::before{content:"\f02b"}.i-minus-circle:before,.md .note.danger::before{content:"\f050"}.i-plus-circle:before,.md .note.primary::before{content:"\f082"}.i-file-word:before{content:"\f299"}.i-check:before,.md ol>li.quiz.show.true::after,.md ol>li.quiz>ul.options li.right::after{content:"\ef65"}.i-times:before,.md ol>li.quiz.show.false::after,.md ol>li.quiz>ul.options li.wrong::after{content:"\f109"}#sidebar .tab .item.contents::before,.i-list-ol:before{content:"\f039"}.i-archive:before{content:"\ef1c"}.i-angle-right:before,details summary::before{content:"\ef1f"}.i-arrow-down:before{content:"\ef25"}.i-arrow-up:before,.tabs .show-btn::before{content:"\ef2a"}.i-chart-area:before{content:"\ef64"}.i-chevron-left:before{content:"\ef6e"}.i-chevron-right:before{content:"\ef6f"}.i-coffee:before{content:"\ef7a"}.i-envelope:before{content:"\efae"}.i-external-link-alt:before{content:"\efb6"}.i-heart:before{content:"\f013"}.i-heartbeat:before,.page .body h2 .anchor::before{content:"\f017"}.i-search:before{content:"\f0a8"}#sidebar .tab .item.related::before,.i-sitemap:before{content:"\f0bd"}.i-tags:before{content:"\f0f3"}.i-th:before{content:"\f0fc"}.i-thumbtack:before{content:"\f107"}.i-times-circle:before,.md ul li.task-list-item input[type=checkbox]+label::before{content:"\f10a"}.i-creative-commons:before{content:"\f17e"}.i-github:before{content:"\f1b4"}.i-twitter:before{content:"\f24d"}.i-weibo:before{content:"\f261"}.i-address-card:before{content:"\f278"}.i-zhihu:before{content:"\e765"}.i-cloud-music:before{content:"\e76a"}html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background:0 0}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:.0625rem dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-0.125rem;-webkit-appearance:textfield}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}::-webkit-scrollbar{width:.3125rem;height:.3125rem;background:0 0}::-webkit-scrollbar-track{border-radius:.3125rem;background:0 0}::-webkit-scrollbar-track-piece{background:0 0}::-webkit-scrollbar-button{background:0 0;height:0}::-webkit-scrollbar-thumb{border-radius:1.25rem;background-clip:padding-box;background-color:var(--grey-3);background-image:linear-gradient(45deg,var(--grey-1-a5) 25%,transparent 0,transparent 50%,var(--grey-1-a5) 0,var(--grey-1-a5) 75%,transparent 0,transparent)}body.loaded::-webkit-scrollbar{width:.5rem;height:.5rem}body.loaded::-webkit-scrollbar-thumb{background-color:var(--color-pink-light)}.page .body h1 .anchor::before,.rotate{animation:rotate 6s linear infinite}.beat,.page .body h2 .anchor::before{animation:beat 1.33s ease-in-out infinite}.flash,.page .body h3 .anchor::before{animation:flash 6s cubic-bezier(.22,.61,.36,1) infinite}.overview .author:hover .image,.ribbon a:hover,.shake{animation:shake 1s}.fade-in,.tabs .tab,.tip,details[open]>div{animation:fadeIn .5s}#tool.affix .player-info.show.hide,.fade-out,.tip.hide{animation:fadeOut .3s}.code-container .show-btn .ic,.up-down{animation:UpDown 2s infinite}.code-container .show-btn.open .ic,.down-up{animation:DownUp 2s infinite}.md ol>li.quiz.show .note,.md ol>li.quiz.show blockquote,.slide{animation:slide .5s}#nav .menu .submenu,.slide-up-in{animation:slideUpIn .3s}.cards .item.show,.segments>.item.show,.slide-up-big-in,body.loaded #main .wrap,body.loaded #sidebar .panel.active{animation:slideUpBigIn .5s}#tool.affix .player-info.show,.slide-right-in{animation:slideRightIn .3s}.slide-left-in{animation:slideLeftIn .3s}.overview .menu .item .submenu,.slide-down-in,body.loaded #brand .pjax{animation:slideDownIn .3s}.blur,.lozaded{animation:blur .8s ease-in-out forwards}.elastic,.highlight.fullscreen{animation:elastic 1s}@keyframes rotate{from{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes rotating{from{transform:rotate(720deg)}to{transform:none}}@keyframes rotate-needle-pause{0%{transform:rotateZ(-35deg)}100%{transform:rotateZ(-60deg)}}@keyframes rotate-needle-resume{0%{transform:rotateZ(-60deg)}100%{transform:rotateZ(-35deg)}}@keyframes beat{0%,100%{transform:scale(1)}10%,30%{transform:scale(.9)}20%,40%,60%,80%{transform:scale(1.1)}50%,70%{transform:scale(1.1)}}@keyframes flash{0%,50%,to{opacity:1}25%,75%{opacity:0}}@keyframes shake{from,to{transform:translate3d(0,0,0)}10%,30%,50%,70%,90%{transform:translate3d(-10px,0,0)}20%,40%,60%,80%{transform:translate3d(10px,0,0)}}@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@keyframes blur{0%{filter:blur(10px)}to{filter:blur(0)}}@keyframes blur-dark{0%{filter:blur(10px) brightness(.9)}to{filter:blur(0) brightness(.9)}}@keyframes UpDown{0%,100%{opacity:.8;transform:translateY(10px)}50%{opacity:.4;transform:translateY(0)}}@keyframes DownUp{0%,100%{opacity:.8;transform:rotate(180deg) translateY(0)}50%{opacity:.4;transform:rotate(180deg) translateY(-10px)}}@keyframes slide{0%{opacity:0;transform:scaleY(0)}100%{opacity:1;transform:scaleY(1)}}@keyframes slideRightIn{0%{opacity:0;transform:translateX(50%)}to{opacity:1;transform:translateX(0)}}@keyframes slideLeftIn{0%{opacity:0;transform:translateX(-50%)}to{opacity:1;transform:translateX(0)}}@keyframes slideUpIn{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes slideUpBigIn{0%{opacity:0;transform:translateY(80px)}100%{opacity:1;transform:translateY(0)}}@keyframes slideDownIn{0%{opacity:0;transform:translateY(-18px)}100%{opacity:1;transform:translateY(0)}}@keyframes elastic{0%{transform:scale(0)}55%{transform:scale(1)}70%{transform:scale(.98)}100%{transform:scale(1)}}::-moz-selection{background:var(--color-orange);color:var(--grey-2)}::selection{background:var(--color-orange);color:var(--grey-2)}*,:after,:before{box-sizing:border-box;margin:0;padding:0}body,html{height:100%}body{background:linear-gradient(to top,var(--body-bg-shadow) 0,var(--grey-1) 20%) no-repeat bottom;color:var(--text-color);font-family:Mulish,-apple-system,"PingFang SC","Microsoft YaHei",sans-serif;font-size:1em;line-height:2;-webkit-font-smoothing:antialiased;overflow:hidden}body.loaded{overflow:auto}body.loaded #sidebar .panel.active{display:block}@media (max-width:991px){body{padding-left:0!important;padding-right:0!important}}body.fullscreen{overflow:hidden}body.fullscreen #sidebar>.inner,body.fullscreen #tool{z-index:0}h1,h2,h3,h4,h5,h6{font-family:Mulish,'Noto Serif SC','Noto Serif JP',Mulish,-apple-system,"PingFang SC","Microsoft YaHei",sans-serif;font-weight:700;line-height:1.5;margin:1.25rem 0 .9375rem}h1.title,h2.title,h3.title,h4.title,h5.title,h6.title{font-family:Mulish,'Noto Serif JP','Noto Serif SC',Mulish,-apple-system,"PingFang SC","Microsoft YaHei",sans-serif}a{border:none;color:currentColor;outline:0;text-decoration:none;overflow-wrap:break-word;word-wrap:break-word;transition:all .2s ease-in-out 0s;cursor:pointer}a:hover{border-bottom-color:var(--color-blue);color:var(--color-blue)}a::after,a::before{transition:all .4s ease-in-out 0s}a,div,li{-webkit-tap-highlight-color:transparent}li{list-style:none}iframe,img,video{display:block;margin-left:auto;margin-right:auto;max-width:100%}hr{background-image:repeating-linear-gradient(-45deg,var(--grey-3),var(--grey-4) .25rem,transparent .25rem,transparent .5rem);border:none;height:.125rem;margin:1.5rem 0}blockquote{border-left:.25rem solid var(--grey-4);color:var(--grey-6);margin:1.25rem 0;padding:.625rem 1.25rem}blockquote cite::before{content:'-';padding:0 .3125rem}dt{font-weight:700}dd{margin:0;padding:0}input,textarea{color:var(--text-color)}@font-face{font-family:ic;src:url("//at.alicdn.com/t/font_1832207_igi8uaupcus.eot");src:url("//at.alicdn.com/t/font_1832207_igi8uaupcus.eot?#iefix") format('embedded-opentype'),url("//at.alicdn.com/t/font_1832207_igi8uaupcus.woff2") format('woff2'),url("//at.alicdn.com/t/font_1832207_igi8uaupcus.woff") format('woff'),url("//at.alicdn.com/t/font_1832207_igi8uaupcus.ttf") format('truetype'),url("//at.alicdn.com/t/font_1832207_igi8uaupcus.svg#ic") format('svg')}.ic{font-family:ic!important;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-align:center;width:1.25em;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.ic em{font-size:0}.ic-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.table-container{overflow:auto}.table-container table{border-collapse:collapse;border-spacing:0;font-size:.875em;margin:0 0 1.25rem 0;width:100%;overflow:auto}.table-container table tbody tr:nth-of-type(2n){background:var(--grey-0)}.table-container table tbody tr:hover{background:var(--grey-2)}.table-container table caption,.table-container table td,.table-container table th{font-weight:400;padding:.5rem;text-align:left;vertical-align:middle}.table-container table td,.table-container table th{border:.0625rem solid var(--grey-3);border-bottom:.1875rem solid var(--grey-3)}.table-container table th{font-weight:700;padding-bottom:.625rem;text-align:center}.table-container table td{border-bottom-width:.0625rem}.table-container table td .highlight:last-child,.table-container table td p:last-child,.table-container table td pre:last-child{margin:0}.button{display:inline-block;cursor:pointer;touch-action:manipulation;text-align:center;text-decoration:none;vertical-align:middle;white-space:nowrap;border-radius:.3rem;border:.0625rem solid var(--grey-3);color:var(--grey-6);font-size:.875em;font-weight:400;line-height:1.5;background:0 0;margin-bottom:0;min-height:1em;padding:.5em 1.25em;-webkit-user-select:none;-moz-user-select:none;user-select:none;outline:0;will-change:auto;transition:all .2s ease-in-out 0s}.button+.button{margin-left:1.25em}.button:active,.button:hover{color:var(--grey-0);background-color:var(--primary-color);border-color:var(--primary-color)}.button:disabled{border-color:var(--grey-4);color:var(--grey-4);background-color:var(--grey-2);cursor:not-allowed}.button .ic{text-align:left;width:1.285714285714286em}.toggle{line-height:0;cursor:pointer}.toggle .line{background:var(--header-text-color);display:inline-block;height:.125rem;left:0;position:relative;border-radius:.0625rem;top:0;transition:all .4s;vertical-align:top;width:100%;box-shadow:0 0 .5rem rgba(0,0,0,.5)}.toggle .line:not(:first-child){margin-top:.1875rem}.toggle.toggle-arrow .toggle-line-first{left:50%;top:.125rem;transform:rotate(45deg);width:50%}.toggle.toggle-arrow .toggle-line-middle{left:.125rem;width:90%}.toggle.toggle-arrow .toggle-line-last{left:50%;top:-.125rem;transform:rotate(-45deg);width:50%}.toggle.close .line:first-child{transform:rotate(-45deg);top:.3125rem}.toggle.close .line:nth-child(2){opacity:0}.toggle.close .line:nth-child(3){transform:rotate(45deg);top:-.3125rem}.pagination .next,.pagination .page-number,.pagination .prev,.pagination .space{display:inline-block;margin:0 .5rem;padding:0 .75rem;position:relative;border-radius:.3125rem}@media (max-width:767px){.pagination .next,.pagination .page-number,.pagination .prev,.pagination .space{margin:0 .3125rem}}.pagination{width:100%;padding:1.25rem 3.125rem;text-align:center;display:inline-block;color:var(--grey-5)}@media (max-width:767px){.pagination{padding:1.25rem .625rem}}.pagination .inner{width:auto;border-radius:.9375rem}.pagination .next,.pagination .page-number,.pagination .prev{transition:all .2s ease-in-out 0s}.pagination .space{margin:0;padding:0}.pagination .prev{margin-left:0}.pagination .next{margin-right:0}#search-pagination .current .page-number:hover,.pagination .page-number.current:hover{box-shadow:0 0 .3125rem var(--primary-color)}.tip{position:fixed;background:var(--grey-9-a5);color:#fff;top:50%;left:50%;z-index:9999;padding:.625rem 1rem;border-radius:.625rem;transform:translate(-50%,-50%);text-align:center;font-size:.875em;-webkit-backdrop-filter:blur(0.625rem);backdrop-filter:blur(0.625rem)}.ribbon{display:inline-block;align-self:flex-start;position:relative;padding:0 1rem 0 2rem;border-radius:0 .3rem .3rem 0;background-image:linear-gradient(to right,var(--color-orange) 0,var(--color-pink) 100%);color:var(--grey-0)}.ribbon::after{content:"";position:absolute;top:100%;left:0;width:0;height:0;background-color:transparent;border-style:solid;border-width:0 1rem 1rem 0;border-color:transparent;border-right-color:var(--color-orange);filter:brightness(.9)}.ribbon a{display:block;margin:0;text-align:center;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ribbon a:hover{color:currentColor}.divider{margin:1rem 0;line-height:1;height:0;font-weight:700;text-transform:uppercase;letter-spacing:.05rem;-webkit-user-select:none;-moz-user-select:none;user-select:none;color:var(--grey-4);display:table;white-space:nowrap;height:auto;line-height:1;text-align:center}.divider::after,.divider::before{content:'';display:table-cell;position:relative;top:50%;width:50%;background-repeat:no-repeat;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABaAAAAACCAYAAACuTHuKAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyFpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo1OThBRDY4OUNDMTYxMUU0OUE3NUVGOEJDMzMzMjE2NyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo1OThBRDY4QUNDMTYxMUU0OUE3NUVGOEJDMzMzMjE2NyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjU5OEFENjg3Q0MxNjExRTQ5QTc1RUY4QkMzMzMyMTY3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjU5OEFENjg4Q0MxNjExRTQ5QTc1RUY4QkMzMzMyMTY3Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+VU513gAAADVJREFUeNrs0DENACAQBDBIWLGBJQby/mUcJn5sJXQmOQMAAAAAAJqt+2prAAAAAACg2xdgANk6BEVuJgyMAAAAAElFTkSuQmCC")}.divider::before{background-position:right 1rem top 50%}.divider::after{background-position:left 1rem top 50%}#container{min-height:100%;min-width:100%;position:relative;display:flex;flex-direction:column}.inner{margin:0 auto;width:100%}main{background:linear-gradient(to top,var(--body-bg-shadow) 0,var(--grey-1) 20%) no-repeat bottom}main>.inner{width:calc(100% - .625rem);align-items:flex-start;display:flex;justify-content:space-between;flex-direction:row-reverse}@media (min-width:1200px){main>.inner{width:72.5rem}}@media (min-width:1600px){main>.inner{width:73%}}#main{background:linear-gradient(to top,var(--grey-0) 0,var(--grey-1) 20%) no-repeat top;box-shadow:0 1.25rem 1rem .3125rem var(--body-bg-shadow);width:calc(100% - 15.75rem);min-height:37.5rem}#main .cat{margin-top:10rem}#main .wrap{position:relative;padding:1.25rem}#main .wrap:first-child{margin-bottom:1.25rem}@media (max-width:991px){#main{width:100%}#main .wrap{padding:.625rem}}@media (max-width:767px){#main .wrap{padding:.5rem}}#header{margin:0 auto;position:relative;width:100%;height:50vh;text-shadow:0 .2rem .3rem rgba(0,0,0,.5);color:var(--header-text-color)}#header a:hover{color:currentColor}#imgs{display:block;position:fixed;top:0;left:0;width:100%;height:70vh;min-height:25rem;z-index:-9;background-color:#363636}#imgs img{width:100%;height:100%;position:absolute;top:0;left:0;-o-object-fit:cover;object-fit:cover}#imgs .item{width:100%;height:100%;position:absolute;top:0;left:0;background-size:cover;background-position:50% 50%;background-repeat:no-repeat;opacity:0;z-index:0;animation:imageAnimation 36s linear infinite 0s;backface-visibility:hidden;transform-style:preserve-3d}#imgs .item:nth-child(2){animation-delay:6s}#imgs .item:nth-child(3){animation-delay:12s}#imgs .item:nth-child(4){animation-delay:18s}#imgs .item:nth-child(5){animation-delay:24s}#imgs .item:nth-child(6){animation-delay:30s}#imgs .item:nth-child(7){animation-delay:36s}#imgs::before{content:'';display:block;position:absolute;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.2);z-index:1;transition:all .2s ease-in-out 0s}@keyframes imageAnimation{0%{opacity:0;animation-timing-function:ease-in}2%{opacity:1}8%{opacity:1;transform:scale(1.05);animation-timing-function:ease-out}17%{opacity:1;transform:scale(1.1)}25%{opacity:0;transform:scale(1.1)}100%{opacity:0}}#nav{position:fixed;z-index:9;width:100%;height:3.125rem;transition:all .2s ease-in-out 0s}#nav.up{transform:translateY(0)}#nav.down{transform:translateY(-100%)}#nav.show{background:var(--nav-bg);box-shadow:.1rem .1rem .2rem var(--grey-9-a1);text-shadow:0 0 .0625rem var(--grey-9-a1);color:var(--text-color)}#nav.show .line{background:var(--text-color);box-shadow:0 0 .0625rem var(--grey-9-a1)}#nav.show .item.active>a,#nav.show .item.expand>a{color:var(--color-aqua);opacity:1}#nav.show .menu .submenu{background-color:var(--grey-1)}#nav.show .menu .submenu .item.active a{color:var(--grey-0);opacity:1}#nav .inner{height:100%;display:flex;width:calc(100% - .625rem);flex-wrap:nowrap}@media (min-width:1200px){#nav .inner{width:72.5rem}}@media (min-width:1600px){#nav .inner{width:73%}}#nav .toggle{display:none}@media (max-width:991px){#nav .toggle{display:flex;flex-direction:column;justify-content:center;align-items:center}}#nav .toggle .lines{padding:1.25rem;width:1.375rem;box-sizing:unset}#nav .menu{padding:.625rem 0;margin:0;width:100%}#nav .menu .item{display:inline-block;position:relative;padding:0 .625rem;letter-spacing:.0625rem;text-align:center}@media (max-width:767px){#nav .menu .item{display:none}#nav .menu .item.title{display:block}}#nav .menu .item .ic{margin-right:.5rem}#nav .menu .item:not(.title) a{display:block;font-size:1em}#nav .menu .item.active:not(.dropdown) a::before,#nav .menu .item:not(.dropdown):hover a::before{width:70%}#nav .menu .submenu{display:none;position:absolute;margin-top:.5rem;padding:0;width:-moz-max-content;width:max-content;background-color:var(--grey-9-a5);box-shadow:0 .3125rem 1.25rem -.25rem var(--grey-9-a1);border-radius:.625rem 0}#nav .menu .submenu::before{position:absolute;top:-1.25rem;left:0;width:100%;height:2.5rem;content:''}#nav .menu .submenu:hover{display:block}#nav .menu .submenu .item{display:block}#nav .menu .submenu .item:first-child{border-radius:.625rem 0 0 0}#nav .menu .submenu .item:last-child{border-radius:0 0 .625rem 0}#nav .menu .submenu .item a{display:inline-block;padding:.3rem .7rem;width:100%;text-shadow:none}#nav .menu .submenu .item a::before{content:none}#nav .menu .submenu .item:hover a{transform:translateX(.3rem)}#nav .menu .submenu .item.active a,#nav .menu .submenu .item:hover a{opacity:1}#nav .menu .item.dropdown>a::after{content:"";display:inline-block;margin-left:.3rem;vertical-align:middle;border:.3rem solid transparent;border-top-color:currentColor;border-bottom:0}#nav .menu .item.dropdown:hover .submenu{display:block}#nav .right{display:inline-flex;align-items:center;justify-content:center}#nav .right .item{padding:.625rem .5rem;cursor:pointer}#nav .right .i-sun{font-size:1.125em}#brand{position:fixed;padding:3rem 5rem 0;text-align:center;width:100%;height:50vh;min-height:10rem}#brand.affix{z-index:-1}#brand,#brand .pjax{display:flex;flex-direction:column;justify-content:center;align-items:center}#brand .artboard{font-family:'Fredericka the Great',Mulish,-apple-system,"PingFang SC","Microsoft YaHei",sans-serif;font-size:3.5em;line-height:1.2}#brand h1{font-size:2.5em;letter-spacing:.125rem}#brand .artboard+h1{margin:.625rem 0}#brand .sticky{font-size:.75em;display:inline-block;transform:rotate(30deg);backface-visibility:hidden}#brand .meta{display:flex;font-size:.875em;margin:0}#brand .meta .item+.item{margin-left:.625rem}@media (min-width:768px) and (max-width:991px){#brand .meta{font-size:.8125em}}@media (max-width:767px){#brand{padding:3rem .5rem 0}#brand h1{font-size:1.5em}#brand .meta{font-size:.75em}#brand .meta .text{display:none}}@media (max-width:413px){#brand .artboard{font-size:2.5em}}#tool{position:fixed;right:1rem;top:50vh;z-index:9}@media (max-width:991px){#tool{right:1rem;left:auto}}#tool .item{display:none;width:1.875rem;height:1.875rem;opacity:.5;cursor:pointer;align-items:center;justify-content:center;flex-direction:column;transition:all .2s ease-in-out 0s}#tool .item:hover{opacity:.9}#tool .player{display:inline-flex;flex-direction:row-reverse;font-size:1.5em;width:auto;height:auto}#tool .player>.btn{font-family:ic;font-weight:400;width:1.875rem;text-align:center}#tool .player>.btn+.btn{margin-right:.625rem}#tool .player .music{display:none}#tool .player-info{border-radius:.5rem;border:.0625rem solid var(--grey-2);box-shadow:0 .625rem 1.875rem -.9375rem var(--box-bg-shadow);background:var(--grey-1-a7);-webkit-backdrop-filter:blur(0.625rem);backdrop-filter:blur(0.625rem);position:fixed;display:none;bottom:0;overflow:hidden;right:3.5rem;width:50vw;z-index:9;max-width:25rem}@media (max-width:767px){#tool .player-info{right:2.5rem}}#tool .player-info .nav{font-size:.75em;height:2.1875rem}#tool .back-to-top span{font-size:.75em}#tool.affix{text-shadow:none;top:auto;box-shadow:0 0 .5rem rgba(0,0,0,.1);background:var(--grey-1-a3);border-radius:.3125rem;right:0;bottom:0}#tool.affix .item{display:flex;color:var(--primary-color)}#tool.affix .player{font-size:1em;flex-direction:column-reverse}#tool.affix .player>.btn+.btn{margin-right:0}#tool.affix .player .music{display:block}#tool.affix .player-info{right:2.5rem}@media (min-width:1200px){#tool.affix .player-info{right:3.5rem}}@media (max-width:991px){#tool.affix .player-info{right:2.5rem;left:auto}}#tool.affix .player-info.show{display:block}#tool.affix .back-to-top{align-items:center;justify-content:center;height:auto;padding:.3125rem 0 0}#tool.affix .contents{display:none}@media (max-width:991px){#tool.affix .contents{display:flex}}@media (min-width:1200px){#tool.affix{right:1rem;bottom:1rem}}@media (max-width:991px){#tool.affix{right:0;bottom:0;left:auto}}.waves{width:100%;height:15vh;margin-bottom:-.6875rem;min-height:3.125rem;max-height:9.375rem;position:relative}@media (max-width:767px){.waves{height:10vh}}.parallax>use{animation:wave 25s cubic-bezier(.55,.5,.45,.5) infinite}.parallax>use:first-child{animation-delay:-2s;animation-duration:7s;fill:var(--grey-1-a7)}.parallax>use:nth-child(2){animation-delay:-3s;animation-duration:10s;fill:var(--grey-1-a5)}.parallax>use:nth-child(3){animation-delay:-4s;animation-duration:13s;fill:var(--grey-1-a3)}.parallax>use:nth-child(4){animation-delay:-5s;animation-duration:20s;fill:var(--grey-1)}@keyframes wave{0%{transform:translate3d(-90px,0,0)}100%{transform:translate3d(85px,0,0)}}#sidebar{position:static;width:15rem;top:0;bottom:0;transition:all .2s ease-in-out 0s}@media (max-width:991px){#sidebar{display:none;position:fixed;right:0;background:var(--grey-1);box-shadow:0 .375rem .9375rem .3125rem rgba(0,0,0,.2);z-index:99}}#sidebar.affix>.inner{position:fixed;top:0}#sidebar.affix .panels{padding-top:3.625rem;height:100vh}#sidebar>.inner{position:relative;width:15rem;color:var(--grey-6);text-align:center;display:flex;justify-content:space-around;align-items:flex-start;flex-wrap:wrap;z-index:1}.panels{padding:4.6875rem 0 2rem;width:100%;overflow:hidden}.panels .inner{overflow-x:hidden;overflow-y:auto;-webkit-overflow-scrolling:touch;width:auto;height:100%}.panels .inner::-webkit-scrollbar{display:none}.panels .panel{display:none;padding:.875rem .9375rem 2rem}.dimmer{display:none}@media (max-width:991px){.dimmer{background:#000;height:100%;left:100%;opacity:0;top:0;width:100%;z-index:9;transition:opacity 1s}#sidebar.on+.dimmer{position:fixed;display:block;opacity:.3;transform:translateX(-100%)}}.overview .author .image{border:.0625rem solid var(--body-bg-shadow);display:block;margin:0 auto;max-width:10rem;padding:.125rem;box-shadow:0 0 1rem .625rem var(--body-bg-shadow);border-radius:50%}.overview .author .name{color:var(--grey-7);font-weight:400;margin:.3125rem 0 0;text-align:center}.overview .author .description{color:var(--grey-5);font-size:1em;margin-top:.3125rem;text-align:center}@keyframes shake{0%{transform:scale(1)}10%,20%{transform:scale(.9) rotate(3deg)}30%,50%,70%,90%{transform:scale(1.1) rotate(-3deg)}40%,60%,80%{transform:scale(1.1) rotate(3deg)}100%{transform:scale(1)}}.overview .menu{padding:1.25rem;margin:0;background-color:transparent}.overview .menu .item{border-radius:.9375rem;margin-bottom:.625rem;display:block;color:var(--grey-5);transition:all .2s ease-in-out 0s}.overview .menu .item a{color:inherit;display:block;line-height:3}.overview .menu .item .submenu{display:none;padding:0}.overview .menu .item:hover{background-color:rgba(0,0,0,.1);color:inherit}.overview .menu .item:hover .submenu{display:block}.overview .menu .item .ic{margin-right:.625rem}.overview .menu .item.active:hover{box-shadow:0 0 .75rem var(--color-pink);color:var(--grey-0)}.overview .menu .item.active .item{color:currentColor}.overview .menu .item.expand{background-color:rgba(0,0,0,.05)}.overview .menu .item.expand .submenu{display:block}.social{margin-top:.9375rem;text-align:center}.social .item{display:inline-block;width:1.875rem;height:1.875rem;line-height:1.875rem;text-align:center;position:relative;overflow:hidden;border-radius:38%}.social .item i{font-size:1.4em;vertical-align:middle;transform:scale(.8)}.social .item::before{top:90%;left:-110%;content:"";width:120%;height:120%;position:absolute;transform:rotate(45deg)}.social .item i,.social .item::before{transition:all .35s cubic-bezier(.31, -.105, .43, 1.59) 0s}.social .item:focus::before,.social .item:hover::before{top:-10%;left:-10%}.social .item.github::before{background-color:#191717}.social .item.github i{color:#191717}.social .item.telegram::before{background-color:#55acd5}.social .item.telegram i{color:#55acd5}.social .item.about::before{background-color:#3b5998}.social .item.about i{color:#3b5998}.social .item.music::before{background-color:#e60026}.social .item.music i{color:#e60026}.social .item.bilibili::before{background-color:#55acd5}.social .item.bilibili i{color:#55acd5}.social .item:focus i,.social .item:hover i{color:var(--grey-0);transform:scale(1)}#quick{display:none;align-items:center;flex-wrap:wrap;width:15rem;margin:0;padding:0;position:fixed;bottom:.125rem}#quick li{width:25%;min-height:1.875rem;transition:all .2s ease-in-out 0s}#quick li i{cursor:pointer}#quick li a{width:100%;display:block}#quick li:hover{color:var(--primary-color)}#quick li.percent{display:block;background:var(--primary-color);width:0;min-height:.125rem}#sidebar.affix #quick,#sidebar.on #quick{display:flex}#sidebar .tab{position:absolute;display:inline-flex;padding:1.875rem 0 .625rem;margin:0;min-height:1.875rem}#sidebar .tab .item{cursor:pointer;display:inline-flex;font-size:.875em;padding:.3125rem .9375rem;color:var(--grey-5);border-radius:.625rem;text-align:center;text-decoration:none;background-color:rgba(0,0,0,.08);transition:all .2s ease-out 0s}#sidebar .tab .item:nth-child(2){margin:auto .625rem}#sidebar .tab .item span{display:none;word-break:keep-all}#sidebar .tab .item.active span{display:inherit}#sidebar .tab .item.active:hover{box-shadow:0 0 .75rem var(--color-pink)}#sidebar .tab .item::before{font-family:ic;font-weight:400}#sidebar .tab .item.active::before{margin-right:.3125rem}#sidebar.affix .tab{padding-top:.625rem}.contents ol{padding:0 .125rem .3125rem .625rem;text-align:left}.contents ol>ol{padding-left:0}.contents .toc-item{font-size:1em;line-height:1.8;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.contents .toc-child{display:none}.contents .active>.toc-child{display:block}.contents .current>.toc-child{display:block}.contents .current>.toc-child>.toc-item{display:block}.contents .active>a{color:var(--primary-color)}.contents .current>a{color:var(--primary-color)}.contents .current>a:hover{color:var(--primary-color)}.related{font-size:.875em}.related ul{padding:0 .125rem .3125rem 1.25rem;text-align:left}.related ul li{position:relative;line-height:1.8;padding-bottom:.625rem}.related ul li a{text-overflow:ellipsis;white-space:nowrap;overflow:hidden;width:100%;display:inline-block}.related ul li.active a{color:var(--primary-color)}.related ul li::before{content:"";width:.5rem;height:.5rem;background:var(--primary-color);box-sizing:unset;left:-1.25rem;top:.3125rem;border-radius:100%;position:absolute;border:.1875rem solid var(--grey-1);z-index:1;transition:all .2s ease-in-out 0s}.related ul li:hover::before{background:var(--color-blue)}.related ul li:not(:last-child)::after{content:"";height:100%;width:.125rem;background:var(--color-red-a3);position:absolute;left:-.875rem;top:.5rem}.state{display:flex;justify-content:center;line-height:1.4;margin-top:.625rem;overflow:hidden;text-align:center;white-space:nowrap}.state .item{padding:0 .9375rem}.state .item:not(:first-child){border-left:.0625rem solid var(--grey-4)}.state .item a{border-bottom:none}.state .item .count{display:block;font-size:1.25em;font-weight:600;text-align:center}.state .item .name{color:inherit;font-size:.875em}#footer{color:var(--grey-5);font-size:.875em;background:var(--body-bg-shadow)}#footer .inner{margin:0 auto;width:calc(100% - .625rem);position:relative;padding-left:16.25rem}@media (min-width:1200px){#footer .inner{width:72.5rem}}@media (min-width:1600px){#footer .inner{width:73%}}@media (max-width:991px){#footer .inner{padding-left:0;padding-right:0;width:auto}}.status{width:100%;text-align:center;margin-top:2rem}.languages{display:inline-block;font-size:1.125em;position:relative}.languages .lang-select-label span{margin:0 .5rem}.languages .lang-select{height:100%;left:0;opacity:0;position:absolute;top:0;width:100%}.with-love{color:pink;display:inline-block;margin:0 .3125rem 0 .125rem}.powered-by,.theme-info{display:inline-block;margin-bottom:.625rem}@media (max-width:567px){.post.block{padding:initial!important}.md h1,.md h2,.md h3,.md h4,.md h5,.md h6{padding-left:1.25rem}.md .note h1,.md .note h2,.md .note h3,.md .note h4,.md .note h5,.md .note h6,.md .tabs .tab-content .tab-pane h1,.md .tabs .tab-content .tab-pane h2,.md .tabs .tab-content .tab-pane h3,.md .tabs .tab-content .tab-pane h4,.md .tabs .tab-content .tab-pane h5,.md .tabs .tab-content .tab-pane h6{margin:0 .3125rem}.md img,.md video{margin-bottom:.625rem!important}.md .tabs .tab-content .tab-pane{padding:.625rem .625rem 0 .625rem!important}.post .eof{margin:2.5rem auto 1.25rem!important}}.post.block{padding:0 2rem}.md{font-family:Mulish,-apple-system,"PingFang SC","Microsoft YaHei",sans-serif;overflow-wrap:break-word;word-wrap:break-word}.md .exturl .ic{font-size:.875em;margin-left:.25rem}.md .button{margin-top:2.5rem;text-align:center}.breadcrumb{display:inline-flex;font-size:.8125em;align-items:center;margin:1.25rem 0;flex-wrap:wrap}.breadcrumb .ic{margin:0 .125rem;color:var(--grey-4)}.breadcrumb .ic:first-child{margin-left:0;margin-right:.3125rem}.breadcrumb span{white-space:pre}.breadcrumb span.current{background-color:var(--color-red-a1);border-radius:.625rem;padding:0 .625rem;transition:all .2s ease-in-out 0s}.breadcrumb span.current span{white-space:normal}.breadcrumb span.current a{color:var(--primary-color)}.breadcrumb span.current:hover{background-color:var(--color-red-a3)}.post header{font-size:1.125em;margin-bottom:.625rem}.post header .title{font-size:1.5em;margin:initial;text-align:center;overflow-wrap:break-word;word-wrap:break-word;padding-bottom:.625rem}.post header .link{display:inline-block;position:relative;vertical-align:top}.post header .link .i-link-alt{font-size:.875em;margin-left:.3125rem}.post header .meta{text-align:center;border-top:.0625rem dashed var(--grey-9-a1);font-family:Mulish,-apple-system,"PingFang SC","Microsoft YaHei",sans-serif}.post .meta{color:var(--grey-5);font-size:.75em;text-align:right}.post .meta .item{display:inline-block;margin-right:.625rem}.post .meta .icon{margin-right:.1875rem}@media (max-width:991px){.post .meta .icon{display:inline-block}}.post-nav{display:flex;margin-bottom:2.5rem}@media (max-width:767px){.post-nav{flex-direction:column}}.post-nav .item{width:50%}@media (max-width:767px){.post-nav .item{width:100%}}.post-nav .item a{display:flex;flex-direction:column;height:100%;color:var(--header-text-color);padding:1.25rem 2.5rem;background-size:cover;position:relative}.post-nav .item a::before{content:"";position:absolute;width:100%;height:100%;background:linear-gradient(135deg,#434343,#000);opacity:.5;transition:all .2s ease-in-out 0s;z-index:-1;top:0;left:0}.post-nav .item a:hover::before{opacity:.4}.post-nav .item span{font-size:.8125em}.post-nav .item.left h3,.post-nav .item.left span{align-self:flex-start}.post-nav .item.right h3,.post-nav .item.right span{align-self:flex-end;text-align:right}.md .links:last-child,.md .tabs:last-child,.md blockquote:last-child,.md img:last-child,.md p:last-child,.md pre:last-child,.md table:last-child{margin-bottom:0}.md dd ol,.md dd ul,.md ol ol,.md ol ul,.md ul ol,.md ul ul{margin-top:0}.md a{color:var(--primary-color)}.md a:hover{color:var(--color-blue)}.md h1{font-size:1.5em}.md h2{font-size:1.375em}.md h3{font-size:1.25em}.md h4{font-size:1.125em}.md h5{font-size:1em}.md h6{font-size:.875em}.md h1,.md h2,.md h3,.md h4,.md h5,.md h6{position:relative;padding-top:.625rem}.md h1:hover .anchor::after,.md h1:hover .anchor::before,.md h2:hover .anchor::after,.md h2:hover .anchor::before,.md h3:hover .anchor::after,.md h3:hover .anchor::before,.md h4:hover .anchor::after,.md h4:hover .anchor::before,.md h5:hover .anchor::after,.md h5:hover .anchor::before,.md h6:hover .anchor::after,.md h6:hover .anchor::before{color:var(--primary-color)}.md h1::after{content:"";display:block;box-sizing:unset;width:100%;height:.0625rem;background:var(--grey-3);padding-right:1.25rem;margin-left:-1.25rem;margin-top:.3125rem}.md .anchor{border-bottom-style:none;color:var(--grey-4);float:right;margin-left:.625rem}.md .anchor:hover{color:inherit}.md .anchor::after,.md .anchor::before{color:var(--grey-4);position:absolute;font-weight:400;transition:all .2s ease-out 0s}.md .active .anchor::after,.md .active .anchor::before{color:var(--primary-color)}.md p{margin:0 0 .8rem}.md blockquote{font-size:90%;background-color:var(--grey-2);margin:1.25rem 0;border-radius:.1875rem}.md blockquote ul{margin:.625rem 0!important}.md blockquote ul>li::before{width:.375rem!important;height:.375rem!important;top:.6875rem!important}.md blockquote ol:last-child,.md blockquote p:last-child,.md blockquote ul:last-child{margin-bottom:0!important}.md>blockquote{border-left-color:var(--primary-color)}.md iframe{margin-bottom:1.25rem}.md .image-info{display:block;text-align:center;font-size:.8125em;color:var(--grey-4)}.md .video-container{height:0;margin-bottom:1.25rem;overflow:hidden;padding-top:75%;position:relative;width:100%}.md .video-container embed,.md .video-container iframe,.md .video-container object{height:100%;left:0;margin:0;position:absolute;top:0;width:100%}.md .kbd,.md kbd{background-color:var(--grey-1);background-image:linear-gradient(var(--grey-2),var(--grey-0),var(--grey-2));border:.0625rem solid var(--grey-4);border-radius:.2rem;box-shadow:.1rem .1rem .2rem var(--grey-9-a1);font-family:inherit;padding:.1rem .3rem;white-space:nowrap}.md mark{background-color:#dbfdad}.md ins{--line-color:var(--note-hover, var(--primary-color));text-decoration:none;border-bottom:.125rem solid var(--line-color)}.md ins.wavy{-webkit-text-decoration-style:wavy;text-decoration-style:wavy;-webkit-text-decoration-line:underline;text-decoration-line:underline;-webkit-text-decoration-color:var(--line-color);text-decoration-color:var(--line-color);border-bottom:none}.md ins.dot{border-bottom:.2rem dotted var(--line-color)}.md s{color:var(--grey-5);-webkit-text-decoration-color:var(--note-hover,var(--grey-5));text-decoration-color:var(--note-hover,var(--grey-5))}.md ruby{padding:0 .3125rem}.md .katex-display{overflow-x:scroll;overflow-y:hidden}.md .spoiler:not(.bulr){background-color:var(--text-color);color:var(--text-color);text-shadow:none;transition:color .3s;padding:0 .1875rem}.md .spoiler:not(.bulr):hover{color:#fff}.md .bulr{text-shadow:rgba(0,0,0,.7) 0 0 .625rem;color:transparent}.md .rainbow{background-image:linear-gradient(to left,#ff4500,orange,gold,#90ee90,#0ff,#1e90ff,#9370db,#ff69b4,#ff4500);background-size:110vw;-webkit-background-clip:text;background-clip:text;color:transparent;animation:rainbow 60s linear infinite}.article .md .anchor::after,.article .md .anchor::before{content:"H";font-family:Mulish,-apple-system,"PingFang SC","Microsoft YaHei",sans-serif;left:-1.875rem;top:1rem;width:1.25rem;height:1.5625rem;text-align:right;visibility:visible;font-size:80%}@media (max-width:567px){.article .md .anchor::after,.article .md .anchor::before{left:-.625rem}}.article .md .anchor::after{font-size:50%;left:-1.375rem;line-height:3}@media (max-width:567px){.article .md .anchor::after{left:-.1875rem}}.article .md h1 .anchor::after{content:" 1 "}.article .md h2 .anchor::after{content:" 2 "}.article .md h3 .anchor::after{content:" 3 "}.article .md h4 .anchor::after{content:" 4 "}.article .md h5 .anchor::after{content:" 5 "}.article .md h6 .anchor::after{content:" 6 "}@keyframes rainbow{to{background-position:-2000vw}}.rtl.body a,.rtl.body h1,.rtl.body h2,.rtl.body h3,.rtl.body h4,.rtl.body h5,.rtl.body h6,.rtl.body li,.rtl.body ol,.rtl.body p,.rtl.body ul{direction:rtl;font-family:UKIJ Ekran}.rtl.title{font-family:UKIJ Ekran}.post footer::before{content:"";width:100%;height:.0625rem;background:var(--grey-3);display:block;margin:1.25rem auto 0}.post .tags{text-align:left;margin-top:.625rem;font-size:.75em}.post .tags a{display:inline-block;position:relative;padding:0 .3125rem;border-radius:.3125rem;background:var(--note-bg);color:var(--note-text)}.post .tags a:not(:last-child){margin-right:.625rem}.post .tags a:before{content:'';position:absolute;bottom:0;height:100%;width:0;right:0;background:var(--color-red-a1);border-radius:.25rem;transition:all .2s ease-in-out 0s}.post .tags a:hover{color:var(--primary-color)}.post .tags a:hover:before{width:104%;left:-2%}.reward{margin:1.25rem auto;padding:.625rem 0;text-align:center}.reward button{background:var(--primary-color);border:0;border-radius:.3125rem;color:var(--grey-0);cursor:pointer;line-height:2;outline:0;padding:0 .9375rem;vertical-align:text-top}.reward button:hover{background:var(--primary-color)}.reward button i{margin-right:.3125rem}.reward p{font-size:.8125em;color:var(--grey-5);margin:0}#qr{padding-top:1.25rem;display:none}#qr a{border:0}#qr img{display:inline-block;max-width:100%}#qr p{text-align:center}#copyright{background:var(--grey-2);padding:1rem 2rem;position:relative;font-size:.75em;border-radius:.625rem;color:var(--grey-6)}#copyright li::before{font-family:ic;font-weight:400;color:var(--grey-5);margin-right:.3125rem;font-size:1.1rem;line-height:.75rem;vertical-align:-.0667rem}.cards .item,.segments>.item{position:relative;color:inherit;width:calc(50% - 2rem);min-width:calc(50% - 2rem);height:14rem;margin:1rem;opacity:0}.cards .item.show,.segments>.item.show{opacity:1}@media (max-width:767px){.cards .item,.segments>.item{width:calc(100% - 1rem)!important;min-width:calc(100% - 1rem)!important;margin:1rem .5rem!important}}.index.wrap .btn{position:absolute;bottom:0;right:0;padding:.3rem 1rem;border-radius:1rem 0;color:var(--grey-0);background-image:linear-gradient(to right,var(--color-pink) 0,var(--color-orange) 100%)}.index.wrap .btn::before{position:absolute;display:block;content:'';height:calc(100% - 1rem);width:calc(100% - 1rem);border-radius:5rem;left:.5rem;top:.8rem;box-shadow:0 0 .6rem .6rem var(--color-pink-a3);background-color:var(--color-pink-a3)}.index.wrap .btn:hover{transform:translateZ(2.5rem)}.index.wrap .btn:hover::before{transform:translateZ(-2.5rem)}.index.wrap .active .btn{transform-style:preserve-3d;transform:translateZ(2rem);backface-visibility:hidden}.index.wrap .active .btn::before{transform-style:preserve-3d;transform:translateZ(-2rem);backface-visibility:hidden}.index.wrap .meta{font-size:.8125em;color:var(--grey-5)}.index.wrap .meta .ic{margin-right:.0625rem}.index.wrap .meta .item+.item{margin-left:.625rem}.index.wrap .meta.footer{position:absolute;bottom:.5rem;max-width:calc(100% - 7rem);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;justify-content:flex-start}.index.wrap .meta.footer span{margin-right:.5rem}.cards{display:flex;margin:0 auto;align-items:center;flex-wrap:wrap;justify-content:space-between}.cards.hide .item{display:none}.cards .item{perspective:62.5rem}.cards .item.show{display:block!important}.cards .item .cover,.cards .item .info{position:absolute;display:flex;flex-direction:column;justify-content:center;align-items:center;border-radius:.375rem;height:100%;width:100%;backface-visibility:hidden;transform-style:preserve-3d;transition:ease-in-out .6s}.cards .item .cover{background-position:center;background-size:cover;padding:.5rem 1rem;font-size:1em;color:var(--header-text-color);overflow:hidden;transform:rotateY(0)}.cards .item .cover .title{margin:0;white-space:normal;text-align:center}.cards .item .cover::before{position:absolute;display:block;content:'';top:0;left:0;right:0;bottom:0;background-image:linear-gradient(135deg,#434343 0,#000 100%);opacity:.25;z-index:-1}.cards .item .cover span{font-size:.75em;position:absolute;right:.9375rem;top:.625rem;padding:0 .3125rem;border-radius:.3125rem;box-shadow:0 0 .3125rem .0625rem rgba(0,0,0,.6);background:rgba(0,0,0,.5)}.cards .item .info{background-color:var(--grey-0);transform:rotateY(-180deg);padding:1rem 1.5rem 4rem;justify-content:space-between}@media (max-width:767px){.cards .item .info{padding:1rem 1rem 4rem}}.cards .item .info .ribbon{left:-2.5rem;margin-bottom:.8rem;max-width:calc(100% + 2rem)}@media (max-width:767px){.cards .item .info .ribbon{left:-2rem}}.cards .item:nth-child(2n) .info{transform:rotateY(180deg)}.cards .item.active .cover{transform:rotateY(180deg)}.cards .item.active .info{transform:rotateY(0);box-shadow:0 0 2rem var(--box-bg-shadow)}.cards .item:nth-child(2n).active .cover{transform:rotateY(-180deg)}.cards .item .title .ic{font-size:80%}.cards .item ul.posts{display:flex;flex-wrap:wrap;justify-content:space-between;align-content:baseline;min-height:5rem;overflow:hidden}.cards .item ul.posts li{width:45%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;color:var(--primary-color)}.segments{display:flex;flex-direction:column;justify-content:center;align-items:center}.segments>.item{display:flex;border-radius:.625rem;width:calc(100% - 2rem);min-width:calc(100% - 2rem);border-radius:.5rem;box-shadow:0 .625rem 1.875rem -.9375rem var(--box-bg-shadow);transition:all .2s ease-in-out 0s}@media (max-width:767px){.segments>.item{flex-direction:column;height:-moz-fit-content;height:fit-content;max-height:-moz-fit-content;max-height:fit-content}}.segments>.item:hover{box-shadow:0 0 2rem var(--box-bg-shadow)}.segments>.item:hover .cover img{transform:scale(1.05) rotate(1deg)}.segments .cover{width:50%;margin-right:1.5rem;-webkit-clip-path:polygon(0 0,92% 0%,100% 100%,0% 100%);clip-path:polygon(0 0,92% 0%,100% 100%,0% 100%);border-radius:.625rem 0 0 .625rem;overflow:hidden}@media (max-width:767px){.segments .cover{width:100%;height:14rem;margin:auto;-webkit-clip-path:polygon(0 0,100% 0,100% 92%,0 100%);clip-path:polygon(0 0,100% 0,100% 92%,0 100%);border-radius:.625rem .625rem 0 0}}.segments .cover img{-o-object-fit:cover;object-fit:cover;width:100%;height:100%;transition:all .2s ease-in-out 0s}.segments .info{position:relative;width:50%;padding:1rem 1.5rem 3rem 0;perspective:62.5rem}@media (max-width:767px){.segments .info{width:100%;height:14rem;padding:0 1rem 3rem}}.segments .info .meta{display:flex;justify-content:flex-end;margin:0}@media (max-width:767px){.segments .info .meta .item:not(:first-child){display:none}}.segments .info h3{text-overflow:ellipsis;overflow:hidden;white-space:nowrap;margin:.625rem 0;color:var(--primary-color)}.segments .info .excerpt{overflow:hidden;font-size:.875em;max-height:5rem;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;text-overflow:ellipsis}.segments>.item:nth-child(2n){flex-direction:row-reverse}@media (max-width:767px){.segments>.item:nth-child(2n){flex-direction:column}}.segments>.item:nth-child(2n) .cover{margin-right:auto;margin-left:1.5rem;-webkit-clip-path:polygon(0 0%,100% 0%,100% 100%,8% 100%);clip-path:polygon(0 0%,100% 0%,100% 100%,8% 100%);border-radius:0 .625rem .625rem 0}@media (max-width:767px){.segments>.item:nth-child(2n) .cover{width:100%;margin:auto;-webkit-clip-path:polygon(0 0,100% 0,100% 100%,0 92%);clip-path:polygon(0 0,100% 0,100% 100%,0 92%);border-radius:.625rem .625rem 0 0}}.segments>.item:nth-child(2n) .info{padding:1rem 0 3rem 1.5rem}@media (max-width:767px){.segments>.item:nth-child(2n) .info{padding:0 1rem 3rem}}.segments>.item:nth-child(2n) .info .meta{justify-content:flex-start}.segments>.item:nth-child(2n) .btn{left:0;right:auto;border-radius:0 1rem;background-image:linear-gradient(to right,var(--color-orange) 0,var(--color-pink) 100%)}.segments>.item:nth-child(2n) .meta.footer{right:.5rem;justify-content:flex-start}.segments>.item:nth-child(2n):hover .cover img{transform:scale(1.05) rotate(-1deg)}.collapse small{color:var(--grey-4);margin:auto .3125rem}.collapse .item{position:relative;padding:1.25rem 1.875rem;margin:0}.collapse .item::before{content:"";position:absolute;z-index:1;transition:all .2s ease-in-out 0s;box-sizing:unset;top:1.9rem;left:0;width:.6rem;height:.6rem;border:.15rem solid var(--primary-color);border-radius:50%;background:var(--grey-1)}.collapse .item:not(:last-child):not(.title)::after{content:"";position:absolute;top:1.9rem;bottom:-1.9rem;left:.35rem;border-left:.2rem solid var(--color-red-a3)}.collapse .item:hover::before{border-color:var(--color-blue)}.collapse .item.header::after{border-left-style:dashed!important}.collapse .item.header .cheers{display:block}.collapse .item.section::before{width:.4rem;height:.4rem;margin-left:.1rem}.collapse .item.header a,.collapse .item.section a,.collapse .item.title a{border-bottom:.0625rem dashed var(--grey-4)}.collapse .item.header:hover a,.collapse .item.section:hover a,.collapse .item.title:hover a{border-bottom-color:var(--color-blue)}.collapse .item.normal{display:flex;flex-wrap:wrap;align-items:center;padding:.625rem 1.875rem}.collapse .item.normal::before{top:1.4rem;width:.2rem;height:.2rem;margin-left:.2rem;background:var(--primary-color)}.collapse .item.normal:hover::before{background:var(--color-blue)}.collapse .item.normal .meta{display:inline;font-size:.75em;margin-right:.625rem}.collapse .item.normal .meta time{color:var(--grey-4)}.collapse .item.normal .title{display:inline}.collapse .item.normal .title a{color:var(--primary-color)}.collapse .item.normal .title a:hover{color:var(--color-blue)}.collapse .item.normal .title .i-link-alt{font-size:.875em;margin-left:.3125rem}.tag.cloud{text-align:center}.tag.cloud a{display:inline-block;margin:.625rem}.tag.cloud a:hover{color:var(--primary-color)!important}.page .notfound{width:18.75rem;height:22.625rem;background:url("../images/404.png") no-repeat center bottom;text-align:center;margin:6.25rem auto}.page .anchor::before{font-family:ic;font-weight:400;color:var(--grey-4);position:absolute;left:-1.5625rem;margin-top:.25rem;visibility:visible}@media (max-width:567px){.page .anchor::before{left:-.1875rem}}.page .body h1 .anchor::before{font-size:.875em;margin-top:.15rem;color:pink;left:-1.875rem}@media (max-width:567px){.page .body h1 .anchor::before{left:-.3125rem}}.page .body h2 .anchor::before{font-size:.8125em;color:var(--color-pink)}.page .body h3 .anchor::before{font-size:.75em;color:var(--color-orange)}.pace{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.pace-inactive{display:none}.pace .pace-progress{background:var(--primary-color);position:fixed;z-index:2000;top:0;right:100%;width:100%;height:.125rem}#loading{background-color:var(--grey-1)}.cat{position:relative;display:block;width:15em;height:100%;font-size:10px;margin:auto;animation:2.74s linear infinite loading-cat}.cat *{box-sizing:content-box}.cat .body,.cat .foot,.cat .head,.cat .paw{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto;border-radius:50%;width:15em;height:15em}.cat .body{background-image:radial-gradient(transparent 0,transparent 35%,#383c4b 35%,#383c4b 39%,#eda65d 39%,#eda65d 46%,#f2c089 46%,#f2c089 60%,#eda65d 60%,#eda65d 67%,#383c4b 67%,#383c4b 100%)}.cat .foot:before,.cat .head:before{background-image:radial-gradient(transparent 0,transparent 35%,#383c4b 35%,#383c4b 39%,#eda65d 39%,#eda65d 67%,#383c4b 67%,#383c4b 100%)}.cat .head:before{content:'';width:100%;height:100%;position:absolute;border-radius:50%;clip-path:polygon(100% 20%,50% 50%,70% -10%);-webkit-clip-path:polygon(100% 20%,50% 50%,70% -10%)}.cat .head:after{content:'';width:4.125em;height:2.5em;position:absolute;top:.8125em;right:3.9375em;background-image:linear-gradient(var(--grey-1) 65%,transparent 65%),radial-gradient(var(--grey-1) 51%,#383c4b 55%,#383c4b 68%,transparent 70%);transform:rotate(-66deg)}.cat .head .face{width:5em;height:3.75em;left:9.0625em;top:1.8125em;position:absolute;transform:rotate(-47deg);background:radial-gradient(circle,#f2c089 0,#f2c089 23%,transparent 23%) -.1875em 1.0625em no-repeat,radial-gradient(circle,#383c4b 0,#383c4b 6%,transparent 6%) .75em -.75em no-repeat,radial-gradient(circle,#383c4b 0,#383c4b 6%,transparent 6%) -.75em -.75em no-repeat,radial-gradient(#eda65d 0,#eda65d 15%,transparent 15%) 0 -.6875em no-repeat,radial-gradient(circle,transparent 5%,#383c4b 5%,#383c4b 10%,transparent 10%) -.1875em -.3125em no-repeat,radial-gradient(circle,transparent 5%,#383c4b 5%,#383c4b 10%,transparent 10%) .1875em -.3125em no-repeat,radial-gradient(circle,#eda65d 45%,transparent 45%) 0 -.1875em,linear-gradient(transparent 35%,#383c4b 35%,#383c4b 41%,transparent 41%,transparent 44%,#383c4b 44%,#383c4b 50%,transparent 50%,transparent 53%,#383c4b 53%,#383c4b 59%,transparent 59%)}.cat .foot:after,.cat .foot:before{content:'';width:100%;height:100%;position:absolute}.cat .foot:before{border-radius:50%;clip-path:polygon(50% 50%,0% 50%,0% 25%);-webkit-clip-path:polygon(50% 50%,0% 50%,0% 25%)}.cat .foot .tummy-end{width:1.5em;height:1.5em;position:absolute;border-radius:50%;background-color:#f2c089;left:1.1875em;top:6.5625em}.cat .foot .bottom{width:2.1875em;height:.9375em;position:absolute;top:4.875em;left:.75em;border:.375em solid #383c4b;border-bottom:0;border-radius:50%;transform:rotate(21deg);background:#eda65d}.cat .foot:after,.cat .hands,.cat .legs{width:.625em;height:1.5625em;position:absolute;border:.375em solid #383c4b;background-color:#eda65d}.cat .hands{border-top:0;border-radius:0 0 .75em .75em}.cat .hands.left{top:4.3em;left:13.1875em;transform:rotate(-20deg)}.cat .hands.right{top:5.125em;left:10.975em;transform:rotate(-25deg)}.cat .legs{border-bottom:0;border-radius:.75em .75em 0 0}.cat .legs.left{top:4.0625em;left:3.125em;transform:rotate(25deg)}.cat .legs.right{top:3.3125em;left:.75em;transform:rotate(22deg)}.cat .foot:after{width:.9em;height:2.5em;top:2.625em;left:2.5em;z-index:-1;transform:rotate(25deg);background-color:#c6823b;border-bottom:0;border-radius:.75em .75em 0 0}.cat .body{animation:2.74s linear infinite body}.cat .foot{animation:2.74s linear infinite foot}.cat:hover{animation-play-state:paused}.cat:hover .body,.cat:hover .foot{animation-play-state:paused}.cat:active{animation-play-state:running}.cat:active .body,.cat:active .foot{animation-play-state:running}@keyframes body{0%{-webkit-clip-path:polygon(50% 50%,0% 50%,0% 100%,100% 100%,100% 20%);clip-path:polygon(50% 50%,0% 50%,0% 100%,100% 100%,100% 20%)}10%{-webkit-clip-path:polygon(50% 50%,30% 120%,50% 100%,100% 100%,100% 20%);clip-path:polygon(50% 50%,30% 120%,50% 100%,100% 100%,100% 20%)}20%{-webkit-clip-path:polygon(50% 50%,100% 90%,120% 90%,100% 100%,100% 20%);clip-path:polygon(50% 50%,100% 90%,120% 90%,100% 100%,100% 20%)}40%{-webkit-clip-path:polygon(50% 50%,100% 45%,120% 45%,120% 50%,100% 20%);clip-path:polygon(50% 50%,100% 45%,120% 45%,120% 50%,100% 20%)}50%{-webkit-clip-path:polygon(50% 50%,100% 45%,120% 45%,120% 50%,100% 20%);clip-path:polygon(50% 50%,100% 45%,120% 45%,120% 50%,100% 20%)}65%{-webkit-clip-path:polygon(50% 50%,100% 65%,120% 65%,120% 50%,100% 20%);clip-path:polygon(50% 50%,100% 65%,120% 65%,120% 50%,100% 20%)}80%{-webkit-clip-path:polygon(50% 50%,75% 130%,120% 65%,120% 50%,100% 20%);clip-path:polygon(50% 50%,75% 130%,120% 65%,120% 50%,100% 20%)}90%{-webkit-clip-path:polygon(50% 50%,-20% 110%,50% 120%,100% 100%,100% 20%);clip-path:polygon(50% 50%,-20% 110%,50% 120%,100% 100%,100% 20%)}100%{-webkit-clip-path:polygon(50% 50%,0% 50%,0% 100%,100% 100%,100% 20%);clip-path:polygon(50% 50%,0% 50%,0% 100%,100% 100%,100% 20%)}}@keyframes loading-cat{0%{transform:rotate(0)}10%{transform:rotate(-80deg)}20%{transform:rotate(-180deg)}40%{transform:rotate(-245deg)}50%{transform:rotate(-250deg)}68%{transform:rotate(-300deg)}90%{transform:rotate(-560deg)}100%{transform:rotate(-720deg)}}@keyframes foot{0%{transform:rotate(-10deg)}10%{transform:rotate(-100deg)}20%{transform:rotate(-145deg)}35%{transform:rotate(-190deg)}50%{transform:rotate(-195deg)}70%{transform:rotate(-165deg)}100%{transform:rotate(-10deg)}}#search{position:fixed;background:var(--nav-bg);left:0;top:0;width:100%;height:100%;padding:1.25rem;z-index:999;display:none}#search>.inner{border-radius:0;height:100%;margin:0 auto;width:43.75rem;text-shadow:none}@media (max-width:767px){#search>.inner{width:100%}}#search>.inner .close-btn,#search>.inner .icon{color:var(--grey-5);font-size:1.125rem;padding:0 .625rem}#search>.inner .close-btn{cursor:pointer}#search>.inner .close-btn:hover i{color:var(--grey-7)}#search>.inner .header{display:flex;background:var(--grey-1-a5);border-radius:3rem;padding:.5rem 1.5rem;margin-bottom:1.25rem;border:.0625rem solid var(--grey-5);font-size:1.125em;align-items:center}#search>.inner .search-input-container{flex-grow:1}#search>.inner .search-input-container form{padding:.125rem}#search>.inner .search-input{background:0 0;border:0;outline:0;width:100%}#search>.inner .search-input::-webkit-search-cancel-button{display:none}#search .results{height:calc(100% - 6.25rem);padding:1.875rem 1.875rem .3125rem;border-radius:.3125rem;background:var(--grey-1-a7) url("../images/search.png") no-repeat bottom right;color:var(--text-color)}#search .results .inner{position:relative;height:100%;overflow:hidden}#search .results hr{margin:.625rem 0}.algolia-powered{float:right;background:url("../images/algolia_logo.svg") no-repeat;display:inline-block;height:1.125rem;width:4.25rem;margin:.5rem auto}#search-hits{overflow-y:scroll;height:calc(100% - 8.125rem)}#search-hits ol{padding:0}#search-hits .item{margin:.9375rem 0}#search-hits .item a{border-bottom:.0625rem dashed var(--grey-4);display:block;transition:all .2s ease-in-out 0s}#search-hits .item span{font-size:70%;display:block}#search-hits .item span i{color:var(--grey-4);margin:0 .3125rem}#search-pagination ul{padding:0;margin:1.25rem 0}#search-pagination .pagination{opacity:1;padding:0}#search-pagination .pagination-item{display:inline-block}#search-pagination .page-number{transition:all .2s ease-in-out 0s}#search-pagination .current .page-number{cursor:default}#search-pagination .disabled-item{color:var(--grey-4);cursor:default}#search-pagination .disabled-item .page-number:hover{color:var(--grey-4);background:0 0;box-shadow:none}#neko{display:none;background:linear-gradient(to top,#fddb92 0,#d1fdff 80%)}#neko .planet{position:fixed;left:-50%;top:-50%;width:200%;height:200%;animation:rotate 2s cubic-bezier(.7,0,0,1);transform-origin:center bottom}#neko:before{content:"";position:absolute;left:0;right:0;top:0;bottom:0;opacity:0;background:linear-gradient(to top,#30cfd0 0,#330867 100%);transition:2s ease all}#neko .moon,#neko .sun{position:absolute;border-radius:100%;left:55%;top:32%}#neko .sun{height:40px;width:40px;background:#ffee94;box-shadow:0 0 40px #ffee94;opacity:1}#neko .moon{height:24px;width:24px;background:#eee;box-shadow:0 0 20px #fff;opacity:0}#neko .body{display:block;position:absolute;bottom:-20px;height:140px;width:135px;left:50%;margin-left:-100px;background:#777;transition:all .25s ease-in-out;animation:slideUpBigIn 1s}#neko .body:after,#neko .body:before{position:absolute;content:"";width:0;height:0;border-bottom:20px solid #777;top:-20px;transition:all .25s ease-in-out}#neko .body:before{border-left:0 solid transparent;border-right:30px solid transparent;left:0}#neko .body:after{border-right:0px solid transparent;border-left:30px solid transparent;right:0}#neko .body .eyes{display:block;position:absolute;background:#ffee94;height:40px;width:40px;border-radius:100%;bottom:80px}#neko .body .eyes.left{left:12px}#neko .body .eyes.right{right:12px}#neko .body .eyes .pupil,#neko .body .nose{display:block;position:relative;background:#ffb399;border-radius:100%;margin:0 auto}#neko .body .eyes .pupil{height:100%;width:5px;transition:width 1s .5s ease-in-out}#neko .body .nose{top:45px;height:10px;width:10px}#neko.dark:before{opacity:1}#neko.dark .sun{opacity:0}#neko.dark .moon{opacity:1}#neko.dark .body{background:#444}#neko.dark .body:before{border-bottom:20px solid #444}#neko.dark .body:after{border-bottom:20px solid #444}#neko.dark .body .eyes .pupil{height:90%;width:34px;margin:5% auto}.widgets{display:flex;z-index:1;background:var(--body-bg-shadow);justify-content:space-around}.widgets>div{width:calc(50% - 2rem);padding:1rem}@media (max-width:767px){.widgets{flex-direction:column-reverse}.widgets>div{width:calc(100% - 1rem)!important}}.widgets ul{counter-reset:counter}.widgets .item{padding:.5rem 0 .5rem 2rem;border-bottom:.0625rem dashed var(--grey-4);position:relative}.widgets .item::before{counter-increment:counter;content:counter(counter);position:absolute;left:0;font-size:1.5em;color:var(--grey-4);line-height:1.2;text-align:right;width:1em}.widgets .item .breadcrumb,.widgets .item span{display:block;text-overflow:ellipsis;overflow:hidden;max-height:2rem;white-space:nowrap}.widgets .item .breadcrumb{margin:0;display:flex;max-height:1.2rem}.katex,.katex-display{-webkit-user-select:all;-moz-user-select:all;user-select:all}.medium-zoom-overlay{z-index:9998}.medium-zoom-image--opened{z-index:9999}.operation{color:var(--grey-5);cursor:pointer;position:absolute;padding:.125rem .375rem;right:.125rem;top:.45rem;font-size:.8125em}.operation span{transition:all .2s ease-in-out 0s;margin:0 .3125rem}.operation span:hover{color:var(--grey-7)}.highlight{background:var(--grey-2);color:var(--grey-7);line-height:1.6;margin:1.25rem auto}.code-container,code,pre{font-family:Inconsolata,consolas,Menlo,-apple-system,"PingFang SC","Microsoft YaHei";font-size:1em}:not(td)>pre{background:var(--grey-1);border:.0625rem solid var(--grey-3);border-radius:.3125rem;padding:1rem;margin-bottom:.8rem;line-break:anywhere;white-space:break-spaces}:not(td)>pre code{background:0 0;color:currentColor}:not(pre)>code{color:var(--primary-color);border-radius:.3rem;border:.0625rem solid rgba(0,0,0,.1);background-color:var(--grey-0);padding:.2rem .3rem;overflow-wrap:break-word;word-wrap:break-word}.highlight{position:relative;overflow:hidden;border-radius:.5rem;box-shadow:0 .3125rem .625rem -.125rem var(--grey-9-a1)}.highlight ::-moz-selection{background:var(--grey-4)}.highlight ::selection{background:var(--grey-4)}.highlight::before{content:" ";position:absolute;border-radius:50%;background:#fc625d;width:.75rem;height:.75rem;left:.75rem;top:.8125rem;box-shadow:1.25rem 0 #fdbc40,2.5rem 0 #35cd4b}.highlight figcaption{color:var(--grey-4);display:inline-flex;font-size:.875em;font-weight:700;padding:0 6rem 0 5rem;min-height:2.5rem;width:100%;text-align:center;align-items:center;justify-content:space-between;background-color:var(--grey-3);margin-bottom:.625rem}.highlight figcaption::before{content:attr(data-lang);text-transform:Capitalize}.highlight figcaption a,.highlight figcaption span{display:block;margin-left:.625rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.highlight figcaption a{color:var(--grey-5)}.highlight figcaption a:hover{color:var(--grey-6)}.highlight.fullscreen{position:fixed;top:0;left:0;width:100%;height:100%;min-width:100%;z-index:9999;margin:0;border-radius:0;overflow-y:scroll;overflow-x:hidden}.highlight.fullscreen .show-btn{position:fixed}.highlight.breakline .code-container table{line-break:anywhere;white-space:break-spaces}.highlight.breakline .code-container table pre{white-space:break-spaces}.code-container{overflow-x:scroll;overflow-y:hidden}.code-container::after{content:"";display:block;height:.625rem;width:100%}.code-container table{white-space:pre;border-spacing:0;width:100%}.code-container tr{background-color:inherit}.code-container tr:hover td{background-color:var(--grey-3)}.code-container td{position:relative;padding:unset;vertical-align:unset;border:unset;transition:all .2s ease-in-out 0s}.code-container td pre::before{content:" "}.code-container td:first-child{position:absolute;background:var(--grey-2);text-align:right;overflow-x:visible!important;overflow-y:hidden;left:0;width:2.5rem;padding-right:.9375rem;color:var(--color-grey);z-index:1}.code-container td:nth-child(2){padding-left:3rem}.code-container td:last-child{padding-right:.9375rem}.code-container td[data-num]::before{content:attr(data-num)}.code-container td[data-command]::before{content:attr(data-command) " ";color:var(--grey-5);display:block;letter-spacing:-1px;padding-right:.5rem;text-align:right;white-space:nowrap}.code-container td[data-command]+td{padding-left:.5rem;border-left:1px solid var(--grey-4)}.code-container .marked td{background-color:var(--grey-3)}.code-container .marked:hover td:last-child{background-color:var(--color-red-a1)}.code-container .show-btn{position:absolute;cursor:pointer;left:0;bottom:0;width:100%;height:2.875rem;text-align:center;color:var(--text-color);background-image:linear-gradient(to bottom,var(--grey-2-a0) 0,var(--grey-2) 80%);z-index:1}.code-container .show-btn::after{content:"";display:block;width:100%;height:1rem;background:var(--grey-2)}.code-container .show-btn .ic{margin-top:1rem}.code-container .show-btn.open{background:0 0;bottom:.5rem}.code-container .show-btn.open::after{display:none}.code-container .deletion{background:var(--color-pink-light)}.code-container .addition{background:var(--color-cyan-light)}.code-container .meta{color:var(--color-yellow);-moz-user-select:none;-webkit-user-select:none;user-select:none}.code-container .comment,.code-container .punctuation{color:var(--grey-5)}.code-container .attribute,.code-container .css .class,.code-container .css .id,.code-container .css .pseudo,.code-container .function,.code-container .html .doctype,.code-container .name,.code-container .regexp,.code-container .ruby .constant,.code-container .tag,.code-container .variable,.code-container .xml .doctype,.code-container .xml .pi,.code-container .xml .tag .title{color:var(--color-red)}.code-container .built_in,.code-container .builtin-name,.code-container .command,.code-container .constant,.code-container .literal,.code-container .number,.code-container .params,.code-container .preprocessor{color:var(--color-orange)}.code-container .css .rules .attribute,.code-container .formula,.code-container .header,.code-container .inheritance,.code-container .ruby .class .title,.code-container .ruby .symbol,.code-container .special,.code-container .string,.code-container .symbol,.code-container .value,.code-container .xml .cdata{color:var(--color-green)}.code-container .css .hexcolor,.code-container .namespace,.code-container .title{color:var(--color-aqua)}.code-container .class-name,.code-container .coffeescript .title,.code-container .javascript .title,.code-container .perl .sub,.code-container .python .decorator,.code-container .python .title,.code-container .ruby .function .title,.code-container .ruby .title .keyword{color:var(--color-blue)}.code-container .javascript .function,.code-container .keyword{color:var(--color-purple)}.md li{position:relative;margin:.2rem 0}.md li:before{transition:all .2s ease-in-out 0s}.md li p{margin:0}.md dl,.md ol,.md ul{margin:.5em 0 .5em;padding:.1em .2em .1em 1.4em}.md dl dt::before,.md ul>li::before{content:"";position:absolute;width:.4em;height:.4em;background:var(--primary-color);border-radius:50%;top:.85em;left:-1em}.md dl dt:hover::before,.md ul>li:hover::before{background:var(--color-pink)}.md ol:not([start]){counter-reset:counter}.md ol>li::before{counter-increment:counter;content:counter(counter);position:absolute;width:1.4em;height:1.4em;border-radius:50%;text-align:center;font-size:.8em;line-height:1.4;top:.5em;left:-1.8em;background:var(--primary-color);color:var(--grey-1);cursor:pointer}.md ol>li:hover::before{color:var(--grey-1);background:var(--color-pink)}.md dl dt{position:relative}.md dl dd{padding-left:.9375em}.md ul li.nodot::before{width:auto;height:auto;background:0 0!important;border:none!important;position:relative;top:0!important;left:0!important}.md ul li.task-list-item::before{width:auto;height:auto;background:0 0!important;border:none!important;position:relative;top:0!important;left:0!important}.md ul li.task-list-item input[type=checkbox]{display:none}.md ul li.task-list-item input[type=checkbox]+label::before{font-family:ic;font-weight:400;color:var(--grey-4);display:inline-block;margin-right:.625em}.md ul li.task-list-item input[type=checkbox]:checked+label::before{color:var(--note-text,var(--primary-color))}.md li ul>li::before{background:var(--grey-1);border:1px solid var(--primary-color)}.md dd ol>li::before,.md li ol>li::before{content:counter(counter) ".";background:0 0;color:var(--primary-color);font-size:1em;line-height:1;width:auto}.md dd ol>li:hover::before,.md li ol>li:hover::before{background:0 0;color:var(--color-pink)}.md ol>li.quiz.show.true::before,.md ol>li.quiz>ul.options li.right::before{color:var(--color-green)}.md ol>li.quiz.show.true::after,.md ol>li.quiz>ul.options li.right::after{color:var(--color-green);animation:fadeIn .5s}.md ol>li.quiz.show.false::before,.md ol>li.quiz>ul.options li.wrong::before{color:var(--color-red)}.md ol>li.quiz.show.false::after,.md ol>li.quiz>ul.options li.wrong::after{color:var(--color-red);animation:fadeIn .5s}.md ol>li.quiz{margin:.625rem 0}.md ol>li.quiz::before{counter-increment:counter;content:counter(counter) ".";position:absolute;color:var(--primary-color);text-align:right;width:2rem;left:-2.2rem;height:auto;background:0 0!important;border:none!important;font-size:1em}.md ol>li.quiz>p{margin:0;cursor:pointer}.md ol>li.quiz>p:first-child::before{content:"[" attr(data-type) "]";font-size:.75em;color:var(--grey-4);margin:auto .3125rem}.md ol>li.quiz.mistake>p:first-child::before{color:var(--primary-color)}.md ol>li.quiz .gap{display:inline-block;min-width:2.5rem;text-align:center;padding:0 .625rem;text-indent:-624.9375rem}.md ol>li.quiz .gap::after{display:block;content:"";background:var(--text-color);width:calc(100% + 1.25rem);height:.0625rem;margin-bottom:-.0625rem;margin-left:-.625rem}.md ol>li.quiz.show.fill .gap{text-indent:0}.md ol>li.quiz::after,.md ol>li.quiz::before{transition:all .2s ease-in-out 0s}.md ol>li.quiz blockquote{display:none}.md ol>li.quiz blockquote .mistake{display:block;border:.1875rem dashed var(--grey-4);padding:.625rem 1.25rem;background:var(--grey-3);margin:.3125rem}.md ol>li.quiz blockquote .mistake::before{display:block;content:"[" attr(data-type) "]";font-size:.8125em;color:var(--grey-4)}.md ol>li.quiz .note{display:none;padding:0;margin:0;background:0 0;border:none;border-radius:inherit;color:unset;font-size:inherit;filter:unset}.md ol>li.quiz.show .note,.md ol>li.quiz.show blockquote{display:block}.md ol>li.quiz ul.options{padding-inline-start:0.625rem}.md ol>li.quiz ul.options li::before{color:var(--color-grey);margin-right:.625rem;transition:all .2s ease-in-out 0s;width:auto;height:auto;background:0 0!important;border:none!important;position:relative;top:0!important;left:0!important}.md ol>li.quiz ul.options li:first-child::before{content:"A."}.md ol>li.quiz ul.options li:nth-child(2)::before{content:"B."}.md ol>li.quiz ul.options li:nth-child(3)::before{content:"C."}.md ol>li.quiz ul.options li:nth-child(4)::before{content:"D."}.md ol>li.quiz ul.options li:nth-child(5)::before{content:"E."}.md ol>li.quiz>ul.options li{cursor:pointer}.md ol>li.quiz>ul.options li::after{font-family:ic;font-weight:400;position:absolute;left:-1.5625rem;top:0}.md ol>li.quiz.show.false::before,.md ol>li.quiz.show.true::before{visibility:hidden}.md ol>li.quiz.show.false::after,.md ol>li.quiz.show.true::after{font-family:ic;font-weight:400;position:absolute;left:-1.2rem;top:.25rem}.links{display:flex;flex-wrap:wrap;font-size:.9rem}.links .item{position:relative;display:inline-flex;justify-self:center;align-items:center;line-height:1.5;width:calc(50% - 2rem);padding:.5rem 1rem;margin:1rem;transition:all .2s ease-in-out 0s;border-radius:.5rem;border:.0625rem solid var(--grey-2);box-shadow:0 .625rem 1.875rem -.9375rem var(--box-bg-shadow);--bg-color:var(--block-color, #666)}.links .item .image{display:block;width:4rem;height:4rem;border-radius:.9375rem;background:var(--grey-1) center no-repeat;background-size:contain;flex-shrink:0;border:none}.links .item .info{padding-left:1rem}.links .item .title{margin:.5rem 0;font-family:Mulish,'Noto Serif JP','Noto Serif SC',Mulish,-apple-system,"PingFang SC","Microsoft YaHei",sans-serif;font-weight:700;color:var(--bg-color);border:none}.links .item .title .ic{display:none}.links .item .desc{font-size:.75em;margin:.5rem 0}.links .item:hover{color:var(--header-text-color);background-color:var(--bg-color);box-shadow:0 .125rem 1.25rem var(--bg-color);border-color:var(--bg-color)}.links .item:hover .image{mix-blend-mode:normal;background-color:var(--bg-color)}.links .item:hover .title{color:var(--header-text-color)}@media (max-width:767px){.links{font-size:1em}.links .item{width:calc(100% - 2rem)}}.md .note{border-radius:.1875rem;margin:1rem 0;padding:1rem;position:relative;background:var(--note-bg,var(--grey-2));color:var(--grey-6);border-left:.25rem solid var(--note-border,var(--grey-4));font-size:.875em;padding-left:2.5rem;--primary-color:var(--note-text)}.md .note::before{position:absolute;left:.5rem;top:calc(50% - 1.5rem);font-family:ic;font-weight:400;font-size:1.5rem;color:var(--note-text,var(--grey-6))}.md .note.no-icon{padding-left:1rem}.md .note.no-icon::before{content:none}::-webkit-details-marker{display:none}details>summary:first-of-type{list-style-type:none}details summary{outline:0;cursor:pointer;padding:.625rem;background:var(--note-bg,none);border-radius:.25rem;transition:all .4s ease}details summary::before{font-family:ic;font-weight:400;color:var(--grey-4);margin-right:.5rem}details>div{padding:.625rem}details.danger,details.info,details.primary,details.success,details.warning{margin:0 0 .8rem}details.danger summary,details.info summary,details.primary summary,details.success summary,details.warning summary{color:var(--note-text)}details.danger summary::before,details.info summary::before,details.primary summary::before,details.success summary::before,details.warning summary::before{color:var(--note-text)}details[open]{background:var(--note-bg,none);border-radius:.25rem;color:var(--grey-6)}details[open] summary{background:var(--note-hover,var(--grey-2));border-radius:.25rem}details[open] summary::before{color:var(--primary-color)}details[open]>div{margin:0 0 .8rem}details[open].danger,details[open].info,details[open].primary,details[open].success,details[open].warning{color:var(--note-text)}details[open].danger>summary,details[open].info>summary,details[open].primary>summary,details[open].success>summary,details[open].warning>summary{color:#fff;border-radius:.25rem .25rem 0 0}details[open].danger>summary::before,details[open].info>summary::before,details[open].primary>summary::before,details[open].success>summary::before,details[open].warning>summary::before{color:#fff}span.label{display:inline;border-radius:.3rem;border:.0625rem solid;padding:.2rem .3rem;font-family:Inconsolata,consolas,Menlo,-apple-system,"PingFang SC","Microsoft YaHei";font-size:1em;background:var(--note-bg,var(--grey-2));border-color:var(--note-border,var(--grey-4));color:var(--note-text,var(--grey-6))}.tabs{display:block;position:relative}.tabs .nav{overflow:hidden;border-bottom:.0625rem solid var(--grey-1-a7);height:2.6875rem}.tabs .nav ul{display:flex;padding:0;white-space:nowrap;overflow-x:auto}.tabs .nav li{position:relative;cursor:pointer;border:none;display:inline-block;padding:.3125rem 1.25rem;margin:0}.tabs .nav li::before{content:"";position:absolute;left:50%;right:50%;top:auto;bottom:0;transition:all .2s ease-in-out;width:auto;height:auto;background:0 0;border-radius:0;border-bottom:.125rem solid transparent}.tabs .nav li.active::before{left:0;right:0;border-bottom-color:var(--note-hover,var(--primary-color))}.tabs .tab{display:none}.tabs .tab.active{display:block}.tabs .show-btn{position:absolute;cursor:pointer;right:0;bottom:0;width:2.875rem;height:2.875rem;text-align:center;color:var(--grey-4);z-index:1}.tabs .show-btn::before{font-family:ic;font-weight:400}.md .tabs{margin:0 0 2rem;border-radius:.5rem;border:.0625rem solid var(--grey-2);box-shadow:0 .625rem 1.875rem -.9375rem var(--box-bg-shadow)}.md .tabs .tab{padding:1.25rem}.tabs .nav{overflow:visible}.tabs .nav li.active{font-weight:700}.md .note h2,.md .note h3,.md .note h4,.md .note h5,.md .note h6,.md details h2,.md details h3,.md details h4,.md details h5,.md details h6{margin-top:.1875rem;border-bottom:initial;margin-bottom:0;padding-top:0}.md .note p,.md details p{line-height:1.8}.md .note a:not(.btn),.md details a:not(.btn){color:var(--note-hover);border-bottom:.0625rem dashed var(--note-text)}.md .note a:not(.btn):hover,.md details a:not(.btn):hover{color:var(--note-text);border-bottom-color:var(--note-text)}.md .note ul li::before,.md details ul li::before{background:var(--note-text)}.md .note ol li:before,.md details ol li:before{background:var(--note-text,var(--primary-color))!important;width:.8rem;height:.8rem;font-size:.45rem;line-height:.8rem;top:.4rem;left:-1.2rem}.media-container{position:relative;border-radius:.5rem;border:.0625rem solid var(--grey-2);box-shadow:0 .625rem 1.875rem -.9375rem var(--box-bg-shadow);overflow:hidden;margin-bottom:2rem}.player-info{color:var(--text-color);font-size:1em;min-width:16.25rem}.player-info .tabs{border:none;box-shadow:none}.player-info .tabs .show-btn{display:none}.player-info .tabs .tab{padding:0}.player-info .controller{font-family:ic;font-weight:400;cursor:pointer;font-size:1.25em;display:flex;justify-content:space-around;align-items:center;text-align:center}.player-info .controller .btn{color:var(--grey-6);width:18%}.player-info .controller .btn:hover{color:var(--color-pink)}.player-info .play-pause{font-size:130%}.player-info .volume{position:relative}.player-info .volume .bar{position:absolute;height:.25rem;background:var(--color-pink-a3);bottom:0;left:0;transition:all .2s ease-out 0s}.player-info .volume.off .bar{height:0}.player-info .playlist{border-top:.125rem solid var(--grey-9-a1)}.player-info ol{font-size:.8125em;padding:.3125rem 0;margin:.625rem 0 0;height:12.5rem;overflow-x:scroll;counter-reset:counter;position:relative}.player-info ol::-webkit-scrollbar{width:.1875rem;height:.1875rem}.player-info ol>li{display:flex;padding:.3125rem .9375rem .3125rem 1.5625rem;cursor:pointer;transition:all .2s ease-in-out 0s;height:2rem;overflow:hidden}.player-info ol>li.error{opacity:.5;-webkit-text-decoration-line:line-through;text-decoration-line:line-through}.player-info ol>li::before{height:auto;background:0 0!important;border:none!important;position:relative;top:0!important;left:0!important;font-size:inherit;line-height:inherit;margin-left:-1.25rem;width:1.875rem;counter-increment:counter;content:counter(counter);text-align:right;padding-right:.3125rem;color:var(--grey-5)}.player-info ol>li .info{display:block;width:100%}.player-info ol>li .info span:nth-child(2){float:right;margin-left:.625rem;color:var(--grey-5)}.player-info ol>li.current{color:var(--primary-color);position:relative}.player-info ol>li.current::before{font-family:ic;font-weight:400;color:currentColor}.player-info ol>li.current .progress .bar{position:absolute;height:100%;background:var(--color-pink-a3);top:0;left:0;transition:all .2s ease-out 0s}.player-info ol>li.current .progress::before{content:attr(data-ptime) " / " attr(data-dtime);color:var(--grey-5);position:absolute;right:0;padding:0 .3rem}.player-info ol>li.current .progress.seeking::before{color:currentColor}.player-info ol>li.current .info{padding-right:5rem;-webkit-user-select:none;-moz-user-select:none;user-select:none}.player-info ol>li.current .info span:nth-child(2){display:none}.player-info ol>li:hover{background-color:var(--grey-1-a7)}.player-info ol>li:hover::before{color:var(--primary-color)}.video{border-radius:0 0 .5rem .5rem}.audio .preview{display:flex;align-items:center;padding:1.25rem 1.25rem 0}@media (max-width:767px){.audio .preview{padding:1.25rem .625rem 0;flex-direction:column}}.audio .preview .info{display:flex;flex-direction:column;margin-left:.625rem;padding:.625rem;text-overflow:ellipsis;overflow:hidden;width:100%}@media (max-width:767px){.audio .preview .info{margin-left:0}}.audio .preview .info h4{margin:0;text-overflow:ellipsis;max-height:3rem;padding:0;overflow:hidden}.audio .preview .info span{font-size:.75em}.audio .preview .lrc{max-height:4rem;margin-top:.3125rem;font-size:.75em;position:relative;text-align:center;overflow:hidden}.audio .preview .lrc .inner{width:100%;transition:all .5s ease-out}.audio .preview .lrc p{font-size:.75rem;color:var(--grey-6);line-height:1rem!important;height:1rem!important;padding:0!important;margin:0!important;transition:all .5s ease-out;opacity:.3;overflow:hidden}.audio .preview .lrc p.current{opacity:1;overflow:visible;height:auto!important;min-height:1rem}.audio .cover{position:relative;flex-shrink:0;cursor:pointer}.audio .cover::before{content:"";position:absolute;z-index:1;background:url("../images/play_needle.png") no-repeat center/contain;width:3.4375rem;height:5.1875rem;top:-1.5625rem;left:-1.5625rem;transform:rotateZ(-60deg);animation:rotate-needle-pause .5s 1 normal linear forwards;transform-origin:0.625rem 0.625rem}.audio .cover .disc{animation:rotate 20s linear infinite;animation-play-state:paused;padding:1.5rem;max-height:144px}.audio .cover .disc::after{content:"";position:absolute;background:url("../images/play_disc.png") no-repeat center/contain;z-index:1;width:100%;height:100%;top:0;left:0}.audio .cover img{-o-object-fit:contain;object-fit:contain;width:6rem;height:6rem;border-radius:50%}.audio.playing .cover::before{animation:rotate-needle-resume .5s 1 normal linear forwards}.audio.playing .cover .disc{animation-play-state:running} /* rebuild by hrmmi */ \ No newline at end of file diff --git a/css/comment.css b/css/comment.css index 5effdc8f..1e743a89 100644 --- a/css/comment.css +++ b/css/comment.css @@ -1,3 +1,3 @@ -/* build time:Wed Aug 14 2024 22:47:41 GMT+0800 (中国标准时间)*/ +/* build time:Wed Aug 14 2024 23:17:33 GMT+0800 (中国标准时间)*/ .v.wrap{animation:none;opacity:0}.v .lozaded{animation:none}.v input,.v textarea{border:none;outline:0;background:0 0;font-size:.75em;transition:all .25s ease}.v a{color:var(--color-aqua)}.v a:hover{color:var(--primary-color)}.v .text-center{text-align:center}.v .text-right{text-align:right}.v .float-right{float:right!important}.v .pd5{padding:5px}.v .pd10{padding:10px}.v .emoji,.v .vemoji{max-height:1.5rem;display:inline;vertical-align:middle}.v .submitting{margin:1em 0}.v .form{border-radius:.5rem;border:.0625rem solid var(--grey-2);box-shadow:0 .625rem 1.875rem -.9375rem var(--box-bg-shadow);margin-bottom:.625rem;position:relative;padding:.625rem}.v .form>.inner .auth-section{display:flex;padding:.3em .6em}@media (max-width:567px){.v .form>.inner{flex-wrap:wrap}}.v .form>.inner .input{flex:1 1 27%;width:27%}@media (max-width:567px){.v .form>.inner .input{flex:1 1 100%;padding-right:0;width:100%}}.v .form>.inner .input input{padding:.625rem .3125rem;width:100%;border-bottom:.0625rem dashed var(--grey-4)}.v .form>.inner .input input:focus{border-bottom-color:var(--primary-color)}.v .form>.inner .textarea{padding:.3em .6em}.v .form>.inner .veditor{width:100%;min-height:8.75em;font-size:.875em;line-height:1.75;resize:vertical}.v .form>.inner .btn-group{padding:.625rem 0;display:flex}.v .form>.inner .btn-group .i-markdown{font-size:.75em}.v .form>.inner .btn-group .left{width:30%}.v .form>.inner .btn-group .right{width:70%;text-align:right}.v .form>.inner .vextra-area{margin:.4em 0 .4em .5em}.v .form>.inner .preview-box{padding:.4375rem 1.25rem;font-size:.8125em;border-radius:.5rem;border:.0625rem solid var(--grey-2);box-shadow:0 .625rem 1.875rem -.9375rem var(--box-bg-shadow)}.v .form>.inner .trigger-section{display:none}.v .form .smile-body img{display:inline-block;width:auto;height:3rem;cursor:pointer;padding:.5rem;border-radius:.25rem;transition:box-shadow .2s ease-out,background .2s ease-out}.v .form .smile-body img:hover,.v .form .smile-body li.active img{background:var(--grey-2);box-shadow:1px 1px 2px var(--grey-1),-1px -1px 2px var(--grey-4),inset 8px 8px 16px var(--grey-1),inset -8px -8px 16px var(--grey-3)}.v .form .smile-body .smile-icons{border-radius:.5rem;margin:.3rem 0;min-height:10rem;max-height:10rem;overflow:auto;background:var(--grey-2);padding:.5rem}.v .form .smile-body .smile-bar li{display:inline-block;margin-right:.25rem}.v .form .smile-body .smile-bar img{width:2.8rem;height:2.8rem;background:var(--grey-2);-o-object-fit:contain;object-fit:contain}.v .form .btn{cursor:pointer;display:inline-block;margin:.5rem;overflow:hidden;vertical-align:middle}.v .form .btn.actived .ic{color:var(--primary-color)}.v .form .btn .ic{color:var(--grey-6);transition:all .25s ease}.v .form .btn .ic:hover{color:var(--color-blue)}.v .form .cancel-reply{position:absolute;right:0;top:0;z-index:1}.v .form .vsubmit{font-size:.875em}.v .msg{position:absolute;background:var(--grey-1-a5);width:100%;height:100%;left:0;top:0}.v .msg .alert{padding:3em 0 0 0}.v .msg .alert .text{color:var(--grey-8);padding:15px}@media (max-width:767px){.v .msg .alert{padding:8em 0}.v .msg .alert .text{padding:10px}}.v .info{padding:.3125rem;font-weight:600;font-size:1.25em}.v .info .col{display:inline-block;padding:0 20px;position:relative;background:0 0;z-index:2}.v .info .col .count{font-size:1.375rem;font-weight:inherit}.v .next .more{cursor:pointer;margin:1em 0}.v .list{width:100%}.v .item{word-break:break-all;padding-top:1.25em}.v .item .avatar{width:3.125em;height:3.125em;float:left;border-radius:50%;margin-right:.7525em;border:.0625rem solid var(--grey-3);padding:.125em}.v .item:hover .avatar{animation:.8s ease-out 0s 1 normal both running shake}.v .item .main{overflow:hidden;padding-bottom:.5em;border-bottom:.0625rem dashed var(--grey-3)}.v .item .head,.v .item .meta{color:var(--grey-5);line-height:1.8}.v .item .name{margin-right:.875rem}.v .item .system,.v .item .tag,.v .item .time{display:inline-block;font-size:.75em}@media (max-width:567px){.v .item .system span{display:none}}.v .item .tag{border-radius:.125rem;color:var(--grey-1);padding:0 .3125rem;margin-right:.5rem;background-color:var(--color-grey)}.v .item .tag.master{background-color:var(--color-orange)}.v .item .tag.friend{background-color:var(--color-aqua)}.v .item .tag.investor{background-color:var(--color-pink)}.v .item .at{color:var(--primary-color)}.v .item .at:hover{color:var(--color-aqua)}.v .item .meta{line-height:1}.v .item .meta .at{float:right}.v .item .content{margin-bottom:.75em;padding:.625em}.v .item .content>.inner{font-size:.875em;overflow-wrap:break-word;word-wrap:break-word;word-break:break-all;line-height:2;position:relative}.v .item .content>.inner.expand{cursor:pointer;max-height:8em;overflow:hidden}.v .item .content>.inner.expand::before{display:block;content:"";position:absolute;width:100%;left:0;top:0;bottom:3.15em;background:linear-gradient(180deg,var(--grey-1-a0),var(--grey-1));z-index:999}.v .item .content>.inner.expand::after{display:block;content:attr(data-expand);text-align:center;position:absolute;width:100%;height:3.15em;line-height:3.15em;left:0;bottom:0;z-index:999;background:var(--grey-1)}.v .item .content .form{margin-top:1rem}.v .item:last-child .main{border-bottom:none}.v .item .children{padding-left:1em;border-left:.0625rem dashed var(--grey-3)}.v .item .children .avatar{width:2.225em;height:2.225em}.v .empty{padding:20px;text-align:center}.v .spinner{margin:10px auto;width:50px;height:30px;text-align:center;font-size:10px}.v .spinner>div{background-color:var(--primary-color);height:100%;width:6px;margin-right:3px;display:inline-block;animation:sk-stretchdelay 1.2s infinite ease-in-out}.v .spinner .r2{animation-delay:-1.1s}.v .spinner .r3{animation-delay:-1s}.v .spinner .r4{animation-delay:-.9s}.v .spinner .r5{animation-delay:-.8s}@keyframes sk-stretchdelay{0%,100%,40%{transform:scaleY(.4)}20%{transform:scaleY(1)}}.hljs-comment,.hljs-quote{color:var(--grey-5);font-style:italic}.hljs-keyword,.hljs-meta,.hljs-selector-tag,.hljs-subst{color:var(--grey-7);font-weight:700}.hljs-literal,.hljs-number,.hljs-tag .hljs-attr,.hljs-template-variable,.hljs-variable{color:var(--color-green)}.hljs-doctag,.hljs-string{color:var(--color-red)}.hljs-section,.hljs-selector-id,.hljs-title{color:var(--color-pink);font-weight:700}.hljs-subst{font-weight:400}.hljs-class .hljs-title,.hljs-type{color:var(--color-grey);font-weight:700}.hljs-attribute,.hljs-name,.hljs-tag{color:var(--color-orange);font-weight:400}.hljs-link,.hljs-regexp{color:var(--color-green)}.hljs-bullet,.hljs-symbol{color:var(--color-purple)}.hljs-built_in,.hljs-builtin-name{color:var(--color-aqua)}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700} /* rebuild by hrmmi */ \ No newline at end of file diff --git a/css/mermaid.css b/css/mermaid.css index 2212421d..3214fdbd 100644 --- a/css/mermaid.css +++ b/css/mermaid.css @@ -1,3 +1,3 @@ -/* build time:Wed Aug 14 2024 22:47:41 GMT+0800 (中国标准时间)*/ +/* build time:Wed Aug 14 2024 23:17:33 GMT+0800 (中国标准时间)*/ pre.graphviz,pre.mermaid{background:0 0;padding:0;border:none}pre>svg{display:block;margin:0 auto}pre.graphviz{white-space:normal;max-width:calc(100% - 3.125rem)}pre.graphviz svg>g>polygon{fill:var(--grey-1)}.mermaid.graph svg{max-height:18.75rem}.mermaid .label{font-family:var(--mermaid-font-family);color:var(--grey-7);font-size:.875em}.mermaid .label text{fill:var(--text-color)}.mermaid .node circle,.mermaid .node ellipse,.mermaid .node path,.mermaid .node polygon,.mermaid .node rect{fill:var(--grey-1);stroke:var(--text-color);stroke-width:.0625rem}.mermaid .node .label{text-align:center}.mermaid .node.clickable{cursor:pointer}.mermaid .arrowheadPath{fill:var(--text-color)}.mermaid .edgePath .path{stroke:var(--text-color)}.mermaid .flowchart-link{stroke:var(--text-color);fill:none}.mermaid .edgeLabel{background-color:var(--grey-2);text-align:center}.mermaid .edgeLabel rect{opacity:.8;fill:var(--grey-2)!important}.mermaid .cluster rect{fill:var(--grey-2);stroke:var(--text-color);stroke-width:.0625rem}.mermaid .cluster text{fill:var(--text-color)}.mermaid div.mermaidTooltip{position:absolute;text-align:center;max-width:12.5rem;padding:.125rem;font-family:var(--mermaid-font-family);font-size:.75rem;background:var(--grey-1);border:.0625rem solid var(--text-color);border-radius:.125rem;pointer-events:none;z-index:99}.mermaid .actor{stroke:var(--text-color);fill:var(--grey-1)}.mermaid text.actor{fill:var(--text-color);stroke:none}.mermaid .actor-line{stroke:var(--text-color)}.mermaid .messageLine0{stroke-width:1.5;stroke-dasharray:'2 2';stroke:var(--text-color)}.mermaid .messageLine1{stroke-width:1.5;stroke-dasharray:'2 2';stroke:var(--text-color)}.mermaid #arrowhead{fill:var(--text-color)}.mermaid .sequenceNumber{fill:#fff}.mermaid #sequencenumber{fill:var(--text-color)}.mermaid #crosshead path{fill:var(--text-color)!important;stroke:var(--text-color)!important}.mermaid .messageText{fill:var(--text-color);stroke:none}.mermaid .labelBox{stroke:var(--text-color);fill:var(--grey-3)}.mermaid .labelText{fill:var(--text-color);stroke:none}.mermaid .loopText{fill:var(--text-color);stroke:none}.mermaid .loopLine{stroke-width:2;stroke-dasharray:'2 2';stroke:var(--text-color)}.mermaid .note{stroke:var(--grey-4);fill:var(--grey-3)}.mermaid .noteText{fill:#000;stroke:none;font-family:var(--mermaid-font-family);font-size:.875rem}.mermaid .activation0{fill:#f4f4f4;stroke:#666}.mermaid .activation1{fill:#f4f4f4;stroke:#666}.mermaid .activation2{fill:#f4f4f4;stroke:#666}.mermaid .mermaid-main-font{font-family:var(--mermaid-font-family)}.mermaid .section{stroke:none;opacity:.2}.mermaid .section0{fill:var(--grey-1)}.mermaid .section2{fill:var(--grey-1)}.mermaid .section1,.mermaid .section3{fill:var(--grey-0);opacity:.2}.mermaid .sectionTitle0{fill:var(--text-color)}.mermaid .sectionTitle1{fill:var(--text-color)}.mermaid .sectionTitle2{fill:var(--text-color)}.mermaid .sectionTitle3{fill:var(--text-color)}.mermaid .sectionTitle{text-anchor:start;font-size:.6875rem;text-height:0.875rem;font-family:var(--mermaid-font-family)}.mermaid .grid .tick{stroke:var(--text-color);opacity:.8;shape-rendering:crispEdges}.mermaid .grid .tick text{font-family:var(--mermaid-font-family)}.mermaid .grid path{stroke-width:0}.mermaid .today{fill:none;stroke:var(--primary-color);stroke-width:.125rem}.mermaid .task{stroke-width:2}.mermaid .taskText{text-anchor:middle;font-family:var(--mermaid-font-family)}.mermaid .taskText:not([font-size]){font-size:.6875rem}.mermaid .taskTextOutsideRight{fill:var(--text-color);text-anchor:start;font-size:.6875rem;font-family:var(--mermaid-font-family)}.mermaid .taskTextOutsideLeft{fill:var(--text-color);text-anchor:end;font-size:.6875rem}.mermaid .task.clickable{cursor:pointer}.mermaid .taskText.clickable{cursor:pointer;fill:#003163!important;font-weight:700}.mermaid .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163!important;font-weight:700}.mermaid .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163!important;font-weight:700}.mermaid .taskText0,.mermaid .taskText1,.mermaid .taskText2,.mermaid .taskText3{fill:var(--grey-1)}.mermaid .task0,.mermaid .task1,.mermaid .task2,.mermaid .task3{fill:var(--text-color);stroke:var(--text-color)}.mermaid .taskTextOutside0,.mermaid .taskTextOutside2{fill:var(--color-blue)}.mermaid .taskTextOutside1,.mermaid .taskTextOutside3{fill:var(--color-purple)}.mermaid .active0,.mermaid .active1,.mermaid .active2,.mermaid .active3{fill:var(--grey-1);stroke:var(--text-color)}.mermaid .activeText0,.mermaid .activeText1,.mermaid .activeText2,.mermaid .activeText3{fill:var(--text-color)!important}.mermaid .done0,.mermaid .done1,.mermaid .done2,.mermaid .done3{stroke:var(--color-green);fill:var(--grey-1);stroke-width:2}.mermaid .doneText0,.mermaid .doneText1,.mermaid .doneText2,.mermaid .doneText3{fill:var(--text-color)!important}.mermaid .crit0,.mermaid .crit1,.mermaid .crit2,.mermaid .crit3{stroke:var(--primary-color);fill:var(--primary-color);stroke-width:2}.mermaid .activeCrit0,.mermaid .activeCrit1,.mermaid .activeCrit2,.mermaid .activeCrit3{stroke:var(--primary-color);fill:var(--grey-1);stroke-width:2}.mermaid .doneCrit0,.mermaid .doneCrit1,.mermaid .doneCrit2,.mermaid .doneCrit3{stroke:var(--text-color);fill:var(--text-color);stroke-width:2;cursor:pointer;shape-rendering:crispEdges}.mermaid .milestone{transform:rotate(45deg) scale(.8,.8)}.mermaid .milestoneText{font-style:italic}.mermaid .doneCritText0,.mermaid .doneCritText1,.mermaid .doneCritText2,.mermaid .doneCritText3{fill:var(--color-green)!important}.mermaid .activeCritText0,.mermaid .activeCritText1,.mermaid .activeCritText2,.mermaid .activeCritText3{fill:var(--text-color)!important}.mermaid .titleText{text-anchor:middle;font-size:1.125rem;fill:var(--text-color);font-family:var(--mermaid-font-family)}.mermaid g.classGroup text{fill:var(--text-color);stroke:none;font-family:var(--mermaid-font-family);font-size:.625rem}.mermaid g.classGroup text .title{font-weight:bolder}.mermaid g.clickable{cursor:pointer}.mermaid g.classGroup rect{fill:var(--grey-1);stroke:var(--text-color)}.mermaid g.classGroup line{stroke:var(--text-color);stroke-width:1}.mermaid .classLabel .box{stroke:none;stroke-width:0;fill:var(--grey-1);opacity:.5}.mermaid .classLabel .label{fill:var(--text-color);font-size:.625rem}.mermaid .relation{stroke:var(--text-color);stroke-width:1;fill:none}.mermaid .dashed-line{stroke-dasharray:3}@mixin composition{fill:var(--text-color);stroke:var(--text-color);stroke-width:1}@include composition;@include composition;@mixin aggregation{fill:var(--grey-1);stroke:var(--text-color);stroke-width:1}@include aggregation;@include aggregation;@include composition;@include composition;@include composition;@include composition;.mermaid .branch-label,.mermaid .commit-id,.mermaid .commit-msg{fill:#d3d3d3;color:#d3d3d3;font-family:var(--mermaid-font-family)}.mermaid .pieTitleText{text-anchor:middle;font-size:1.5625rem;fill:$taskTextDarkColor;font-family:var(--mermaid-font-family)}.mermaid .slice{font-family:var(--mermaid-font-family)}.mermaid g.stateGroup text{fill:var(--text-color);stroke:none;font-size:.625rem;font-family:var(--mermaid-font-family)}.mermaid g.stateGroup text{fill:var(--text-color);stroke:none;font-size:.625rem}.mermaid g.stateGroup .state-title{font-weight:bolder;fill:#000}.mermaid g.stateGroup rect{fill:var(--grey-1);stroke:var(--text-color)}.mermaid g.stateGroup line{stroke:var(--text-color);stroke-width:1}.mermaid .transition{stroke:var(--text-color);stroke-width:1;fill:none}.mermaid .stateGroup .composit{fill:#fff;border-bottom:.0625rem}.mermaid .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:.0625rem}.mermaid .state-note{stroke:var(--grey-4);fill:var(--grey-3)}.mermaid .state-note text{fill:#000;stroke:none;font-size:.625rem}.mermaid .stateLabel .box{stroke:none;stroke-width:0;fill:var(--grey-1);opacity:.5}.mermaid .stateLabel text{fill:#000;font-size:.625rem;font-weight:700;font-family:var(--mermaid-font-family)}.mermaid .node circle.state-start{fill:#000;stroke:#000}.mermaid .node circle.state-end{fill:#000;stroke:#fff;stroke-width:1.5}.mermaid #statediagram-barbEnd{fill:var(--text-color)}.mermaid .statediagram-cluster rect{fill:var(--grey-1);stroke:var(--text-color);stroke-width:.0625rem}.mermaid .statediagram-cluster rect.outer{rx:0.3125rem;ry:0.3125rem}.mermaid .statediagram-state .divider{stroke:var(--text-color)}.mermaid .statediagram-state .title-state{rx:0.3125rem;ry:0.3125rem}.mermaid .statediagram-cluster.statediagram-cluster .inner{fill:#fff}.mermaid .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}.mermaid .statediagram-cluster .inner{rx:0;ry:0}.mermaid .statediagram-state rect.basic{rx:0.3125rem;ry:0.3125rem}.mermaid .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}.mermaid .note-edge{stroke-dasharray:5}.mermaid .statediagram-note rect{stroke:var(--grey-4);fill:var(--grey-3);stroke-width:.0625rem;rx:0;ry:0}:root{--mermaid-font-family:"trebuchet ms",verdana,arial} /* rebuild by hrmmi */ \ No newline at end of file diff --git a/feed.json b/feed.json index 08fbbb82..fb768ed2 100644 --- a/feed.json +++ b/feed.json @@ -66,8 +66,8 @@ "计算机科学", "操作系统", "YSOSv2", - "OS", "Rust", + "OS", "大作业" ] }, @@ -110,11 +110,11 @@ ] }, { - "id": "https://fuuzen.github.io/ie/de/sequential-circuit/", - "url": "https://fuuzen.github.io/ie/de/sequential-circuit/", - "title": "时序逻辑电路", + "id": "https://fuuzen.github.io/ie/de/shift-register/", + "url": "https://fuuzen.github.io/ie/de/shift-register/", + "title": "移位寄存器", "date_published": "2024-05-30T16:00:00.000Z", - "content_html": "

# 基础元件

\n

# 555 Timer

\n
\n

可能会考哦

\n
\n

mono-stable one-shot (单稳态触发器)

\n

\"555-单稳态触发器\"
\n非稳态延续时间:

\n

tw=1.1R1C1t_w=1.1R_1C_1\ntw=1.1R1C1

\n

astable multi-vibration oscillator (非稳态多谐振荡器)

\n

\"555-振荡器\"

\n

tH=0.7R1C1tL=1.4R2C1t_H=0.7R_1C_1\\\\\nt_L=1.4R_2C_1\ntH=0.7R1C1tL=1.4R2C1

\n

频率:

\n

f=1.44(R1+2R2)C1f=\\frac{1.44}{(R_1+2R_2)C_1}\\\\\nf=(R1+2R2)C11.44

\n

占空比(Duty Cycle)DCDCDC(非空 / 周期):

\n

DC=(R1+R2R1+2R2)100%DC=\\big(\\frac{R_1+R_2}{R_1+2R_2}\\big)100\\%\nDC=(R1+2R2R1+R2)100%

\n

上述公式中 DC>12DC\\gt\\frac{1}{2}DC>21,若要设计 50% 占空比的振荡器,如下图所示:

\n

tH=0.7R1C1tL=0.7R2C1t_H=0.7R_1C_1\\\\\nt_L=0.7R_2C_1\ntH=0.7R1C1tL=0.7R2C1

\n

\"50%占空比\"

\n

# S-R 触发器

\n

Qn+1=S+RQnQ^{n+1}=S+\\overline{R}Q^{n}\nQn+1=S+RQn

\n

# D 触发器

\n

Q=DQ'=D\nQ=D

\n

GATEGATEGATE 高电平有效使能:

\n

Qn+1=GATED+GATEQnQ^{n+1}=GATE\\cdot D+\\overline{GATE}\\cdot Q^{n}\nQn+1=GATED+GATEQn

\n

# ⭐️J-K 触发器

\n

Qn+1=JQn+QnKQ^{n+1}=J\\overline{Q^{n}}+Q^{n}\\overline{K}\nQn+1=JQn+QnK

\n

\"JK\"

\n

# 设计

\n

# 思路一

\n
    \n
  1. State Diagram 状态转移图\n
      \n
    • 有多少状态决定使用多少触发器,nnn 个状态应使用 log2n\\lceil\\log_2n\\rceillog2n
    • \n
    \n
  2. \n
  3. Next-State Table 次态表(状态转移表)
  4. \n
  5. Flip-Flop Transition Table 触发器转换表,由触发器特性方程决定
  6. \n
  7. Karnaugh Maps 根据次态表、触发器转换表画出卡诺图
  8. \n
  9. Locgi Expressions for Flip-Flop Inputs 根据卡诺图化简得到逻辑表达式
  10. \n
  11. Counter Implementation 根据逻辑表达式设计逻辑电路
  12. \n
\n

# 思路二

\n

每一个输入也要视为一个状态位(类似于 QQQ )来画卡诺图

\n

卡诺图每一个格子内容为:

\n

Q3n+1Q2n+1Q1n+1Q0n+1/CQ^{n+1}_3Q^{n+1}_2Q^{n+1}_1Q^{n+1}_0/C\nQ3n+1Q2n+1Q1n+1Q0n+1/C

\n

对于不可能的情况,也就是无关项,那么 5 个值统一为 X ,也就是:XXXX/XXXXX/XXXXX/X

\n

将内容拆开,则对应地画出 5 个卡诺图,然后分别化简,则能够得到:

\n
    \n
  • 4 个状态 (转移) 方程
  • \n
  • 1 个状态输出方程
  • \n
\n

再根据选定的触发器的特性方程,则可以写出各个触发器的各个输入的驱动方程以及输出方程

\n

在一些芯片上,计数使能被简单地标记为 CTEN (或者一些诸如 G 之类的其他名称), 终端计数 (TC) 和一些 IC 计数器上的异步 (行波) 时钟输出 (RCO) 比较相似

\n

一些计数器:

\n
    \n
  • 74HC161 十六进制计数器
  • \n
  • 74HC190 十进制计数器
  • \n
\n", + "content_html": "

# 串行输入 / 串行输出

\n

\"串行输入:串行输出\"

\n

# 串行输入 / 并行输出

\n

\"串行输入:并行输出\"

\n

# 并行输入 / 串行输出

\n

\"并行输入:串行输出\"

\n

# 并行输入 / 并行输出

\n

最简单

\n

# 双向移位寄存器

\n

\"4位双向位移\"

\n

# 74HC194

\n

通用 4 位双向移位寄存器

\n

\"74HC194\"

\n

\"74HC94波形图\"

\n

# 移位寄存器计数器

\n

# 约翰逊计数器

\n

\"约翰逊计数器\"

\n

\"约翰逊计数器波形图\"

\n

一般来说,约翰逊计 数器将会产生模 2n2n2n ,其中 nnn 是计数器中级的个数

\n

# 环形计数器

\n

\"环形计数器\"

\n

\"环形计数器波形图\"

\n

# 移位寄存器应用

\n

# 精确延时控制

\n

串行输入 / 串行输出移位寄存器可以用来提供从输入到输出的时间延迟,此时间延迟是寄存器中数 nnn 和时钟频率的函数

\n

从一个数字系统到另一个数字系统的串行数据传送,常常用来减少传输线中的导线数

\n

\"8位串并转换器\"

\n

当没有数据被传送时,串行数据线上就会有连续的 1 存在 ,0 位就是数据起始位,告诉串并转换器即将有 8 位数据序列到来:

\n

\"8位串并转换器数据串格式\"

\n

详细波形图解释工作流程如下:

\n

\"8位串并转换器波形图\"

\n", "tags": [ "电子信息", "数字逻辑电路", @@ -122,11 +122,11 @@ ] }, { - "id": "https://fuuzen.github.io/ie/de/shift-register/", - "url": "https://fuuzen.github.io/ie/de/shift-register/", - "title": "移位寄存器", + "id": "https://fuuzen.github.io/ie/de/sequential-circuit/", + "url": "https://fuuzen.github.io/ie/de/sequential-circuit/", + "title": "时序逻辑电路", "date_published": "2024-05-30T16:00:00.000Z", - "content_html": "

# 串行输入 / 串行输出

\n

\"串行输入:串行输出\"

\n

# 串行输入 / 并行输出

\n

\"串行输入:并行输出\"

\n

# 并行输入 / 串行输出

\n

\"并行输入:串行输出\"

\n

# 并行输入 / 并行输出

\n

最简单

\n

# 双向移位寄存器

\n

\"4位双向位移\"

\n

# 74HC194

\n

通用 4 位双向移位寄存器

\n

\"74HC194\"

\n

\"74HC94波形图\"

\n

# 移位寄存器计数器

\n

# 约翰逊计数器

\n

\"约翰逊计数器\"

\n

\"约翰逊计数器波形图\"

\n

一般来说,约翰逊计 数器将会产生模 2n2n2n ,其中 nnn 是计数器中级的个数

\n

# 环形计数器

\n

\"环形计数器\"

\n

\"环形计数器波形图\"

\n

# 移位寄存器应用

\n

# 精确延时控制

\n

串行输入 / 串行输出移位寄存器可以用来提供从输入到输出的时间延迟,此时间延迟是寄存器中数 nnn 和时钟频率的函数

\n

从一个数字系统到另一个数字系统的串行数据传送,常常用来减少传输线中的导线数

\n

\"8位串并转换器\"

\n

当没有数据被传送时,串行数据线上就会有连续的 1 存在 ,0 位就是数据起始位,告诉串并转换器即将有 8 位数据序列到来:

\n

\"8位串并转换器数据串格式\"

\n

详细波形图解释工作流程如下:

\n

\"8位串并转换器波形图\"

\n", + "content_html": "

# 基础元件

\n

# 555 Timer

\n
\n

可能会考哦

\n
\n

mono-stable one-shot (单稳态触发器)

\n

\"555-单稳态触发器\"
\n非稳态延续时间:

\n

tw=1.1R1C1t_w=1.1R_1C_1\ntw=1.1R1C1

\n

astable multi-vibration oscillator (非稳态多谐振荡器)

\n

\"555-振荡器\"

\n

tH=0.7R1C1tL=1.4R2C1t_H=0.7R_1C_1\\\\\nt_L=1.4R_2C_1\ntH=0.7R1C1tL=1.4R2C1

\n

频率:

\n

f=1.44(R1+2R2)C1f=\\frac{1.44}{(R_1+2R_2)C_1}\\\\\nf=(R1+2R2)C11.44

\n

占空比(Duty Cycle)DCDCDC(非空 / 周期):

\n

DC=(R1+R2R1+2R2)100%DC=\\big(\\frac{R_1+R_2}{R_1+2R_2}\\big)100\\%\nDC=(R1+2R2R1+R2)100%

\n

上述公式中 DC>12DC\\gt\\frac{1}{2}DC>21,若要设计 50% 占空比的振荡器,如下图所示:

\n

tH=0.7R1C1tL=0.7R2C1t_H=0.7R_1C_1\\\\\nt_L=0.7R_2C_1\ntH=0.7R1C1tL=0.7R2C1

\n

\"50%占空比\"

\n

# S-R 触发器

\n

Qn+1=S+RQnQ^{n+1}=S+\\overline{R}Q^{n}\nQn+1=S+RQn

\n

# D 触发器

\n

Q=DQ'=D\nQ=D

\n

GATEGATEGATE 高电平有效使能:

\n

Qn+1=GATED+GATEQnQ^{n+1}=GATE\\cdot D+\\overline{GATE}\\cdot Q^{n}\nQn+1=GATED+GATEQn

\n

# ⭐️J-K 触发器

\n

Qn+1=JQn+QnKQ^{n+1}=J\\overline{Q^{n}}+Q^{n}\\overline{K}\nQn+1=JQn+QnK

\n

\"JK\"

\n

# 设计

\n

# 思路一

\n
    \n
  1. State Diagram 状态转移图\n
      \n
    • 有多少状态决定使用多少触发器,nnn 个状态应使用 log2n\\lceil\\log_2n\\rceillog2n
    • \n
    \n
  2. \n
  3. Next-State Table 次态表(状态转移表)
  4. \n
  5. Flip-Flop Transition Table 触发器转换表,由触发器特性方程决定
  6. \n
  7. Karnaugh Maps 根据次态表、触发器转换表画出卡诺图
  8. \n
  9. Locgi Expressions for Flip-Flop Inputs 根据卡诺图化简得到逻辑表达式
  10. \n
  11. Counter Implementation 根据逻辑表达式设计逻辑电路
  12. \n
\n

# 思路二

\n

每一个输入也要视为一个状态位(类似于 QQQ )来画卡诺图

\n

卡诺图每一个格子内容为:

\n

Q3n+1Q2n+1Q1n+1Q0n+1/CQ^{n+1}_3Q^{n+1}_2Q^{n+1}_1Q^{n+1}_0/C\nQ3n+1Q2n+1Q1n+1Q0n+1/C

\n

对于不可能的情况,也就是无关项,那么 5 个值统一为 X ,也就是:XXXX/XXXXX/XXXXX/X

\n

将内容拆开,则对应地画出 5 个卡诺图,然后分别化简,则能够得到:

\n
    \n
  • 4 个状态 (转移) 方程
  • \n
  • 1 个状态输出方程
  • \n
\n

再根据选定的触发器的特性方程,则可以写出各个触发器的各个输入的驱动方程以及输出方程

\n

在一些芯片上,计数使能被简单地标记为 CTEN (或者一些诸如 G 之类的其他名称), 终端计数 (TC) 和一些 IC 计数器上的异步 (行波) 时钟输出 (RCO) 比较相似

\n

一些计数器:

\n
    \n
  • 74HC161 十六进制计数器
  • \n
  • 74HC190 十进制计数器
  • \n
\n", "tags": [ "电子信息", "数字逻辑电路", @@ -204,8 +204,8 @@ "计算机科学", "操作系统", "YSOSv2", - "OS", "Rust", + "OS", "大作业" ] }, @@ -248,18 +248,17 @@ ] }, { - "id": "https://fuuzen.github.io/math/discrete-math/algebra/ring/", - "url": "https://fuuzen.github.io/math/discrete-math/algebra/ring/", - "title": "环", + "id": "https://fuuzen.github.io/math/discrete-math/graph/euler_hamilton/", + "url": "https://fuuzen.github.io/math/discrete-math/graph/euler_hamilton/", + "title": "欧拉图与哈密顿图", "date_published": "2024-05-16T16:00:00.000Z", - "content_html": "

# 环的相关定义

\n

RRR 是非空集合,如果在 RRR 上定义了两个二元运算 “+++”(称为加法)和 “ \\cdot ”(称为乘法),且满足:

\n
    \n
  • (1) RRR 关于加法 +++ 构成交换群(即加群)
  • \n
  • (2) RRR 关于乘法 \\cdot 构成半群,即乘法满足结合律:a,b,cR,  a(bc)=(ab)c\\forall a,b,c\\in R,\\ \\ a\\cdot(b\\cdot c)=(a\\cdot b)\\cdot ca,b,cR,  a(bc)=(ab)c
  • \n
  • (3) 乘法 \\cdot 对加法有左右分配律
  • \n
\n

a,b,cRa(b+c)=ab+ac(b+c)a=ba+ca\\forall a,b,c\\in R\\\\\na\\cdot(b+c)=a\\cdot b+a\\cdot c\\\\\n(b+c)\\cdot a=b\\cdot a+c\\cdot a\na,b,cRa(b+c)=ab+ac(b+c)a=ba+ca

\n

则称代数 (R,+,  )(R,+,\\ \\cdot\\ )(R,+,  ) 是环(ring)。在通过上下文能明确运算时,通常直接称 RRR 为环。

\n
\n

有教材要求环乘法必须有单位元,也有教材要求环乘法必须满足交换律等

\n
\n

对环 (R,+,  )(R,+,\\ \\cdot\\ )(R,+,  )(R ,+)(R\\ ,+)(R ,+) 是交换群,称为环 RRR 的加法群,其单位元通常用 0 表示,称为环 RRR 的零元,元素 aaa 的加法逆元记为 a-aa ,称为 aaa 的负元。

\n

通过负元引入环的减法,即 aba-bab 定义为 a+(b)a+(-b)a+(b)

\n
    \n
  • 环乘法是否满足交换律\n
      \n
    • 若环 RRR 的乘法也满足交换律,则称为交换环 (commutative ring)
    • \n
    \n
  • \n
  • 是否有单位元\n
      \n
    • 若环 RRR 的乘法有单位元,则称为有单位元环,环乘法的单位元通常记为 eee111 ,并称为环 RRR 的单位元
    • \n
    \n
  • \n
  • 环乘法当环 RRR 有单位元 eee 时,考虑环的元素是否有逆元\n
      \n
    • 若对 aRa\\in RaR ,存在 bRb\\in RbR ,使得 ab=ba=eab=ba=eab=ba=e ,则称 aaa 是可逆元,或称为环 RRR单位 (unit),并称 bbbaaa 的逆元。当然这时 bbb 也是可逆元,且 aaabbb 的逆元
    • \n
    • 所有可逆元关于环乘法构成群,称为 RRR单位群 (group of units),记为 U(R)U(R)U(R)
    • \n
    \n
  • \n
  • 环乘法是否有零因子\n
      \n
    • 对环 RRR 的两个非零元素 a,ba,ba,b ,若 ab=0a\\cdot b=0ab=0 ,则称 aaa左零因子 (left zero-divisor),b 是右零因子 (right zero-divisor)。左零因子和右零因子统称为零因子
    • \n
    • 若环 RRR 的所有非零元素都不是左零因子或右零因子,则称 RRR 为无零因子环。
    • \n
    \n
  • \n
\n

当集合 RRR 只有一个元素 000 ,定义 RRR 的加法运算和乘法运算:0+0=0, 00=00+0=0,\\ 0\\cdot 0=00+0=0, 00=0,则 ({0},+,  )(\\{0\\},+,\\ \\cdot\\ )({0},+,  ) 构成环,这个环称为零环。在这个环中,零元也是单位元,而零元也是可逆元

\n

零环过于简单,通常在对环进行讨论时都将零环排除在外。因此在提到环时,总是默认环至少有两个元素,这时零元不可能是单位元,也不可能是可逆元。

\n

# 整环

\n
    \n
  • 有单位元
  • \n
  • 无零因子
  • \n
  • (乘法) 可交换
  • \n
\n

的环称为整环 (integral domain)

\n
\n

证明一个环是整环:

\n\\forall a,b\\in R,\\ \\ ab=0\\Rightarrow a=0\\or b=0\n\n

# 除环

\n
    \n
  • 有单位元
  • \n
  • 至少有两个元素
  • \n
  • 每个非零元都可逆 (乘法)
  • \n
  • (无零因子,可逆元都不是零因子)
  • \n
\n

的环称为除环 (division ring)

\n

#

\n

交换除环称为 (field) (比较常用),也即需满足:

\n
    \n
  • 有单位元
  • \n
  • 至少有两个元素
  • \n
  • 每个非零元都可逆 (乘法)
  • \n
  • (乘法) 可交换
  • \n
  • (无零因子,可逆元都不是零因子)
  • \n
\n
\n

可逆元都不是零因子(为什么?),因此域都是整环!

\n
\n

非交换除环也称 (skew field) (比较少用)

\n

# 常用环

\n

# 整数环及其子环

\n
    \n
  • \n

    整数集 Z\\mathbb ZZ 关于普通加法 +++ 和普通乘法 \\cdot 构成环,称为整数环

    \n
      \n
    • \n

      整数环 Z\\mathbb ZZ交换环,(乘法) 零元是 0,单位元是 1

      \n
    • \n
    • \n

      只有 1 和 -1 是可逆元,因此整数环的单位群是 ({1,1},  )(\\{1, -1\\},\\ \\cdot\\ )({1,1},  )

      \n
    • \n
    • \n

      整数环的每个非零整数都不是零因子,因此整数环是整环

      \n
    • \n
    \n
  • \n
  • \n

    固定整数 ddd ,集合 dZ={kdkZ}d\\mathbb Z=\\{kd|k\\in \\mathbb Z\\}dZ={kdkZ} 关于普通加法 +++ 和普通乘法 \\cdot 也构成交换环

    \n
      \n
    • \n

      d1d≠1d=1 时,环 dZd\\mathbb ZdZ 没有单位元。显然环 dZd\\mathbb ZdZ 也是无零因子环

      \n
    • \n
    • \n

      具体来说,所有偶数构成的集合 2Z2\\mathbb Z2Z 关于普通加法和普通乘法构成无单位元、无零因子的交换环。

      \n
    • \n
    \n
  • \n
\n

# 模 m 剩余类环及其子环

\n

固定整数 m2m≥2m2 ,模 mmm 剩余类 Zm={0,1,,m1}\\mathbb Z_m=\\{\\overline{0},\\overline{1},\\cdots,\\overline{m-1}\\}Zm={0,1,,m1} 关于模 mmmm⊕_mm 和模 mmmm⊗_mm 构成环,称为模 mmm 剩余类环 (residue class ring)

\n
    \n
  • \n

    0\\overline 00 表示整除 mmm 余 0 的所有整数构成的集合,Zm\\mathbb Z_mZm 的元素是集合

    \n
  • \n
  • \n

    mmm 剩余类环 Z\\mathbb ZZ 是有单位元交换环,零元是 0,有单位元 1

    \n
  • \n
  • \n

    对于 aZma\\in \\mathbb Z_maZm ,如果 aaammm 互质,则 aaa 关于模 mmm 乘有逆元,因此单位群是 U(m)U(m)U(m)

    \n
  • \n
  • \n

    mmm 是质数 ppp 时,Zp={0}U(p)\\mathbb Z_p=\\{0\\}\\cup U(p)Zp={0}U(p) ,关于 p⊕_ppp⊗_pp 构成有单位元、每个非零元都可逆的交换环,也即这时 Zp\\mathbb Z_pZp 是域

    \n
  • \n
  • \n

    mmm 不是质数时,若 m=kd(2km,2km)m=kd(2≤k≤m,2≤k≤m)m=kd(2km,2km) ,则 kkkddd 都是模 mmm 剩余类环的零因子,这时就不是无零因子环,当然也不是整环

    \n
  • \n
\n

# 有理数域

\n

有理数集 QQQ 关于普通加法 +++ 和普通乘法 \\cdot 构成环

\n
    \n
  • \n

    有单位元 1,是交换环,而且每个非零有理数 rrr 都有逆 1/r1/r1/r

    \n
  • \n
  • \n

    单位群是所有非零有理数集 Q\\mathbb Q^*Q 关于普通乘法构成的群 (Q,  )(\\mathbb Q^*,\\ \\cdot\\ )(Q,  )

    \n
  • \n
  • \n

    因此通常直接称有理数集 Q\\mathbb QQ 为有理数域

    \n
  • \n
\n

实数集 R\\mathbb RR 和复数集 C\\mathbb CC 关于普通加法 +++ 和普通乘法 \\cdot 也都构成域,分别称为实数域 R\\mathbb RR 和复数域 C\\mathbb CC

\n
    \n
  • \n

    单位群分别是所有非零实数集 R\\mathbb R^*R 和非零复数集 C\\mathbb C^*C 关于普通乘法构成的群

    \n
  • \n
  • \n

    复数域 C\\mathbb CC 的零元是实数 0,单位元是实数 1,而复数乘法的逆为:(a+bi)1=abia2+b2(a+bi)^{-1}=\\frac{a-bi}{a^2+b^2}(a+bi)1=a2+b2abi

    \n
  • \n
\n

# 高斯整环

\n

\"高斯整环\"

\n

# 类高斯整环

\n
\n

看起来和高斯整环很像,我乱起的名字,不是很重要

\n
\n

\"类高斯整环1\"

\n

\"类高斯整环2\"

\n

# 全矩阵环

\n

\"全矩阵环\"

\n

# 多项式环

\n

\"多项式环1\"\"多项式环2\"

\n
\n

例子

\n
\n

\"多项式环举例\"

\n

# 理想

\n

# 定义

\n

RRR 是环,IIIRRR 的非空子集。若 I 满足:

\n
    \n
  1. r1,r2I\\forall r_1,r_2\\in Ir1,r2I,有 r1r2Ir_1-r_2\\in Ir1r2I
  2. \n
  3. rI, sR,  rs,srI\\forall r\\in I,\\ \\forall s\\in R,\\ \\ rs,sr\\in IrI, sR,  rs,srI
  4. \n
\n

则称 III 为环 RRR理想 (ideal),记为 IRI⊲RIR,若 IIIRRR 的真子集,则称 IIIRRR真理想 (proper ideal)。

\n

理想是子环:显然如果 IIIRRR 的理想,则 III 必定是 RRR 的子环;

\n
\n

⚠️ 当然子环不一定是理想 ⚠️

\n
\n

RRR 的单个零元构成的集合 {0}\\{0\\}{0}(称为零理想)和 RRR 本身都是 RRR 的理想,这两个理想称为 RRR平凡理想。因此 RRR 的非平凡理想就是非零真理想

\n

# 常用理想

\n

整数环 ZZZ 的所有理想是 dZ={dzzZ}, d=0,1,dZ=\\{dz|z\\in Z\\},\\ d=0,1,\\cdotsdZ={dzzZ}, d=0,1,

\n

mmm 剩余类环 ZmZ_mZm 的所有理想是 dZm={dzzZm}, d=0,1,,m1dZ_m=\\{dz|z\\in Z_m\\},\\ d=0, 1, \\cdots, m-1dZm={dzzZm}, d=0,1,,m1

\n
\n

证明

\n

理想是子环,而 ZZZ 的每个子环都具有形式 dZdZdZ ,而且对任意子环 dZdZdZ ,对任意 dzdZdz\\in dZdzdZ ,以及 sZs\\in ZsZ ,显然有 dzs,sdzdZdzs, sdz\\in dZdzs,sdzdZ ,因此每个子环 dZdZdZ 都是 ZZZ 的理想

\n

类似可得到模 mmm 剩余类环 ZmZ_mZm 的所有理想是 dZm,d=0,1,,m1dZ_m, d=0, 1, \\cdots, m-1dZm,d=0,1,,m1

\n

# 运算

\n

#

\n

RRR 是环,I,JI,JI,J 都是 RRR 的理想,I+JI+JI+J 称为理想 IIIJJJ

\n

I+J={a+bRaI,bJ}I+J=\\{a+b\\in R|a\\in I, b\\in J\\}\nI+J={a+bRaI,bJ}

\n

#

\n

IJI\\cap JIJ 称为 IIIJJJ

\n

IJ={xRxI,xJ}I\\cap J=\\{x\\in R|x\\in I,x\\in J\\}\nIJ={xRxI,xJ}

\n

#

\n

IJIJIJ 称为理想 IIIJJJ

\n

IJ={a1b1+a2b2++anbnnN,akI,bkJ}IJ=\\{a_1b_1+a_2b_2+\\cdots+a_nb_n|n\\in\\mathbb N^*,a_k\\in I,b_k\\in J\\}\nIJ={a1b1+a2b2++anbnnN,akI,bkJ}

\n

# 和交积保持理想

\n

IIIJJJ 都是环 RRR 的理想,则 I+JI+JI+JIJI\\cap JIJIJIJIJ 也是环 RRR 的理想

\n

环的任意有限多个理想的和仍是理想,而任意有限或无限多个理想的交仍是理想

\n

# 主理想

\n

# 定义

\n

RRR 是环,aaaRRR 的元素,记所有包含 aaa 的理想构成的集合为:

\n

={IRaI}\\sum=\\{I\\lhd R|a\\in I\\}\n={IRaI}

\n

至少有 RR\\in\\sumR ,所以 \\sum 非空。令:

\n

a=II\\langle a\\rangle=\\bigcap_{I\\in\\sum}I\na=II

\n

a\\langle a\\ranglea 是理想,而且是包含 aaa 的最小理想。这个理想称由 aaa 生成的主理想(principal ideal),aaa 为其生成元

\n

# 定理结论

\n

RRR 的由 aaa 生成的主理想满足:

\n

a={(i=1nxiayi)+xa+ay+maxi,yi,x,yR,nZ+,mZ}\\langle a\\rangle=\\big\\{\n\\big(\\sum_{i=1}^{n}x_iay_i\\big)\n+xa+ay+ma\\big|x_i,y_i,x,y\\in R,n\\in\\mathbb Z^+,m\\in\\mathbb Z\n\\big\\}\na={(i=1nxiayi)+xa+ay+maxi,yi,x,yR,nZ+,mZ}

\n

RRR 有单位元,则:

\n\\langle a\\rangle=\\big\\{\n\\big(\\sum_{i=1}^{n}x_iay_i\\big)\n\\big|x_i,y_i\\in R\n\\big\\}\\\n\n

RRR交换环,则:

\n

a={xa+maxR,mZ}\\langle a\\rangle=\\big\\{\nxa+ma\\big|x\\in R,m\\in\\mathbb Z\n\\big\\}\na={xa+maxR,mZ}

\n

⭐️若 RRR有单位元的交换环,则:

\n

a=aR={arrR}\\langle a\\rangle=aR=\\big\\{\nar\\big|r\\in R\n\\big\\}\na=aR={arrR}

\n

# 常用理想的主理想

\n
    \n
  • 整数环 Z\\mathbb ZZ 的每个理想 dZd\\mathbb ZdZ 都是主理想,即是 d\\langle d\\rangled
  • \n
  • mmm 剩余类环 Zm\\mathbb Z_mZm 的每个理想 dZmd\\mathbb Z_mdZm 也都是主理想,即也是 d\\langle d\\rangled
  • \n
\n

RRR 是环,a1,a2,,anRa_1,a_2,\\cdots,a_n\\in Ra1,a2,,anR,则:

\n

a1,a2,,an=a1+a2++an\\langle a_1,a_2,\\cdots,a_n\\rangle=\\langle a_1\\rangle+\\langle a_2\\rangle+\\cdots+\\langle a_n\\rangle\na1,a2,,an=a1+a2++an

\n

也是 RRR 的理想,并且是包含 a1,a2,,ana_1,a_2,\\cdots,a_na1,a2,,an 的最小理想!称为由 a1,a2,,ana_1,a_2,\\cdots,a_na1,a2,,an 生成的理想。

\n

整数环 Z\\mathbb ZZa1,a2a_1,a_2a1,a2 生成的理想是gcd(a1,a2)\\langle\\gcd(a_1,a_2)\\ranglegcd(a1,a2)

\n

# 商环

\n
\n

环关于理想的商环

\n
\n

# 定义

\n

RRR 是环,III(R,+,  )(R,+,\\ \\cdot\\ )(R,+,  ) 的一个理想,则 (I,+)(I,+)(I,+)(R,+)(R,+)(R,+) 的正规子群,它所有(关于加群)的陪集构成集合 R/I{x+IxR}R/I=\\{x+I|x\\in R\\}R/I{x+IxR} 、记陪集 x+Ix+Ix+Ix\\overline xx

\n

# 运算的定义

\n

# 加法

\n

在集合 R/IR/IR/I 上可定义加法 +++

\n

x,yR/I,x+y=x+y(x+I)+(y+I)=(x+y)+I\\forall \\overline x,\\overline y\\in R/I,\\\\\n\\overline{x}+\\overline{y}=\\overline{x+y}\\Longleftrightarrow (x+I)+(y+I)=(x+y)+I\nx,yR/I,x+y=x+y(x+I)+(y+I)=(x+y)+I

\n

这里 x+y\\overline{x}+\\overline{y}x+y 中的 +++ 是要定义的加法,即后面所说商环中的加法,而 x+y\\overline{x+y}x+y 中的 +++ 是环 RRR 中的加法。

\n

根据正规子群的性质,该定义是合适的。

\n

# 乘法

\n

在集合 R/IR/IR/I 上可定义乘法 ×\\times×

\n

x,yR/I,xy=xy(x+I)(y+I)=(xy)+I\\forall \\overline x,\\overline y\\in R/I,\\\\\n\\overline{x}\\cdot\\overline{y}=\\overline{x\\cdot y}\\Longleftrightarrow (x+I)\\cdot(y+I)=(x\\cdot y)+I\nx,yR/I,xy=xy(x+I)(y+I)=(xy)+I

\n

这里 xy\\overline{x}\\cdot\\overline{y}xy 中的 $\\cdot $ 是要定义的乘法,即后面所说商环中的乘法,而 xy\\overline{x\\cdot y}xy 中的 $\\cdot $ 是环 RRR 中的乘法。

\n
\n

由于这定义在等价类(陪集)上,因此需要证明该定义是合适的,即与选择的代表无关,即:

\n

x1=x2 y1=y2x1y1=x2y2\\overline{x_1}=\\overline{x_2}\\ \\land\\overline{y_1}=\\overline{y_2}\\\\\n\\Downarrow\\\\\n\\overline{x_1\\cdot y_1}=\\overline{x_2\\cdot y_2}\nx1=x2 y1=y2x1y1=x2y2

\n

\"商环乘法合适定义证明\"

\n

# 构成环

\n

\"商环构成环证明1\"

\n

\"商环构成环证明2\"

\n

# 商环定义

\n

RRR 是环,III 是理想,则环的加群关于理想的商群 R/IR/IR/I构成环(基于上面定义的加法和乘法),称为环 RRR 关于理想 III 的商环(quotient ring),仍记为 R/IR/IR/I

\n

R/I={x+IxR}R/I=\\{x+I|x\\in R\\}\nR/I={x+IxR}

\n

基本性质:

\n
    \n
  • a=a+I\\overline{a}=a+Ia=a+I
  • \n
  • 商环的(加法)零元:0=0+I\\overline{0}=0+I0=0+I
  • \n
  • 商环的(加法)单位元:e=e+I\\overline{e}=e+Ie=e+I
  • \n
\n

# 环同态

\n
\n

环的同态就是与环的加法与乘法都可交换的函数

\n
\n

(R,+,)(R,+,\\cdot)(R,+,)(R,,)(R',\\oplus,\\otimes)(R,,) 是环,φ:RR\\varphi:R\\to R'φ:RRRRRRR'R 的函数,若对 a,bR\\forall a,b\\in Ra,bR 有:

\n

φ(a+b)=φ(a)φ(b)φ(ab)=φ(a)φ(b)\\varphi(a+b)=\\varphi(a)\\oplus\\varphi(b)\\\\\n\\varphi(a\\cdot b)=\\varphi(a)\\otimes\\varphi(b)\nφ(a+b)=φ(a)φ(b)φ(ab)=φ(a)φ(b)

\n

则称 φ\\varphiφRRRRR'R同态

\n
    \n
  • φ\\varphiφ 是单函数,则称为单同态
  • \n
  • φ\\varphiφ 是满函数,则称为满同态
  • \n
  • φ\\varphiφ 是双函数,则称为同构,记为:RRR\\cong R'RR
  • \n
\n

RRRRR'R 是两个环,定义函数 φ:RRφ:R→R^′φ:RRaR,φ(a)=0∀a\\in R,φ(a)= 0aR,φ(a)=0,这里 0 是 RR'R 的零元,则容易验证 φφφ 是同态,这个同态称为零同态 (zero homomorphism)

\n

RRR 是环,IIIRRR 的理想,则很自然地有同态 ρ:RR/Iρ:R→R/Iρ:RR/IaR,ρ(a)=a∀a\\in R,ρ(a)=\\overline aaR,ρ(a)=a,这里 a\\overline aaaaa 所在的等价类,即 a+Ia+Ia+I 。这个同态称为商环 R/IR/IR/I自然同态 (natural morphism)

\n

零同态、自然同态都是满同态。

\n

自然同态一个例子:

\n
    \n
  • 整数环 Z\\mathbb ZZ 到模 mmm 剩余类环 Zm\\mathbb Z_mZm 有很自然的满同态 φ:ZZmφ:\\mathbb Z→\\mathbb Z_mφ:ZZmzZ,φ(z)=zmodm∀z\\in \\mathbb Z, φ(z)=z\\bmod mzZ,φ(z)=zmodm
  • \n
\n
\n

零同态全部映射到零元,单同态给出子代数,满同态给出商代数

\n
\n

环同态保持:

\n
    \n
  • 加法单位元
  • \n
  • 子环
  • \n
\n

不保持:

\n
    \n
  • 理想
  • \n
\n

# Zm\\mathbb{Z}_mZmZn\\mathbb{Z}_nZn 的同态

\n

\"zm到zn的同态符号约定\"

\n

φ:ZmZn\\varphi:\\mathbb{Z}_m\\to\\mathbb{Z}_nφ:ZmZnZm\\mathbb{Z}_mZmZn\\mathbb{Z}_nZn 的同态,当且仅当:

\n
    \n
  • φ(1)=[a]\\varphi(\\overline1)=[a]φ(1)=[a];(环同态由该值决定)
  • \n
  • φ(x)=x[a]\\varphi(\\overline{x})=x[a]φ(x)=x[a];(乘法陪集)
  • \n
  • m[a]=[0]m[a]=[0]m[a]=[0]
  • \n
  • [a]2=[a][a]^2=[a][a]2=[a];([a][a][a]Zm\\mathbb{Z}_mZm 的幂等元)
  • \n
\n

# 环扩张

\n

环的扩张定理,也称为挖补定理

\n

\"环扩张定理\"

\n

如图,RRRSS'S 是 2 个没有公共元素的环,存在 RRRSS'S 的单同态:

\n

ψ:RS\\psi:R\\to S'\nψ:RS

\n

并且:ψ(R)=S\\psi(R)=Sψ(R)=S

\n

那么 RRR 可以扩张为 RR'R ,满足:

\n
    \n
  • RR=SSR'-R=S'-SRR=SS
  • \n
  • SRS'\\cong R'SR
  • \n
\n

RRR 是一个没有单位元的环,则存在一个有单位元的环 RR'R ,使得 RRRRR'R 的子环。

\n

# 特征

\n

RRR 是环。若存在最小正整数 nnn 使得对所有 aRa\\in RaRna=0na=0na=0 ,则称 nnn 为环 RRR特征。如果不存在这样的正整数,则称 RRR 的特征为 0。环 R 的特征记为 Char RRR

\n

数域 Z,Q,R,C\\mathbb Z, \\mathbb Q, \\mathbb R, \\mathbb CZ,Q,R,C 的特征都是 0,而模 mmm 剩余类环 Zm\\mathbb Z_mZm 的特征是 mmm

\n

【定理】设 RRR 是有单位元 eee 的环。若 eee 关于加法的阶为无穷大,则 Char R=0R=0R=0,否则 Char R=eR=|e|R=e,这里 e|e|e 在环的加群中的阶。

\n

证明 若 eee 的加法的阶为无穷大,则不存在正整数 nnn 使得 ne=0ne=0ne=0 ,从而 Char R=0R= 0R=0,否则,若 e=n|e|=ne=n ,则 ne=0ne=0ne=0 ,从而对任意 aRa\\in RaRna=n(ea)=(ne)a=0na=n(ea)=(ne)a=0na=n(ea)=(ne)a=0

\n

整环的特征是 0 或是一个素数,进而域的特征也只能是 0 或是素数。

\n
\n

根据 RRR 的特征构造 Z\\mathbb ZZRRR 的同态

\n
\n

【定理】设 RRR 是有单位元 eee 的环,定义函数 φ:ZRφ:\\mathbb Z→Rφ:ZRnZ,φ(n)=ne∀n\\in \\mathbb Z, φ(n)=nenZ,φ(n)=ne,则 φφφ 是环 Z\\mathbb ZZRRR 的同态。

\n

【推论】设 RRR 是有单位元 eee 的环。

\n
    \n
  1. \n

    如果 RRR 的特征为 n>0n>0n>0,则 RRR 包含一个与 Zn\\mathbb Z_nZn 同构的子环;

    \n
  2. \n
  3. \n

    如果 RRR 的特征为 0 ,则 RRR 包含一个与 Z\\mathbb ZZ 同构的子环。

    \n
      \n
    • 所以特征为 0 的环一定是无穷环
    • \n
    \n
  4. \n
\n

⭐️每个有限域的阶必为素数的幂,即有限域的阶可表示为 pnp^npn ( ppp 是素数、nnn 是正整数),该有限域通常称为 Galois 域 (Galois Fields),记为 GF(pn)GF(p^n)GF(pn)

\n

【推论】设 FFF 是域。

\n

1. 如果 FFF 的特征为 0 ,则 FFF 包含一个与有理数域同构的子域;

\n

2. 如果 RRR 的特征是素数 ppp ,则 FFF 包含一个与模 ppp 剩余类环 Zp\\mathbb Z_pZp 同构的子域。

\n

# 素域

\n

若域 FFF 不包含任何真子域,则称 F 是素域 (prime field)。

\n

特征为素数 ppp交换环中:

\n

(a±b)pn=apn+bpn(a\\pm b)^{p^n}=a^{p^n}+b^{p^n}\n(a±b)pn=apn+bpn

\n
\n

证明思路

\n

交换环中也有二项式定理,以此证明 (a±b)p=ap+bp(a\\pm b)^{p}=a^{p}+b^{p}(a±b)p=ap+bp ,然后数学归纳法即可。

\n", + "content_html": "

# 欧拉图

\n

# 定义

\n

欧拉图存在欧拉闭迹,半欧拉图只存在欧拉迹

\n

若能遍历完所有的边但是没法回到起始点,称为非欧拉图但是有欧拉迹

\n

# 欧拉图

\n

假定 GGG 是一个连通图,且是欧拉图,则下列命题等价:

\n
    \n
  • GGG 是欧拉图
  • \n
  • GGG 的每个点的度数是偶数
  • \n
  • GGG 的边集能划分为边不重的圈的并
  • \n
  • GGG 存在欧拉闭迹)
  • \n
\n

# 半欧拉图

\n

假定 GGG 是一个连通图,且是半欧拉图,则下列命题等价:

\n
    \n
  • GGG 是半欧拉图
  • \n
  • GGG 有且仅有 2 个点的度数是奇数
  • \n
  • GGG 存在欧拉迹)
  • \n
\n

# 小结论💡

\n
    \n
  • nnn 满足什么条件时,完全图 KnK_nKn 是欧拉图?\t nnn 为奇数
  • \n
  • nnn 满足什么条件时,nnn 方体 QnQ_nQn 是欧拉图?\t nnn 为偶数
  • \n
  • 若完全二部图 Ka,bK_{a,b}Ka,b 为欧拉图,aaabbb 需满足什么条件?\t a,ba,ba,b 均为偶数
  • \n
  • 假设图 GGG 恰好有两个连通分支,并且每个连通分支都是欧拉图,若要将 GGG 变为欧拉图,最少需要添加几条边?\t 最少需要添加 2 条边
  • \n
  • 欧拉图、半欧拉图是否存在割边?\t 欧拉图不存在割边,半欧拉图存在割边
  • \n
\n

# Fleury 算法

\n
\n

弗勒里算法解决了在欧拉图中求出一条具体欧拉环游的方法,核心思想是尽可能避割边行走

\n
\n

# 算法流程

\n
    \n
  • (1)任意选取一个顶点 v0v_0v0 ,置 w0=v0w_0=v_0w0=v0
  • \n
  • (2)假设迹 wi=v0e1v1eiviw_i=v_0e_1v_1\\cdots e_iv_iwi=v0e1v1eivi 已经确定,按如下方法从 E{e1,e2,,ei}E-\\{e_1,e_2,\\cdots,e_{i}\\}E{e1,e2,,ei} 选一个 ei+1e_{i+1}ei+1:\n
      \n
    • ei+1e_{i+1}ei+1viv_ivi 相关联;
    • \n
    • 除非没有其他边可选,否则 ei+1e_{i+1}ei+1 不能是 Gi=G{e1,e2,,ei}G_i=G-\\{e_1,e_2,\\cdots,e_{i}\\}Gi=G{e1,e2,,ei}割边
    • \n
    \n
  • \n
  • (3)若(2)无法进行则算法停止
  • \n
\n

利用 Fluery 算法可以求一个半欧拉图的欧拉迹,半欧拉图有且仅有 2 个奇度顶点 u,vu,vu,v ,在这 2 个点之间增加一条边 mmm ,就可以得到一个欧拉图,然后从其中一个奇度顶点,例如 uuu ,开始求欧拉环游。得到的欧拉环游去掉 mmm 就是从 uuuvvv 的欧拉迹。

\n

# 欧拉图中扩展欧拉环游充要条件

\n

GGG 是非平凡的欧拉图,且 vV(G)v\\in V(G)vV(G) ,则 GGG 的每条具有起点 vvv 的迹都能扩展成 GGG 的欧拉环游当且仅当 GvG-vGv 是森林。

\n

# 中国邮递员问题

\n
\n

1962,中国数学家管梅谷提出并解决了 “中国邮路问题”

\n
\n

即最优环游问题:在一个连通具有非负权的赋权图 GGG 中找到一条包含每条边(允许重复)且边权之和最小的闭途径,称之为最优 (欧拉) 环游

\n
    \n
  • 若图 GGG 是一个欧拉图,则找出 GGG 的欧拉环游即可
  • \n
  • 对一般图,其解法为:添加重复边以使 GGG 成为欧拉图 GG^*G ,并使添加的重复边的边权之和为最小,再求 GG^*G 的欧拉回路
  • \n
\n
\n

管梅谷的结论:

\n
\n

假定 GG^*G 是在图 GGG 中添加一些重复边得到的欧拉图,则 GG^*G 具有最小权值的充要条件是:

\n
    \n
  • GGG 的每一条边最多被添加一次
  • \n
  • 对于 GG^*G 的每个圈来说,该圈新添加的边的总权值不超过该圈总权值的一半
  • \n
\n
\n

证明:必要性

\n

GGG 中某条边在 GG^*G 中被添加的次数超过 1,则去掉其中两条重复的边,我们将得到一个总权值更小,且以 GGG 为生成子图的欧拉图

\n

上述与 “ GG^*G 总权值最小” 相矛盾,因此每条边最多被添加一次

\n

假定在 GG^*G 中存在某个圈使得该圈新添加的边的总权值大于该圈权值的一半,不妨设为 CCC

\n

那么在 GG^*G 中,将 CCC 上新添加的边全部去掉,然后将原圈未添加新边的边都添加一条重复边

\n

这样的操作使得该圈所有点的度数不变或改变 2,相应的图仍然是欧拉图,但是权值更小,这与 “ GG^*G 总权值最小” 相矛盾

\n
\n

这个必要性的证明给出了最优欧拉环游的构造方法

\n
\n

# 半欧拉图最优欧拉环游

\n

一个非负权的边赋权图 GGG 中只有两个奇度顶点 uuuvvv , 设计一个求其最优欧拉环游的算法如下:

\n
    \n
  • (1) 在 uuuvvv 间求出一条最短路 PPP; (最短路算法)
  • \n
  • (2) 在最短路 PPP 上,给每条边添加一条重复边得 GGG 的欧拉图 GG^*G
  • \n
  • (3) 在 GGG 的欧拉图 GG^*G 中用 Fleury 算法求出一条欧拉环游;
  • \n
\n
\n

证明

\n

uuuvvvGGG 的两个奇度顶点,GG^*GGGG 的任意一个欧拉图。

\n

考虑 G[EE]G^*[E^*-E]G[EE], 显然它只有两个奇数顶点 uuuvvv, 当然它们必须在 G[EE]G^*[E^*-E]G[EE] 的同一个分支中,因此,存在 (u,v)(u,v)(u,v)PP^*P

\n

eEEw(e)w(P)w(P)\\sum_{e\\in E^*-E}w(e)\\geq w(P^*)\\geq w(P)\neEEw(e)w(P)w(P)

\n

# 哈密顿图

\n

# 定义

\n

# 哈姆顿图

\n

如果经过图 GGG 的每个顶点恰好一次后能够回到出发点,称这样的图为哈密尔顿图,简称 HHH。所经过的闭途径是 GGG 的一个生成圈,称为 GGG哈密尔顿圈,简称 HHH

\n

# 半哈密顿图

\n
\n

不需回到出发点

\n
\n

如果存在经过 GGG 的每个顶点恰好一次的路,称这样的图为半哈密尔顿图,称该路为 GGG哈密尔顿路,简称 HHH

\n

# 小结论💡

\n
    \n
  • n3n\\geq3n3 时,完全图 KnK_nKn 是否为哈密尔顿图?\t
  • \n
  • n2n\\geq2n2 时, 方体 QnQ_nQn 是否为哈密尔顿图?\t
  • \n
  • 若完全二部图 Ka,bK_{a,b}Ka,b 为哈密尔顿图,aaabbb 需满足什么条件?a=b2\\Rightarrow a=b\\geq2a=b2
  • \n
  • 是否存在一个具有奇数个顶点的连通图,它既是二部图,也是哈密尔顿图?\t不存在,否则二部图中出现了奇圈
  • \n
  • 若二部图是哈密尔顿图,则它的二部划分 (X,Y)(X,Y)(X,Y) 满足什么条件?X=Y\\Rightarrow|X|=|Y|X=Y
  • \n
\n

哈密顿图目前为止没有充要条件,实际上图的 HHH 性判定是 NP - 困难问题,下面介绍一个必要条件和一些充分条件

\n

# 必要条件

\n

GGGHHH 图,则对于 VVV 的每个非空真子集 SSS,均有:

\n

ω(GS)S\\omega(G-S)\\leq|S|\nω(GS)S

\n
\n

💡别忘了 ω(...)\\omega(...)ω(...) 的意思是连通分支数,这里还容易得到 HHH 图不存在割点

\n
\n

只是必要条件而不是充分条件,经典例子 —— 彼得森图

\n

用于判断非 HHH 图:SV,  ω(GS)>S\\exist S\\subset V,\\ \\ \\omega(G-S)\\gt|S|SV,  ω(GS)>S ,则 GGG 不是 HHH 图。

\n

# 充分条件

\n

# Dirac

\n

对于 n3n≥3n3 的简单图 GGG , 如果 GGG 中有:

\n

δ(G)n2\\delta(G)\\geq\\frac{n}{2}\nδ(G)2n

\n

那么 GGGHHH 图。

\n

# Ore

\n

对于 n3n≥3n3 的单图 GGG , 如果 GGG 中的任意两个不相邻顶点 uuuvvv ,有:

\n

d(u)+d(v)nd(u)+d(v)\\geq n\nd(u)+d(v)n

\n

那么 GGGHHH 图。

\n
\n

该定理证明和 Dirac 定理可以完全一致!

\n

该定理的条件是紧的。例如:设 GGG 是由 Kk+1Κ_{k+1}Kk+1 的一个顶点和另一个 Kk+1Κ_{k+1}Kk+1 的一个顶点重合得到的图,那么对于 GGG 的任意两个不相邻顶点 uuuvvv,有:

\n

d(u)+d(v)=2k=n1d(u)+d(v)=2k=n-1\nd(u)+d(v)=2k=n1

\n

GGG 是非 HHH 图。

\n
\n

# Bondy

\n

# 引理

\n

对于单图 GGG ,如果 GGG 中有两个不相邻顶点 uuuvvv ,满足:d(u)+d(v)nd(u)+d(v)≥nd(u)+d(v)n,那么 GGGHHH 图当且仅当 G+uvG+uvG+uvHHH 图。

\n

# 闭图

\n

nnn 阶简单图中,若对 d(u)+d(v)nd(u)+d(v)≥nd(u)+d(v)n 的任意一对顶点 uuuvvv ,均有 u adj vu\\ \\text{adj}\\ vu adj v , 则称 GGG 是闭图。

\n
# 引理
\n

G1G_1G1G2G_2G2 是同一个点集 VVV 的两个闭图,则 G1G2G_1\\cap G_2G1G2 是闭图,但 G1G2G_1\\cup G_2G1G2 不一定是闭图。

\n

# 闭包

\n

G\\overline GG 是图 GGG 的闭包,如果它是包含 GGG 的极小闭图,即对 H∀HH,若有 GHGG\\subseteq H \\subset\\overline GGHG,则 HHH 不是闭图。

\n
    \n
  • 如果 GGG 本身是闭图,则其闭包是它本身;
  • \n
  • 否则由定义可以通过在度和 n\\geq nn 的不相邻顶点对间加边来构造 GGG 的闭图;加边之后还要继续检查是否需要加边。
  • \n
\n

GGG 的闭包是唯一的。

\n

# 闭包定理

\n
\n

由闭包定理也可以推出 Dirac 和 Ore 定理

\n
\n

GGGHHH 图当且仅当它的闭包是 HHH

\n

# Chavatal

\n
\n

度序列判定法

\n

HHH 图充分条件

\n
\n

设简单图 GGG 的度序列是 d(d1,d2,,dn)d(d_1,d_2,\\cdots,d_n)d(d1,d2,,dn),这里,d1d2dnd_1≤d_2≤⋯≤d_nd1d2dn,并且 n3n≥3n3。若对任意的 m<n2m<\\frac{n}{2}m<2n

\n
    \n
  • 或有 dm>md_m>mdm>m
  • \n
  • 或有 dnmnmd_{n-m}≥n-mdnmnm
  • \n
\n

GGGHHH 图。(GGG 的闭包是完全图!证明也是证明这个)

\n

# TSP

\n

# 边交换

\n

# 最优 H 圈下界

\n

可以通过如下方法求出最优 HHH 圈的一个下界:(不是下确界,不一定达得到!)

\n

(1) 在 GGG 中删掉一点 vvv (任意的) 得图 G1G_1G1

\n

(2) 在图 G1G_1G1 中求出一棵最小生成树 TTT

\n

(3) 在 vvv 的关联边中选出两条权值最小者 e1e_1e1e2e_2e2

\n

HHHGGG 的最优圈,则有权值下界:

\n

W(H)W(T)+W(e1)+W(e2)W(H)\\geq W(T)+W(e_1)+W(e_2)\nW(H)W(T)+W(e1)+W(e2)

\n", "tags": [ "数学", "离散数学", - "代数结构", + "图论", "离散数学", - "代数", - "环" + "图论" ] } ] diff --git a/friends/index.html b/friends/index.html index c166b22b..0f815611 100644 --- a/friends/index.html +++ b/friends/index.html @@ -1 +1 @@ -友情链接 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file +友情链接 | Balloon Party = 風船のパーティー = fuusen no party
\ No newline at end of file diff --git a/ie/de/bool-algebra/index.html b/ie/de/bool-algebra/index.html index cd262e22..d2a31345 100644 --- a/ie/de/bool-algebra/index.html +++ b/ie/de/bool-algebra/index.html @@ -1 +1 @@ -逻辑代数 - 数字逻辑电路 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 逻辑代数中的基本运算

# 三种基本运算

三种基本运算

# 真值表

表征逻辑事件输入(条件)和输出(结果)之间全部可能状态的表格

与运算:

ABY
000
010
100
111

或运算:

ABY
000
011
101
111

非运算:

AY
01
10

# 其他复合逻辑运算

# 与非

“先与再非”

与非

# 或非

“先或再非”

或非

# 与或非

“先与再或再非”

与或非

# 异或 XOR

不同时输出 1,相同时输出 0

AB=AB+ABA\oplus B=\overline{A}B+A\overline{B}

XOR

⭐️异或运算满足的性质

  • 交换律
  • 结合律
  • 对于任何数 x,都有 xx=0x\oplus x=0x0=xx\oplus 0=xx1=xx\oplus 1=\overline{x}
  • 自反性 ABB=A0=AA\oplus B\oplus B=A\oplus0=A;(经典 coding 小技巧)

# 同或 XNOR

同或 —— 相同时输出 1,不同时输出 0

同或

# 逻辑代数的公式和定理

# 基本公式

逻辑代数的基本公式1

逻辑代数的基本公式2

# 常考公式 7/17 分配律

A(B+C)=AB+ACA+BC=(A+B)(A+C)A(B +C) = AB + AC\\ A + BC = (A +B)(A +C)

用途:将 “混杂” 在一起的变量分离,将逻辑函数表达式化成 “与或” 形式和 “或与” 形式;在后面逻辑函数的 “最小项之和” 和 “最大项之积” 表示时非常有用

# 常考公式 8/18 反演律(德・摩根定律)

(AB)=A+B(A+B)=AB(AB)' = A' + B' (A + B) ' = A'B'

记忆方法:“与的非等于非的或,或的非等于非的与”;

门电路的角度上,就是:

  • 负或门 = 与非门
  • 负与门 = 或非门

与在概率论课程中学习的德摩根定律一致,即 “交的反等于反的并,并的反等于反的交”

用途:实现与运算和或运算之间的转换,在后面对函数式进行特定形式的变换时非常有用

# 基本定理

# 代入定理

在任何一个包含 A 的逻辑等式中,若以另外一个逻辑式代入式中 A 的位置,则等式依然成立;

# 反演定理

对任一逻辑式 Y ,在求解它的反时(即已知 Y 求解 Y’),只需要在保证运算优先次序不变的原则下,将其中所有的 \cdot 换成 ++++ 换成 \cdot ,原变量换成反变量,反变量换成原变量(不属于单个变量上的反号不动),1 变成 0,0 变成 1,得到的结果就是 Y’;

# 对偶定理

若两逻辑表达式相等,则它们的对偶式也相等;

所谓的对偶式指的是在保持运算优先顺序不变的原则下,将表达式中所有的 \cdot 换成 ++++ 换成 \cdot ,0 换成 1,1 换成 0;

注意与反演定理的区别!变量不取反!

主要应用于证明题当中,证明两个形式较复杂的逻辑式相等,可以尝试:

  • 两边同时取对偶式,证明它们的对偶式相等
  • 对等号某一侧表达式先取对偶式,对对偶式进行化简之后,再取对偶就可以得到等号另一侧表达式

# 逻辑函数及其表示方法

以逻辑变量为输入,运算结果为输出,则输入变量值确定以后,输出的取值也随之而定,因此输入 — 输出之间是一种函数关系,称作逻辑函数;

在我们学习的二值逻辑 (布尔逻辑) 中,输入变量和输出变量只有 0 和 1 两种状态;

在求解实际应用问题中的逻辑函数关系时,首先必须做的事情是将具体事物抽象为逻辑变量并规定其不同状态(0 或 1),这是很重要的解题习惯,类似于在概率论答题时首先要记不同的事件为 A、B……;这里只研究现有的抽象后的逻辑函数式;

# 不同表示方法

# 真值表

遍历输入变量所有取值下的输出值,列成表格

# 逻辑函数式

将输出写成输入变量的与、或、非等逻辑运算的组合式

# 逻辑图

逻辑函数式用图形符号表示

# 波形图

输入变量所有取值可能与对应输出的时域波形

# 卡诺图

# 计算机软件中的描述方式

例如 Verilog 语言

# 不同表示方法间的转换

# 真值表 -> 逻辑函数式 (重点)

(逻辑函数的最小项之和形式)

  1. 找出真值表中使逻辑函数输出 Y = 1 的输入变量取值的组合即使 Y = 1 的行;
  2. 使 Y = 1 的每组输入变量取值的组合(即每一行)对应一个乘积项,取值为 1 写入原变量,取值为 0 写入反变量;
  3. 将各行对应的乘积项相加,即最终结果为 “与或” 形式;

# 逻辑函数式 <-> 逻辑图

# 逻辑函数式 -> 逻辑图

用图形符号代替逻辑函数式中的逻辑运算符;

# 逻辑图 -> 逻辑函数式

从输入到输出逐级写出每个图形符号对应的逻辑运算式;

# 真值表 <-> 波形图

# 真值表 -> 波形图

将所有输入变量与对应输出变量的取值依次排列,以时间为横轴;

# 波形图 -> 真值表

在波形图中找出每个时间段里输入变量与输出变量的取值列成表格( 对于 NN 个输入变量要对应 2N2^N 个组合即 2N2^N 行)

# 标准 / 规范 形式

# DNF/SOP

别名:

  • 最小项标准式
  • 析取范式
  • 积之和范式
  • 与或范式
  • Disjunctive Normal Form (DNF)
  • Sum of Product (SOP)

任何一个逻辑函数式都可以化为若干个最小项之和的形式

# 最小项 m 的定义:

m 是乘积项,包含 n 个因子,n 个变量均以原变量或反变量的形式在 m 中出现一次;

# 最小项的特点

  • 全体最小项之和为 1
  • 各个最小项之间是互斥的,即任何两个最小项之积为 0 ;换句话说,对于任何一个特定的输入变量取值,有且仅有一个最小项为 1;
  • 两个相邻的最小项之和可以合并,消去一对因子,只留下公共因子;

这里的 “相邻” 不是按照自然二进制数编号后的相邻,而是指逻辑上的相邻,规定仅一个变量不同的最小项彼此称为相邻;

例如 ABCA' B' CABCA'BC'ABCA'BCm1m_1m2m_2m3m_3m1m_1m2m_2 不是相邻,m1m_1m3m_3 才是相邻;m1m_1m3m_3 可以合并消去因子 B+BB+B'

# 转化为 DNF

事实上最小项就是在列写 n 个输入变量的逻辑函数的真值表时每一行对应的输入变量的乘积项,取值为 1 写入原变量,取值为 0 写入反变量;使最小项取值为 1 的变量取值,按照 n 位自然二进制数排列后对应的十进制数就是这个最小项的编号

# CNF/POS

别名:

  • 最大项标准式
  • 合取范式
  • 和之积范式
  • 或与范式
  • conjunctive normal form (CNF)
  • Product of Sum (POS)

任何一个逻辑函数式都可以化为若干个最大项之积的形式

# 最大项 M 的定义

M 是相加项,包含 n 个因子,n 个变量均以原变量和反变量的形式在 M 中出现一次;可以把最大项看作是对每一个最小项应用反演定理,因此,最大项的编号原则是反的,即原变量记为 0,反变量记为 1,n 位自然二进制数排列后对应的十进制数为编号;

例如 A+B+C′ 的编号是 001 即 M1 ;

(记忆方法:对于与运算即乘积项,得 1 “容易”,即得 1 时输入变量组唯一确定;对于或运算即相加项,得 0 “容易”,即得 0 时输入变量组唯一确定;)

# 最大项的特点

  • 全体最大项之积为 0 ;
  • 任何两个最大项之和为 1 ;换句话说,对于任何一个特定的输入变量取值,有且仅有一个最小项为 0;
  • 两个相邻的最大项之积保留公共变量

这里的相邻和前面最小项的相邻一致,都是指逻辑上的相邻,即只有一个变量不同。

例如 A+B+CA+B+C'A+B+CA+B'+C' 为相邻,即 M1M_1M3M_3 相邻,两者的乘积项即相与的结果是 A+CA+C'

# 转化为 CNF

当给定的逻辑函数式不是标准的最大项之积的形式时,一般不断地利用 AA=0A\cdot A'=0 补全缺少的因子,并结合分配律 A+BC=(A+B)(A+C)A + BC = (A +B)(A +C) 将与或形式转化为或与形式;

# 最小项与最大项的关系

根据最大项和最小项的定义以及德・摩根定理,易推导得到:

Mi=miM_i=m'_i

如果将逻辑函数写成最小项之和的形式:

iR1mi\sum_{i\in R_1} m_i

再将其写成最大项之积的形式:

iR2Mi\prod_{i\in R_2} M_i

则两者的下标编号集合 R1R_1R2R_2 是互补的。

所以很多时候不需要直接展开求解最大项之积,先求解最小项之和更方便

# 逻辑函数的化简

# 逻辑函数的化简的目标

逻辑函数的最小项之和虽然是通用的标准形式,但不一定就是最简的;在实际数字逻辑电路设计时,需要考虑在逻辑功能相同的条件下使用尽可能简单的电路,即电子器件数量足够少;

事实上,没有绝对的最简,由于我们习惯性将逻辑函数写成 最小项之和 即 与或形式 ,因此对于 与或形式 的逻辑函数,包含的乘积项最少,且每个乘积项里的因子也不能再减少时,称其为最简形式即最简与或形式;其他形式的最简同理;

常考最简式包括:

  • 最简与或式
  • 最简或与式
  • 最简与非 — 与非式
  • 最简或非 — 或非式
  • 最简与或非式

实际的逻辑电路设计可能会受到电子器件种类与数量的限制,因此可能要进行变换;直接用卡诺图化简得到的最简与或式并不一定是设计时需要的逻辑函数形式,所以还会需要其他最简形式,例如:

  • 只能用或非门实现:与非 — 与非式
  • 只能用或非门实现:或非 — 或非式

# 公式化简法

  • 使用前面学习的基本公式和常用公式
  • 没有固定的步骤,
  • 难以确定结果正确与否
  • 不通用但有时很快速好用

对公式化简法,要求掌握但不必深入研究,熟悉教材上的例题和课后题即可;

一个可能会用到公式化简法的情况是,当逻辑函数含有变量数很多时,即很难直接采用卡诺图去进行化简时,一般题目的设计会使解题时经常需要用 AB+AC+BCD=AB+ACAB + A'C + BCD = AB + A'C 这个公式来消去多余的变量,接着再用卡诺图去进行化简

# ⭐️卡诺图化简法 (重点)

# 卡诺图 (Karnaugh)

2n2^n 个小方块分别代表 n 变量的所有最小项,并将它们排列成矩阵,而且使几何位置相邻的两个最小项在逻辑上也是相邻的(只有一个变量不同),就得到表示 n 变量全部最小项的卡诺图;

# 卡诺图的绘制

横纵轴不是按照自然二进制数排列,按照格雷码排列,目的是为了使逻辑上相邻对应几何上相邻,保证相邻的方块只有一个变量不同

卡诺图的绘制

记忆方法:

  • 增加一个变量看作是折纸一样翻折
  • 轴对称位置上的最小项也满足相邻
  • 把卡诺图看作是闭合的图形 (横纵轴都是循环的)

教材上的卡诺图并不是唯一的,只要能够保证逻辑对称性几何对称性一致即可,最好去理解卡诺图绘制的过程

无关项可以用 x 表示,表示可圈起来也可不圈起来

# 卡诺图化简法的本质

将最小项之和用图形描述,将逻辑上的相邻表现为几何图形的相邻,通过合并相邻的几何图形,合并后对应仅保留公共因子的最小项,最终结果就是最简与或式

# 卡诺图化简逻辑函数的步骤

# 最简与或式

若只给出逻辑函数则从步骤 1 开始,若给出卡诺图则直接从步骤 2 开始

  1. 将逻辑函数写成最小项之和的形式
  2. 根据最小项之和绘制对应的卡诺图,逻辑函数式中含有的最小项的对应位置填 1,其余的位置填 0
  3. 合并相邻的最小项,对应最终结果为 最简与或式
  • 相邻表示逻辑相邻,轴对称位置上的方块也可合并
  • 合并时,每个方块可以重复使用,因为 A+A=AA+A=A
  • 合并的原则是乘积项的数目最少,每个乘积项的因子最少,即画的圈要尽量大(消去尽量多的不同的因子),画圈的数目尽量少
  • 结果不唯一,但乘积项的数目和每个乘积项的因子个数一致(这也是检查答案是否正确的依据)

# 最简或与式

  1. 对原逻辑函数 YY 取反得到 YY'
  2. YY' 采用上述卡诺图求最简与或式步骤得到 YY' 的 最简与或式
  3. YY' 的 最简与或式 取反变换得到的 或与式 就是原逻辑函数 YY 的 最简或与式

或者直接:

  1. 采用上述卡诺图求最简与或式步骤,但是合并为 0 的方块而不是 1 ,得到 YY' 的最简与或式
  2. YY' 的 最简与或式 取反变换得到的 或与式 就是原逻辑函数 YY 的 最简或与式

# 最简与或非形式

与最简或与式实际上是等价的,按照求最简或与式步骤即可,只是最后一步取反直接加上取反符号不需要再变换为或与式

# 最简与非 — 与非式

将得到的最简与或式取两次反,即逆向利用德・摩根定理

# 最简或非 — 或非形式

将与或非形式中的每个乘积项再利用德・摩根定理,即变为或非形式

# 含有无关项的卡诺图化简

一般第二章的题目会直接给出无关项,例如:

  • $ (...) + (...) +…… = 0 $
  • d()=0\sum d(…)= 0 (无关项 集合用 dd 表示)

后面在基于实际应用设计逻辑电路时应自行根据实际情况来分析确定无关项

  1. 根据题意确定无关项
  2. 绘制卡诺图时,无关项的方块用 × 表示
  3. 化简时根据需要,将无关项填入 1 或 0 ,原则依然是是使化简后的项数最少,每项的因子最少,即画的圈最大,圈的个数最少
Edited on Views times
\ No newline at end of file +逻辑代数 - 数字逻辑电路 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 逻辑代数中的基本运算

# 三种基本运算

三种基本运算

# 真值表

表征逻辑事件输入(条件)和输出(结果)之间全部可能状态的表格

与运算:

ABY
000
010
100
111

或运算:

ABY
000
011
101
111

非运算:

AY
01
10

# 其他复合逻辑运算

# 与非

“先与再非”

与非

# 或非

“先或再非”

或非

# 与或非

“先与再或再非”

与或非

# 异或 XOR

不同时输出 1,相同时输出 0

AB=AB+ABA\oplus B=\overline{A}B+A\overline{B}

XOR

⭐️异或运算满足的性质

  • 交换律
  • 结合律
  • 对于任何数 x,都有 xx=0x\oplus x=0x0=xx\oplus 0=xx1=xx\oplus 1=\overline{x}
  • 自反性 ABB=A0=AA\oplus B\oplus B=A\oplus0=A;(经典 coding 小技巧)

# 同或 XNOR

同或 —— 相同时输出 1,不同时输出 0

同或

# 逻辑代数的公式和定理

# 基本公式

逻辑代数的基本公式1

逻辑代数的基本公式2

# 常考公式 7/17 分配律

A(B+C)=AB+ACA+BC=(A+B)(A+C)A(B +C) = AB + AC\\ A + BC = (A +B)(A +C)

用途:将 “混杂” 在一起的变量分离,将逻辑函数表达式化成 “与或” 形式和 “或与” 形式;在后面逻辑函数的 “最小项之和” 和 “最大项之积” 表示时非常有用

# 常考公式 8/18 反演律(德・摩根定律)

(AB)=A+B(A+B)=AB(AB)' = A' + B' (A + B) ' = A'B'

记忆方法:“与的非等于非的或,或的非等于非的与”;

门电路的角度上,就是:

  • 负或门 = 与非门
  • 负与门 = 或非门

与在概率论课程中学习的德摩根定律一致,即 “交的反等于反的并,并的反等于反的交”

用途:实现与运算和或运算之间的转换,在后面对函数式进行特定形式的变换时非常有用

# 基本定理

# 代入定理

在任何一个包含 A 的逻辑等式中,若以另外一个逻辑式代入式中 A 的位置,则等式依然成立;

# 反演定理

对任一逻辑式 Y ,在求解它的反时(即已知 Y 求解 Y’),只需要在保证运算优先次序不变的原则下,将其中所有的 \cdot 换成 ++++ 换成 \cdot ,原变量换成反变量,反变量换成原变量(不属于单个变量上的反号不动),1 变成 0,0 变成 1,得到的结果就是 Y’;

# 对偶定理

若两逻辑表达式相等,则它们的对偶式也相等;

所谓的对偶式指的是在保持运算优先顺序不变的原则下,将表达式中所有的 \cdot 换成 ++++ 换成 \cdot ,0 换成 1,1 换成 0;

注意与反演定理的区别!变量不取反!

主要应用于证明题当中,证明两个形式较复杂的逻辑式相等,可以尝试:

  • 两边同时取对偶式,证明它们的对偶式相等
  • 对等号某一侧表达式先取对偶式,对对偶式进行化简之后,再取对偶就可以得到等号另一侧表达式

# 逻辑函数及其表示方法

以逻辑变量为输入,运算结果为输出,则输入变量值确定以后,输出的取值也随之而定,因此输入 — 输出之间是一种函数关系,称作逻辑函数;

在我们学习的二值逻辑 (布尔逻辑) 中,输入变量和输出变量只有 0 和 1 两种状态;

在求解实际应用问题中的逻辑函数关系时,首先必须做的事情是将具体事物抽象为逻辑变量并规定其不同状态(0 或 1),这是很重要的解题习惯,类似于在概率论答题时首先要记不同的事件为 A、B……;这里只研究现有的抽象后的逻辑函数式;

# 不同表示方法

# 真值表

遍历输入变量所有取值下的输出值,列成表格

# 逻辑函数式

将输出写成输入变量的与、或、非等逻辑运算的组合式

# 逻辑图

逻辑函数式用图形符号表示

# 波形图

输入变量所有取值可能与对应输出的时域波形

# 卡诺图

# 计算机软件中的描述方式

例如 Verilog 语言

# 不同表示方法间的转换

# 真值表 -> 逻辑函数式 (重点)

(逻辑函数的最小项之和形式)

  1. 找出真值表中使逻辑函数输出 Y = 1 的输入变量取值的组合即使 Y = 1 的行;
  2. 使 Y = 1 的每组输入变量取值的组合(即每一行)对应一个乘积项,取值为 1 写入原变量,取值为 0 写入反变量;
  3. 将各行对应的乘积项相加,即最终结果为 “与或” 形式;

# 逻辑函数式 <-> 逻辑图

# 逻辑函数式 -> 逻辑图

用图形符号代替逻辑函数式中的逻辑运算符;

# 逻辑图 -> 逻辑函数式

从输入到输出逐级写出每个图形符号对应的逻辑运算式;

# 真值表 <-> 波形图

# 真值表 -> 波形图

将所有输入变量与对应输出变量的取值依次排列,以时间为横轴;

# 波形图 -> 真值表

在波形图中找出每个时间段里输入变量与输出变量的取值列成表格( 对于 NN 个输入变量要对应 2N2^N 个组合即 2N2^N 行)

# 标准 / 规范 形式

# DNF/SOP

别名:

  • 最小项标准式
  • 析取范式
  • 积之和范式
  • 与或范式
  • Disjunctive Normal Form (DNF)
  • Sum of Product (SOP)

任何一个逻辑函数式都可以化为若干个最小项之和的形式

# 最小项 m 的定义:

m 是乘积项,包含 n 个因子,n 个变量均以原变量或反变量的形式在 m 中出现一次;

# 最小项的特点

  • 全体最小项之和为 1
  • 各个最小项之间是互斥的,即任何两个最小项之积为 0 ;换句话说,对于任何一个特定的输入变量取值,有且仅有一个最小项为 1;
  • 两个相邻的最小项之和可以合并,消去一对因子,只留下公共因子;

这里的 “相邻” 不是按照自然二进制数编号后的相邻,而是指逻辑上的相邻,规定仅一个变量不同的最小项彼此称为相邻;

例如 ABCA' B' CABCA'BC'ABCA'BCm1m_1m2m_2m3m_3m1m_1m2m_2 不是相邻,m1m_1m3m_3 才是相邻;m1m_1m3m_3 可以合并消去因子 B+BB+B'

# 转化为 DNF

事实上最小项就是在列写 n 个输入变量的逻辑函数的真值表时每一行对应的输入变量的乘积项,取值为 1 写入原变量,取值为 0 写入反变量;使最小项取值为 1 的变量取值,按照 n 位自然二进制数排列后对应的十进制数就是这个最小项的编号

# CNF/POS

别名:

  • 最大项标准式
  • 合取范式
  • 和之积范式
  • 或与范式
  • conjunctive normal form (CNF)
  • Product of Sum (POS)

任何一个逻辑函数式都可以化为若干个最大项之积的形式

# 最大项 M 的定义

M 是相加项,包含 n 个因子,n 个变量均以原变量和反变量的形式在 M 中出现一次;可以把最大项看作是对每一个最小项应用反演定理,因此,最大项的编号原则是反的,即原变量记为 0,反变量记为 1,n 位自然二进制数排列后对应的十进制数为编号;

例如 A+B+C′ 的编号是 001 即 M1 ;

(记忆方法:对于与运算即乘积项,得 1 “容易”,即得 1 时输入变量组唯一确定;对于或运算即相加项,得 0 “容易”,即得 0 时输入变量组唯一确定;)

# 最大项的特点

  • 全体最大项之积为 0 ;
  • 任何两个最大项之和为 1 ;换句话说,对于任何一个特定的输入变量取值,有且仅有一个最小项为 0;
  • 两个相邻的最大项之积保留公共变量

这里的相邻和前面最小项的相邻一致,都是指逻辑上的相邻,即只有一个变量不同。

例如 A+B+CA+B+C'A+B+CA+B'+C' 为相邻,即 M1M_1M3M_3 相邻,两者的乘积项即相与的结果是 A+CA+C'

# 转化为 CNF

当给定的逻辑函数式不是标准的最大项之积的形式时,一般不断地利用 AA=0A\cdot A'=0 补全缺少的因子,并结合分配律 A+BC=(A+B)(A+C)A + BC = (A +B)(A +C) 将与或形式转化为或与形式;

# 最小项与最大项的关系

根据最大项和最小项的定义以及德・摩根定理,易推导得到:

Mi=miM_i=m'_i

如果将逻辑函数写成最小项之和的形式:

iR1mi\sum_{i\in R_1} m_i

再将其写成最大项之积的形式:

iR2Mi\prod_{i\in R_2} M_i

则两者的下标编号集合 R1R_1R2R_2 是互补的。

所以很多时候不需要直接展开求解最大项之积,先求解最小项之和更方便

# 逻辑函数的化简

# 逻辑函数的化简的目标

逻辑函数的最小项之和虽然是通用的标准形式,但不一定就是最简的;在实际数字逻辑电路设计时,需要考虑在逻辑功能相同的条件下使用尽可能简单的电路,即电子器件数量足够少;

事实上,没有绝对的最简,由于我们习惯性将逻辑函数写成 最小项之和 即 与或形式 ,因此对于 与或形式 的逻辑函数,包含的乘积项最少,且每个乘积项里的因子也不能再减少时,称其为最简形式即最简与或形式;其他形式的最简同理;

常考最简式包括:

  • 最简与或式
  • 最简或与式
  • 最简与非 — 与非式
  • 最简或非 — 或非式
  • 最简与或非式

实际的逻辑电路设计可能会受到电子器件种类与数量的限制,因此可能要进行变换;直接用卡诺图化简得到的最简与或式并不一定是设计时需要的逻辑函数形式,所以还会需要其他最简形式,例如:

  • 只能用或非门实现:与非 — 与非式
  • 只能用或非门实现:或非 — 或非式

# 公式化简法

  • 使用前面学习的基本公式和常用公式
  • 没有固定的步骤,
  • 难以确定结果正确与否
  • 不通用但有时很快速好用

对公式化简法,要求掌握但不必深入研究,熟悉教材上的例题和课后题即可;

一个可能会用到公式化简法的情况是,当逻辑函数含有变量数很多时,即很难直接采用卡诺图去进行化简时,一般题目的设计会使解题时经常需要用 AB+AC+BCD=AB+ACAB + A'C + BCD = AB + A'C 这个公式来消去多余的变量,接着再用卡诺图去进行化简

# ⭐️卡诺图化简法 (重点)

# 卡诺图 (Karnaugh)

2n2^n 个小方块分别代表 n 变量的所有最小项,并将它们排列成矩阵,而且使几何位置相邻的两个最小项在逻辑上也是相邻的(只有一个变量不同),就得到表示 n 变量全部最小项的卡诺图;

# 卡诺图的绘制

横纵轴不是按照自然二进制数排列,按照格雷码排列,目的是为了使逻辑上相邻对应几何上相邻,保证相邻的方块只有一个变量不同

卡诺图的绘制

记忆方法:

  • 增加一个变量看作是折纸一样翻折
  • 轴对称位置上的最小项也满足相邻
  • 把卡诺图看作是闭合的图形 (横纵轴都是循环的)

教材上的卡诺图并不是唯一的,只要能够保证逻辑对称性几何对称性一致即可,最好去理解卡诺图绘制的过程

无关项可以用 x 表示,表示可圈起来也可不圈起来

# 卡诺图化简法的本质

将最小项之和用图形描述,将逻辑上的相邻表现为几何图形的相邻,通过合并相邻的几何图形,合并后对应仅保留公共因子的最小项,最终结果就是最简与或式

# 卡诺图化简逻辑函数的步骤

# 最简与或式

若只给出逻辑函数则从步骤 1 开始,若给出卡诺图则直接从步骤 2 开始

  1. 将逻辑函数写成最小项之和的形式
  2. 根据最小项之和绘制对应的卡诺图,逻辑函数式中含有的最小项的对应位置填 1,其余的位置填 0
  3. 合并相邻的最小项,对应最终结果为 最简与或式
  • 相邻表示逻辑相邻,轴对称位置上的方块也可合并
  • 合并时,每个方块可以重复使用,因为 A+A=AA+A=A
  • 合并的原则是乘积项的数目最少,每个乘积项的因子最少,即画的圈要尽量大(消去尽量多的不同的因子),画圈的数目尽量少
  • 结果不唯一,但乘积项的数目和每个乘积项的因子个数一致(这也是检查答案是否正确的依据)

# 最简或与式

  1. 对原逻辑函数 YY 取反得到 YY'
  2. YY' 采用上述卡诺图求最简与或式步骤得到 YY' 的 最简与或式
  3. YY' 的 最简与或式 取反变换得到的 或与式 就是原逻辑函数 YY 的 最简或与式

或者直接:

  1. 采用上述卡诺图求最简与或式步骤,但是合并为 0 的方块而不是 1 ,得到 YY' 的最简与或式
  2. YY' 的 最简与或式 取反变换得到的 或与式 就是原逻辑函数 YY 的 最简或与式

# 最简与或非形式

与最简或与式实际上是等价的,按照求最简或与式步骤即可,只是最后一步取反直接加上取反符号不需要再变换为或与式

# 最简与非 — 与非式

将得到的最简与或式取两次反,即逆向利用德・摩根定理

# 最简或非 — 或非形式

将与或非形式中的每个乘积项再利用德・摩根定理,即变为或非形式

# 含有无关项的卡诺图化简

一般第二章的题目会直接给出无关项,例如:

  • $ (...) + (...) +…… = 0 $
  • d()=0\sum d(…)= 0 (无关项 集合用 dd 表示)

后面在基于实际应用设计逻辑电路时应自行根据实际情况来分析确定无关项

  1. 根据题意确定无关项
  2. 绘制卡诺图时,无关项的方块用 × 表示
  3. 化简时根据需要,将无关项填入 1 或 0 ,原则依然是是使化简后的项数最少,每项的因子最少,即画的圈最大,圈的个数最少
Edited on Views times
\ No newline at end of file diff --git a/ie/de/coding/index.html b/ie/de/coding/index.html index eab3f9d0..c93e0b19 100644 --- a/ie/de/coding/index.html +++ b/ie/de/coding/index.html @@ -1 +1 @@ -码制 - 数字逻辑电路 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 编码的概念

广义的编码指的就是将信息从一种形式转换为另一种规范的形式;

对于数字电路,就是将现实世界中的各种物理信息转换为离散的电压序列,来表示、处理和分析信息;

事实上,进位计数制也是一种编码,用不同进制数来表示 “量”;

数制码制分开介绍,首先单独讲解数制是因为数制的一个重要的特点是其编码后能够参与算术运算;而一般来说码制是对非数值信息的表示;

教材中的缩写术语:

  • MSB: Most Significant Bit,最高位
  • LSB: Least Significant Bit,最低位

# 二进制编码

无符号二进制编码只能表示 0 和正数,这里接下来讨论的都是有符号数。

(有符号)二进制数:在前面增加一个符号位,0 表示正数,1 表示负数;引入符号位后,一个二进制数的最高位是符号位,符号位的 0 / 1 不代表大小,只是代表正负

有符号二进制数的三种编码表示:

  • 原码 ——Sign Magnitude Representation

    • 正数和 0:普通的二进制数表示
    • 负数:绝对值的二进制数表示加上负号
  • 反码 ——One's Complement

    • 正数和 0: = 原码
    • 负数:原码所有数字位取反
  • 补码 ——Two's Complement

    • 正数和 0: = 原码
    • 负数:= 反码 + 1

nn 位补码 Bn1Bn2Bn3...B0B_{n-1} B_{n-2} B_{n-3}... B_{0} 统一表示:

Bn1(2n1)+Bn22n2+Bn32n3+...+B020B_{n-1}\cdot(-2^{n-1})+B_{n-2}\cdot2^{n-2}+B_{n-3}\cdot2^{n-3}+...+B_{0}\cdot2^{0}

nn 位原码 Bn1Bn2Bn3...B0B_{n-1} B_{n-2} B_{n-3}... B_{0} 统一表示:

Bn12n1+Bn22n2+Bn32n3+...+B020B_{n-1}\cdot2^{n-1}+B_{n-2}\cdot2^{n-2}+B_{n-3}\cdot2^{n-3}+...+B_{0}\cdot2^{0}

补码的补码即为原码

关于原码、反码、补码的易错点:

  • 反码取反是指对数字位取反,不改变符号位!
    • 例如 -7 即 1111 的反码是 1000,不是 0000 !
  • 补码是不对称的,例如补码为 1000 代表 - 8 ,而不代表 - 0 ! 即同样位数的二进制补码,负数会比正数 “多一个”;
  • 补码的 “加 1” 指的是在最低位加 1 的二进制加法运算,不是指数值 1,即如果含有小数部分,1 是加在整体的最右边;

利用二进制补码运算求解带符号数的加法运算:

  1. 分析需要使用多少个数字位;(培养思维习惯!不能忽略!)
  2. 用带符号位的二进制数表示,求解每个二进制数的补码;
  3. 对补码进行加法运算,再对结果求补码,即为最终结果;

注意最后一步,对补码进行加法运算时,数字位最高位产生的进位要进到符号位上去!(教材中描述的 “舍弃产生的进位” 指的是舍弃符号位产生的进位)

# 补码的扩展

将一个 n 位补码扩展到 n+k 位,只需将最高位符号位复制 k 个前置。

# 反码的加法

若最高位产生进位,需要循环进位,即最低位 “进一位”( +1 )。

# 无符号数:原码 -> 补码

# 方法一:

原码全部取反,再 +1

# 方法二:

从右向左找到第一个 1 ,这个 1 前面的所有位取反

若没有 1 ,也就是 0 ,原码 = 补码

# 负数:补码 -> 原码

这里只讨论负数的转换,正数不需要转换

# 方法一:

补码 -1 ,再取反

# 方法二:

从右向左找到第一个 1 ,这个 1 前面的位取反(符号位也要变为 0

若没有 1 ,也就是 0 ,原码 = 补码

# 浮点数

IEEE754 标准的 32 位浮点数:

SignExponentMantissa(Fraction)表示
1 位8 位23 位
000
5110±\pm\infin
511none zeroNaN

Number=(1)S(1+F)2E127Number=(-1)^{S}(1+F)2^{E-127}

公式中 FF 的小数点在最高位前面,将 EE 视为无符号二进制数。

# 十进制数的二进制代码

十进制代码用四位二进制数(最多可表示 24=162^4=16 个)来表示 0 ~ 9 ,没有 10 ⚠️

常见十进制代码

8421、2421、5211 每个数字指的是每个位的权;

# BCD/8421

8421 码也叫 BCD 码 (Binary Coded Decimal)。可以视为一种压缩编码(相比 intchar )。

余 3 码是在 BCD 码即 8421 码的基础上 +3 ,即用 3 ~ 12 对应的二进制数来表示 0 ~ 9

余 3 循环码是取格雷码中的 3 ~ 12

# 格雷码

教材中的格雷码特指的是四位格雷码,即用四位代码来表示 015 共十六种状态;

# 编码特点:

  • 每一位的状态变化都按一定的顺序循环,以 4 位格雷码为例:
    • 0110 (最低位)
    • 00111100
    • 0000111111110000
    • 0000000011111111 (最高位)
      (四位 16 个,只循环半个周期)

其他位数的格雷码表依次类推,自右向左每一位状态循环中连续的 01 数目加倍。
按表中顺序变化时,相邻的代码只有一位改变状态,这是格雷码最大的特点和优点;(应用:减少代码转换过程中的过渡噪声)

# 四维格雷码表

需要熟练掌握!重点是熟悉编码的规则和特点

四维格雷码表

# 二进制码与格雷码的映射

二进制码转换成格雷码:

  • 最高位相同
  • 二进制码从左到右,将相邻 AB 两位异或(无进位加法),得到格雷码对应的 B

格雷码转换成二进制码:

  • 最高位相同
  • 格雷码从左到右,将二进制码上一位 A ,格雷码当前位 B 两位异或,得到二进制码对应的 B

# 格雷码应用

旋转编码器(Rotate Encoder)

# ASCII 码

美国信息交换标准代码,用 7 位二进制代码(共 128 个)来表示信息,广泛应用于计算机和通信领域中;

ascii

在线查询:

  • 菜鸟教程
  • OSchina

# 校验

  • 奇校验
    • 在二进制串的末尾增加一位 10 ,使得整个新二进制的 1 的个数为奇数
  • 偶校验
    • 在二进制串的末尾增加一位 10 ,使得整个新二进制的 1 的个数为偶数
Edited on Views times
\ No newline at end of file +码制 - 数字逻辑电路 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 编码的概念

广义的编码指的就是将信息从一种形式转换为另一种规范的形式;

对于数字电路,就是将现实世界中的各种物理信息转换为离散的电压序列,来表示、处理和分析信息;

事实上,进位计数制也是一种编码,用不同进制数来表示 “量”;

数制码制分开介绍,首先单独讲解数制是因为数制的一个重要的特点是其编码后能够参与算术运算;而一般来说码制是对非数值信息的表示;

教材中的缩写术语:

  • MSB: Most Significant Bit,最高位
  • LSB: Least Significant Bit,最低位

# 二进制编码

无符号二进制编码只能表示 0 和正数,这里接下来讨论的都是有符号数。

(有符号)二进制数:在前面增加一个符号位,0 表示正数,1 表示负数;引入符号位后,一个二进制数的最高位是符号位,符号位的 0 / 1 不代表大小,只是代表正负

有符号二进制数的三种编码表示:

  • 原码 ——Sign Magnitude Representation

    • 正数和 0:普通的二进制数表示
    • 负数:绝对值的二进制数表示加上负号
  • 反码 ——One's Complement

    • 正数和 0: = 原码
    • 负数:原码所有数字位取反
  • 补码 ——Two's Complement

    • 正数和 0: = 原码
    • 负数:= 反码 + 1

nn 位补码 Bn1Bn2Bn3...B0B_{n-1} B_{n-2} B_{n-3}... B_{0} 统一表示:

Bn1(2n1)+Bn22n2+Bn32n3+...+B020B_{n-1}\cdot(-2^{n-1})+B_{n-2}\cdot2^{n-2}+B_{n-3}\cdot2^{n-3}+...+B_{0}\cdot2^{0}

nn 位原码 Bn1Bn2Bn3...B0B_{n-1} B_{n-2} B_{n-3}... B_{0} 统一表示:

Bn12n1+Bn22n2+Bn32n3+...+B020B_{n-1}\cdot2^{n-1}+B_{n-2}\cdot2^{n-2}+B_{n-3}\cdot2^{n-3}+...+B_{0}\cdot2^{0}

补码的补码即为原码

关于原码、反码、补码的易错点:

  • 反码取反是指对数字位取反,不改变符号位!
    • 例如 -7 即 1111 的反码是 1000,不是 0000 !
  • 补码是不对称的,例如补码为 1000 代表 - 8 ,而不代表 - 0 ! 即同样位数的二进制补码,负数会比正数 “多一个”;
  • 补码的 “加 1” 指的是在最低位加 1 的二进制加法运算,不是指数值 1,即如果含有小数部分,1 是加在整体的最右边;

利用二进制补码运算求解带符号数的加法运算:

  1. 分析需要使用多少个数字位;(培养思维习惯!不能忽略!)
  2. 用带符号位的二进制数表示,求解每个二进制数的补码;
  3. 对补码进行加法运算,再对结果求补码,即为最终结果;

注意最后一步,对补码进行加法运算时,数字位最高位产生的进位要进到符号位上去!(教材中描述的 “舍弃产生的进位” 指的是舍弃符号位产生的进位)

# 补码的扩展

将一个 n 位补码扩展到 n+k 位,只需将最高位符号位复制 k 个前置。

# 反码的加法

若最高位产生进位,需要循环进位,即最低位 “进一位”( +1 )。

# 无符号数:原码 -> 补码

# 方法一:

原码全部取反,再 +1

# 方法二:

从右向左找到第一个 1 ,这个 1 前面的所有位取反

若没有 1 ,也就是 0 ,原码 = 补码

# 负数:补码 -> 原码

这里只讨论负数的转换,正数不需要转换

# 方法一:

补码 -1 ,再取反

# 方法二:

从右向左找到第一个 1 ,这个 1 前面的位取反(符号位也要变为 0

若没有 1 ,也就是 0 ,原码 = 补码

# 浮点数

IEEE754 标准的 32 位浮点数:

SignExponentMantissa(Fraction)表示
1 位8 位23 位
000
5110±\pm\infin
511none zeroNaN

Number=(1)S(1+F)2E127Number=(-1)^{S}(1+F)2^{E-127}

公式中 FF 的小数点在最高位前面,将 EE 视为无符号二进制数。

# 十进制数的二进制代码

十进制代码用四位二进制数(最多可表示 24=162^4=16 个)来表示 0 ~ 9 ,没有 10 ⚠️

常见十进制代码

8421、2421、5211 每个数字指的是每个位的权;

# BCD/8421

8421 码也叫 BCD 码 (Binary Coded Decimal)。可以视为一种压缩编码(相比 intchar )。

余 3 码是在 BCD 码即 8421 码的基础上 +3 ,即用 3 ~ 12 对应的二进制数来表示 0 ~ 9

余 3 循环码是取格雷码中的 3 ~ 12

# 格雷码

教材中的格雷码特指的是四位格雷码,即用四位代码来表示 015 共十六种状态;

# 编码特点:

  • 每一位的状态变化都按一定的顺序循环,以 4 位格雷码为例:
    • 0110 (最低位)
    • 00111100
    • 0000111111110000
    • 0000000011111111 (最高位)
      (四位 16 个,只循环半个周期)

其他位数的格雷码表依次类推,自右向左每一位状态循环中连续的 01 数目加倍。
按表中顺序变化时,相邻的代码只有一位改变状态,这是格雷码最大的特点和优点;(应用:减少代码转换过程中的过渡噪声)

# 四维格雷码表

需要熟练掌握!重点是熟悉编码的规则和特点

四维格雷码表

# 二进制码与格雷码的映射

二进制码转换成格雷码:

  • 最高位相同
  • 二进制码从左到右,将相邻 AB 两位异或(无进位加法),得到格雷码对应的 B

格雷码转换成二进制码:

  • 最高位相同
  • 格雷码从左到右,将二进制码上一位 A ,格雷码当前位 B 两位异或,得到二进制码对应的 B

# 格雷码应用

旋转编码器(Rotate Encoder)

# ASCII 码

美国信息交换标准代码,用 7 位二进制代码(共 128 个)来表示信息,广泛应用于计算机和通信领域中;

ascii

在线查询:

  • 菜鸟教程
  • OSchina

# 校验

  • 奇校验
    • 在二进制串的末尾增加一位 10 ,使得整个新二进制的 1 的个数为奇数
  • 偶校验
    • 在二进制串的末尾增加一位 10 ,使得整个新二进制的 1 的个数为偶数
Edited on Views times
\ No newline at end of file diff --git a/ie/de/combinatorial-logic/index.html b/ie/de/combinatorial-logic/index.html index 0ddea061..f26187df 100644 --- a/ie/de/combinatorial-logic/index.html +++ b/ie/de/combinatorial-logic/index.html @@ -1 +1 @@ -组合逻辑电路 - 数字逻辑电路 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

基本框架

  • 数字电路
    • 组合逻辑电路
      • 以门电路为基本单元
    • 时序逻辑电路
      • 以触发器为基本单元

# 组合逻辑电路基础

Programmable Logic Device : PLD —— 可编程逻辑器件

# 特点

功能上,任意时刻的输出仅仅取决于该时刻的输入,与电路原来的状态无关;

结构上,组合逻辑电路不含有存储单元(记忆单元),只有从输入到输出的通路,没有反馈环路

# 分析方法

给定一个组合逻辑电路,分析其电路逻辑功能:

  1. 根据电路图,从输入到输出逐级分析,得到输出与输入的逻辑函数式;
  2. 对得到的逻辑函数式进行化简、形式变换或列出真值表,最后分析其逻辑功能;

# 设计方法

  • Step 1:逻辑抽象;
    • 分析因果关系,确定输入 / 输出变量;
    • 定义逻辑状态的含意(赋值);
      • 输入和输出都有可能需要多个变量
      • 一个对象有 kk 种状态,则可能需要 n=log2kn=\lceil\log_2k\rceil 个信号来表示;若 2n>k2^n\gt k,多余的项为无关项中的约束项,可以不写在真值表中
    • 列出真值表;
  • Step 2:将真值表转换为逻辑函数式;
  • Step 3:选定器件类型;
    • 是否有器件类型限制,例如 “只能用与非门” 这类条件;
    • 是否有指定使用的中规模器件,例如 “使用数据选择器” 这类条件;
  • Step 4:根据所选器件,对逻辑式进行化简或形式变换;(或进行相应的描述(PLD))
    • 与非门 —— 与非 — 与非式
    • 或非门 —— 或非 — 或非式
  • Step 5:画出逻辑电路连接图

# 加法器

# 半加法器

Basic Adders

半加法器

ABC_Σ\Sigma
0000
0101
1001
1110

Cout=ABΣ=AB\begin{aligned} C_{out}&=AB\\ \Sigma&=A\oplus B \end{aligned}

门电路实现:

半加法器门电路实现

# 全加法器

Full-adder

全加法器

ABC_C_Σ\Sigma
00000
00101
01001
01110
10001
10110
11010
11111

Cout=AB+(AB)CinΣ=ABCin\begin{aligned} C_{out}&=AB+(A\oplus B)C_{in}\\ \Sigma&=A\oplus B\oplus C_{in} \end{aligned}

输出写为这个形式,与半加法器的输出对比,全加法器可以用 2 个半加法器级联和 1 个或门实现

门电路实现全加法器:

门电路实现全加法器

半加法器实现全加法器:

半加法器实现全加法器

# 二进制加法器

Parallel Binary Adders

全加法器级联实现,利用了模块化设计的思想

模块化思想,或者说集成化思想,是人们不断积累的设计经验。有很多场合下的逻辑问题是具有共性的,为了更方便地设计电路,通常可以将一些具有特定功能、解决某类问题的电路封装打包即集成化,组成一些常用的组合逻辑电路模块(中规模集成器件);在设计大规模的集成电路时,就可以调用这些典型的电路模块而避免使用复杂且数量巨大的分立的门电路

# 74LS283

4-bit parallel adder, 4 位二进制加法器

4位并行加法器

2 个 74LS283 级联可以得到 8 位二进制加法器(8-bit parallel adder):

全加法器级联实现4位并行加法器

4 个全加法器级联实现,但是这样上一级的 CoutC_{out} 到下一级 CinC_{in} 会存在延迟,级联越多,这样的串行部分产生的延迟越多

全加法器中,令:

Cg=ABCp=A+B\begin{aligned} C_{g}&=AB\\ C_{p}&=A+B \end{aligned}

则有:

Cout=Cg+CpCinC_{out}=C_{g}+C_{p}C_{in}

look-ahead-adder

# 比较器

comparator

简单的 1、2 位比较器直接利用异或门可以实现。

位数比较多时,比如 4 位比较器,从高位开始比较,若出现不一样则剩余低位可以不必比较,直接输出结果(大于、小于)否则直到所有位比较完,并且都相等,则输出 “相等”

# 74LS85

4 位比较器

74LS85

  • 8 位数据输入,按从 3 到 0 的高位到低位顺序比较
  • 3 位级联输入,当本次比较结果为相等时输出级联输入的结果
  • 3 位比较结果输出,高电平有效

注意 3 个级联输入: A<BA<BA=BA=BA>BA>B 。 这些输入允许几个比较器级联起来,用来比较大于 4 位数字的数。

  • 低位比较器的 A<BA<BA=BA =BA>BA>B 输出与对应的下一个较高位比较器的级联输入相连接;
  • 最低位比较器在 A=BA=B 输入端又必须接高电平,在 A<BA<BA>BA>B 输入端又必须接低电平;

# 扩展 8 位比较器

2 个 74HC85 扩展为 8 位比较器:

74LS85扩展8位比较器

# 扩展 16 位比较器

5 个 74LS85 扩展为 16 位比较器:

74LS85扩展16位比较器

# 译码器 (n:m)

decoder

# 74HC154(4:16)

4 位译码器,4 线 - 16 线译码器,也是 4 线 - 16 线解多路复用器

  • 4 位输入
  • 2 位片选,当且仅当 2 位都为低位时才正常工作
  • 16 位输出,低电平有效

74HC154

# 扩展

74HC54 扩展实现 5 位输入译码器:

74HC54实现5位输入译码器

# 74HC42

BCD - 十进制译码器,把每 一个 BCD 码 (8421 码) 转换成 10 个十进制数中的一个数所表示的输出

  • 4 位输入,A0,A1,A2,A3A_0,A_1,A_2,A_3 分别表示 1 2 4 8
  • 10 位输出, 低电平有效

# 74LS47

BCD-7 段译码器 / 驱动器,它把一个 BCD 输入进行译码,并驱动 7 段显示器

  • 4 位输入,A0,A1,A2,A3A_0,A_1,A_2,A_3 分别表示 1 2 4 8 ,高电平有效
  • 3 位控制位
    • LT\overline{LT},输入低电平有效时试灯
    • RBI\overline{RBI},输入低电平有效,且该位当前状态为 00
    • BI/RBO\overline{BI}/\overline{RBO},输出低电平有效表示该位当前状态为 0
  • 7 位输出,低电平有效

74LS48 与它的区别在于输出的 7 位没有取非,它的输出是高电平有效

# 灭零

LTRBI=10\overline{LT}\ \overline{RBI}=10灭零。把数字前面的 0 熄灭称为头部灭零,把数字尾端的 0 熄灭称为尾部灭零。只是把不需要的零熄灭!

# 头部灭零

头部灭零

# 尾部灭零

尾部灭零

# 试灯

LT=0\overline{LT}=0 时试灯,即显示为 8

# 2-4 译码器

# 3-8 译码器

3 线 - 8 线译码器

# ⭐️74LS138(3:8)

  • 3 位输入位为选择位
  • 8 位输出位
  • 3 位片选位

# 5-32 译码器

可以用 1 个 74LS139 和 4 个 74LS138 实现

# 编码器 (n:m)

数字电路中的编码器是在已经实现了非电信号到电信号的转换、模拟信号到数字信号的转换之后对信息进行编码,即此时输入的信号是一组 高、低电平 (1 和 0 );

编码器的功能就是根据输入的每一个高、低电平来输出其对应的二进制代码

输入 nn电平信号,至少需要 log2n\lceil\log_2n\rceil 个输出端口,即 log2n\lceil\log_2n\rceil 位二进制编码

# 普通编码器

普通编码器规定了任意时刻有且只有一个有效输入信号,作为默认给定的约束条件

# 十进制 - BCD 编码器

十进制-BCD编码器

# 8/3 普通编码器

普通8-3编码器

真值表:(不包含无关项)

I0I_0I1I_1I2I_2I3I_3I4I_4I5I_5I6I_6I7I_7Y2Y_2Y1Y_1Y0Y_0
1
11
11
111
11
111
111
1111

因为任一时刻只能有一个输入为 1,因此只需要将输入为 1 的变量保留,其余的变量无关(相当于在卡诺图中 x 的方块填入 1 合并消去无关变量)化简为最简与或式:

Y2=I4+I5+I6+I7Y1=I2+I3+I6+I7Y0=I1+I3+I5+I7Y_2=I_4+I_5+I_6+I_7\\ Y_1=I_2+I_3+I_6+I_7\\ Y_0=I_1+I_3+I_5+I_7

从而可画出逻辑电路图:

普通8-3编码器逻辑电路图

此设计存在的问题:

  • 不能有多个信号同时输入
  • 也不能没有信号输入(因为根据我们的约束条件,00000000 也属于无关项);

因此我们以上的设计只是一个思路的训练,最终的设计结果并不能直接应用到实际当中

# 优先编码器

  • 允许多个信号同时输入
  • 编码时存在优先顺序

# 8/3 优先编码器

规定:

  • 高电平输入有效,即输入 1 表示对此输入信号编码,输出的 Y2Y1Y0Y_2Y_1Y_0 即为 0 ~ 7 对应的三位二进制代码 000~111;
  • 二进制数大的优先级高,即 I7I_7 优先级最高,I0I_0 最低;

真值表:(不包含无关项)

I0I_0I1I_1I2I_2I3I_3I4I_4I5I_5I6I_6I7I_7Y2Y_2Y1Y_1Y0Y_0
xxxxxxx1111
xxxxxx111
xxxxx111
xxxx11
xxx111
xx11
x11
1

此真值表不完整!当前只有 2812^8–1 行,缺少了一行 00000000 !

这时存在的问题是,输入全为 0 时输出为 I0I_0 表示的状态,无法表示输入全为 0 的状态。在实际应用的 8/3 优先编码器中,还附加了其他的输入输出端口,以便于片选和拓展。

附加了其他的输入输出端口进行片选和拓展的最主要目还是厂家希望产品应用更广泛,同种型号芯片可以实现不同功能

# 75LS148(8:3)

  • 8 位输入,低电平有效
  • 1 位片选位 EI\overline{EI} ,低电平有效,正常工作
  • 3 位输出编码,低电平有效⚠️
  • 2 位输出有效位
    • EO\overline{EO}EI\overline{EI} 有效且所有输入都无效时为 0
    • GS\overline{GS}EI\overline{EI} 无效且任何一个输入有效时为 0

功能表:

EIEI'I0I_0'I1I_1'I2I_2'I3I_3'I4I_4'I5I_5'I6I_6'I7I_7'Y2Y_2'Y1Y_1'Y0Y_0'EOEO'GSGS'
1xxxxxxxx11111
111111111111
xxxxxxx1
xxxxxx111
xxxxx1111
xxxx111111
xxx111111
xx11111111
x111111111
11111111111

# 扩展

2 个 74LS148 实现 16 线 - 4 线编码器:

74LS148实现16线-4线编码器

# 多路复用器 (n:1)

(Mux)多路复用器(Multiplexer)或数据选择器(Data Selector),能够实现并行数据到串行数据的转化。

包括:

  • 数据选择位(低电平有效)
  • 数据输入位
  • 数据输出位

此时数据输入输出位不必再关心是否低电平有效

# 4 路复用器

  • 2 位数据选择位 S0,S1\overline{S_0},\overline{S_1} ,低电平有效
  • 4 位数据输入位 D0,D1,D2,D3D_0,D_1,D_2,D_3
  • 1 位数据输出位 YY

Y=S1S0D0+S1S0D1+S1S0D0+S1S0D1Y=\overline{S_1S_0}D_0+\overline{S_1}S_0D_1+S_1\overline{S_0}D_0+S_1S_0D_1

4位多路复用器

# 8 路复用器

Y=S3S2S1S0D0+S3S2S1S0D1+S3S2S1S0D2+S3S2S1S0D3\begin{aligned} Y&=\overline{S_3S_2S_1S_0}D_0+\overline{S_3S_2S_1}S_0D_1+\overline{S_3S_2}S_1\overline{S_0}D_2+\overline{S_3S_2S_1S_0}D_3 \end{aligned}

# 74LS151

# 扩展 16 路复用器

2 个 74LS151 扩展实现 16 路复用器

74LS151扩展实现16路复用器

# 74LS153

双 4 选 1 数据选择器,也就是 2 组 4 选 1 共用同一个选择输入和同一个片选输入。

# 74LS157

四 2 选 1 数据选择器,也就是 4 组 2 选 1 共用同一个选择输入和同一个片选输入。

  • 1 位片选输入,电平有效
  • 1 位选择输入
  • 8 位数据输入
  • 4 位数据输出

# 7 段显示多路复用器

把 BCD 数字分配到一个 7 段显示器上的一个简单方法

# ⭐️扩展

2 个 4 选 1 扩展为 8 选 1

1 个 4 选 1 + 门电路扩展为 5 选 1

5 个 4 选 1 扩展为 16 选 1 (⭐️树状扩展)

# ⭐️实现门电路

# 解多路复用器 (1:n)

解多路分配器(Demultiplexer)或数据分配器()

数据选择器的逆

# 1 线 - 4 线多路分配器

1线-4线多路分配器

1线-4线多路分配器波形图

# 74HC154

4 位译码器 74HC154 可以作为 4 线 - 16 线解多路复用器

74HC154作4线-16线解多路复用器

# 传输时延与竞争冒险

  • 毛刺 glitch
  • 竞争 race
  • 冒险 hazard

时延导致竞争的存在,竞争可能产生毛刺,竞争导致了逻辑误判,就是冒险

# 消除冒险的方法

# 滤波电容

# 冗余项

\ No newline at end of file +组合逻辑电路 - 数字逻辑电路 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

基本框架

  • 数字电路
    • 组合逻辑电路
      • 以门电路为基本单元
    • 时序逻辑电路
      • 以触发器为基本单元

# 组合逻辑电路基础

Programmable Logic Device : PLD —— 可编程逻辑器件

# 特点

功能上,任意时刻的输出仅仅取决于该时刻的输入,与电路原来的状态无关;

结构上,组合逻辑电路不含有存储单元(记忆单元),只有从输入到输出的通路,没有反馈环路

# 分析方法

给定一个组合逻辑电路,分析其电路逻辑功能:

  1. 根据电路图,从输入到输出逐级分析,得到输出与输入的逻辑函数式;
  2. 对得到的逻辑函数式进行化简、形式变换或列出真值表,最后分析其逻辑功能;

# 设计方法

  • Step 1:逻辑抽象;
    • 分析因果关系,确定输入 / 输出变量;
    • 定义逻辑状态的含意(赋值);
      • 输入和输出都有可能需要多个变量
      • 一个对象有 kk 种状态,则可能需要 n=log2kn=\lceil\log_2k\rceil 个信号来表示;若 2n>k2^n\gt k,多余的项为无关项中的约束项,可以不写在真值表中
    • 列出真值表;
  • Step 2:将真值表转换为逻辑函数式;
  • Step 3:选定器件类型;
    • 是否有器件类型限制,例如 “只能用与非门” 这类条件;
    • 是否有指定使用的中规模器件,例如 “使用数据选择器” 这类条件;
  • Step 4:根据所选器件,对逻辑式进行化简或形式变换;(或进行相应的描述(PLD))
    • 与非门 —— 与非 — 与非式
    • 或非门 —— 或非 — 或非式
  • Step 5:画出逻辑电路连接图

# 加法器

# 半加法器

Basic Adders

半加法器

ABC_Σ\Sigma
0000
0101
1001
1110

Cout=ABΣ=AB\begin{aligned} C_{out}&=AB\\ \Sigma&=A\oplus B \end{aligned}

门电路实现:

半加法器门电路实现

# 全加法器

Full-adder

全加法器

ABC_C_Σ\Sigma
00000
00101
01001
01110
10001
10110
11010
11111

Cout=AB+(AB)CinΣ=ABCin\begin{aligned} C_{out}&=AB+(A\oplus B)C_{in}\\ \Sigma&=A\oplus B\oplus C_{in} \end{aligned}

输出写为这个形式,与半加法器的输出对比,全加法器可以用 2 个半加法器级联和 1 个或门实现

门电路实现全加法器:

门电路实现全加法器

半加法器实现全加法器:

半加法器实现全加法器

# 二进制加法器

Parallel Binary Adders

全加法器级联实现,利用了模块化设计的思想

模块化思想,或者说集成化思想,是人们不断积累的设计经验。有很多场合下的逻辑问题是具有共性的,为了更方便地设计电路,通常可以将一些具有特定功能、解决某类问题的电路封装打包即集成化,组成一些常用的组合逻辑电路模块(中规模集成器件);在设计大规模的集成电路时,就可以调用这些典型的电路模块而避免使用复杂且数量巨大的分立的门电路

# 74LS283

4-bit parallel adder, 4 位二进制加法器

4位并行加法器

2 个 74LS283 级联可以得到 8 位二进制加法器(8-bit parallel adder):

全加法器级联实现4位并行加法器

4 个全加法器级联实现,但是这样上一级的 CoutC_{out} 到下一级 CinC_{in} 会存在延迟,级联越多,这样的串行部分产生的延迟越多

全加法器中,令:

Cg=ABCp=A+B\begin{aligned} C_{g}&=AB\\ C_{p}&=A+B \end{aligned}

则有:

Cout=Cg+CpCinC_{out}=C_{g}+C_{p}C_{in}

look-ahead-adder

# 比较器

comparator

简单的 1、2 位比较器直接利用异或门可以实现。

位数比较多时,比如 4 位比较器,从高位开始比较,若出现不一样则剩余低位可以不必比较,直接输出结果(大于、小于)否则直到所有位比较完,并且都相等,则输出 “相等”

# 74LS85

4 位比较器

74LS85

  • 8 位数据输入,按从 3 到 0 的高位到低位顺序比较
  • 3 位级联输入,当本次比较结果为相等时输出级联输入的结果
  • 3 位比较结果输出,高电平有效

注意 3 个级联输入: A<BA<BA=BA=BA>BA>B 。 这些输入允许几个比较器级联起来,用来比较大于 4 位数字的数。

  • 低位比较器的 A<BA<BA=BA =BA>BA>B 输出与对应的下一个较高位比较器的级联输入相连接;
  • 最低位比较器在 A=BA=B 输入端又必须接高电平,在 A<BA<BA>BA>B 输入端又必须接低电平;

# 扩展 8 位比较器

2 个 74HC85 扩展为 8 位比较器:

74LS85扩展8位比较器

# 扩展 16 位比较器

5 个 74LS85 扩展为 16 位比较器:

74LS85扩展16位比较器

# 译码器 (n:m)

decoder

# 74HC154(4:16)

4 位译码器,4 线 - 16 线译码器,也是 4 线 - 16 线解多路复用器

  • 4 位输入
  • 2 位片选,当且仅当 2 位都为低位时才正常工作
  • 16 位输出,低电平有效

74HC154

# 扩展

74HC54 扩展实现 5 位输入译码器:

74HC54实现5位输入译码器

# 74HC42

BCD - 十进制译码器,把每 一个 BCD 码 (8421 码) 转换成 10 个十进制数中的一个数所表示的输出

  • 4 位输入,A0,A1,A2,A3A_0,A_1,A_2,A_3 分别表示 1 2 4 8
  • 10 位输出, 低电平有效

# 74LS47

BCD-7 段译码器 / 驱动器,它把一个 BCD 输入进行译码,并驱动 7 段显示器

  • 4 位输入,A0,A1,A2,A3A_0,A_1,A_2,A_3 分别表示 1 2 4 8 ,高电平有效
  • 3 位控制位
    • LT\overline{LT},输入低电平有效时试灯
    • RBI\overline{RBI},输入低电平有效,且该位当前状态为 00
    • BI/RBO\overline{BI}/\overline{RBO},输出低电平有效表示该位当前状态为 0
  • 7 位输出,低电平有效

74LS48 与它的区别在于输出的 7 位没有取非,它的输出是高电平有效

# 灭零

LTRBI=10\overline{LT}\ \overline{RBI}=10灭零。把数字前面的 0 熄灭称为头部灭零,把数字尾端的 0 熄灭称为尾部灭零。只是把不需要的零熄灭!

# 头部灭零

头部灭零

# 尾部灭零

尾部灭零

# 试灯

LT=0\overline{LT}=0 时试灯,即显示为 8

# 2-4 译码器

# 3-8 译码器

3 线 - 8 线译码器

# ⭐️74LS138(3:8)

  • 3 位输入位为选择位
  • 8 位输出位
  • 3 位片选位

# 5-32 译码器

可以用 1 个 74LS139 和 4 个 74LS138 实现

# 编码器 (n:m)

数字电路中的编码器是在已经实现了非电信号到电信号的转换、模拟信号到数字信号的转换之后对信息进行编码,即此时输入的信号是一组 高、低电平 (1 和 0 );

编码器的功能就是根据输入的每一个高、低电平来输出其对应的二进制代码

输入 nn电平信号,至少需要 log2n\lceil\log_2n\rceil 个输出端口,即 log2n\lceil\log_2n\rceil 位二进制编码

# 普通编码器

普通编码器规定了任意时刻有且只有一个有效输入信号,作为默认给定的约束条件

# 十进制 - BCD 编码器

十进制-BCD编码器

# 8/3 普通编码器

普通8-3编码器

真值表:(不包含无关项)

I0I_0I1I_1I2I_2I3I_3I4I_4I5I_5I6I_6I7I_7Y2Y_2Y1Y_1Y0Y_0
1
11
11
111
11
111
111
1111

因为任一时刻只能有一个输入为 1,因此只需要将输入为 1 的变量保留,其余的变量无关(相当于在卡诺图中 x 的方块填入 1 合并消去无关变量)化简为最简与或式:

Y2=I4+I5+I6+I7Y1=I2+I3+I6+I7Y0=I1+I3+I5+I7Y_2=I_4+I_5+I_6+I_7\\ Y_1=I_2+I_3+I_6+I_7\\ Y_0=I_1+I_3+I_5+I_7

从而可画出逻辑电路图:

普通8-3编码器逻辑电路图

此设计存在的问题:

  • 不能有多个信号同时输入
  • 也不能没有信号输入(因为根据我们的约束条件,00000000 也属于无关项);

因此我们以上的设计只是一个思路的训练,最终的设计结果并不能直接应用到实际当中

# 优先编码器

  • 允许多个信号同时输入
  • 编码时存在优先顺序

# 8/3 优先编码器

规定:

  • 高电平输入有效,即输入 1 表示对此输入信号编码,输出的 Y2Y1Y0Y_2Y_1Y_0 即为 0 ~ 7 对应的三位二进制代码 000~111;
  • 二进制数大的优先级高,即 I7I_7 优先级最高,I0I_0 最低;

真值表:(不包含无关项)

I0I_0I1I_1I2I_2I3I_3I4I_4I5I_5I6I_6I7I_7Y2Y_2Y1Y_1Y0Y_0
xxxxxxx1111
xxxxxx111
xxxxx111
xxxx11
xxx111
xx11
x11
1

此真值表不完整!当前只有 2812^8–1 行,缺少了一行 00000000 !

这时存在的问题是,输入全为 0 时输出为 I0I_0 表示的状态,无法表示输入全为 0 的状态。在实际应用的 8/3 优先编码器中,还附加了其他的输入输出端口,以便于片选和拓展。

附加了其他的输入输出端口进行片选和拓展的最主要目还是厂家希望产品应用更广泛,同种型号芯片可以实现不同功能

# 75LS148(8:3)

  • 8 位输入,低电平有效
  • 1 位片选位 EI\overline{EI} ,低电平有效,正常工作
  • 3 位输出编码,低电平有效⚠️
  • 2 位输出有效位
    • EO\overline{EO}EI\overline{EI} 有效且所有输入都无效时为 0
    • GS\overline{GS}EI\overline{EI} 无效且任何一个输入有效时为 0

功能表:

EIEI'I0I_0'I1I_1'I2I_2'I3I_3'I4I_4'I5I_5'I6I_6'I7I_7'Y2Y_2'Y1Y_1'Y0Y_0'EOEO'GSGS'
1xxxxxxxx11111
111111111111
xxxxxxx1
xxxxxx111
xxxxx1111
xxxx111111
xxx111111
xx11111111
x111111111
11111111111

# 扩展

2 个 74LS148 实现 16 线 - 4 线编码器:

74LS148实现16线-4线编码器

# 多路复用器 (n:1)

(Mux)多路复用器(Multiplexer)或数据选择器(Data Selector),能够实现并行数据到串行数据的转化。

包括:

  • 数据选择位(低电平有效)
  • 数据输入位
  • 数据输出位

此时数据输入输出位不必再关心是否低电平有效

# 4 路复用器

  • 2 位数据选择位 S0,S1\overline{S_0},\overline{S_1} ,低电平有效
  • 4 位数据输入位 D0,D1,D2,D3D_0,D_1,D_2,D_3
  • 1 位数据输出位 YY

Y=S1S0D0+S1S0D1+S1S0D0+S1S0D1Y=\overline{S_1S_0}D_0+\overline{S_1}S_0D_1+S_1\overline{S_0}D_0+S_1S_0D_1

4位多路复用器

# 8 路复用器

Y=S3S2S1S0D0+S3S2S1S0D1+S3S2S1S0D2+S3S2S1S0D3\begin{aligned} Y&=\overline{S_3S_2S_1S_0}D_0+\overline{S_3S_2S_1}S_0D_1+\overline{S_3S_2}S_1\overline{S_0}D_2+\overline{S_3S_2S_1S_0}D_3 \end{aligned}

# 74LS151

# 扩展 16 路复用器

2 个 74LS151 扩展实现 16 路复用器

74LS151扩展实现16路复用器

# 74LS153

双 4 选 1 数据选择器,也就是 2 组 4 选 1 共用同一个选择输入和同一个片选输入。

# 74LS157

四 2 选 1 数据选择器,也就是 4 组 2 选 1 共用同一个选择输入和同一个片选输入。

  • 1 位片选输入,电平有效
  • 1 位选择输入
  • 8 位数据输入
  • 4 位数据输出

# 7 段显示多路复用器

把 BCD 数字分配到一个 7 段显示器上的一个简单方法

# ⭐️扩展

2 个 4 选 1 扩展为 8 选 1

1 个 4 选 1 + 门电路扩展为 5 选 1

5 个 4 选 1 扩展为 16 选 1 (⭐️树状扩展)

# ⭐️实现门电路

# 解多路复用器 (1:n)

解多路分配器(Demultiplexer)或数据分配器()

数据选择器的逆

# 1 线 - 4 线多路分配器

1线-4线多路分配器

1线-4线多路分配器波形图

# 74HC154

4 位译码器 74HC154 可以作为 4 线 - 16 线解多路复用器

74HC154作4线-16线解多路复用器

# 传输时延与竞争冒险

  • 毛刺 glitch
  • 竞争 race
  • 冒险 hazard

时延导致竞争的存在,竞争可能产生毛刺,竞争导致了逻辑误判,就是冒险

# 消除冒险的方法

# 滤波电容

# 冗余项

\ No newline at end of file diff --git a/ie/de/digital-process/index.html b/ie/de/digital-process/index.html index 1217c863..4862f276 100644 --- a/ie/de/digital-process/index.html +++ b/ie/de/digital-process/index.html @@ -1 +1 @@ -数模转换 - 数字逻辑电路 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 采样定理

# ADC

# 运算放大器

运算放大器是一种线性放大器。

  • 两个输入
    • 反相
    • 同相
  • 和一个输出

特点:

  • 很高的电压增益
  • 很大的输入阻抗
  • 很低的输出阻抗

运算放大器的 3 种使用方式:

运算放大器

用做反相放大器时,图中,虚地处电压为 0 V ,由于很大的输入阻抗没有电流流入运算放大器,输入电压处 VinV_{in} 所有电流流向输出电压处 VoutV_{out} ,可得:

VoutVin=RfRi\frac{V_{out}}{V_{in}}=-\frac{R_f}{R_i}

其中 RfR_f 是反馈电阻,RiR_i 是输入电阻。

其 中 VoutVin\frac{V_{out}}{V_{in}}闭环电压增益 (闭环是指由电阻 R,提供的从输出到输入的反馈),负号表示反相。

# 快速 ADC

3 位快速 ADC:

3位快速ADC

每个比较器的参考电压都由电阻分压电路设定。每个比较器的输出都连接到优先权编码器的一个输入。编码器由 EN 输入上的一个脉冲使能,3 位码表示出现在编码器输出上的输入值。 二进制数由最高级别输入的高电平决定。 二进制数的序列表示 ADC 的输入,每次使能脉冲有效的期间,输入信号得到采样。转换的精度由 2 个因素确定:

  • 使能脉冲的频率
  • 二进制编码的位数

# 双积分 ADC

一个斜坡发生器 (积分器) 用来产生双积分特性。本质是在一个计数器进位的时间周期内,信号对电容充电,然后在恒定的电容放电速度下,在放电时间内计数器计数实现对这一信号电压大小的量化。

双积分ADC原理

这里可变斜率由 VinV_{in} 的大小决定,越大则可变斜率越大,电容充电速度越快。而电容放电的速度是固定的。

双积分ADC

由于需要充电、放电,所以 DAC 相对较慢,而且该方法要求采样保持时间足够长。

# DAC

# 二进制权值输入 DAC

4位二进制权值输入DAC

输入的高电平电压若为 5 V ,输出:

4位二进制权值输入DAC输出

# R/2R 阶梯形 DAC

这里利用了戴维南定理等效电路

该方法结构更加精简,容易实现。

nn 输入的高电平电压若为 ViV_i ,则输出电压为从 00ViV_i ,以 Vi2n\frac{V_i}{2^n} 为间隔,依次对应输入信号的 0 到 2n12^n-1

R-2R阶梯形DAC

Edited on Views times
\ No newline at end of file +数模转换 - 数字逻辑电路 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 采样定理

# ADC

# 运算放大器

运算放大器是一种线性放大器。

  • 两个输入
    • 反相
    • 同相
  • 和一个输出

特点:

  • 很高的电压增益
  • 很大的输入阻抗
  • 很低的输出阻抗

运算放大器的 3 种使用方式:

运算放大器

用做反相放大器时,图中,虚地处电压为 0 V ,由于很大的输入阻抗没有电流流入运算放大器,输入电压处 VinV_{in} 所有电流流向输出电压处 VoutV_{out} ,可得:

VoutVin=RfRi\frac{V_{out}}{V_{in}}=-\frac{R_f}{R_i}

其中 RfR_f 是反馈电阻,RiR_i 是输入电阻。

其 中 VoutVin\frac{V_{out}}{V_{in}}闭环电压增益 (闭环是指由电阻 R,提供的从输出到输入的反馈),负号表示反相。

# 快速 ADC

3 位快速 ADC:

3位快速ADC

每个比较器的参考电压都由电阻分压电路设定。每个比较器的输出都连接到优先权编码器的一个输入。编码器由 EN 输入上的一个脉冲使能,3 位码表示出现在编码器输出上的输入值。 二进制数由最高级别输入的高电平决定。 二进制数的序列表示 ADC 的输入,每次使能脉冲有效的期间,输入信号得到采样。转换的精度由 2 个因素确定:

  • 使能脉冲的频率
  • 二进制编码的位数

# 双积分 ADC

一个斜坡发生器 (积分器) 用来产生双积分特性。本质是在一个计数器进位的时间周期内,信号对电容充电,然后在恒定的电容放电速度下,在放电时间内计数器计数实现对这一信号电压大小的量化。

双积分ADC原理

这里可变斜率由 VinV_{in} 的大小决定,越大则可变斜率越大,电容充电速度越快。而电容放电的速度是固定的。

双积分ADC

由于需要充电、放电,所以 DAC 相对较慢,而且该方法要求采样保持时间足够长。

# DAC

# 二进制权值输入 DAC

4位二进制权值输入DAC

输入的高电平电压若为 5 V ,输出:

4位二进制权值输入DAC输出

# R/2R 阶梯形 DAC

这里利用了戴维南定理等效电路

该方法结构更加精简,容易实现。

nn 输入的高电平电压若为 ViV_i ,则输出电压为从 00ViV_i ,以 Vi2n\frac{V_i}{2^n} 为间隔,依次对应输入信号的 0 到 2n12^n-1

R-2R阶梯形DAC

Edited on Views times
\ No newline at end of file diff --git a/ie/de/gate-circuit/index.html b/ie/de/gate-circuit/index.html index 82e50c42..5b90e779 100644 --- a/ie/de/gate-circuit/index.html +++ b/ie/de/gate-circuit/index.html @@ -1 +1 @@ -门电路 - 数字逻辑电路 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 基本概念

!!! 可能会在选择填空题中考察

  • 上拉 —— 使输出钳位至高电平

  • 下拉 —— 使输出钳位至低电平;

  • 灌电流 —— 输出为低电平时,负载电流从外部电路注入输出端口;

  • 拉电流 —— 输出为高电平时,负载电流从输出端口流出到外部电路;

当门电路没有外部的有源输入信号,而是输入端口与地之间接入一个电阻时:

  • 关门电阻 —— 能够维持门电路输出高电平的电阻的最大值;
  • 开门电阻 —— 能够维持门电路输出低电平的电阻的最小值;

(联想 TTL 反相器的输入端负载特性曲线)

  • 扇入系数 —— 门电路允许的输入端的个数;

  • 扇出系数 —— 门电路允许驱动的同类型负载门的个数;

  • 高阻态 —— 从输出端口往里看的等效电阻近似无穷大,门电路失去对输出电压的控制,输出端口处电平由外部电路决定,即门电路与后级电路无联系;

  • 传输延迟时间 —— 由于半导体器件寄生电容的存在,输出量的变化总是滞后于输入量的变化;

  • 输入端噪声容限 —— 能够维持输出电压在规定高低电平范围内的输入电压的波动范围;

  • 缓冲级 —— 多级集成门电路应用中为了保持输入输出特性一致性输入级和输出级各加一级反相器;

# 基本逻辑元件

元件分类

# 与门 AND

X=ABX=AB

AND

与非门 NAND 构造与门 AND :

AND-from-NAND

或非门 NOR 构造与门 AND :

AND-from-NOR

# 或门 OR

X=A+BX=A+B

OR

与非门 NAND 构造或门 OR :

OR-from-NAND

或非门 NOR 构造或门 OR :

OR-fron-NOR

# 非门 Inverter

也叫反相器

Y=XY=\overline{X}

Inverter

与非门 NAND 构造非门 Inverter :

Inverter-from-NAND

或非门 NOR 构造非门 Inverter :

Inverter-from-NOR

# 与非门 NAND

等价于 Negative-OR

X=ABX=\overline{AB}

NAND

两个输入的与非门真值表:

输入 1输入 2输出
001
011
101
110

对于 n 个输入的与非门,当且仅当输入全部为 1 时,输出为 0 ,其余情况输出均为 1 ;或者说任何一个输入为 0 ,则输出为 1

与非门可以实现与门、或门、非门、或非门

NOR 门来实现 NAND 门:

NAND-from-NOR

# 或非门 NOR

等价于 Negative-AND

X=A+BX=\overline{A+B}

NOR

两个输入的或非门真值表:

输入 1输入 2输出
001
010
100
110

对于 n 个输入的或非门,当且仅当输入全部为 0 时,输出为 1 ,其余情况输出均为 0 ;或者说任何一个输入为 1 ,则输出为 0

或非门可以实现与门、或门、非门、或非门

NAND 门来实现 NOR 门:

NOR-from-NAND

# 异或门 XOR

Exclusive-OR

XOR (/ˌɛks ˈɔːr/, /ˌɛks ˈɔː/, /ˈksɔːr/ or /ˈksɔː/), EOR, EXOR, {\displaystyle {\dot {\vee }}}, {\displaystyle {\overline {\vee }}}, {\displaystyle {\underline {\vee }}}, , {\displaystyle \oplus }, {\displaystyle \nleftrightarrow }, {\displaystyle \not \equiv }.

XOR

两个输入的或非门真值表:

输入 1输入 2输出
000
011
101
110

对于 n 个输入的异或门,当且仅当输入不同时,输出为 1 ;输入相同时,输出为 0

异或门可以作为半加法器,输出为进位

# 同或门 XNOR

Exclusive-NOR

XNOR

两个输入的或非门真值表:

输入 1输入 2输出
001
010
100
111

对于 n 个输入的同或门,当且仅当输入相同时,输出为 1 ;输入不同时,输出为 0

# 门电路逻辑功能的分析与设计

一个 CMOS 门电路的构成:

  • 上拉部分
    • 由 PMOS 管实现,导通对应输入低电平,输出高电平
  • 下拉部分
    • 由 NMOS 管实现,导通对应输入高电平,输出低电平

逻辑功能上:

  • 与运算对应到电路中就是串联结构
  • 或运算对应到电路中就是并联结构

根据前面的基本设计思想,当含有多个输入变量时,只需要:

  • 根据其逻辑输出为 0 时设计下拉部分电路

    • (或先根据其逻辑输出为 1 时设计上拉部分电路,输入变量取反),
  • 然后根据对称性绘制另一侧的上 / 下拉电路(串变为并,并变为串)

  • 组合在一起即可;

# 门电路的输入特性与输出特性

# 门电路的输入端负载特性

# OD 门 / OC 门外接上拉电阻的计算分析

Edited on Views times
\ No newline at end of file +门电路 - 数字逻辑电路 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 基本概念

!!! 可能会在选择填空题中考察

  • 上拉 —— 使输出钳位至高电平

  • 下拉 —— 使输出钳位至低电平;

  • 灌电流 —— 输出为低电平时,负载电流从外部电路注入输出端口;

  • 拉电流 —— 输出为高电平时,负载电流从输出端口流出到外部电路;

当门电路没有外部的有源输入信号,而是输入端口与地之间接入一个电阻时:

  • 关门电阻 —— 能够维持门电路输出高电平的电阻的最大值;
  • 开门电阻 —— 能够维持门电路输出低电平的电阻的最小值;

(联想 TTL 反相器的输入端负载特性曲线)

  • 扇入系数 —— 门电路允许的输入端的个数;

  • 扇出系数 —— 门电路允许驱动的同类型负载门的个数;

  • 高阻态 —— 从输出端口往里看的等效电阻近似无穷大,门电路失去对输出电压的控制,输出端口处电平由外部电路决定,即门电路与后级电路无联系;

  • 传输延迟时间 —— 由于半导体器件寄生电容的存在,输出量的变化总是滞后于输入量的变化;

  • 输入端噪声容限 —— 能够维持输出电压在规定高低电平范围内的输入电压的波动范围;

  • 缓冲级 —— 多级集成门电路应用中为了保持输入输出特性一致性输入级和输出级各加一级反相器;

# 基本逻辑元件

元件分类

# 与门 AND

X=ABX=AB

AND

与非门 NAND 构造与门 AND :

AND-from-NAND

或非门 NOR 构造与门 AND :

AND-from-NOR

# 或门 OR

X=A+BX=A+B

OR

与非门 NAND 构造或门 OR :

OR-from-NAND

或非门 NOR 构造或门 OR :

OR-fron-NOR

# 非门 Inverter

也叫反相器

Y=XY=\overline{X}

Inverter

与非门 NAND 构造非门 Inverter :

Inverter-from-NAND

或非门 NOR 构造非门 Inverter :

Inverter-from-NOR

# 与非门 NAND

等价于 Negative-OR

X=ABX=\overline{AB}

NAND

两个输入的与非门真值表:

输入 1输入 2输出
001
011
101
110

对于 n 个输入的与非门,当且仅当输入全部为 1 时,输出为 0 ,其余情况输出均为 1 ;或者说任何一个输入为 0 ,则输出为 1

与非门可以实现与门、或门、非门、或非门

NOR 门来实现 NAND 门:

NAND-from-NOR

# 或非门 NOR

等价于 Negative-AND

X=A+BX=\overline{A+B}

NOR

两个输入的或非门真值表:

输入 1输入 2输出
001
010
100
110

对于 n 个输入的或非门,当且仅当输入全部为 0 时,输出为 1 ,其余情况输出均为 0 ;或者说任何一个输入为 1 ,则输出为 0

或非门可以实现与门、或门、非门、或非门

NAND 门来实现 NOR 门:

NOR-from-NAND

# 异或门 XOR

Exclusive-OR

XOR (/ˌɛks ˈɔːr/, /ˌɛks ˈɔː/, /ˈksɔːr/ or /ˈksɔː/), EOR, EXOR, {\displaystyle {\dot {\vee }}}, {\displaystyle {\overline {\vee }}}, {\displaystyle {\underline {\vee }}}, , {\displaystyle \oplus }, {\displaystyle \nleftrightarrow }, {\displaystyle \not \equiv }.

XOR

两个输入的或非门真值表:

输入 1输入 2输出
000
011
101
110

对于 n 个输入的异或门,当且仅当输入不同时,输出为 1 ;输入相同时,输出为 0

异或门可以作为半加法器,输出为进位

# 同或门 XNOR

Exclusive-NOR

XNOR

两个输入的或非门真值表:

输入 1输入 2输出
001
010
100
111

对于 n 个输入的同或门,当且仅当输入相同时,输出为 1 ;输入不同时,输出为 0

# 门电路逻辑功能的分析与设计

一个 CMOS 门电路的构成:

  • 上拉部分
    • 由 PMOS 管实现,导通对应输入低电平,输出高电平
  • 下拉部分
    • 由 NMOS 管实现,导通对应输入高电平,输出低电平

逻辑功能上:

  • 与运算对应到电路中就是串联结构
  • 或运算对应到电路中就是并联结构

根据前面的基本设计思想,当含有多个输入变量时,只需要:

  • 根据其逻辑输出为 0 时设计下拉部分电路

    • (或先根据其逻辑输出为 1 时设计上拉部分电路,输入变量取反),
  • 然后根据对称性绘制另一侧的上 / 下拉电路(串变为并,并变为串)

  • 组合在一起即可;

# 门电路的输入特性与输出特性

# 门电路的输入端负载特性

# OD 门 / OC 门外接上拉电阻的计算分析

Edited on Views times
\ No newline at end of file diff --git a/ie/de/integrated-circuit/index.html b/ie/de/integrated-circuit/index.html index ffa4f9bf..b40fc43a 100644 --- a/ie/de/integrated-circuit/index.html +++ b/ie/de/integrated-circuit/index.html @@ -1 +1 @@ -集成电路 (CMOS&TTL) - 数字逻辑电路 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 逻辑电平规范与抗噪

# 逻辑电平规范

⭐️保证输出的电平作为下一级输入是有效的

# CMOS

cmos输入输出逻辑电平

# TTL

ttl输入输出逻辑电平

# 噪声容限

⭐️保证输出的电平作为下一级输入是有效的基础上,输出与输入的界限相差即为噪声容限

电路抗噪度的一个衡量标准叫做噪声容限 (noisemargin),用伏特表示。对于一个给定的逻辑电路,有两个噪声容限值:

  • 噪声容限高电平 (VNHV_{NH}) (Noisemargin High)
  • 噪声容限低电平 (VNLV_{NL}) (Noisemargin Low)

这两个参数由如下的公式定义:

VNH=VOH(min)VIH(min)VNL=VIL(max)VOL(max)V_{NH}=V_{OH(\min)}-V_{IH(\min)}\\ V_{NL}=V_{IL(\max)}-V_{OL(\max)}

有时看到噪声容限是用 VCCV_{CC} 的百分比来表示的

噪声容限

# 负载和扇出

当一个逻辑门的输出连接到了一个或多个其他门的输人时,驱动门上就会有一个负载,对于一个给定的门,它可以驱动的负载门输人是有数量限制的。这个限制就称为这个门的扇出

基本概念:

  • 灌电流 —— 输出为低电平时,负载电流从外部电路注入输出端口;
  • 拉电流 —— 输出为高电平时,负载电流从输出端口流出到外部电路;
  • 扇入系数 —— 门电路允许的输入端的个数;
  • 扇出系数 —— 门电路允许驱动的同类型负载门的个数;

# CMOS

当驱动门的输出是高电平时,负载门的输入电容通过驱动门的输出电阻充电。当驱动门电路的输出是低电平时,电容放电:

cmos容性负载

如果给驱动门的输出添加更多的负载门输人,那么总的电容将会增加,因为输入电容实际上是并行出现的。电容的增加会延长充电和放电时间,因此就会降低这个门电路的最大工作频率。因此,CMOS 门电路的扇出是和工作频率有关的。负载门输入越少,最大频率就越高。

# TTL

TTL 驱动门向处于高电平状态的负载门提供灌电流 (IIHI_{IH}),从处于低电平状态的负载门吸收拉电流 (IILI_{IL})。

TTL 电路的功耗在工作频率的范围以内基本上是恒定功率。

ttl负载

负载元件越多,驱动门承载的灌电流或拉电流就越大,驱动门中内阻的压降就越大,要保证不能脱离标准逻辑电平,限制了扇出。

# CMOS

数字电路中只考虑增强型 MOS 管

nmos-and-pmos

# NMOS

NMOSFET,N 型金氧半场效晶体管

N 沟道增强型 MOS 管,箭头往里走,栅级无圆圈

NMOS

左侧是简化符号,右侧是标准符号

状态栅级 G漏级 D源级 S (接地)
导通101
关闭010

nmos

# PMOS

PMOSFET,P 型金氧半场效晶体管

P 沟道增强型 MOS 管,箭头往外走,栅级有圆圈

PMOS

左侧是简化符号,右侧是标准符号

状态栅级 G漏级 D源级 S (接电源)
导通010
关闭101

pmos

# CMOS

由 NMOS 和 PMOS 两种管子组成的互补 MOS 电路,即 CMOS 电路。

CMOS 电路元件不使用的管脚尽量不能悬空⚠️

# 非门

cmos非门

# 与非门

cmos与非门

或非门和与非门之间存在对偶关系,将 NMOS 和 PMOS 交换、高电平和低电平交换,就能够相互转换

# 或非门

cmos或非门

# 三态门

三态门引入了高阻抗状态

三态门的 3 个状态如下:

三态门3个状态

一个错误❌的三态 CMOS 反相器:

三态CMOS反相器-错误

Enable\overline{Enable} 和输入是对称设计的,所以输入为高电平时,输出也一样处于高阻抗状态。

正确设计:

cmos三态非门

# 漏极开路门

Open-drain,OD 门

术语漏极开路的意思是输出晶体管的漏极端没有连接,必须从外部通过负载连接到 VDDV_{DD}

实现大负载

与非门示例:

cmos漏极开路与非门

# TTL

TTL 电路中悬空的输入端将起到高电平的效果。

TTL 电路元件不使用的管脚尽量不能悬空⚠️,避免噪声影响。

# 双极型晶体管

Bipoplar Junction Transistor (BJT) (三极管)

开关效应原理图:

双极型晶体管原理

# TTL 门电路

# 非门

ttl非门

工作原理如下:

ttl非门原理

# 与非门

ttl与非门

# 集电极开路门

Open-Collector Gates,OC 门

集电路开路

驱动 LED 和灯泡:

ttl集电极开路

\ No newline at end of file +集成电路 (CMOS&TTL) - 数字逻辑电路 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 逻辑电平规范与抗噪

# 逻辑电平规范

⭐️保证输出的电平作为下一级输入是有效的

# CMOS

cmos输入输出逻辑电平

# TTL

ttl输入输出逻辑电平

# 噪声容限

⭐️保证输出的电平作为下一级输入是有效的基础上,输出与输入的界限相差即为噪声容限

电路抗噪度的一个衡量标准叫做噪声容限 (noisemargin),用伏特表示。对于一个给定的逻辑电路,有两个噪声容限值:

  • 噪声容限高电平 (VNHV_{NH}) (Noisemargin High)
  • 噪声容限低电平 (VNLV_{NL}) (Noisemargin Low)

这两个参数由如下的公式定义:

VNH=VOH(min)VIH(min)VNL=VIL(max)VOL(max)V_{NH}=V_{OH(\min)}-V_{IH(\min)}\\ V_{NL}=V_{IL(\max)}-V_{OL(\max)}

有时看到噪声容限是用 VCCV_{CC} 的百分比来表示的

噪声容限

# 负载和扇出

当一个逻辑门的输出连接到了一个或多个其他门的输人时,驱动门上就会有一个负载,对于一个给定的门,它可以驱动的负载门输人是有数量限制的。这个限制就称为这个门的扇出

基本概念:

  • 灌电流 —— 输出为低电平时,负载电流从外部电路注入输出端口;
  • 拉电流 —— 输出为高电平时,负载电流从输出端口流出到外部电路;
  • 扇入系数 —— 门电路允许的输入端的个数;
  • 扇出系数 —— 门电路允许驱动的同类型负载门的个数;

# CMOS

当驱动门的输出是高电平时,负载门的输入电容通过驱动门的输出电阻充电。当驱动门电路的输出是低电平时,电容放电:

cmos容性负载

如果给驱动门的输出添加更多的负载门输人,那么总的电容将会增加,因为输入电容实际上是并行出现的。电容的增加会延长充电和放电时间,因此就会降低这个门电路的最大工作频率。因此,CMOS 门电路的扇出是和工作频率有关的。负载门输入越少,最大频率就越高。

# TTL

TTL 驱动门向处于高电平状态的负载门提供灌电流 (IIHI_{IH}),从处于低电平状态的负载门吸收拉电流 (IILI_{IL})。

TTL 电路的功耗在工作频率的范围以内基本上是恒定功率。

ttl负载

负载元件越多,驱动门承载的灌电流或拉电流就越大,驱动门中内阻的压降就越大,要保证不能脱离标准逻辑电平,限制了扇出。

# CMOS

数字电路中只考虑增强型 MOS 管

nmos-and-pmos

# NMOS

NMOSFET,N 型金氧半场效晶体管

N 沟道增强型 MOS 管,箭头往里走,栅级无圆圈

NMOS

左侧是简化符号,右侧是标准符号

状态栅级 G漏级 D源级 S (接地)
导通101
关闭010

nmos

# PMOS

PMOSFET,P 型金氧半场效晶体管

P 沟道增强型 MOS 管,箭头往外走,栅级有圆圈

PMOS

左侧是简化符号,右侧是标准符号

状态栅级 G漏级 D源级 S (接电源)
导通010
关闭101

pmos

# CMOS

由 NMOS 和 PMOS 两种管子组成的互补 MOS 电路,即 CMOS 电路。

CMOS 电路元件不使用的管脚尽量不能悬空⚠️

# 非门

cmos非门

# 与非门

cmos与非门

或非门和与非门之间存在对偶关系,将 NMOS 和 PMOS 交换、高电平和低电平交换,就能够相互转换

# 或非门

cmos或非门

# 三态门

三态门引入了高阻抗状态

三态门的 3 个状态如下:

三态门3个状态

一个错误❌的三态 CMOS 反相器:

三态CMOS反相器-错误

Enable\overline{Enable} 和输入是对称设计的,所以输入为高电平时,输出也一样处于高阻抗状态。

正确设计:

cmos三态非门

# 漏极开路门

Open-drain,OD 门

术语漏极开路的意思是输出晶体管的漏极端没有连接,必须从外部通过负载连接到 VDDV_{DD}

实现大负载

与非门示例:

cmos漏极开路与非门

# TTL

TTL 电路中悬空的输入端将起到高电平的效果。

TTL 电路元件不使用的管脚尽量不能悬空⚠️,避免噪声影响。

# 双极型晶体管

Bipoplar Junction Transistor (BJT) (三极管)

开关效应原理图:

双极型晶体管原理

# TTL 门电路

# 非门

ttl非门

工作原理如下:

ttl非门原理

# 与非门

ttl与非门

# 集电极开路门

Open-Collector Gates,OC 门

集电路开路

驱动 LED 和灯泡:

ttl集电极开路

\ No newline at end of file diff --git a/ie/de/memory-storage/index.html b/ie/de/memory-storage/index.html index fa26e3c8..378dd4c7 100644 --- a/ie/de/memory-storage/index.html +++ b/ie/de/memory-storage/index.html @@ -1 +1 @@ -存储器 - 数字逻辑电路 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

两类主要的半导体存储器是 RAM 和 ROM。

  • RAM (随机访问存储器) 类型的存储器在等量时间内可以访问所有的地址,并且可以按照任何顺序来选择这些地址以执行读或者写操作。所有的 RAM 都具有读和写的能力。因为 RAM 在电源关闭时会丢失所存储的数据,所以它是易失性内存。 RAM 系列 RAM 的两种类别是静 RAM (SRAM) 和动态 RAM (DRAM) 。当直流电源移走后, SRAM 和 DRAM 都会丢失存储的数据,因此被归类为易失性存储器。
    • 静态 RAM 通常使用锁存器作为存储元件,因而只要加上直流电源,就可以永远地存储数据。
      • 异步 SRAM (ASRAM)
      • 同步 SRAM (SB SRAM),具有突发特性
    • 动态 RAM 使用电容作为存储元件,如果没有对电容再充电就不能长期存储数据,再充电则称为刷新过程。
      • 快速页模式 DRAM (FPMDRAM)
      • 扩充数据输出 DRAM (EDO DRAM)
      • 突发 EDO DRAM (BEDO DRAM)
      • 同步 DRAM (SDRAM)
  • ROM (只读存储器) 类型的存储器将永久或者半永久地保存数据。数据可以从 ROM 中读出,但是和 RAM 不同,它没有写操作。ROM 和 RAM 相似,也是随机存储器,但是术语 RAM 的 传统意思是随机读 / 写存储器。本章将会介绍几种类型的 RAM 和 ROM。因为 ROM 在电源关闭 后仍然保存着数据,所以它是永久性存储器
    • MROM (Mask ROM) —— 掩膜 ROM,出场时已经固定,不能更改,适合大量生产,简单,便宜,非易失性。
    • PROM —— 可一次性编程 ROM
    • EPROM —— 可擦除 PROM,也就是可多次编程
    • UV EPROM —— 紫外线版本的 EPROM
    • EEPROM —— 电版本的

对于给定的物理空间和成本,DRAM 可以存储比 SRAM 多得多的数据,因为 DRAM 单元更加简单,并在给定芯片面积里,因此可以比 SRAM 填充更多的单元

# RAM

# SRAM

SRAM 基本单元(是 D - 触发器 ):

sram单元

32k×832k\times8 SRAM

32kx8sram

逻辑组成如下:

32kx8sram逻辑图

读:

32kx8sram读

写:

32kx8sram写

# DRAM

DRAM 的基本单元,使用电容,电容充电表示 1 高电位,放电表示 0 低电位。

mosdram单元

DRAM 的 4 种基本操作:

mosdram单元基本操作

1M×11M\times1 DRAM 逻辑图:

1mx1dram逻辑图

DRAM 的读写周期:

dram读写周期

# ROM

ROM(Read Only Memory), 即只读存储器,由于其在掉电后数据不会丢失,因此在早期的时候,ROM 芯片中的内容一般都是在生产的时候被烧写进去的,然后终生具有这些固定的内容。不过,随着技术的不断发展和革新,现在很多型号的 ROM 都已经可以被多次修改了,但是大家仍然习惯对其沿用 “只读存储器” 的称号。

# MOS ROM

MOS ROM 基本单元:

mosrom单元

256x4rom

256x4rom逻辑图

# ROM 设计组合逻辑电路

实际上是枚举所有的输入输出,也就是真值表,存储到 ROM 里。

输入作为地址,通过地址译码器,输出相应地址的数据。

  • 有黑点⚫️表示存储 1 ;
  • 否则表示存储 0 ;

给出逻辑表达式(函数)时,求出标准的极小值只和的形式,依据极小值的下标确定画⚫️的位置

# PROM

PROM(Programmable Read Only Memory), 即可编程只读存储器,不过它也只能被程序写一次,以后就只能保存和使用这些数据了,所以 PROM 也称为一次可编程存储器。

# EPROM

EPROM(Erasable Programmable Read Only Memory),即可擦除可编程只读存储器。它解决了 PROM 只能编程一次的问题,不过其存储内容的擦除必须借助紫外线的长时间照射才能完成,所以 EPROM 又叫紫外线擦除可编程只读存储器。

# EEPROM

EEPROM(Electrically Erasable Programmable Read Only Memory),即电可擦除可编程只读存储器。它克服了 EPROM 在擦除时较为麻烦的问题,可以直接通过计算机程序对其进行重复的擦写,其擦除、重写的原理是通过使用高于常规的操作电压实现的。对于 EEPROM 来说,最重要的参数指标就是寿命问题,也就是可擦写的次数。

# 闪存

闪存 Flash Memory 是 EEPROM 的一种特殊形式,也就是变种。

EEPROM 的擦除和重写都是针对整个芯片而言的,但 Flash 的数据删除和重写则是以块(块的容量一般在 256KB~20MB 之间)为单位的,因此 Flash 的更新速度要远比 EEPROM 快。不过由于数据的删除和重写不是以单个字节为单位的,因此 Flash 仍不能达到 RAM 的要求。

Flash 又分为 NOR 型和 NAND 型两个大类,其中 NOR 型具有独立的地址线和数据线,适合频繁的随机读、写场合,适合程序代码的存储和直接运行,但容量通常较小,价格也比较贵;而 NAND 型的地址线和数据线是公用的,因此其本身的操作速度和频率就会偏低,但是容量相对较大,且价格也要便宜,所以适合大量资料的存储。

# 存储器扩展

# 字长扩展

共享数据线和控制线,并联数据线。

2 个 64k×464k\times4 ROM 的字长扩展得到个 64k×864k\times8 ROM :

64kx4rom字长扩展64kx8rom

# 字容量扩展

514kx4ram字容量扩展1mx4ram

💡 利用译码器

# 字长字扩展结合

# 特殊存储器

# FIFO

FIFO

FIFO 寄存器模块的应用,实现数据整型:

FIFO应用

# LIFO

类似栈的效果,LIFO 寄存器结构:

LIFO结构

Edited on Views times
\ No newline at end of file +存储器 - 数字逻辑电路 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

两类主要的半导体存储器是 RAM 和 ROM。

  • RAM (随机访问存储器) 类型的存储器在等量时间内可以访问所有的地址,并且可以按照任何顺序来选择这些地址以执行读或者写操作。所有的 RAM 都具有读和写的能力。因为 RAM 在电源关闭时会丢失所存储的数据,所以它是易失性内存。 RAM 系列 RAM 的两种类别是静 RAM (SRAM) 和动态 RAM (DRAM) 。当直流电源移走后, SRAM 和 DRAM 都会丢失存储的数据,因此被归类为易失性存储器。
    • 静态 RAM 通常使用锁存器作为存储元件,因而只要加上直流电源,就可以永远地存储数据。
      • 异步 SRAM (ASRAM)
      • 同步 SRAM (SB SRAM),具有突发特性
    • 动态 RAM 使用电容作为存储元件,如果没有对电容再充电就不能长期存储数据,再充电则称为刷新过程。
      • 快速页模式 DRAM (FPMDRAM)
      • 扩充数据输出 DRAM (EDO DRAM)
      • 突发 EDO DRAM (BEDO DRAM)
      • 同步 DRAM (SDRAM)
  • ROM (只读存储器) 类型的存储器将永久或者半永久地保存数据。数据可以从 ROM 中读出,但是和 RAM 不同,它没有写操作。ROM 和 RAM 相似,也是随机存储器,但是术语 RAM 的 传统意思是随机读 / 写存储器。本章将会介绍几种类型的 RAM 和 ROM。因为 ROM 在电源关闭 后仍然保存着数据,所以它是永久性存储器
    • MROM (Mask ROM) —— 掩膜 ROM,出场时已经固定,不能更改,适合大量生产,简单,便宜,非易失性。
    • PROM —— 可一次性编程 ROM
    • EPROM —— 可擦除 PROM,也就是可多次编程
    • UV EPROM —— 紫外线版本的 EPROM
    • EEPROM —— 电版本的

对于给定的物理空间和成本,DRAM 可以存储比 SRAM 多得多的数据,因为 DRAM 单元更加简单,并在给定芯片面积里,因此可以比 SRAM 填充更多的单元

# RAM

# SRAM

SRAM 基本单元(是 D - 触发器 ):

sram单元

32k×832k\times8 SRAM

32kx8sram

逻辑组成如下:

32kx8sram逻辑图

读:

32kx8sram读

写:

32kx8sram写

# DRAM

DRAM 的基本单元,使用电容,电容充电表示 1 高电位,放电表示 0 低电位。

mosdram单元

DRAM 的 4 种基本操作:

mosdram单元基本操作

1M×11M\times1 DRAM 逻辑图:

1mx1dram逻辑图

DRAM 的读写周期:

dram读写周期

# ROM

ROM(Read Only Memory), 即只读存储器,由于其在掉电后数据不会丢失,因此在早期的时候,ROM 芯片中的内容一般都是在生产的时候被烧写进去的,然后终生具有这些固定的内容。不过,随着技术的不断发展和革新,现在很多型号的 ROM 都已经可以被多次修改了,但是大家仍然习惯对其沿用 “只读存储器” 的称号。

# MOS ROM

MOS ROM 基本单元:

mosrom单元

256x4rom

256x4rom逻辑图

# ROM 设计组合逻辑电路

实际上是枚举所有的输入输出,也就是真值表,存储到 ROM 里。

输入作为地址,通过地址译码器,输出相应地址的数据。

  • 有黑点⚫️表示存储 1 ;
  • 否则表示存储 0 ;

给出逻辑表达式(函数)时,求出标准的极小值只和的形式,依据极小值的下标确定画⚫️的位置

# PROM

PROM(Programmable Read Only Memory), 即可编程只读存储器,不过它也只能被程序写一次,以后就只能保存和使用这些数据了,所以 PROM 也称为一次可编程存储器。

# EPROM

EPROM(Erasable Programmable Read Only Memory),即可擦除可编程只读存储器。它解决了 PROM 只能编程一次的问题,不过其存储内容的擦除必须借助紫外线的长时间照射才能完成,所以 EPROM 又叫紫外线擦除可编程只读存储器。

# EEPROM

EEPROM(Electrically Erasable Programmable Read Only Memory),即电可擦除可编程只读存储器。它克服了 EPROM 在擦除时较为麻烦的问题,可以直接通过计算机程序对其进行重复的擦写,其擦除、重写的原理是通过使用高于常规的操作电压实现的。对于 EEPROM 来说,最重要的参数指标就是寿命问题,也就是可擦写的次数。

# 闪存

闪存 Flash Memory 是 EEPROM 的一种特殊形式,也就是变种。

EEPROM 的擦除和重写都是针对整个芯片而言的,但 Flash 的数据删除和重写则是以块(块的容量一般在 256KB~20MB 之间)为单位的,因此 Flash 的更新速度要远比 EEPROM 快。不过由于数据的删除和重写不是以单个字节为单位的,因此 Flash 仍不能达到 RAM 的要求。

Flash 又分为 NOR 型和 NAND 型两个大类,其中 NOR 型具有独立的地址线和数据线,适合频繁的随机读、写场合,适合程序代码的存储和直接运行,但容量通常较小,价格也比较贵;而 NAND 型的地址线和数据线是公用的,因此其本身的操作速度和频率就会偏低,但是容量相对较大,且价格也要便宜,所以适合大量资料的存储。

# 存储器扩展

# 字长扩展

共享数据线和控制线,并联数据线。

2 个 64k×464k\times4 ROM 的字长扩展得到个 64k×864k\times8 ROM :

64kx4rom字长扩展64kx8rom

# 字容量扩展

514kx4ram字容量扩展1mx4ram

💡 利用译码器

# 字长字扩展结合

# 特殊存储器

# FIFO

FIFO

FIFO 寄存器模块的应用,实现数据整型:

FIFO应用

# LIFO

类似栈的效果,LIFO 寄存器结构:

LIFO结构

Edited on Views times
\ No newline at end of file diff --git a/ie/de/numerical-system/index.html b/ie/de/numerical-system/index.html index b1b54956..d6b71553 100644 --- a/ie/de/numerical-system/index.html +++ b/ie/de/numerical-system/index.html @@ -1 +1 @@ -数制 - 数字逻辑电路 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 数制

# 数制的概念

数制 (numerical system),又称 “计数制”,指用一组固定的符号和统一的规则来表示数值的方法;

数制关注的内容:每一位的构成(使用什么符号即数码)和进位的规则;

基本概念:

  • 基数 —— 使用的数码的个数,即每一位最多能用多少个符号来表示;基数是 N 则称为 N 进制, 即 “逢 N 进一”
  • 权 —— 每一位的 1 代表的大小;

# 常用数制

常用数制

# 不同进制的转换

# 其他进制 -> 十进制

只需要按照 D=kiNiD=\sum k_i N^i 展开即可;

  • kik_i 为第 i 位的系数
  • NiN^i 为第 i 位的权
  • NN 为基数

# 十进制 -> 二进制

# 整数部分

反复除 2 取余数,倒排(从右向左排列)(从低位到高位排列);

# 小数部分

反复乘 2 取整数部分,正排(从左向右排列)(从高位到低位排列);

# 二进制 -> 十六进制

# 整数部分

从右向左(从低位到高位)每四个划为一组(不够的在左边补 0 ),

# 小数部分

从左向右(从高位到低位)每四个划为一组(不够的在右边补 0 );

# 二进制 -> 八进制

# 整数部分

从右向左(从低位到高位)每三个划为一组(不够的在左边补 0 ),

# 小数部分

从左向右(从高位到低位)每三个划为一组(不够的在右边补 0 );

# 十六进制 -> 二进制

将每一位用对应的四位二进制数代替即可

# 八进制 -> 二进制

将每一位用对应的三位二进制数代替即可

# 十进制 -> 八进制、十六进制

先转换为二进制,再将二进制转换为八进制、十六进制

# 八进制 <-> 十六进制

先转换为二进制,再将二进制转换为目标进制

# 二进制

# 二进制算术运算

特点:

  • 和十进制算数运算的规则基本相同,区别在于 “逢二进一”
  • 乘法和除法可以转化为移位操作与加减操作
  • 通过补码运算(即将引入的概念),可以将减法运算转换为加法运算;

因此,数字电路普遍采用二进制进行算术运算

Edited on Views times
\ No newline at end of file +数制 - 数字逻辑电路 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 数制

# 数制的概念

数制 (numerical system),又称 “计数制”,指用一组固定的符号和统一的规则来表示数值的方法;

数制关注的内容:每一位的构成(使用什么符号即数码)和进位的规则;

基本概念:

  • 基数 —— 使用的数码的个数,即每一位最多能用多少个符号来表示;基数是 N 则称为 N 进制, 即 “逢 N 进一”
  • 权 —— 每一位的 1 代表的大小;

# 常用数制

常用数制

# 不同进制的转换

# 其他进制 -> 十进制

只需要按照 D=kiNiD=\sum k_i N^i 展开即可;

  • kik_i 为第 i 位的系数
  • NiN^i 为第 i 位的权
  • NN 为基数

# 十进制 -> 二进制

# 整数部分

反复除 2 取余数,倒排(从右向左排列)(从低位到高位排列);

# 小数部分

反复乘 2 取整数部分,正排(从左向右排列)(从高位到低位排列);

# 二进制 -> 十六进制

# 整数部分

从右向左(从低位到高位)每四个划为一组(不够的在左边补 0 ),

# 小数部分

从左向右(从高位到低位)每四个划为一组(不够的在右边补 0 );

# 二进制 -> 八进制

# 整数部分

从右向左(从低位到高位)每三个划为一组(不够的在左边补 0 ),

# 小数部分

从左向右(从高位到低位)每三个划为一组(不够的在右边补 0 );

# 十六进制 -> 二进制

将每一位用对应的四位二进制数代替即可

# 八进制 -> 二进制

将每一位用对应的三位二进制数代替即可

# 十进制 -> 八进制、十六进制

先转换为二进制,再将二进制转换为八进制、十六进制

# 八进制 <-> 十六进制

先转换为二进制,再将二进制转换为目标进制

# 二进制

# 二进制算术运算

特点:

  • 和十进制算数运算的规则基本相同,区别在于 “逢二进一”
  • 乘法和除法可以转化为移位操作与加减操作
  • 通过补码运算(即将引入的概念),可以将减法运算转换为加法运算;

因此,数字电路普遍采用二进制进行算术运算

Edited on Views times
\ No newline at end of file diff --git a/ie/de/sequential-circuit/index.html b/ie/de/sequential-circuit/index.html index 6cd45de4..216c7f37 100644 --- a/ie/de/sequential-circuit/index.html +++ b/ie/de/sequential-circuit/index.html @@ -1 +1 @@ -时序逻辑电路 - 数字逻辑电路 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 基础元件

# 555 Timer

可能会考哦

mono-stable one-shot (单稳态触发器)

555-单稳态触发器
非稳态延续时间:

tw=1.1R1C1t_w=1.1R_1C_1

astable multi-vibration oscillator (非稳态多谐振荡器)

555-振荡器

tH=0.7R1C1tL=1.4R2C1t_H=0.7R_1C_1\\ t_L=1.4R_2C_1

频率:

f=1.44(R1+2R2)C1f=\frac{1.44}{(R_1+2R_2)C_1}\\

占空比(Duty Cycle)DCDC(非空 / 周期):

DC=(R1+R2R1+2R2)100%DC=\big(\frac{R_1+R_2}{R_1+2R_2}\big)100\%

上述公式中 DC>12DC\gt\frac{1}{2},若要设计 50% 占空比的振荡器,如下图所示:

tH=0.7R1C1tL=0.7R2C1t_H=0.7R_1C_1\\ t_L=0.7R_2C_1

50%占空比

# S-R 触发器

Qn+1=S+RQnQ^{n+1}=S+\overline{R}Q^{n}

# D 触发器

Q=DQ'=D

GATEGATE 高电平有效使能:

Qn+1=GATED+GATEQnQ^{n+1}=GATE\cdot D+\overline{GATE}\cdot Q^{n}

# ⭐️J-K 触发器

Qn+1=JQn+QnKQ^{n+1}=J\overline{Q^{n}}+Q^{n}\overline{K}

JK

# 设计

# 思路一

  1. State Diagram 状态转移图
    • 有多少状态决定使用多少触发器,nn 个状态应使用 log2n\lceil\log_2n\rceil
  2. Next-State Table 次态表(状态转移表)
  3. Flip-Flop Transition Table 触发器转换表,由触发器特性方程决定
  4. Karnaugh Maps 根据次态表、触发器转换表画出卡诺图
  5. Locgi Expressions for Flip-Flop Inputs 根据卡诺图化简得到逻辑表达式
  6. Counter Implementation 根据逻辑表达式设计逻辑电路

# 思路二

每一个输入也要视为一个状态位(类似于 QQ )来画卡诺图

卡诺图每一个格子内容为:

Q3n+1Q2n+1Q1n+1Q0n+1/CQ^{n+1}_3Q^{n+1}_2Q^{n+1}_1Q^{n+1}_0/C

对于不可能的情况,也就是无关项,那么 5 个值统一为 X ,也就是:XXXX/XXXXX/X

将内容拆开,则对应地画出 5 个卡诺图,然后分别化简,则能够得到:

  • 4 个状态 (转移) 方程
  • 1 个状态输出方程

再根据选定的触发器的特性方程,则可以写出各个触发器的各个输入的驱动方程以及输出方程

在一些芯片上,计数使能被简单地标记为 CTEN (或者一些诸如 G 之类的其他名称), 终端计数 (TC) 和一些 IC 计数器上的异步 (行波) 时钟输出 (RCO) 比较相似

一些计数器:

  • 74HC161 十六进制计数器
  • 74HC190 十进制计数器
\ No newline at end of file +时序逻辑电路 - 数字逻辑电路 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 基础元件

# 555 Timer

可能会考哦

mono-stable one-shot (单稳态触发器)

555-单稳态触发器
非稳态延续时间:

tw=1.1R1C1t_w=1.1R_1C_1

astable multi-vibration oscillator (非稳态多谐振荡器)

555-振荡器

tH=0.7R1C1tL=1.4R2C1t_H=0.7R_1C_1\\ t_L=1.4R_2C_1

频率:

f=1.44(R1+2R2)C1f=\frac{1.44}{(R_1+2R_2)C_1}\\

占空比(Duty Cycle)DCDC(非空 / 周期):

DC=(R1+R2R1+2R2)100%DC=\big(\frac{R_1+R_2}{R_1+2R_2}\big)100\%

上述公式中 DC>12DC\gt\frac{1}{2},若要设计 50% 占空比的振荡器,如下图所示:

tH=0.7R1C1tL=0.7R2C1t_H=0.7R_1C_1\\ t_L=0.7R_2C_1

50%占空比

# S-R 触发器

Qn+1=S+RQnQ^{n+1}=S+\overline{R}Q^{n}

# D 触发器

Q=DQ'=D

GATEGATE 高电平有效使能:

Qn+1=GATED+GATEQnQ^{n+1}=GATE\cdot D+\overline{GATE}\cdot Q^{n}

# ⭐️J-K 触发器

Qn+1=JQn+QnKQ^{n+1}=J\overline{Q^{n}}+Q^{n}\overline{K}

JK

# 设计

# 思路一

  1. State Diagram 状态转移图
    • 有多少状态决定使用多少触发器,nn 个状态应使用 log2n\lceil\log_2n\rceil
  2. Next-State Table 次态表(状态转移表)
  3. Flip-Flop Transition Table 触发器转换表,由触发器特性方程决定
  4. Karnaugh Maps 根据次态表、触发器转换表画出卡诺图
  5. Locgi Expressions for Flip-Flop Inputs 根据卡诺图化简得到逻辑表达式
  6. Counter Implementation 根据逻辑表达式设计逻辑电路

# 思路二

每一个输入也要视为一个状态位(类似于 QQ )来画卡诺图

卡诺图每一个格子内容为:

Q3n+1Q2n+1Q1n+1Q0n+1/CQ^{n+1}_3Q^{n+1}_2Q^{n+1}_1Q^{n+1}_0/C

对于不可能的情况,也就是无关项,那么 5 个值统一为 X ,也就是:XXXX/XXXXX/X

将内容拆开,则对应地画出 5 个卡诺图,然后分别化简,则能够得到:

  • 4 个状态 (转移) 方程
  • 1 个状态输出方程

再根据选定的触发器的特性方程,则可以写出各个触发器的各个输入的驱动方程以及输出方程

在一些芯片上,计数使能被简单地标记为 CTEN (或者一些诸如 G 之类的其他名称), 终端计数 (TC) 和一些 IC 计数器上的异步 (行波) 时钟输出 (RCO) 比较相似

一些计数器:

  • 74HC161 十六进制计数器
  • 74HC190 十进制计数器
\ No newline at end of file diff --git a/ie/de/shift-register/index.html b/ie/de/shift-register/index.html index 21d7c5a7..16d10b51 100644 --- a/ie/de/shift-register/index.html +++ b/ie/de/shift-register/index.html @@ -1 +1 @@ -移位寄存器 - 数字逻辑电路 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 串行输入 / 串行输出

串行输入:串行输出

# 串行输入 / 并行输出

串行输入:并行输出

# 并行输入 / 串行输出

并行输入:串行输出

# 并行输入 / 并行输出

最简单

# 双向移位寄存器

4位双向位移

# 74HC194

通用 4 位双向移位寄存器

74HC194

74HC94波形图

# 移位寄存器计数器

# 约翰逊计数器

约翰逊计数器

约翰逊计数器波形图

一般来说,约翰逊计 数器将会产生模 2n2n ,其中 nn 是计数器中级的个数

# 环形计数器

环形计数器

环形计数器波形图

# 移位寄存器应用

# 精确延时控制

串行输入 / 串行输出移位寄存器可以用来提供从输入到输出的时间延迟,此时间延迟是寄存器中数 nn 和时钟频率的函数

从一个数字系统到另一个数字系统的串行数据传送,常常用来减少传输线中的导线数

8位串并转换器

当没有数据被传送时,串行数据线上就会有连续的 1 存在 ,0 位就是数据起始位,告诉串并转换器即将有 8 位数据序列到来:

8位串并转换器数据串格式

详细波形图解释工作流程如下:

8位串并转换器波形图

Edited on Views times
\ No newline at end of file +移位寄存器 - 数字逻辑电路 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 串行输入 / 串行输出

串行输入:串行输出

# 串行输入 / 并行输出

串行输入:并行输出

# 并行输入 / 串行输出

并行输入:串行输出

# 并行输入 / 并行输出

最简单

# 双向移位寄存器

4位双向位移

# 74HC194

通用 4 位双向移位寄存器

74HC194

74HC94波形图

# 移位寄存器计数器

# 约翰逊计数器

约翰逊计数器

约翰逊计数器波形图

一般来说,约翰逊计 数器将会产生模 2n2n ,其中 nn 是计数器中级的个数

# 环形计数器

环形计数器

环形计数器波形图

# 移位寄存器应用

# 精确延时控制

串行输入 / 串行输出移位寄存器可以用来提供从输入到输出的时间延迟,此时间延迟是寄存器中数 nn 和时钟频率的函数

从一个数字系统到另一个数字系统的串行数据传送,常常用来减少传输线中的导线数

8位串并转换器

当没有数据被传送时,串行数据线上就会有连续的 1 存在 ,0 位就是数据起始位,告诉串并转换器即将有 8 位数据序列到来:

8位串并转换器数据串格式

详细波形图解释工作流程如下:

8位串并转换器波形图

Edited on Views times
\ No newline at end of file diff --git a/ie/signals-and-systems/CTFT/index.html b/ie/signals-and-systems/CTFT/index.html index 9c7b0b53..97cddddc 100644 --- a/ie/signals-and-systems/CTFT/index.html +++ b/ie/signals-and-systems/CTFT/index.html @@ -1,4 +1,4 @@ -连续时间信号的傅里叶变换 - 信号与系统 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 公式表

# 傅里叶变换性质

傅里叶变换性质1傅里叶变换性质2

# 基本傅里叶变换对

基本傅里叶变换对表

连续时间非周期信号傅里叶变换的推导基本思想

  • 非周期函数可以通过周期性延拓得到周期函数
  • 周期函数可以令基波周期趋于无穷大得到连续的非周期函数

对于周期性矩形脉冲信号:

ak=2T1TSa(kπ2T1T)Tak=2T1Sa(ωT1)\begin{aligned} a_k &= \frac{2T_1}{T}\text{Sa}(k\pi\frac{2T_1}{T})\\ Ta_k &= 2T_1\text{Sa}(\omega T_1) \end{aligned}

其中:ω=kω0=2kπT\omega=k\omega_0=\frac{2k\pi}{T}

两点之间的距离:

Δω=(k+1)ω0kω0=ω0=2πT\Delta\omega=(k+1)\omega_0-k\omega_0=\omega_0=\frac{2\pi}{T}

TT\to\infin 时有 ω0=2πT0\omega_0=\frac{2\pi}{T}\to 0 ,即两点之间距离趋于 0 ,函数包络线趋于连续函数。

# 非周期信号

# FT 公式推导

连续时间非周期信号傅里叶变换的推导

连续时间非周期信号傅里叶变换的推导

周期函数 x~(t)\tilde{x}(t) 以 T 为周期,在 [T2,T2][-\frac{T}{2},\frac{T}{2}] 内与 x(t)x(t) 相等,它的傅里叶级数表示为:

x~(t)=k=+akejkω0t\tilde{x}(t)=\sum_{k=-\infin}^{+\infin}a_k e^{jk\omega_0 t}

波浪号表示周期性

TT\to\infin 时,在 (,)(-\infin,\infin)x~(t)=x(t)\tilde{x}(t)=x(t)

ak=1TT2T2x~(t)ejkω0tdt=1TT2T2x(t)ejkω0tdt=1Tx(t)ejkω0tdt\begin{aligned} a_k &= \frac{1}{T}{\int}_{-\frac{T}{2}}^{\frac{T}{2}} \tilde{x}(t) e^{-jk\omega_0 t}dt\\ &= \frac{1}{T}{\int}_{-\frac{T}{2}}^{\frac{T}{2}} x(t) e^{-jk\omega_0 t}dt\\ &= \frac{1}{T}{\int}_{-\infin}^{\infin} x(t) e^{-jk\omega_0 t}dt\\ \end{aligned}

定义频谱:(傅里叶正变换)

X(jω)=x(t)ejkω0tdtX(j\omega)={\int}_{-\infin}^{\infin} x(t) e^{-jk\omega_0 t}dt

从而 aka_k 可以表示为:

ak=1TX(jkω0)a_k=\frac{1}{T}X(jk\omega_0)

因此,在 [T2,T2][-\frac{T}{2},\frac{T}{2}] 内有:

x(t)=x~(t)=k=+akejkω0t=1Tk=+X(jkω0)ejkω0t=12πk=+X(jkω0)ejkω0tω0=12πk=+X(jω)ejωtΔω\begin{aligned} x(t)=\tilde{x}(t) &= \sum_{k=-\infin}^{+\infin} a_k e^{jk\omega_0 t}\\ &= \frac{1}{T} \sum_{k=-\infin}^{+\infin} X(jk\omega_0) e^{jk\omega_0 t}\\ &= \frac{1}{2\pi} \sum_{k=-\infin}^{+\infin} X(jk\omega_0) e^{jk\omega_0 t}\omega_0\\ &= \frac{1}{2\pi} \sum_{k=-\infin}^{+\infin} X(j\omega) e^{j\omega t}\Delta\omega\\ \end{aligned}

TT\to\infin 时,Δω=ω00\Delta\omega=\omega_0\to0,即 Δωdω\Delta\omega\to d\omega 则得到(傅里叶反变换):

x(t)=x~(t)=12π+X(jω)ejωtdω\begin{aligned} x(t)=\tilde{x}(t) &= \frac{1}{2\pi} \int_{-\infin}^{+\infin} X(j\omega) e^{j\omega t}d\omega\\ \end{aligned}

从而得到傅里叶变换对

这两个公式是 “一对” 的,要么同时可积,要么都不可积

傅里叶正变换,分析公式,(ejωte^{j\omega t} 的线性组合)

X(jω)=x(t)ejωtdtX(j\omega)={\int}_{-\infin}^{\infin} x(t) e^{-j\omega t}dt

傅里叶反变换,综合公式,(获得 x(t)x(t) 的频谱)

x(t)=12π+X(jω)ejωtdω\begin{aligned} x(t)=\frac{1}{2\pi} \int_{-\infin}^{+\infin} X(j\omega) e^{j\omega t}d\omega\\ \end{aligned}

可以表示为:

x(t)CTFTX(jω)F{x(t)}=X(jω)x(t)\stackrel{CTFT}{\longleftrightarrow}X(j\omega)\\\\ \mathscr{F}\{x(t)\}=X(j\omega)

周期信号傅里叶级数的系数为其一个周期内信号傅里叶变换的等间隔采样:

{x(t)X(jω)x~(t)akak=1TX(jkω0)\begin{cases} x(t)\lrarr X(j\omega)\\ \tilde{x}(t)\lrarr a_k \end{cases} \rArr a_k=\frac{1}{T}X(jk\omega_0)

# 收敛性

既然傅里叶变换是从周期信号的傅里叶级数引出的,傅里叶变换的收敛问题就应该和傅里叶级数的收敛相一致。所以也有对应的两组条件;同样地两组条件并不完全等价。它们都是傅里叶变换存在的充分条件。

和周期信号的情况一样,当 x(t)x(t) 的傅里叶变换 X(jω)X(j\omega) 存在时,其反变换在间断点附近会产生 Gibbs 现象

# 平方可积条件

# Dirichlet 条件

# 常见信号的 FT

# 低通信号 (单侧)

低通信号(单侧)1

x(t)=eatu(t),a>0x(t)=e^{-at}u(t),\ \ \ a\gt0

有正变换:

X(jω)=0+eatejωtdt=1a+jωX(jω)=1a2+ω2ddωX(jω)=arctanωa\begin{aligned} X(j\omega) &=\int_{0}^{+\infin}e^{-at}e^{-j\omega t}dt=\frac{1}{a+j\omega}\\ |X(j\omega)| &=\frac{1}{\sqrt{a^2+\omega^2}}\\ \frac{d}{d\omega}|X(j\omega)| &=-\arctan\frac{\omega}{a} \end{aligned}

# 公式表

# 傅里叶变换性质

傅里叶变换性质1傅里叶变换性质2

# 基本傅里叶变换对

基本傅里叶变换对表

连续时间非周期信号傅里叶变换的推导基本思想

  • 非周期函数可以通过周期性延拓得到周期函数
  • 周期函数可以令基波周期趋于无穷大得到连续的非周期函数

对于周期性矩形脉冲信号:

ak=2T1TSa(kπ2T1T)Tak=2T1Sa(ωT1)\begin{aligned} a_k &= \frac{2T_1}{T}\text{Sa}(k\pi\frac{2T_1}{T})\\ Ta_k &= 2T_1\text{Sa}(\omega T_1) \end{aligned}

其中:ω=kω0=2kπT\omega=k\omega_0=\frac{2k\pi}{T}

两点之间的距离:

Δω=(k+1)ω0kω0=ω0=2πT\Delta\omega=(k+1)\omega_0-k\omega_0=\omega_0=\frac{2\pi}{T}

TT\to\infin 时有 ω0=2πT0\omega_0=\frac{2\pi}{T}\to 0 ,即两点之间距离趋于 0 ,函数包络线趋于连续函数。

# 非周期信号

# FT 公式推导

连续时间非周期信号傅里叶变换的推导

连续时间非周期信号傅里叶变换的推导

周期函数 x~(t)\tilde{x}(t) 以 T 为周期,在 [T2,T2][-\frac{T}{2},\frac{T}{2}] 内与 x(t)x(t) 相等,它的傅里叶级数表示为:

x~(t)=k=+akejkω0t\tilde{x}(t)=\sum_{k=-\infin}^{+\infin}a_k e^{jk\omega_0 t}

波浪号表示周期性

TT\to\infin 时,在 (,)(-\infin,\infin)x~(t)=x(t)\tilde{x}(t)=x(t)

ak=1TT2T2x~(t)ejkω0tdt=1TT2T2x(t)ejkω0tdt=1Tx(t)ejkω0tdt\begin{aligned} a_k &= \frac{1}{T}{\int}_{-\frac{T}{2}}^{\frac{T}{2}} \tilde{x}(t) e^{-jk\omega_0 t}dt\\ &= \frac{1}{T}{\int}_{-\frac{T}{2}}^{\frac{T}{2}} x(t) e^{-jk\omega_0 t}dt\\ &= \frac{1}{T}{\int}_{-\infin}^{\infin} x(t) e^{-jk\omega_0 t}dt\\ \end{aligned}

定义频谱:(傅里叶正变换)

X(jω)=x(t)ejkω0tdtX(j\omega)={\int}_{-\infin}^{\infin} x(t) e^{-jk\omega_0 t}dt

从而 aka_k 可以表示为:

ak=1TX(jkω0)a_k=\frac{1}{T}X(jk\omega_0)

因此,在 [T2,T2][-\frac{T}{2},\frac{T}{2}] 内有:

x(t)=x~(t)=k=+akejkω0t=1Tk=+X(jkω0)ejkω0t=12πk=+X(jkω0)ejkω0tω0=12πk=+X(jω)ejωtΔω\begin{aligned} x(t)=\tilde{x}(t) &= \sum_{k=-\infin}^{+\infin} a_k e^{jk\omega_0 t}\\ &= \frac{1}{T} \sum_{k=-\infin}^{+\infin} X(jk\omega_0) e^{jk\omega_0 t}\\ &= \frac{1}{2\pi} \sum_{k=-\infin}^{+\infin} X(jk\omega_0) e^{jk\omega_0 t}\omega_0\\ &= \frac{1}{2\pi} \sum_{k=-\infin}^{+\infin} X(j\omega) e^{j\omega t}\Delta\omega\\ \end{aligned}

TT\to\infin 时,Δω=ω00\Delta\omega=\omega_0\to0,即 Δωdω\Delta\omega\to d\omega 则得到(傅里叶反变换):

x(t)=x~(t)=12π+X(jω)ejωtdω\begin{aligned} x(t)=\tilde{x}(t) &= \frac{1}{2\pi} \int_{-\infin}^{+\infin} X(j\omega) e^{j\omega t}d\omega\\ \end{aligned}

从而得到傅里叶变换对

这两个公式是 “一对” 的,要么同时可积,要么都不可积

傅里叶正变换,分析公式,(ejωte^{j\omega t} 的线性组合)

X(jω)=x(t)ejωtdtX(j\omega)={\int}_{-\infin}^{\infin} x(t) e^{-j\omega t}dt

傅里叶反变换,综合公式,(获得 x(t)x(t) 的频谱)

x(t)=12π+X(jω)ejωtdω\begin{aligned} x(t)=\frac{1}{2\pi} \int_{-\infin}^{+\infin} X(j\omega) e^{j\omega t}d\omega\\ \end{aligned}

可以表示为:

x(t)CTFTX(jω)F{x(t)}=X(jω)x(t)\stackrel{CTFT}{\longleftrightarrow}X(j\omega)\\\\ \mathscr{F}\{x(t)\}=X(j\omega)

周期信号傅里叶级数的系数为其一个周期内信号傅里叶变换的等间隔采样:

{x(t)X(jω)x~(t)akak=1TX(jkω0)\begin{cases} x(t)\lrarr X(j\omega)\\ \tilde{x}(t)\lrarr a_k \end{cases} \rArr a_k=\frac{1}{T}X(jk\omega_0)

# 收敛性

既然傅里叶变换是从周期信号的傅里叶级数引出的,傅里叶变换的收敛问题就应该和傅里叶级数的收敛相一致。所以也有对应的两组条件;同样地两组条件并不完全等价。它们都是傅里叶变换存在的充分条件。

和周期信号的情况一样,当 x(t)x(t) 的傅里叶变换 X(jω)X(j\omega) 存在时,其反变换在间断点附近会产生 Gibbs 现象

# 平方可积条件

# Dirichlet 条件

# 常见信号的 FT

# 低通信号 (单侧)

低通信号(单侧)1

x(t)=eatu(t),a>0x(t)=e^{-at}u(t),\ \ \ a\gt0

有正变换:

X(jω)=0+eatejωtdt=1a+jωX(jω)=1a2+ω2ddωX(jω)=arctanωa\begin{aligned} X(j\omega) &=\int_{0}^{+\infin}e^{-at}e^{-j\omega t}dt=\frac{1}{a+j\omega}\\ |X(j\omega)| &=\frac{1}{\sqrt{a^2+\omega^2}}\\ \frac{d}{d\omega}|X(j\omega)| &=-\arctan\frac{\omega}{a} \end{aligned}

低通信号(单侧)2

低通信号(单侧)3

# 低通信号 (双侧)

低通信号(双侧)1

x(t)=eat,a>0x(t)=e^{-a|t|},\ \ \ a\gt0

有正变换:

X(jω)=0eatejωtdt+0+eatejωtdt=1ajω+1a+jω=2aa2+ω2X(jω)=X(jω)\begin{aligned} X(j\omega) &=\int_{-\infin}^{0}e^{at}e^{-j\omega t}dt +\int_{0}^{+\infin}e^{-at}e^{-j\omega t}dt\\ &=\frac{1}{a-j\omega}+\frac{1}{a+j\omega}\\ &= \frac{2a}{a^2+\omega^2}\\ \\ |X(j\omega)| &= X(j\omega)\\ \end{aligned}

低通信号(双侧)2

# 冲激信号

x(t)=δ(t)x(t)=\delta(t)

有正变换:

X(jω)=+δ(t)ejωtdt=1X(j\omega)=\int_{-\infin}^{+\infin}\delta(t)e^{-j\omega t}dt=1

冲激信号正变换

这表明 δ(t)\delta(t) 中包括了所有的频率成分,且所有频率分量的幅度、相位都相同。因此,系统的单位冲激响应 h(t)h(t) 才能完全描述一个 LTI 系统的特性,δ(t)\delta(t) 才在信号与系统分析中具有如此重要的意义。

# 常数信号

* 这个名字我乱起的

x(t)=1x(t)=1

因为:

12π+2πδ(ω)ejωtdω=1\begin{aligned} \frac{1}{2\pi} \int_{-\infin}^{+\infin} 2\pi\ \delta(\omega)\ e^{j\omega t}d\omega = 1 \end{aligned}

所以有反变换:

X(jω)=2πδ(ω)\begin{aligned} X(j\omega) &= 2\pi\delta(\omega) \end{aligned}


冲激信号和双侧阶跃信号 (我乱起名) 的对偶关系:

δ(t)F1F2πδ(ω)\delta(t)\stackrel{F}{\longleftrightarrow}1\stackrel{F}{\longleftrightarrow}2\pi\delta(\omega)

# 矩形信号

矩形信号

x(t)={1,t<T10,t>T1x(t)= \begin{cases} 1,\ \ \ |t|\lt T_1\\ 0,\ \ \ |t|\gt T_1 \end{cases}

有正变换:

X(jω)=T1T1ejωtdt=2sinωT1ω=2T1sinωT1ωT1=2T1Sa(ωT1)=2T1sinc(ωT1π)ak=X(jω)T=2T1TSa(kω0T1)=2T1TSa(2T1T)\begin{aligned} X(j\omega) &=\int_{-T_1}^{T_1} e^{-j\omega t}dt\\ &=\frac{2\sin{\omega T_1}}{\omega}\\ &=\frac{2T_1\sin{\omega T_1}}{\omega T_1}\\ &=2T_1\text{Sa}(\omega T_1) = 2T_1\text{sinc}(\frac{\omega T_1}{\pi})\\\\ a_k = \frac{X(j\omega)}{T} &= \frac{2T_1}{T}\text{Sa}(k\omega_0 T_1) = \frac{2T_1}{T}\text{Sa}(\frac{2T_1}{T}) \end{aligned}

不同脉冲宽度对频谱的影响:

不同脉冲宽度对矩形信号频谱的影响

可见,信号宽度在时域和频域之间有一种相反的关系。

# 采样信号

X(jω)={1,ω<W0,ω>WX(j\omega)= \begin{cases} 1,\ \ \ |\omega|\lt W\\ 0,\ \ \ |\omega|\gt W \end{cases}

有反变换:

x(t)=12πW+Wejωtdω=sinWtπt=WπSa(Wt)=WπSa(Wtπ)\begin{aligned} x(t) &= \frac{1}{2\pi}\int_{-W}^{+W} e^{-j\omega t}d\omega\\ &=\frac{\sin{Wt}}{\pi t}\\ &= \frac{W}{\pi}\text{Sa}(Wt) = \frac{W}{\pi}\text{Sa}(\frac{Wt}{\pi}) \end{aligned}

采样信号

可见 x(t)x(t) 是采样信号


矩形信号和采样信号的对偶关系:(上矩形信号、下采样信号)

矩形信号和采样信号对偶关系

# 周期信号

TakTa_k 无论在 TT 有限还是无限的时候都可以是有限的,所以我们可以将 TT 有限时的周期信号和 TT 无限时的非周期信号用傅里叶变换统一起来

但是 aka_k 却不是,所以我们无法将周期信号和非周期信号都用傅里叶级数表示。

# FT 公式推导

考虑 X(jω)=2πδ(ωω0)X(j\omega)=2\pi\delta(\omega-\omega_0) 所对应的信号:

x(t)=12π+X(jω)ejωtdω=+δ(ωω0)ejωtdω=ejω0t\begin{aligned} x(t) &=\frac{1}{2\pi} \int_{-\infin}^{+\infin} X(j\omega)\ e^{j\omega t}d\omega\\ &=\int_{-\infin}^{+\infin} \delta(\omega-\omega_0)\ e^{j\omega t}d\omega\\ &= e^{j\omega_0 t} \end{aligned}

于是对于表示为傅里叶级数的周期信号 x(t)x(t)

x(t)=k=+akejkω0tx(t)=\sum_{k=-\infin}^{+\infin}a_k\ e^{jk\omega_0 t}

就有频谱正变换

X(jω)=2πk=+akδ(ωω0)X(j\omega)=2\pi \sum_{k=-\infin}^{+\infin} a_k\ \delta(\omega-\omega_0)

这表明周期信号的傅里叶正变换由一系列位于谐波频率处的冲激组成,其中 kω0k\omega_0 处的冲激强度为对应傅里叶级数系数 aka_k2π2\pi 倍。

# 常见信号的 FT

# 正弦信号

x(t)=sin(ω0t)=12j(ejω0tejω0t)x(t)=\sin(\omega_0 t)=\frac{1}{2j}(e^{j\omega_0 t}-e^{-j\omega_0 t})

有正变换:

X(jω)=πj[δ(ωω0)δ(ω+ω0)]X(j\omega)=\frac{\pi}{j}[\delta(\omega-\omega_0)-\delta(\omega+\omega_0)]

正弦信号

# 余弦信号

x(t)=cos(ω0t)=12(ejω0t+ejω0t)x(t)=\cos(\omega_0 t)=\frac{1}{2}(e^{j\omega_0 t}+e^{-j\omega_0 t})

有正变换:

X(jω)=π[δ(ωω0)+δ(ω+ω0)]X(j\omega)=\pi[\delta(\omega-\omega_0)+\delta(\omega+\omega_0)]

余弦信号

# 均匀冲激串

x(t)=n=+δ(tnT)x(t)=\sum_{n=-\infin}^{+\infin}\delta(t-nT)

其中 T=2πω0T=\frac{2\pi}{\omega_0}

其傅里叶系数:

ak=1TT2T2δ(t)ej2πTktdt=1TT2T2δ(t)dt=1T\begin{aligned} a_k &=\frac{1}{T}\int_{-\frac{T}{2}}^{\frac{T}{2}}\delta(t)\ e^{-j\frac{2\pi}{T}kt}dt\\ &=\frac{1}{T}\int_{-\frac{T}{2}}^{\frac{T}{2}}\delta(t)dt\\ &=\frac{1}{T} \end{aligned}

可得傅里叶正变换:

X(jω)=2πTk=+δ(ω2πTk)X(j\omega)=\frac{2\pi}{T}\sum_{k=-\infin}^{+\infin}\delta(\omega-\frac{2\pi}{T}k)

均匀冲激串

# 周期性矩形脉冲

其傅里叶系数:

ak=2T1TSa(πk2T1T)a_k=\frac{2T_1}{T}\text{Sa}(\pi k\frac{2T_1}{T})

有傅里叶正变换:

X(jω)=4πT1Tk=+Sa(πk2T1T)δ(ω2πTk)=2T1ω0k=+Sa(ω0T1k)δ(ωω0k)X(j\omega)=\frac{4\pi T_1}{T}\sum_{k=-\infin}^{+\infin}\text{Sa}(\pi k\frac{2T_1}{T})\ \delta(\omega-\frac{2\pi}{T}k) =2T_1\omega_0\sum_{k=-\infin}^{+\infin}\text{Sa}(\omega_0T_1\cdot k)\ \delta(\omega-\omega_0\cdot k)

其中 ω0=2πT\omega_0=\frac{2\pi}{T} 为谱线间隔。

# 特殊信号 FT

# 符号函数

符号函数

可以将符号函数定义为:

Sgn(t)=lima0[eatu(t)eatu(t)]\text{Sgn}(t)=\lim_{a\to0}[e^{-at}u(t)-e^{at}u(-t)]

其傅里叶变换为:

F{Sgn(t)}=lima0[1a+jω1ajω]=lima0j2ωa2+(jω)2=2jω\begin{aligned} \mathscr{F}\{\text{Sgn}(t)\} &=\lim_{a\to0}[\frac{1}{a+j\omega}-\frac{1}{a-j\omega}]\\ &=\lim_{a\to0}\frac{-j2\omega}{a^2+(j\omega)^2}\\ &=\frac{2}{j\omega} \end{aligned}

# 单位阶跃函数

u(t)u(t) 分解为偶部和奇部有:

u(t)=ue(t)+uo(t)ue(t)=12uo(t)=12Sgn(t)\begin{aligned} &u(t)=u_e(t)+u_o(t)\\ &u_e(t)=\frac{1}{2}\\ &u_o(t)=\frac{1}{2}\text{Sgn}(t) \end{aligned}

1CTFT2πδ(ω)1\stackrel{CTFT}{\longleftrightarrow}2\pi\delta(\omega)Sgn(t)CTFT2jω\text{Sgn}(t)\stackrel{CTFT}{\longleftrightarrow}\frac{2}{j\omega} ,因此有:

u(t)F1jω+πδ(ω)u(t)\stackrel{F}{\longleftrightarrow}\frac{1}{j\omega}+\pi\delta(\omega)

# 性质

# 线性

x(t)FX(jω),y(t)FY(jω)ax(t)+by(t)FaX(jω)+bY(jω)x(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\ \ ,\ \ y(t)\stackrel{F}{\longleftrightarrow}Y(j\omega)\\ \dArr\\ ax(t)+by(t)\stackrel{F}{\longleftrightarrow}aX(j\omega)+bY(j\omega)

# 时移特性

信号的时移会导致其频谱产生一个线性相移

x(t)FX(jω)x(tt0)FX(jω)ejωt0x(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\\ \dArr\\ x(t-t_0)\stackrel{F}{\longleftrightarrow}X(j\omega)e^{-j\omega t_0}


证明

F{x(tt0)}=+x(tt0)ejωtdt=+x(t)ejω(t+t0)dt=ejωt0+x(t)ejωtdt=ejωt0X(jω)\begin{aligned} \mathscr{F}\{x(t-t_0)\} &=\int_{-\infin}^{+\infin}x(t-t_0)\ e^{-j\omega t}dt\\ &=\int_{-\infin}^{+\infin}x(t')\ e^{-j\omega(t'+t_0)}dt'\\ &=e^{-j\omega t_0}\int_{-\infin}^{+\infin}x(t')\ e^{-j\omega t'}dt'\\ &=e^{-j\omega t_0}X(j\omega) \end{aligned}

# 共轭对称性

x(t)FX(jω)x(t)FX(jω)x(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\\ \dArr\\ x^*(t)\stackrel{F}{\longleftrightarrow}X^*(-j\omega)

特别地,当 x(t)x(t) 是实信号 (实函数),则有频谱: X(jω)=X(jω)X(j\omega)=X^*(-j\omega)共轭偶函数实幅偶,虚相奇


证明

x(t)x(t) 的傅里叶正变换两侧同时取共轭有:

X(jω)=[x(t)ejkω0t]dt=x(t)ejkω0tdt\begin{aligned} X^*(j\omega) &={\int}_{-\infin}^{\infin} [x(t) e^{-jk\omega_0 t}]^* dt\\ &={\int}_{-\infin}^{\infin} x(t)^* e^{jk\omega_0 t} dt\\ \end{aligned}

所以:

X(jω)=x(t)ejkω0tdt\begin{aligned} X^*(-j\omega) &={\int}_{-\infin}^{\infin} x(t)^* e^{-jk\omega_0 t} dt\\ \end{aligned}

即得证:

x(t)FX(jω)x^*(t)\stackrel{F}{\longleftrightarrow}X^*(-j\omega)


x(t)x(t) 是实信号时有 x(t)=x(t)x(t)=x^*(t) ,于是有:

X(jω)=X(jω)=Re[X(jω)]+jIm[X(jω)]X(j\omega)=X^*(-j\omega)=\text{Re}[X(-j\omega)]+j\ \text{Im}[X(-j\omega)]

共轭偶函数:

  • 部是函数:Re[X(jω)]=Re[X(jω)]\text{Re}[X(j\omega)]=\text{Re}[X(-j\omega)]
  • 部是函数:Im[X(jω)]=Im[X(jω)]\text{Im}[X(j\omega)]=-\text{Im}[X(-j\omega)]
  • 幅度函数:X(jω)=X(jω)|X(j\omega)|=|X(-j\omega)|
  • 相位函数:ArgX(jω)=ArgX(jω)\text{Arg}X(j\omega)=-\text{Arg}X(-j\omega)

# 奇偶对称性

  • 偶信号的傅里叶 (正) 变换还是偶函数
  • 实偶信号的傅里叶 (正) 变换还是实偶函数
  • 奇信号的傅里叶 (正) 变换还是奇函数
  • 实奇信号的傅里叶 (正) 变换是虚奇函数

用表格总结奇偶性、是否为实函数的不同情况下的傅里叶正变换奇偶情况:

x(t)x(t)偶函数:x(t)=x(t)x(t)=x(-t)奇函数:x(t)=x(t)x(t)=-x(-t)
一般的X(jω)=X(jω)X(j\omega)=X(-j\omega)X(jω)=X(jω)X(j\omega)=-X(-j\omega)
x(t)x(t) 是实函数:x(t)=x(t)x(t)=x^*(t)X(jω)=X(jω)=X(jω)=X(jω)X(j\omega)=X(-j\omega)=X^*(j\omega)=X^*(-j\omega)X(jω)=X(jω)=X(jω)X(j\omega)=-X(-j\omega)=X^*(-j\omega)

# 奇偶分解

实信号 x(t)x(t) 若有奇偶分解 x(t)=xe(t)+xo(t)x(t)=x_e(t)+x_o(t) ,则有:

X(jω)=Xe(jω)+Xo(jω)xe(t)FXe(jω)xo(t)FXo(jω)X(j\omega)=X_e(j\omega)+X_o(j\omega)\\ x_e(t)\stackrel{F}{\longleftrightarrow}X_e(-j\omega)\\ x_o(t)\stackrel{F}{\longleftrightarrow}X_o(-j\omega)

# 时域微分特性

可将微分运算转变为代数运算

x(t)FX(jω)ddtx(t)FjωX(jω)x(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\\ \dArr\\ \frac{d}{dt}x(t)\stackrel{F}{\longleftrightarrow}j\omega X(j\omega)

可以推广到高次微分,在后面的微分方程分析 LTI 系统中会用到:

dkdtkx(t)F(jω)kX(jω)\frac{d^k}{dt^k}x(t)\stackrel{F}{\longleftrightarrow}(j\omega)^k X(j\omega)


证明:傅里叶反变换两侧同时对 tt 微分即可

x(t)=12π+X(jω)ejωtdωddtx(t)=12π+X(jω)ddtejωtdω=12π+jωX(jω)ejωtdω\begin{aligned} x(t) &=\frac{1}{2\pi} \int_{-\infin}^{+\infin} X(j\omega) e^{j\omega t}d\omega\\ \frac{d}{dt}x(t) &=\frac{1}{2\pi}\int_{-\infin}^{+\infin} X(j\omega)\frac{d}{dt}e^{j\omega t}d\omega\\ &=\frac{1}{2\pi}\int_{-\infin}^{+\infin} j\omega X(j\omega)\ e^{j\omega t}d\omega\\ \end{aligned}

# 时域积分特性

可将积分运算转变为代数运算

x(t)FX(jω)tx(τ)dτF1jωX(jω)+πX(0)δ(ω)x(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\\ \dArr\\ \int_{-\infin}^{t}x(\tau)d\tau\stackrel{F}{\longleftrightarrow}\frac{1}{j\omega}X(j\omega)+\pi X(0)\delta(\omega)


证明:傅里叶正变换两侧同时对 τ\tau 积分即可

F{tx(τ)dτ}=+[tx(τ)dτ]ejωtdt=+[+x(τ)u(tτ)dτ]ejωtdt=+x(τ)[+ejωtu(tτ)dt]dτ=+x(τ)[+ejω(tτ)jωτu(tτ)d(tτ)]dτ=+x(τ)ejωτ[+ejωsu(s)ds]dτ=[1jω+πδ(ω)]+x(τ)ejωτdτ=[1jω+πδ(ω)]X(jω)=1jωX(jω)+πX(0)δ(ω)\begin{aligned} \mathscr{F}\{\int_{-\infin}^{t}x(\tau)d\tau\} &=\int_{-\infin}^{+\infin}[\int_{-\infin}^{t}x(\tau)d\tau]e^{-j\omega t}dt\\ &=\int_{-\infin}^{+\infin}[\int_{-\infin}^{+\infin}x(\tau)u(t-\tau)d\tau]e^{-j\omega t}dt\\ &=\int_{-\infin}^{+\infin}x(\tau)[\int_{-\infin}^{+\infin}e^{-j\omega t}u(t-\tau)dt]d\tau\\ &=\int_{-\infin}^{+\infin}x(\tau)[\int_{-\infin}^{+\infin}e^{-j\omega(t-\tau)-j\omega\tau}u(t-\tau)d(t-\tau)]d\tau\\ &=\int_{-\infin}^{+\infin}x(\tau)e^{-j\omega\tau}[\int_{-\infin}^{+\infin}e^{-j\omega s}u(s)ds]d\tau\\ &=[\frac{1}{j\omega}+\pi\delta(\omega)]\int_{-\infin}^{+\infin}x(\tau)e^{-j\omega \tau}d\tau\\ &=[\frac{1}{j\omega}+\pi\delta(\omega)]X(j\omega)\\ &=\frac{1}{j\omega}X(j\omega)+\pi X(0)\delta(\omega) \end{aligned}

其中 u(s)CTFT1jω+πδ(ω)u(s)\stackrel{CTFT}{\longleftrightarrow}\frac{1}{j\omega}+\pi\delta(\omega) 是单位阶跃函数的傅里叶变换

# 时域和频域的尺度变换

信号如果在时域扩展 a 倍,则其带宽相应压缩 a 倍,反之亦然

x(t)FX(jω)x(at)F1aX(jωa)x(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\\ \dArr\\ x(at)\stackrel{F}{\longleftrightarrow}\frac{1}{|a|}X(\frac{j\omega}{a})


证明:

F{x(at)}=+x(at)ejωtdt=1a+x(τ)ejωaτdτ=1aX(jωa)\begin{aligned} \mathscr{F}\{x(at)\} &=\int_{-\infin}^{+\infin}x(at)e^{-j\omega t}dt\\ &=\frac{1}{|a|}\int_{-\infin}^{+\infin}x(\tau)e^{-j\frac{\omega}{a}\tau}d\tau\\ &=\frac{1}{|a|}X(\frac{j\omega}{a}) \end{aligned}

# 对偶性

由对偶性可以方便地将时域的某些特性对偶到频域

x(t)CTFTX(jω)X(jt)CTFT2πx(ω)x(t)\stackrel{CTFT}{\longleftrightarrow}X(j\omega)\\ \dArr\\ X(jt)\stackrel{CTFT}{\longleftrightarrow}2\pi x(-\omega)


证明:

x(t)=12π+X(jω)ejωtdω2πx(t)=+X(jω)ejωtdω2πx(ω)=+X(jt)ejωtdt2πx(ω)=+X(jt)ejωtdt\begin{aligned} x(t) &=\frac{1}{2\pi} \int_{-\infin}^{+\infin} X(j\omega) e^{j\omega t}d\omega\\ 2\pi x(t) &=\int_{-\infin}^{+\infin} X(j\omega) e^{j\omega t}d\omega\\ 2\pi x(\omega) &=\int_{-\infin}^{+\infin} X(jt) e^{j\omega t}dt\\ 2\pi x(-\omega) &=\int_{-\infin}^{+\infin} X(jt) e^{-j\omega t}dt\\ \end{aligned}

# 移频特性

将时域的时移性对偶可以得到频域的移频特性

x(t)FX(jω)x(t)ejω0tFX[j(ωω0)]x(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\\ \dArr\\ x(t)e^{j\omega_0 t}\stackrel{F}{\longleftrightarrow}X[j(\omega-\omega_0)]


证明:

x(t)FX(jω)对偶性X(jt)F2πx(ω)时移特性X(j(tω0))F2πx(ω)ejω0t对偶性2πx(t)ejω0tF2πX[j(ωω0)]x(t)ejω0tFX[j(ωω0)]x(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\\ \dArr\text{对偶性}\\ X(jt)\stackrel{F}{\longleftrightarrow}2\pi x(-\omega)\\ \dArr\text{时移特性}\\ X(j(t-\omega_0))\stackrel{F}{\longleftrightarrow}2\pi x(-\omega)e^{-j\omega_0 t}\\ \dArr\text{对偶性}\\ 2\pi x(-t)e^{-j\omega_0 t}\stackrel{F}{\longleftrightarrow}2\pi X[j(-\omega-\omega_0)]\\ \dArr\\ x(t)e^{j\omega_0 t}\stackrel{F}{\longleftrightarrow}X[j(\omega-\omega_0)]

# 频域微分特性

x(t)FX(jω)jtx(t)FddωX(jω)x(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\\ \dArr\\ -jtx(t)\stackrel{F}{\longleftrightarrow}\frac{d}{d\omega}X(j\omega)

# 频域积分特性

x(t)FX(jω)x(t)jt+πx(0)δ(t)FωX(jτ)dτx(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\\ \dArr\\ \frac{x(t)}{-jt}+\pi x(0)\delta(t)\stackrel{F}{\longleftrightarrow}\int_{-\infin}^{\omega}X(j\tau)d\tau

# Parseval 定理

x(t)FX(jω)+x(t)2dt=12π+X(jω)2dωx(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\\ \dArr\\ \int_{-\infin}^{+\infin}|x(t)|^2dt=\frac{1}{2\pi}\int_{-\infin}^{+\infin}|X(j\omega)|^2d\omega

这表明:信号的能量既可以在时域求得,也可以在频域求得。由于 X(jω)2|X(j\omega)^2| 表示了信号能量在频域的分布,因而称其为能量谱密度函数

# ⭐️卷积特性

x(t)FX(jω),h(t)FH(jω)x(t)h(t)FX(jω)H(jω)x(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\ \ \ ,\ \ \ h(t)\stackrel{F}{\longleftrightarrow}H(j\omega)\\ \dArr\\ x(t)*h(t)\stackrel{F}{\longleftrightarrow}X(j\omega)H(j\omega)

本质上,卷积特性的成立正是因为复指数信号 ejωte^{jωt} 是一切 LTI 系统的特征函数,H(jω)H(j\omega) 则是对应的特征值


证明

y(t)=x(t)h(t)=+x(τ)h(tτ)dτy(t)=x(t)*h(t)=\int_{-\infin}^{+\infin}x(\tau)\ h(t-\tau)\ d\tau ,求其傅里叶正变换为:

F{y(t)}=Y(jω)=+ejωt+x(τ)h(tτ)dτdt=+ejω(tτ)jωτ+x(τ)h(tτ)dτd(tτ)=+ejωsjωτ+x(τ)h(s)dτds=+ejωsejωτ+x(τ)h(s)dτds=+x(τ)ejωτdτ+h(s)ejωsds=X(jω)H(jω)\begin{aligned} \mathscr{F}\{y(t)\}=Y(j\omega) &=\int_{-\infin}^{+\infin} e^{-j\omega t}\int_{-\infin}^{+\infin}x(\tau)\ h(t-\tau)\ d\tau\ dt\\ &=\int_{-\infin}^{+\infin} e^{-j\omega(t-\tau)-j\omega \tau}\int_{-\infin}^{+\infin}x(\tau)\ h(t-\tau)\ d\tau\ d(t-\tau)\\ &=\int_{-\infin}^{+\infin} e^{-j\omega s-j\omega \tau}\int_{-\infin}^{+\infin}x(\tau)\ h(s)\ d\tau\ ds\\ &=\int_{-\infin}^{+\infin}e^{-j\omega s}e^{-j\omega \tau}\int_{-\infin}^{+\infin}x(\tau)\ h(s)\ d\tau\ ds\\ &=\int_{-\infin}^{+\infin}x(\tau)\ e^{-j\omega \tau}\ d\tau\int_{-\infin}^{+\infin}h(s)\ e^{-j\omega s}\ ds\\ &=X(j\omega)H(j\omega) \end{aligned}

另外,可将 x(t)x(t) 视为复指数分量 ejωte^{j\omega t} 的线性组合,每个 ejωte^{j\omega t} 通过 LTI 系统时都要受到系统对应的特征值 H(jω)H(j\omega) 的加权


LTI 系统的单位冲激响应 h(t)h(t) 与频率响应 H(jω)H(j\omega) 一一对应,因而 LTI 系统可以由其频率响应完全表征。

⚠️ 并非任何系统的频率响应都存在。

用频率响应表征系统时,一般都限于对稳定系统。

稳定性保证了 h(t)h(t) 的绝对可积,结合 Dirichlet 的另外两个条件(实际系统一般满足),则频率响应必然存在

# ⭐️相乘特性

s(t)FS(jω),p(t)FP(jω)s(t)p(t)F12πS(jω)P(jω)s(t)\stackrel{F}{\longleftrightarrow}S(j\omega)\ \ \ ,\ \ \ p(t)\stackrel{F}{\longleftrightarrow}P(j\omega)\\ \dArr\\ s(t)p(t)\stackrel{F}{\longleftrightarrow}\frac{1}{2\pi}S(j\omega)*P(j\omega)


证明:利用对偶性可以从卷积性质得出相乘性质

由对偶性有:

s(t)FS(jω),p(t)FP(jω)S(jt)F2πS(ω),P(jt)F2πP(ω)s(t)\stackrel{F}{\longleftrightarrow}S(j\omega)\ \ \ ,\ \ \ p(t)\stackrel{F}{\longleftrightarrow}P(j\omega)\\ \dArr\\ S(jt)\stackrel{F}{\longleftrightarrow}2\pi S(-\omega)\ \ \ ,\ \ \ P(jt)\stackrel{F}{\longleftrightarrow}2\pi P(-\omega)\\

由卷积特性有:

S(jt)P(jt)F4π2s(ω)p(ω)S(jt)*P(jt)\stackrel{F}{\longleftrightarrow}4\pi^2s(-\omega)p(-\omega)

由对偶性有:

4π2s(t)p(t)F2πS(jω)P(jω)s(t)p(t)F12πS(jω)P(jω)\begin{aligned} 4\pi^2s(-t)p(-t)&\stackrel{F}{\longleftrightarrow}2\pi S(-j\omega)*P(-j\omega)\\ s(-t)p(-t)&\stackrel{F}{\longleftrightarrow}\frac{1}{2\pi}S(-j\omega)*P(-j\omega) \end{aligned}

# 连续时间 LTI 系统的分析

利用傅里叶变换及其特性对 LTI 系统分析

# 频域分析法

根据卷积特性,可以对 LTI 系统进行频域分析,其过程为:

  1. 求出(或已知、根据系统描述直接得出)系统单位冲激响应 h(t)h(t)
  2. 求输入 x(t)x(t) 的傅里叶正变换:x(t)CTFTX(jω)x(t)\stackrel{CTFT}{\longleftrightarrow}X(j\omega)
  3. 求单位冲激响应 h(t)h(t) 的傅里叶正变换:h(t)CTFTH(jω)h(t)\stackrel{CTFT}{\longleftrightarrow}H(j\omega)
  4. 若需要求 Y(jω)Y(j\omega) ,由傅里叶变换卷积特性得:Y(jω)=X(jω)H(jω)Y(j\omega)=X(j\omega)H(j\omega)
  5. 若需要求 y(t)y(t)
    • x(t)x(t) 是非周期的(或非周期部分):
      • 往往由傅里叶反变换求得:y(t)=F1{Y(jω)}=12π+Y(jω)ejωtdωy(t)=\mathscr{F}^{-1}\{Y(j\omega)\}=\frac{1}{2\pi} \int_{-\infin}^{+\infin} Y(j\omega) e^{j\omega t}d\omega
      • 对有理函数求傅里叶反变换通常采用部分分式展开和利用常用变换对进行
    • x(t)x(t) 是周期的(或周期部分):
      • Y(jω)=X(jω)×H(jω)|Y(j\omega)|=|X(j\omega)|\times|H(j\omega)|
      • argY(jω)=argX(jω)+argH(jω)\text{arg}Y(j\omega)=\text{arg}X(j\omega)+\text{arg}H(j\omega)

# 线性常微分方程

* 线性常系数微分方程

对于由线性常系数微分方程描述的 LTI 系统:

k=0Nakdky(t)dtk=k=0Mbkdkx(t)dtk\sum_{k=0}^{N}a_k\frac{d^ky(t)}{dt^k}=\sum_{k=0}^{M}b_k\frac{d^kx(t)}{dt^k}

对方程两边进行傅里叶变换,有:

k=0Nak(jω)kY(jω)=k=0Mbk(jω)kX(jω)Y(jω)k=0Nak(jω)k=X(jω)k=0Mbk(jω)kY(jω)X(jω)=k=0Mbk(jω)kk=0Nak(jω)k\begin{aligned} \sum_{k=0}^{N}a_{k}(j\omega)^{k}Y(j\omega) &= \sum_{k=0}^{M}b_{k}(j\omega)^{k}X(j\omega)\\ Y(j\omega)\sum_{k=0}^{N}a_{k}(j\omega)^{k} &= X(j\omega)\sum_{k=0}^{M}b_{k}(j\omega)^{k}\\ {Y(j\omega)\over X(j\omega)} &= {\sum_{k=0}^{M}b_{k}(j\omega)^{k}\over\sum_{k=0}^{N}a_{k}(j\omega)^{k}} \end{aligned}

由 CTFT 卷积特性有:

Y(jω)=X(jω)H(jω)Y(j\omega)=X(j\omega)H(j\omega)

可得:

H(jω)=Y(jω)X(jω)=k=0Mbk(jω)kk=0Nak(jω)kH(j\omega)={Y(j\omega)\over X(j\omega)}={\sum_{k=0}^{M}b_{k}(j\omega)^{k}\over\sum_{k=0}^{N}a_{k}(j\omega)^{k}}

可见由线性常系数微分方程描述的 LTI 系统的频率响应是一个有理函数。

若要求 h(t)h(t) ,也就是系统的单位冲激响应,则往往可以对有理函数(有理分式)形式的 H(jω)H(j\omega) 变形化得到常用变换对的表示形式,再利用常用变换对反变换得到 h(t)h(t)


反之,若已知一个 LTI 系统的频率响应 H(jω)=Y(jω)X(jω)H(j\omega)={Y(j\omega)\over X(j\omega)} ,则可以列出两侧分别是关于 Y(jω)Y(j\omega)X(jω)X(j\omega) 的方程,两侧同时进行傅里叶反变换,(注意将 jωj\omega 视为一个整体)则可得到描述该 LTI 系统的线性常系数微分方程

\ No newline at end of file +M834 80h400000v40h-400000z"/>1=arctanaω

低通信号(单侧)2

低通信号(单侧)3

# 低通信号 (双侧)

低通信号(双侧)1

x(t)=eat,a>0x(t)=e^{-a|t|},\ \ \ a\gt0

有正变换:

X(jω)=0eatejωtdt+0+eatejωtdt=1ajω+1a+jω=2aa2+ω2X(jω)=X(jω)\begin{aligned} X(j\omega) &=\int_{-\infin}^{0}e^{at}e^{-j\omega t}dt +\int_{0}^{+\infin}e^{-at}e^{-j\omega t}dt\\ &=\frac{1}{a-j\omega}+\frac{1}{a+j\omega}\\ &= \frac{2a}{a^2+\omega^2}\\ \\ |X(j\omega)| &= X(j\omega)\\ \end{aligned}

低通信号(双侧)2

# 冲激信号

x(t)=δ(t)x(t)=\delta(t)

有正变换:

X(jω)=+δ(t)ejωtdt=1X(j\omega)=\int_{-\infin}^{+\infin}\delta(t)e^{-j\omega t}dt=1

冲激信号正变换

这表明 δ(t)\delta(t) 中包括了所有的频率成分,且所有频率分量的幅度、相位都相同。因此,系统的单位冲激响应 h(t)h(t) 才能完全描述一个 LTI 系统的特性,δ(t)\delta(t) 才在信号与系统分析中具有如此重要的意义。

# 常数信号

* 这个名字我乱起的

x(t)=1x(t)=1

因为:

12π+2πδ(ω)ejωtdω=1\begin{aligned} \frac{1}{2\pi} \int_{-\infin}^{+\infin} 2\pi\ \delta(\omega)\ e^{j\omega t}d\omega = 1 \end{aligned}

所以有反变换:

X(jω)=2πδ(ω)\begin{aligned} X(j\omega) &= 2\pi\delta(\omega) \end{aligned}


冲激信号和双侧阶跃信号 (我乱起名) 的对偶关系:

δ(t)F1F2πδ(ω)\delta(t)\stackrel{F}{\longleftrightarrow}1\stackrel{F}{\longleftrightarrow}2\pi\delta(\omega)

# 矩形信号

矩形信号

x(t)={1,t<T10,t>T1x(t)= \begin{cases} 1,\ \ \ |t|\lt T_1\\ 0,\ \ \ |t|\gt T_1 \end{cases}

有正变换:

X(jω)=T1T1ejωtdt=2sinωT1ω=2T1sinωT1ωT1=2T1Sa(ωT1)=2T1sinc(ωT1π)ak=X(jω)T=2T1TSa(kω0T1)=2T1TSa(2T1T)\begin{aligned} X(j\omega) &=\int_{-T_1}^{T_1} e^{-j\omega t}dt\\ &=\frac{2\sin{\omega T_1}}{\omega}\\ &=\frac{2T_1\sin{\omega T_1}}{\omega T_1}\\ &=2T_1\text{Sa}(\omega T_1) = 2T_1\text{sinc}(\frac{\omega T_1}{\pi})\\\\ a_k = \frac{X(j\omega)}{T} &= \frac{2T_1}{T}\text{Sa}(k\omega_0 T_1) = \frac{2T_1}{T}\text{Sa}(\frac{2T_1}{T}) \end{aligned}

不同脉冲宽度对频谱的影响:

不同脉冲宽度对矩形信号频谱的影响

可见,信号宽度在时域和频域之间有一种相反的关系。

# 采样信号

X(jω)={1,ω<W0,ω>WX(j\omega)= \begin{cases} 1,\ \ \ |\omega|\lt W\\ 0,\ \ \ |\omega|\gt W \end{cases}

有反变换:

x(t)=12πW+Wejωtdω=sinWtπt=WπSa(Wt)=WπSa(Wtπ)\begin{aligned} x(t) &= \frac{1}{2\pi}\int_{-W}^{+W} e^{-j\omega t}d\omega\\ &=\frac{\sin{Wt}}{\pi t}\\ &= \frac{W}{\pi}\text{Sa}(Wt) = \frac{W}{\pi}\text{Sa}(\frac{Wt}{\pi}) \end{aligned}

采样信号

可见 x(t)x(t) 是采样信号


矩形信号和采样信号的对偶关系:(上矩形信号、下采样信号)

矩形信号和采样信号对偶关系

# 周期信号

TakTa_k 无论在 TT 有限还是无限的时候都可以是有限的,所以我们可以将 TT 有限时的周期信号和 TT 无限时的非周期信号用傅里叶变换统一起来

但是 aka_k 却不是,所以我们无法将周期信号和非周期信号都用傅里叶级数表示。

# FT 公式推导

考虑 X(jω)=2πδ(ωω0)X(j\omega)=2\pi\delta(\omega-\omega_0) 所对应的信号:

x(t)=12π+X(jω)ejωtdω=+δ(ωω0)ejωtdω=ejω0t\begin{aligned} x(t) &=\frac{1}{2\pi} \int_{-\infin}^{+\infin} X(j\omega)\ e^{j\omega t}d\omega\\ &=\int_{-\infin}^{+\infin} \delta(\omega-\omega_0)\ e^{j\omega t}d\omega\\ &= e^{j\omega_0 t} \end{aligned}

于是对于表示为傅里叶级数的周期信号 x(t)x(t)

x(t)=k=+akejkω0tx(t)=\sum_{k=-\infin}^{+\infin}a_k\ e^{jk\omega_0 t}

就有频谱正变换

X(jω)=2πk=+akδ(ωω0)X(j\omega)=2\pi \sum_{k=-\infin}^{+\infin} a_k\ \delta(\omega-\omega_0)

这表明周期信号的傅里叶正变换由一系列位于谐波频率处的冲激组成,其中 kω0k\omega_0 处的冲激强度为对应傅里叶级数系数 aka_k2π2\pi 倍。

# 常见信号的 FT

# 正弦信号

x(t)=sin(ω0t)=12j(ejω0tejω0t)x(t)=\sin(\omega_0 t)=\frac{1}{2j}(e^{j\omega_0 t}-e^{-j\omega_0 t})

有正变换:

X(jω)=πj[δ(ωω0)δ(ω+ω0)]X(j\omega)=\frac{\pi}{j}[\delta(\omega-\omega_0)-\delta(\omega+\omega_0)]

正弦信号

# 余弦信号

x(t)=cos(ω0t)=12(ejω0t+ejω0t)x(t)=\cos(\omega_0 t)=\frac{1}{2}(e^{j\omega_0 t}+e^{-j\omega_0 t})

有正变换:

X(jω)=π[δ(ωω0)+δ(ω+ω0)]X(j\omega)=\pi[\delta(\omega-\omega_0)+\delta(\omega+\omega_0)]

余弦信号

# 均匀冲激串

x(t)=n=+δ(tnT)x(t)=\sum_{n=-\infin}^{+\infin}\delta(t-nT)

其中 T=2πω0T=\frac{2\pi}{\omega_0}

其傅里叶系数:

ak=1TT2T2δ(t)ej2πTktdt=1TT2T2δ(t)dt=1T\begin{aligned} a_k &=\frac{1}{T}\int_{-\frac{T}{2}}^{\frac{T}{2}}\delta(t)\ e^{-j\frac{2\pi}{T}kt}dt\\ &=\frac{1}{T}\int_{-\frac{T}{2}}^{\frac{T}{2}}\delta(t)dt\\ &=\frac{1}{T} \end{aligned}

可得傅里叶正变换:

X(jω)=2πTk=+δ(ω2πTk)X(j\omega)=\frac{2\pi}{T}\sum_{k=-\infin}^{+\infin}\delta(\omega-\frac{2\pi}{T}k)

均匀冲激串

# 周期性矩形脉冲

其傅里叶系数:

ak=2T1TSa(πk2T1T)a_k=\frac{2T_1}{T}\text{Sa}(\pi k\frac{2T_1}{T})

有傅里叶正变换:

X(jω)=4πT1Tk=+Sa(πk2T1T)δ(ω2πTk)=2T1ω0k=+Sa(ω0T1k)δ(ωω0k)X(j\omega)=\frac{4\pi T_1}{T}\sum_{k=-\infin}^{+\infin}\text{Sa}(\pi k\frac{2T_1}{T})\ \delta(\omega-\frac{2\pi}{T}k) =2T_1\omega_0\sum_{k=-\infin}^{+\infin}\text{Sa}(\omega_0T_1\cdot k)\ \delta(\omega-\omega_0\cdot k)

其中 ω0=2πT\omega_0=\frac{2\pi}{T} 为谱线间隔。

# 特殊信号 FT

# 符号函数

符号函数

可以将符号函数定义为:

Sgn(t)=lima0[eatu(t)eatu(t)]\text{Sgn}(t)=\lim_{a\to0}[e^{-at}u(t)-e^{at}u(-t)]

其傅里叶变换为:

F{Sgn(t)}=lima0[1a+jω1ajω]=lima0j2ωa2+(jω)2=2jω\begin{aligned} \mathscr{F}\{\text{Sgn}(t)\} &=\lim_{a\to0}[\frac{1}{a+j\omega}-\frac{1}{a-j\omega}]\\ &=\lim_{a\to0}\frac{-j2\omega}{a^2+(j\omega)^2}\\ &=\frac{2}{j\omega} \end{aligned}

# 单位阶跃函数

u(t)u(t) 分解为偶部和奇部有:

u(t)=ue(t)+uo(t)ue(t)=12uo(t)=12Sgn(t)\begin{aligned} &u(t)=u_e(t)+u_o(t)\\ &u_e(t)=\frac{1}{2}\\ &u_o(t)=\frac{1}{2}\text{Sgn}(t) \end{aligned}

1CTFT2πδ(ω)1\stackrel{CTFT}{\longleftrightarrow}2\pi\delta(\omega)Sgn(t)CTFT2jω\text{Sgn}(t)\stackrel{CTFT}{\longleftrightarrow}\frac{2}{j\omega} ,因此有:

u(t)F1jω+πδ(ω)u(t)\stackrel{F}{\longleftrightarrow}\frac{1}{j\omega}+\pi\delta(\omega)

# 性质

# 线性

x(t)FX(jω),y(t)FY(jω)ax(t)+by(t)FaX(jω)+bY(jω)x(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\ \ ,\ \ y(t)\stackrel{F}{\longleftrightarrow}Y(j\omega)\\ \dArr\\ ax(t)+by(t)\stackrel{F}{\longleftrightarrow}aX(j\omega)+bY(j\omega)

# 时移特性

信号的时移会导致其频谱产生一个线性相移

x(t)FX(jω)x(tt0)FX(jω)ejωt0x(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\\ \dArr\\ x(t-t_0)\stackrel{F}{\longleftrightarrow}X(j\omega)e^{-j\omega t_0}


证明

F{x(tt0)}=+x(tt0)ejωtdt=+x(t)ejω(t+t0)dt=ejωt0+x(t)ejωtdt=ejωt0X(jω)\begin{aligned} \mathscr{F}\{x(t-t_0)\} &=\int_{-\infin}^{+\infin}x(t-t_0)\ e^{-j\omega t}dt\\ &=\int_{-\infin}^{+\infin}x(t')\ e^{-j\omega(t'+t_0)}dt'\\ &=e^{-j\omega t_0}\int_{-\infin}^{+\infin}x(t')\ e^{-j\omega t'}dt'\\ &=e^{-j\omega t_0}X(j\omega) \end{aligned}

# 共轭对称性

x(t)FX(jω)x(t)FX(jω)x(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\\ \dArr\\ x^*(t)\stackrel{F}{\longleftrightarrow}X^*(-j\omega)

特别地,当 x(t)x(t) 是实信号 (实函数),则有频谱: X(jω)=X(jω)X(j\omega)=X^*(-j\omega)共轭偶函数实幅偶,虚相奇


证明

x(t)x(t) 的傅里叶正变换两侧同时取共轭有:

X(jω)=[x(t)ejkω0t]dt=x(t)ejkω0tdt\begin{aligned} X^*(j\omega) &={\int}_{-\infin}^{\infin} [x(t) e^{-jk\omega_0 t}]^* dt\\ &={\int}_{-\infin}^{\infin} x(t)^* e^{jk\omega_0 t} dt\\ \end{aligned}

所以:

X(jω)=x(t)ejkω0tdt\begin{aligned} X^*(-j\omega) &={\int}_{-\infin}^{\infin} x(t)^* e^{-jk\omega_0 t} dt\\ \end{aligned}

即得证:

x(t)FX(jω)x^*(t)\stackrel{F}{\longleftrightarrow}X^*(-j\omega)


x(t)x(t) 是实信号时有 x(t)=x(t)x(t)=x^*(t) ,于是有:

X(jω)=X(jω)=Re[X(jω)]+jIm[X(jω)]X(j\omega)=X^*(-j\omega)=\text{Re}[X(-j\omega)]+j\ \text{Im}[X(-j\omega)]

共轭偶函数:

  • 部是函数:Re[X(jω)]=Re[X(jω)]\text{Re}[X(j\omega)]=\text{Re}[X(-j\omega)]
  • 部是函数:Im[X(jω)]=Im[X(jω)]\text{Im}[X(j\omega)]=-\text{Im}[X(-j\omega)]
  • 幅度函数:X(jω)=X(jω)|X(j\omega)|=|X(-j\omega)|
  • 相位函数:ArgX(jω)=ArgX(jω)\text{Arg}X(j\omega)=-\text{Arg}X(-j\omega)

# 奇偶对称性

  • 偶信号的傅里叶 (正) 变换还是偶函数
  • 实偶信号的傅里叶 (正) 变换还是实偶函数
  • 奇信号的傅里叶 (正) 变换还是奇函数
  • 实奇信号的傅里叶 (正) 变换是虚奇函数

用表格总结奇偶性、是否为实函数的不同情况下的傅里叶正变换奇偶情况:

x(t)x(t)偶函数:x(t)=x(t)x(t)=x(-t)奇函数:x(t)=x(t)x(t)=-x(-t)
一般的X(jω)=X(jω)X(j\omega)=X(-j\omega)X(jω)=X(jω)X(j\omega)=-X(-j\omega)
x(t)x(t) 是实函数:x(t)=x(t)x(t)=x^*(t)X(jω)=X(jω)=X(jω)=X(jω)X(j\omega)=X(-j\omega)=X^*(j\omega)=X^*(-j\omega)X(jω)=X(jω)=X(jω)X(j\omega)=-X(-j\omega)=X^*(-j\omega)

# 奇偶分解

实信号 x(t)x(t) 若有奇偶分解 x(t)=xe(t)+xo(t)x(t)=x_e(t)+x_o(t) ,则有:

X(jω)=Xe(jω)+Xo(jω)xe(t)FXe(jω)xo(t)FXo(jω)X(j\omega)=X_e(j\omega)+X_o(j\omega)\\ x_e(t)\stackrel{F}{\longleftrightarrow}X_e(-j\omega)\\ x_o(t)\stackrel{F}{\longleftrightarrow}X_o(-j\omega)

# 时域微分特性

可将微分运算转变为代数运算

x(t)FX(jω)ddtx(t)FjωX(jω)x(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\\ \dArr\\ \frac{d}{dt}x(t)\stackrel{F}{\longleftrightarrow}j\omega X(j\omega)

可以推广到高次微分,在后面的微分方程分析 LTI 系统中会用到:

dkdtkx(t)F(jω)kX(jω)\frac{d^k}{dt^k}x(t)\stackrel{F}{\longleftrightarrow}(j\omega)^k X(j\omega)


证明:傅里叶反变换两侧同时对 tt 微分即可

x(t)=12π+X(jω)ejωtdωddtx(t)=12π+X(jω)ddtejωtdω=12π+jωX(jω)ejωtdω\begin{aligned} x(t) &=\frac{1}{2\pi} \int_{-\infin}^{+\infin} X(j\omega) e^{j\omega t}d\omega\\ \frac{d}{dt}x(t) &=\frac{1}{2\pi}\int_{-\infin}^{+\infin} X(j\omega)\frac{d}{dt}e^{j\omega t}d\omega\\ &=\frac{1}{2\pi}\int_{-\infin}^{+\infin} j\omega X(j\omega)\ e^{j\omega t}d\omega\\ \end{aligned}

# 时域积分特性

可将积分运算转变为代数运算

x(t)FX(jω)tx(τ)dτF1jωX(jω)+πX(0)δ(ω)x(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\\ \dArr\\ \int_{-\infin}^{t}x(\tau)d\tau\stackrel{F}{\longleftrightarrow}\frac{1}{j\omega}X(j\omega)+\pi X(0)\delta(\omega)


证明:傅里叶正变换两侧同时对 τ\tau 积分即可

F{tx(τ)dτ}=+[tx(τ)dτ]ejωtdt=+[+x(τ)u(tτ)dτ]ejωtdt=+x(τ)[+ejωtu(tτ)dt]dτ=+x(τ)[+ejω(tτ)jωτu(tτ)d(tτ)]dτ=+x(τ)ejωτ[+ejωsu(s)ds]dτ=[1jω+πδ(ω)]+x(τ)ejωτdτ=[1jω+πδ(ω)]X(jω)=1jωX(jω)+πX(0)δ(ω)\begin{aligned} \mathscr{F}\{\int_{-\infin}^{t}x(\tau)d\tau\} &=\int_{-\infin}^{+\infin}[\int_{-\infin}^{t}x(\tau)d\tau]e^{-j\omega t}dt\\ &=\int_{-\infin}^{+\infin}[\int_{-\infin}^{+\infin}x(\tau)u(t-\tau)d\tau]e^{-j\omega t}dt\\ &=\int_{-\infin}^{+\infin}x(\tau)[\int_{-\infin}^{+\infin}e^{-j\omega t}u(t-\tau)dt]d\tau\\ &=\int_{-\infin}^{+\infin}x(\tau)[\int_{-\infin}^{+\infin}e^{-j\omega(t-\tau)-j\omega\tau}u(t-\tau)d(t-\tau)]d\tau\\ &=\int_{-\infin}^{+\infin}x(\tau)e^{-j\omega\tau}[\int_{-\infin}^{+\infin}e^{-j\omega s}u(s)ds]d\tau\\ &=[\frac{1}{j\omega}+\pi\delta(\omega)]\int_{-\infin}^{+\infin}x(\tau)e^{-j\omega \tau}d\tau\\ &=[\frac{1}{j\omega}+\pi\delta(\omega)]X(j\omega)\\ &=\frac{1}{j\omega}X(j\omega)+\pi X(0)\delta(\omega) \end{aligned}

其中 u(s)CTFT1jω+πδ(ω)u(s)\stackrel{CTFT}{\longleftrightarrow}\frac{1}{j\omega}+\pi\delta(\omega) 是单位阶跃函数的傅里叶变换

# 时域和频域的尺度变换

信号如果在时域扩展 a 倍,则其带宽相应压缩 a 倍,反之亦然

x(t)FX(jω)x(at)F1aX(jωa)x(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\\ \dArr\\ x(at)\stackrel{F}{\longleftrightarrow}\frac{1}{|a|}X(\frac{j\omega}{a})


证明:

F{x(at)}=+x(at)ejωtdt=1a+x(τ)ejωaτdτ=1aX(jωa)\begin{aligned} \mathscr{F}\{x(at)\} &=\int_{-\infin}^{+\infin}x(at)e^{-j\omega t}dt\\ &=\frac{1}{|a|}\int_{-\infin}^{+\infin}x(\tau)e^{-j\frac{\omega}{a}\tau}d\tau\\ &=\frac{1}{|a|}X(\frac{j\omega}{a}) \end{aligned}

# 对偶性

由对偶性可以方便地将时域的某些特性对偶到频域

x(t)CTFTX(jω)X(jt)CTFT2πx(ω)x(t)\stackrel{CTFT}{\longleftrightarrow}X(j\omega)\\ \dArr\\ X(jt)\stackrel{CTFT}{\longleftrightarrow}2\pi x(-\omega)


证明:

x(t)=12π+X(jω)ejωtdω2πx(t)=+X(jω)ejωtdω2πx(ω)=+X(jt)ejωtdt2πx(ω)=+X(jt)ejωtdt\begin{aligned} x(t) &=\frac{1}{2\pi} \int_{-\infin}^{+\infin} X(j\omega) e^{j\omega t}d\omega\\ 2\pi x(t) &=\int_{-\infin}^{+\infin} X(j\omega) e^{j\omega t}d\omega\\ 2\pi x(\omega) &=\int_{-\infin}^{+\infin} X(jt) e^{j\omega t}dt\\ 2\pi x(-\omega) &=\int_{-\infin}^{+\infin} X(jt) e^{-j\omega t}dt\\ \end{aligned}

# 移频特性

将时域的时移性对偶可以得到频域的移频特性

x(t)FX(jω)x(t)ejω0tFX[j(ωω0)]x(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\\ \dArr\\ x(t)e^{j\omega_0 t}\stackrel{F}{\longleftrightarrow}X[j(\omega-\omega_0)]


证明:

x(t)FX(jω)对偶性X(jt)F2πx(ω)时移特性X(j(tω0))F2πx(ω)ejω0t对偶性2πx(t)ejω0tF2πX[j(ωω0)]x(t)ejω0tFX[j(ωω0)]x(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\\ \dArr\text{对偶性}\\ X(jt)\stackrel{F}{\longleftrightarrow}2\pi x(-\omega)\\ \dArr\text{时移特性}\\ X(j(t-\omega_0))\stackrel{F}{\longleftrightarrow}2\pi x(-\omega)e^{-j\omega_0 t}\\ \dArr\text{对偶性}\\ 2\pi x(-t)e^{-j\omega_0 t}\stackrel{F}{\longleftrightarrow}2\pi X[j(-\omega-\omega_0)]\\ \dArr\\ x(t)e^{j\omega_0 t}\stackrel{F}{\longleftrightarrow}X[j(\omega-\omega_0)]

# 频域微分特性

x(t)FX(jω)jtx(t)FddωX(jω)x(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\\ \dArr\\ -jtx(t)\stackrel{F}{\longleftrightarrow}\frac{d}{d\omega}X(j\omega)

# 频域积分特性

x(t)FX(jω)x(t)jt+πx(0)δ(t)FωX(jτ)dτx(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\\ \dArr\\ \frac{x(t)}{-jt}+\pi x(0)\delta(t)\stackrel{F}{\longleftrightarrow}\int_{-\infin}^{\omega}X(j\tau)d\tau

# Parseval 定理

x(t)FX(jω)+x(t)2dt=12π+X(jω)2dωx(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\\ \dArr\\ \int_{-\infin}^{+\infin}|x(t)|^2dt=\frac{1}{2\pi}\int_{-\infin}^{+\infin}|X(j\omega)|^2d\omega

这表明:信号的能量既可以在时域求得,也可以在频域求得。由于 X(jω)2|X(j\omega)^2| 表示了信号能量在频域的分布,因而称其为能量谱密度函数

# ⭐️卷积特性

x(t)FX(jω),h(t)FH(jω)x(t)h(t)FX(jω)H(jω)x(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\ \ \ ,\ \ \ h(t)\stackrel{F}{\longleftrightarrow}H(j\omega)\\ \dArr\\ x(t)*h(t)\stackrel{F}{\longleftrightarrow}X(j\omega)H(j\omega)

本质上,卷积特性的成立正是因为复指数信号 ejωte^{jωt} 是一切 LTI 系统的特征函数,H(jω)H(j\omega) 则是对应的特征值


证明

y(t)=x(t)h(t)=+x(τ)h(tτ)dτy(t)=x(t)*h(t)=\int_{-\infin}^{+\infin}x(\tau)\ h(t-\tau)\ d\tau ,求其傅里叶正变换为:

F{y(t)}=Y(jω)=+ejωt+x(τ)h(tτ)dτdt=+ejω(tτ)jωτ+x(τ)h(tτ)dτd(tτ)=+ejωsjωτ+x(τ)h(s)dτds=+ejωsejωτ+x(τ)h(s)dτds=+x(τ)ejωτdτ+h(s)ejωsds=X(jω)H(jω)\begin{aligned} \mathscr{F}\{y(t)\}=Y(j\omega) &=\int_{-\infin}^{+\infin} e^{-j\omega t}\int_{-\infin}^{+\infin}x(\tau)\ h(t-\tau)\ d\tau\ dt\\ &=\int_{-\infin}^{+\infin} e^{-j\omega(t-\tau)-j\omega \tau}\int_{-\infin}^{+\infin}x(\tau)\ h(t-\tau)\ d\tau\ d(t-\tau)\\ &=\int_{-\infin}^{+\infin} e^{-j\omega s-j\omega \tau}\int_{-\infin}^{+\infin}x(\tau)\ h(s)\ d\tau\ ds\\ &=\int_{-\infin}^{+\infin}e^{-j\omega s}e^{-j\omega \tau}\int_{-\infin}^{+\infin}x(\tau)\ h(s)\ d\tau\ ds\\ &=\int_{-\infin}^{+\infin}x(\tau)\ e^{-j\omega \tau}\ d\tau\int_{-\infin}^{+\infin}h(s)\ e^{-j\omega s}\ ds\\ &=X(j\omega)H(j\omega) \end{aligned}

另外,可将 x(t)x(t) 视为复指数分量 ejωte^{j\omega t} 的线性组合,每个 ejωte^{j\omega t} 通过 LTI 系统时都要受到系统对应的特征值 H(jω)H(j\omega) 的加权


LTI 系统的单位冲激响应 h(t)h(t) 与频率响应 H(jω)H(j\omega) 一一对应,因而 LTI 系统可以由其频率响应完全表征。

⚠️ 并非任何系统的频率响应都存在。

用频率响应表征系统时,一般都限于对稳定系统。

稳定性保证了 h(t)h(t) 的绝对可积,结合 Dirichlet 的另外两个条件(实际系统一般满足),则频率响应必然存在

# ⭐️相乘特性

s(t)FS(jω),p(t)FP(jω)s(t)p(t)F12πS(jω)P(jω)s(t)\stackrel{F}{\longleftrightarrow}S(j\omega)\ \ \ ,\ \ \ p(t)\stackrel{F}{\longleftrightarrow}P(j\omega)\\ \dArr\\ s(t)p(t)\stackrel{F}{\longleftrightarrow}\frac{1}{2\pi}S(j\omega)*P(j\omega)


证明:利用对偶性可以从卷积性质得出相乘性质

由对偶性有:

s(t)FS(jω),p(t)FP(jω)S(jt)F2πS(ω),P(jt)F2πP(ω)s(t)\stackrel{F}{\longleftrightarrow}S(j\omega)\ \ \ ,\ \ \ p(t)\stackrel{F}{\longleftrightarrow}P(j\omega)\\ \dArr\\ S(jt)\stackrel{F}{\longleftrightarrow}2\pi S(-\omega)\ \ \ ,\ \ \ P(jt)\stackrel{F}{\longleftrightarrow}2\pi P(-\omega)\\

由卷积特性有:

S(jt)P(jt)F4π2s(ω)p(ω)S(jt)*P(jt)\stackrel{F}{\longleftrightarrow}4\pi^2s(-\omega)p(-\omega)

由对偶性有:

4π2s(t)p(t)F2πS(jω)P(jω)s(t)p(t)F12πS(jω)P(jω)\begin{aligned} 4\pi^2s(-t)p(-t)&\stackrel{F}{\longleftrightarrow}2\pi S(-j\omega)*P(-j\omega)\\ s(-t)p(-t)&\stackrel{F}{\longleftrightarrow}\frac{1}{2\pi}S(-j\omega)*P(-j\omega) \end{aligned}

# 连续时间 LTI 系统的分析

利用傅里叶变换及其特性对 LTI 系统分析

# 频域分析法

根据卷积特性,可以对 LTI 系统进行频域分析,其过程为:

  1. 求出(或已知、根据系统描述直接得出)系统单位冲激响应 h(t)h(t)
  2. 求输入 x(t)x(t) 的傅里叶正变换:x(t)CTFTX(jω)x(t)\stackrel{CTFT}{\longleftrightarrow}X(j\omega)
  3. 求单位冲激响应 h(t)h(t) 的傅里叶正变换:h(t)CTFTH(jω)h(t)\stackrel{CTFT}{\longleftrightarrow}H(j\omega)
  4. 若需要求 Y(jω)Y(j\omega) ,由傅里叶变换卷积特性得:Y(jω)=X(jω)H(jω)Y(j\omega)=X(j\omega)H(j\omega)
  5. 若需要求 y(t)y(t)
    • x(t)x(t) 是非周期的(或非周期部分):
      • 往往由傅里叶反变换求得:y(t)=F1{Y(jω)}=12π+Y(jω)ejωtdωy(t)=\mathscr{F}^{-1}\{Y(j\omega)\}=\frac{1}{2\pi} \int_{-\infin}^{+\infin} Y(j\omega) e^{j\omega t}d\omega
      • 对有理函数求傅里叶反变换通常采用部分分式展开和利用常用变换对进行
    • x(t)x(t) 是周期的(或周期部分):
      • Y(jω)=X(jω)×H(jω)|Y(j\omega)|=|X(j\omega)|\times|H(j\omega)|
      • argY(jω)=argX(jω)+argH(jω)\text{arg}Y(j\omega)=\text{arg}X(j\omega)+\text{arg}H(j\omega)

# 线性常微分方程

* 线性常系数微分方程

对于由线性常系数微分方程描述的 LTI 系统:

k=0Nakdky(t)dtk=k=0Mbkdkx(t)dtk\sum_{k=0}^{N}a_k\frac{d^ky(t)}{dt^k}=\sum_{k=0}^{M}b_k\frac{d^kx(t)}{dt^k}

对方程两边进行傅里叶变换,有:

k=0Nak(jω)kY(jω)=k=0Mbk(jω)kX(jω)Y(jω)k=0Nak(jω)k=X(jω)k=0Mbk(jω)kY(jω)X(jω)=k=0Mbk(jω)kk=0Nak(jω)k\begin{aligned} \sum_{k=0}^{N}a_{k}(j\omega)^{k}Y(j\omega) &= \sum_{k=0}^{M}b_{k}(j\omega)^{k}X(j\omega)\\ Y(j\omega)\sum_{k=0}^{N}a_{k}(j\omega)^{k} &= X(j\omega)\sum_{k=0}^{M}b_{k}(j\omega)^{k}\\ {Y(j\omega)\over X(j\omega)} &= {\sum_{k=0}^{M}b_{k}(j\omega)^{k}\over\sum_{k=0}^{N}a_{k}(j\omega)^{k}} \end{aligned}

由 CTFT 卷积特性有:

Y(jω)=X(jω)H(jω)Y(j\omega)=X(j\omega)H(j\omega)

可得:

H(jω)=Y(jω)X(jω)=k=0Mbk(jω)kk=0Nak(jω)kH(j\omega)={Y(j\omega)\over X(j\omega)}={\sum_{k=0}^{M}b_{k}(j\omega)^{k}\over\sum_{k=0}^{N}a_{k}(j\omega)^{k}}

可见由线性常系数微分方程描述的 LTI 系统的频率响应是一个有理函数。

若要求 h(t)h(t) ,也就是系统的单位冲激响应,则往往可以对有理函数(有理分式)形式的 H(jω)H(j\omega) 变形化得到常用变换对的表示形式,再利用常用变换对反变换得到 h(t)h(t)


反之,若已知一个 LTI 系统的频率响应 H(jω)=Y(jω)X(jω)H(j\omega)={Y(j\omega)\over X(j\omega)} ,则可以列出两侧分别是关于 Y(jω)Y(j\omega)X(jω)X(j\omega) 的方程,两侧同时进行傅里叶反变换,(注意将 jωj\omega 视为一个整体)则可得到描述该 LTI 系统的线性常系数微分方程

\ No newline at end of file diff --git a/ie/signals-and-systems/DTFT/index.html b/ie/signals-and-systems/DTFT/index.html index d57b97b4..1dfb10be 100644 --- a/ie/signals-and-systems/DTFT/index.html +++ b/ie/signals-and-systems/DTFT/index.html @@ -1,4 +1,4 @@ -离散时间信号的傅里叶变换 - 信号与系统 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 公式表

# 基本傅里叶变换对

基本FT对1基本FT对2

# 性质

性质表1性质表2

# 非周期信号

# FT 公式推导

定义 x~[n]\widetilde{x}[n]

# 公式表

# 基本傅里叶变换对

基本FT对1基本FT对2

# 性质

性质表1性质表2

# 非周期信号

# FT 公式推导

定义 x~[n]\widetilde{x}[n]1argX(e(jω)=arctan1acosωasinω

信号1

# 衰减脉冲 (双侧)

* 名字是我乱起的

x[n]=ana<1x[n]=a^{|n|}\ \ \ \ \ |a|\lt1

x[n]=anu[n1]+anu[n]x[n]=a^{-n}u[-n-1]+a^nu[n]

有傅里叶正变换:

X(ejω)=n=1anejωn+n=0+anejωn=n=1+anejωn+n=0+anejωn=n=1+(aejω)n+n=0+(aejω)n=aejω1aejω+11aejω=1a21+a22acosω\begin{aligned} X(e^{j\omega}) &=\sum_{n=-\infin}^{-1}a^{-n}e^{-j\omega n}+\sum_{n=0}^{+\infin}a^ne^{-j\omega n}\\ &=\sum_{n=1}^{+\infin}a^{n}e^{j\omega n}+\sum_{n=0}^{+\infin}a^ne^{-j\omega n}\\ &=\sum_{n=1}^{+\infin}(ae^{j\omega})^n+\sum_{n=0}^{+\infin}(ae^{-j\omega})^n\\ &=\frac{ae^{j\omega}}{1-ae^{j\omega}}+\frac{1}{1-ae^{-j\omega}}\\ &=\frac{1-a^2}{1+a^2-2a\cos\omega} \end{aligned}

# 冲激信号

x[n]=δ[n]x[n]=\delta[n]

有傅里叶正变换:

X(ejω)=n=+δ[n]ejωn=1X(e^{j\omega})=\sum_{n=-\infin}^{+\infin}\delta[n]e^{-j\omega n}=1

δ(t)\delta(t) 类似,δ[n]\delta[n] 中也包括所有的频率成分,且所有频率分量的幅度、相位都相同

# 矩形脉冲

x[n]={1,nN10,n>N1x[n]= \begin{cases} 1,\ \ \ |n|\leq N_1\\ 0,\ \ \ |n|\gt N_1 \end{cases}

有傅里叶正变换:

X(ejω)=n=N1+N1ejωn=sin[(2N1+1)ω2]sinω2X(e^{j\omega})=\sum_{n=-N_1}^{+N_1}e^{-j\omega n}=\frac{\sin[(2N_1+1)\frac{\omega}{2}]}{\sin\frac{\omega}{2}}

显然,将 X(ejω)X(e^{j\omega}) 中的 ω\omega 代之以 kω0k\omega_0 再乘以 1N\frac{1}{N} ,即是相应周期延拓序列的频谱(傅里叶级数的系数):ak=1NX(ejω)ω=kωa_k=\frac{1}{N}X(e^{j\omega})|_{\omega=k\omega}

# 采样信号

X(ejω)={1,ω<W0,W<ωπX(e^{j\omega})= \begin{cases} 1,\ \ \ |\omega|\lt W\\ 0,\ \ \ W\lt|\omega|\leq\pi \end{cases}

有傅里叶正变换:

x[n]=12πWWejωndω=sinWnπn=WπSa(Wn)=WπSinc(Wnπ)\begin{aligned} x[n] &=\frac{1}{2\pi}\int_{-W}^{W}e^{j\omega n}d\omega\\ &=\frac{\sin Wn}{\pi n}\\ &=\frac{W}{\pi}\text{Sa}(Wn)\\ &=\frac{W}{\pi}\text{Sinc}(\frac{Wn}{\pi}) \end{aligned}

# 常数信号

x[n]=1x[n]=1

因为:

ππδ(ω)ejωndω=112πππ2πδ(ω)ejωndω=1\begin{aligned} \int_{-\pi}^{\pi}\delta(\omega)\cdot e^{j\omega n}d\omega&=1\\ \frac{1}{2\pi}\int_{-\pi}^{\pi}2\pi\cdot\delta(\omega)\cdot e^{j\omega n}d\omega&=1 \end{aligned}

2πδ(ω)2\pi\delta(\omega)2π2\pi 为周期进行周期延拓,得到 x[n]=1x[n]=1 的傅里叶正变换为:

X(ejω)=2πl=+δ(ω2πl)X(e^{j\omega})=2\pi\sum_{l=-\infin}^{+\infin}\delta(\omega-2\pi l)

# 周期信号

# FT 公式推导

对连续时间信号,有 ejω0tCTFT2πδ(ωω0)e^{j\omega_0 t}\stackrel{CTFT}{\longleftrightarrow}2\pi\delta(\omega-\omega_0) ,由此推断,对离散时间信号或许有相似的情况

但对于 x[n]=ejkω0nx[n]=e^{jk\omega_0 n} ,由于离散时间傅里叶变换是以 2π2\pi 为周期的,因此频域的冲激应该是周期性的冲激串(周期延拓),也就是:

X(ejω)=l=+2πδ(ωkω02πl)X(e^{j\omega})=\sum_{l=-\infin}^{+\infin}2\pi\delta(\omega-k\omega_0-2\pi l)

将反变换积分范围包含 ω0\omega_0 ,可以得到:

x[n]=12π2πX(ejω)ejωndω=ω0πω0+πδ(ωω0)ejωndω=ejω0n\begin{aligned} x[n] &=\frac{1}{2\pi}\int_{2\pi}X(e^{j\omega})e^{j\omega n}d\omega\\ &=\int_{\omega_0-\pi}^{\omega_0+\pi}\delta(\omega-\omega_0)e^{j\omega n}d\omega\\ &=e^{j\omega_0 n} \end{aligned}

于是对于表示为傅里叶级数的离散时间周期信号:

x[n]=k=Nakejkω0n,ω0=2πNx[n]=\sum_{k=\langle N\rangle}a_{k}e^{jk\omega_0 n},\ \ \ \omega_0=\frac{2\pi}{N}

就有(傅里叶正变换):

X(ejω)=F{x[n]}=k=NakF{ejkω0n}=k=Nakl=+2πδ(ωkω02πl)=2πl=+k=Nakδ(ωkω0lNω0)=2πl=+k=0N1akδ(ω(lN+k)ω0)=2πl=+lN+k=lNlN+N1alN+kδ(ω(lN+k)ω0)=2πl=+lN+k=lNlN+N1alN+kδ(ω(lN+k)ω0)=2πl=+akδ(ωkω0)\begin{aligned} X(e^{j\omega})=\mathscr{F}\{x[n]\} &=\sum_{k=\langle N\rangle}a_{k}\cdot\mathscr{F}\{e^{jk\omega_{0}n}\}\\ &=\sum_{k=\langle N\rangle}a_{k}\sum_{l=-\infin}^{+\infin}2\pi\delta(\omega-k\omega_0-2\pi l)\\ &=2\pi\sum_{l=-\infin}^{+\infin}\sum_{k=\langle N\rangle}a_{k}\delta(\omega-k\omega_0-lN\omega_0)\\ &=2\pi\sum_{l=-\infin}^{+\infin}\sum_{k=0}^{N-1}a_{k}\delta(\omega-(lN+k)\omega_0)\\ &=2\pi\sum_{l=-\infin}^{+\infin}\ \sum_{lN+k=lN}^{lN+N-1}a_{lN+k}\delta(\omega-(lN+k)\omega_0)\\ &=2\pi\sum_{l=-\infin}^{+\infin}\ \sum_{lN+k=lN}^{lN+N-1}a_{lN+k}\delta(\omega-(lN+k)\omega_0)\\ &=2\pi\sum_{l=-\infin}^{+\infin}a_{k}\delta(\omega-k\omega_0) \end{aligned}

可以发现 DTFT 与 CTFT 形式一致

# 性质

x[n]DTFTX(ejω)x[n]\stackrel{DTFT}{\longleftrightarrow}X(e^{j\omega}) ,则有以下性质成立:

# 周期性

X(ej(ω+2π))=X(ejω)X(e^{j(\omega+2\pi)})=X(e^{j\omega})

# 线性

x[n]DTFTX(ejω),y[n]DTFTY(ejω)ax[n]+by[n]DTFTaX(ejω)+bY(ejω)x[n]\stackrel{DTFT}{\longleftrightarrow}X(e^{j\omega})\ \ ,\ \ y[n]\stackrel{DTFT}{\longleftrightarrow}Y(e^{j\omega})\\ \dArr\\ ax[n]+by[n]\stackrel{DTFT}{\longleftrightarrow}aX(e^{j\omega})+bY(e^{j\omega})

# 时移特性

x[nn0]DTFTX(ejω)ejωn0x[n-n_0]\stackrel{DTFT}{\longleftrightarrow}X(e^{j\omega})e^{-j\omega n_0}

# 频移特性

x[n]ejω0nDTFTX(ej(ωω0))x[n]e^{j\omega_0 n}\stackrel{DTFT}{\longleftrightarrow}X(e^{j(\omega-\omega_0)})

# 时域反转

x[n]DTFTX(ejω)x[-n]\stackrel{DTFT}{\longleftrightarrow}X(e^{-j\omega})

# 共轭对称性

x[n]DTFTX(ejω)x^*[n]\stackrel{DTFT}{\longleftrightarrow}X^*(e^{-j\omega})

特别地,当 x[n]x[n] 是实信号 (实函数),则有频谱: X(ejω)=X(ejω)X(e^{-j\omega})=X^*(e^{-j\omega})共轭偶函数实幅偶,虚相奇

共轭偶函数:

  • 部是函数:Re[X(jω)]=Re[X(jω)]\text{Re}[X(j\omega)]=\text{Re}[X(-j\omega)]
  • 部是函数:Im[X(jω)]=Im[X(jω)]\text{Im}[X(j\omega)]=-\text{Im}[X(-j\omega)]
  • 幅度函数:X(jω)=X(jω)|X(j\omega)|=|X(-j\omega)|
  • 相位函数:ArgX(jω)=ArgX(jω)\text{Arg}X(j\omega)=-\text{Arg}X(-j\omega)

# 奇偶对称性

与 CTFT 的奇偶对称性一致

  • 偶信号的傅里叶 (正) 变换还是偶函数
  • 实偶信号的傅里叶 (正) 变换还是实偶函数
  • 奇信号的傅里叶 (正) 变换还是奇函数
  • 实奇信号的傅里叶 (正) 变换是虚奇函数

用表格总结奇偶性、是否为实函数的不同情况下的傅里叶正变换奇偶情况:

x[n]x[n]偶函数:x[n]=x[n]x[n]=x[-n]奇函数:x[n]=x[n]x[n]=-x[-n]
一般的X(jω)=X(jω)X(j\omega)=X(-j\omega)X(jω)=X(jω)X(j\omega)=-X(-j\omega)
实函数:x[n]=x[n]x[n]=x^*[n]X(jω)=X(jω)=X(jω)=X(jω)X(j\omega)=X(-j\omega)=X^*(j\omega)=X^*(-j\omega)X(jω)=X(jω)=X(jω)X(j\omega)=-X(-j\omega)=X^*(-j\omega)

# 时域差分特性

x[n]x[n1]DTFT(1ejω)X(ejω)x[n]-x[n-1]\stackrel{DTFT}{\longleftrightarrow}(1-e^{-j\omega})X(e^{j\omega})

# 时域累加特性

k=nx[k]DTFTX(ejω)1ejω+πX(ej0)k=+δ(ω2πk)\sum_{k=-\infin}^{n}x[k]\stackrel{DTFT}{\longleftrightarrow}\frac{X(e^{j\omega})}{1-e^{-j\omega}}+\pi X(e^{j0})\sum_{k=-\infin}^{+\infin}\delta(\omega-2\pi k)


时域差分与累加特性说明:离散时间傅里叶变换中的 1ejω1-e^{-j\omega} 对应于连续时间傅里叶变换中的 jωj\omega

# 时域内插

信号的时域特性与频域特性之间有一种相反的关系

定义:

xk[n]={x[nk],n为k的整数倍0,其他nx_k[n]= \begin{cases} x[\frac{n}{k}], &\text{n为k的整数倍}\\ 0, & \text{其他n} \end{cases}

则有:

xk[n]DTFTX(ejkω)x_k[n]\stackrel{DTFT}{\longleftrightarrow}X(e^{jk\omega})


证明:

Xk(ejω)=n=+xk[n]ejωn=r=+xk[rk]ejωrk=r=+x[rkk]ejωrk=r=+x[r]ejkωr=X(ejkω)\begin{aligned} X_k(e^{j\omega}) &=\sum_{n=-\infin}^{+\infin}x_k[n]e^{-j\omega n}\\ &=\sum_{r=-\infin}^{+\infin}x_k[rk]e^{-j\omega rk}\\ &=\sum_{r=-\infin}^{+\infin}x[\frac{rk}{k}]e^{-j\omega rk}\\ &=\sum_{r=-\infin}^{+\infin}x[r]e^{-jk\omega r}\\ &=X(e^{jk\omega}) \end{aligned}

# 频域微分

jnx[n]DTFTdX(ejω)dω-jnx[n]\stackrel{DTFT}{\longleftrightarrow}\frac{dX(e^{j\omega})}{d\omega}

# Parseval 定理

n=+x[n]2=12π2πX(ejω)2dω\sum_{n=-\infin}^{+\infin}|x[n]|^2=\frac{1}{2\pi}\int_{2\pi}|X(e^{j\omega})|^2d\omega

# 卷积特性

x[n]DTFTX(ejω),h[n]DTFTH(ejω)x[n]h[n]DTFTX(ejω)H(ejω)x[n]\stackrel{DTFT}{\longleftrightarrow}X(e^{j\omega})\ \ ,\ \ h[n]\stackrel{DTFT}{\longleftrightarrow}H(e^{j\omega})\\ \dArr\\ x[n]*h[n]\stackrel{DTFT}{\longleftrightarrow}X(e^{j\omega})H(e^{j\omega})

该卷积性质使离散时间 LTI 系统的频域分析非常便利。本质上,卷积性质的成立仍是因为复指数信号 e^{j𝜔n} 是一切离散时间 LTI 系统的特征函数,H(ejω)H(e^{j\omega}) 则是对应的特征值。

# 相乘特性

如果:

y[n]=x1[n]x2[n]y[n]=x_1[n]\cdot x_2[n]

则:

Y(ejω)=12π2πX1(ejθ)X2(ej(ωθ))dθ=12πX1(ejω)X2(ejω)\begin{aligned} Y(e^{j\omega}) &=\frac{1}{2\pi}\int_{2\pi}X_1(e^{j\theta})X_2(e^{j(\omega-\theta)})d\theta\\ &=\frac{1}{2\pi}X_1(e^{j\omega})\otimes X_2(e^{j\omega}) \end{aligned}

因此上述卷积称为周期卷积,因为 X1(ejω)X_1(e^{j\omega})X2(ejω)X_2(e^{j\omega}) 都是以 2π2\pi 为周期的

# 离散时间 LTI 系统的分析

# 频域分析法

⚠️并非所有的 LTI 系统都存在频率响应!一般只考虑稳定的 LTI 系统的频率响应,因为此时 h[n]h[n] 绝对可和,离散时间傅里叶变换(即频率响应)H(ejω)H(e^{j\omega}) 存在。

与连续时间 LTI 系统的频域分析法基本一致

根据卷积特性,可以对 LTI 系统进行频域分析,其过程为:

  1. 求出(或已知、根据系统描述直接得出)系统单位冲激响应 h[n]h[n]
  2. 求输入 x[n]x[n] 的傅里叶正变换:x[n]DTFTX(ejω)x[n]\stackrel{DTFT}{\longleftrightarrow}X(e^{j\omega})
  3. 求单位冲激响应 h[n]h[n] 的傅里叶正变换:h[n]DTFTH(ejω)h[n]\stackrel{DTFT}{\longleftrightarrow}H(e^{j\omega})
  4. 若需要求 Y(ejω)Y(e^{j\omega}) ,由傅里叶变换卷积特性得:Y(ejω)=X(ejω)H(ejω)Y(e^{j\omega})=X(e^{j\omega})H(e^{j\omega})
  5. 若需要求 y[n]y[n]
    • x[n]x[n] 是非周期的(或非周期部分):
      • 往往由傅里叶反变换求得:y[n]=F1{Y(ejω)}=12π+Y(ejω)ejωtdωy[n]=\mathscr{F}^{-1}\{Y(e^{j\omega})\}=\frac{1}{2\pi}\int_{-\infin}^{+\infin} Y(e^{j\omega}) e^{j\omega t}d\omega
      • 对有理函数求傅里叶反变换通常采用部分分式展开和利用常用变换对进行
    • x[n]x[n] 是周期的(或周期部分):
      • Y(ejω)=X(ejω)×H(ejω)|Y(e^{j\omega})|=|X(e^{j\omega})|\times|H(e^{j\omega})|
      • argY(ejω)=argX(ejω)+argH(ejω)\text{arg}Y(e^{j\omega})=\text{arg}X(e^{j\omega})+\text{arg}H(e^{j\omega})

# 线性常差分方程

* 线性常系数差分方程

对于由线性常差分方程描述的 LTI 系统:

k=0Naky[nk]=k=0Mbkx[nk]\sum_{k=0}^{N}a_ky[n-k]=\sum_{k=0}^{M}b_kx[n-k]

对方程两边进行傅里叶变换,有:

k=0NakejkωY(ejω)=k=0MbkejkωX(ejω)Y(ejω)k=0Nakejkω=X(ejω)k=0MbkejkωY(ejω)X(ejω)=k=0Mbkejkωk=0Nakejkω\begin{aligned} \sum_{k=0}^{N}a_{k}e^{-jk\omega}Y(e^{j\omega}) &= \sum_{k=0}^{M}b_{k}e^{-jk\omega}X(e^{j\omega})\\ Y(e^{j\omega})\sum_{k=0}^{N}a_{k}e^{-jk\omega} &= X(e^{j\omega})\sum_{k=0}^{M}b_{k}e^{-jk\omega}\\ {Y(e^{j\omega})\over X(e^{j\omega})} &= {\sum_{k=0}^{M}b_{k}e^{-jk\omega}\over\sum_{k=0}^{N}a_{k}e^{-jk\omega}} \end{aligned}

由 DTFT 卷积特性有:

Y(ejω)=X(ejω)H(ejω)Y(e^{j\omega})=X(e^{j\omega})H(e^{j\omega})

可得:

H(ejω)=Y(ejω)X(ejω)=k=0Mbkejkωk=0NakejkωH(e^{j\omega})={Y(e^{j\omega})\over X(e^{j\omega})}={\sum_{k=0}^{M}b_{k}e^{-jk\omega}\over\sum_{k=0}^{N}a_{k}e^{-jk\omega}}

可见由线性常系数差分方程描述的 LTI 系统的频率响应是一个有理函数。

若要求 h[n]h[n] ,也就是系统的单位冲激响应,则往往可以对有理函数(有理分式)形式的 H(ejω)H(e^{j\omega}) 变形化得到常用变换对的表示形式,再利用常用变换对反变换得到 h[t]h[t]


反之,若已知一个 LTI 系统的频率响应 H(ejω)=Y(ejω)X(ejω)H(e^{j\omega})={Y(e^{j\omega})\over X(e^{j\omega})} ,则可以列出两侧分别是关于 Y(ejω)Y(e^{j\omega})X(ejω)X(e^{j\omega}) 的方程,两侧同时进行傅里叶反变换,(注意将 ejωe^{j\omega} 视为一个整体)则可得到描述该 LTI 系统的线性常系数微分方程

\ No newline at end of file +M834 80h400000v40h-400000z"/>1argX(e(jω)=arctan1acosωasinω

信号1

# 衰减脉冲 (双侧)

* 名字是我乱起的

x[n]=ana<1x[n]=a^{|n|}\ \ \ \ \ |a|\lt1

x[n]=anu[n1]+anu[n]x[n]=a^{-n}u[-n-1]+a^nu[n]

有傅里叶正变换:

X(ejω)=n=1anejωn+n=0+anejωn=n=1+anejωn+n=0+anejωn=n=1+(aejω)n+n=0+(aejω)n=aejω1aejω+11aejω=1a21+a22acosω\begin{aligned} X(e^{j\omega}) &=\sum_{n=-\infin}^{-1}a^{-n}e^{-j\omega n}+\sum_{n=0}^{+\infin}a^ne^{-j\omega n}\\ &=\sum_{n=1}^{+\infin}a^{n}e^{j\omega n}+\sum_{n=0}^{+\infin}a^ne^{-j\omega n}\\ &=\sum_{n=1}^{+\infin}(ae^{j\omega})^n+\sum_{n=0}^{+\infin}(ae^{-j\omega})^n\\ &=\frac{ae^{j\omega}}{1-ae^{j\omega}}+\frac{1}{1-ae^{-j\omega}}\\ &=\frac{1-a^2}{1+a^2-2a\cos\omega} \end{aligned}

# 冲激信号

x[n]=δ[n]x[n]=\delta[n]

有傅里叶正变换:

X(ejω)=n=+δ[n]ejωn=1X(e^{j\omega})=\sum_{n=-\infin}^{+\infin}\delta[n]e^{-j\omega n}=1

δ(t)\delta(t) 类似,δ[n]\delta[n] 中也包括所有的频率成分,且所有频率分量的幅度、相位都相同

# 矩形脉冲

x[n]={1,nN10,n>N1x[n]= \begin{cases} 1,\ \ \ |n|\leq N_1\\ 0,\ \ \ |n|\gt N_1 \end{cases}

有傅里叶正变换:

X(ejω)=n=N1+N1ejωn=sin[(2N1+1)ω2]sinω2X(e^{j\omega})=\sum_{n=-N_1}^{+N_1}e^{-j\omega n}=\frac{\sin[(2N_1+1)\frac{\omega}{2}]}{\sin\frac{\omega}{2}}

显然,将 X(ejω)X(e^{j\omega}) 中的 ω\omega 代之以 kω0k\omega_0 再乘以 1N\frac{1}{N} ,即是相应周期延拓序列的频谱(傅里叶级数的系数):ak=1NX(ejω)ω=kωa_k=\frac{1}{N}X(e^{j\omega})|_{\omega=k\omega}

# 采样信号

X(ejω)={1,ω<W0,W<ωπX(e^{j\omega})= \begin{cases} 1,\ \ \ |\omega|\lt W\\ 0,\ \ \ W\lt|\omega|\leq\pi \end{cases}

有傅里叶正变换:

x[n]=12πWWejωndω=sinWnπn=WπSa(Wn)=WπSinc(Wnπ)\begin{aligned} x[n] &=\frac{1}{2\pi}\int_{-W}^{W}e^{j\omega n}d\omega\\ &=\frac{\sin Wn}{\pi n}\\ &=\frac{W}{\pi}\text{Sa}(Wn)\\ &=\frac{W}{\pi}\text{Sinc}(\frac{Wn}{\pi}) \end{aligned}

# 常数信号

x[n]=1x[n]=1

因为:

ππδ(ω)ejωndω=112πππ2πδ(ω)ejωndω=1\begin{aligned} \int_{-\pi}^{\pi}\delta(\omega)\cdot e^{j\omega n}d\omega&=1\\ \frac{1}{2\pi}\int_{-\pi}^{\pi}2\pi\cdot\delta(\omega)\cdot e^{j\omega n}d\omega&=1 \end{aligned}

2πδ(ω)2\pi\delta(\omega)2π2\pi 为周期进行周期延拓,得到 x[n]=1x[n]=1 的傅里叶正变换为:

X(ejω)=2πl=+δ(ω2πl)X(e^{j\omega})=2\pi\sum_{l=-\infin}^{+\infin}\delta(\omega-2\pi l)

# 周期信号

# FT 公式推导

对连续时间信号,有 ejω0tCTFT2πδ(ωω0)e^{j\omega_0 t}\stackrel{CTFT}{\longleftrightarrow}2\pi\delta(\omega-\omega_0) ,由此推断,对离散时间信号或许有相似的情况

但对于 x[n]=ejkω0nx[n]=e^{jk\omega_0 n} ,由于离散时间傅里叶变换是以 2π2\pi 为周期的,因此频域的冲激应该是周期性的冲激串(周期延拓),也就是:

X(ejω)=l=+2πδ(ωkω02πl)X(e^{j\omega})=\sum_{l=-\infin}^{+\infin}2\pi\delta(\omega-k\omega_0-2\pi l)

将反变换积分范围包含 ω0\omega_0 ,可以得到:

x[n]=12π2πX(ejω)ejωndω=ω0πω0+πδ(ωω0)ejωndω=ejω0n\begin{aligned} x[n] &=\frac{1}{2\pi}\int_{2\pi}X(e^{j\omega})e^{j\omega n}d\omega\\ &=\int_{\omega_0-\pi}^{\omega_0+\pi}\delta(\omega-\omega_0)e^{j\omega n}d\omega\\ &=e^{j\omega_0 n} \end{aligned}

于是对于表示为傅里叶级数的离散时间周期信号:

x[n]=k=Nakejkω0n,ω0=2πNx[n]=\sum_{k=\langle N\rangle}a_{k}e^{jk\omega_0 n},\ \ \ \omega_0=\frac{2\pi}{N}

就有(傅里叶正变换):

X(ejω)=F{x[n]}=k=NakF{ejkω0n}=k=Nakl=+2πδ(ωkω02πl)=2πl=+k=Nakδ(ωkω0lNω0)=2πl=+k=0N1akδ(ω(lN+k)ω0)=2πl=+lN+k=lNlN+N1alN+kδ(ω(lN+k)ω0)=2πl=+lN+k=lNlN+N1alN+kδ(ω(lN+k)ω0)=2πl=+akδ(ωkω0)\begin{aligned} X(e^{j\omega})=\mathscr{F}\{x[n]\} &=\sum_{k=\langle N\rangle}a_{k}\cdot\mathscr{F}\{e^{jk\omega_{0}n}\}\\ &=\sum_{k=\langle N\rangle}a_{k}\sum_{l=-\infin}^{+\infin}2\pi\delta(\omega-k\omega_0-2\pi l)\\ &=2\pi\sum_{l=-\infin}^{+\infin}\sum_{k=\langle N\rangle}a_{k}\delta(\omega-k\omega_0-lN\omega_0)\\ &=2\pi\sum_{l=-\infin}^{+\infin}\sum_{k=0}^{N-1}a_{k}\delta(\omega-(lN+k)\omega_0)\\ &=2\pi\sum_{l=-\infin}^{+\infin}\ \sum_{lN+k=lN}^{lN+N-1}a_{lN+k}\delta(\omega-(lN+k)\omega_0)\\ &=2\pi\sum_{l=-\infin}^{+\infin}\ \sum_{lN+k=lN}^{lN+N-1}a_{lN+k}\delta(\omega-(lN+k)\omega_0)\\ &=2\pi\sum_{l=-\infin}^{+\infin}a_{k}\delta(\omega-k\omega_0) \end{aligned}

可以发现 DTFT 与 CTFT 形式一致

# 性质

x[n]DTFTX(ejω)x[n]\stackrel{DTFT}{\longleftrightarrow}X(e^{j\omega}) ,则有以下性质成立:

# 周期性

X(ej(ω+2π))=X(ejω)X(e^{j(\omega+2\pi)})=X(e^{j\omega})

# 线性

x[n]DTFTX(ejω),y[n]DTFTY(ejω)ax[n]+by[n]DTFTaX(ejω)+bY(ejω)x[n]\stackrel{DTFT}{\longleftrightarrow}X(e^{j\omega})\ \ ,\ \ y[n]\stackrel{DTFT}{\longleftrightarrow}Y(e^{j\omega})\\ \dArr\\ ax[n]+by[n]\stackrel{DTFT}{\longleftrightarrow}aX(e^{j\omega})+bY(e^{j\omega})

# 时移特性

x[nn0]DTFTX(ejω)ejωn0x[n-n_0]\stackrel{DTFT}{\longleftrightarrow}X(e^{j\omega})e^{-j\omega n_0}

# 频移特性

x[n]ejω0nDTFTX(ej(ωω0))x[n]e^{j\omega_0 n}\stackrel{DTFT}{\longleftrightarrow}X(e^{j(\omega-\omega_0)})

# 时域反转

x[n]DTFTX(ejω)x[-n]\stackrel{DTFT}{\longleftrightarrow}X(e^{-j\omega})

# 共轭对称性

x[n]DTFTX(ejω)x^*[n]\stackrel{DTFT}{\longleftrightarrow}X^*(e^{-j\omega})

特别地,当 x[n]x[n] 是实信号 (实函数),则有频谱: X(ejω)=X(ejω)X(e^{-j\omega})=X^*(e^{-j\omega})共轭偶函数实幅偶,虚相奇

共轭偶函数:

  • 部是函数:Re[X(jω)]=Re[X(jω)]\text{Re}[X(j\omega)]=\text{Re}[X(-j\omega)]
  • 部是函数:Im[X(jω)]=Im[X(jω)]\text{Im}[X(j\omega)]=-\text{Im}[X(-j\omega)]
  • 幅度函数:X(jω)=X(jω)|X(j\omega)|=|X(-j\omega)|
  • 相位函数:ArgX(jω)=ArgX(jω)\text{Arg}X(j\omega)=-\text{Arg}X(-j\omega)

# 奇偶对称性

与 CTFT 的奇偶对称性一致

  • 偶信号的傅里叶 (正) 变换还是偶函数
  • 实偶信号的傅里叶 (正) 变换还是实偶函数
  • 奇信号的傅里叶 (正) 变换还是奇函数
  • 实奇信号的傅里叶 (正) 变换是虚奇函数

用表格总结奇偶性、是否为实函数的不同情况下的傅里叶正变换奇偶情况:

x[n]x[n]偶函数:x[n]=x[n]x[n]=x[-n]奇函数:x[n]=x[n]x[n]=-x[-n]
一般的X(jω)=X(jω)X(j\omega)=X(-j\omega)X(jω)=X(jω)X(j\omega)=-X(-j\omega)
实函数:x[n]=x[n]x[n]=x^*[n]X(jω)=X(jω)=X(jω)=X(jω)X(j\omega)=X(-j\omega)=X^*(j\omega)=X^*(-j\omega)X(jω)=X(jω)=X(jω)X(j\omega)=-X(-j\omega)=X^*(-j\omega)

# 时域差分特性

x[n]x[n1]DTFT(1ejω)X(ejω)x[n]-x[n-1]\stackrel{DTFT}{\longleftrightarrow}(1-e^{-j\omega})X(e^{j\omega})

# 时域累加特性

k=nx[k]DTFTX(ejω)1ejω+πX(ej0)k=+δ(ω2πk)\sum_{k=-\infin}^{n}x[k]\stackrel{DTFT}{\longleftrightarrow}\frac{X(e^{j\omega})}{1-e^{-j\omega}}+\pi X(e^{j0})\sum_{k=-\infin}^{+\infin}\delta(\omega-2\pi k)


时域差分与累加特性说明:离散时间傅里叶变换中的 1ejω1-e^{-j\omega} 对应于连续时间傅里叶变换中的 jωj\omega

# 时域内插

信号的时域特性与频域特性之间有一种相反的关系

定义:

xk[n]={x[nk],n为k的整数倍0,其他nx_k[n]= \begin{cases} x[\frac{n}{k}], &\text{n为k的整数倍}\\ 0, & \text{其他n} \end{cases}

则有:

xk[n]DTFTX(ejkω)x_k[n]\stackrel{DTFT}{\longleftrightarrow}X(e^{jk\omega})


证明:

Xk(ejω)=n=+xk[n]ejωn=r=+xk[rk]ejωrk=r=+x[rkk]ejωrk=r=+x[r]ejkωr=X(ejkω)\begin{aligned} X_k(e^{j\omega}) &=\sum_{n=-\infin}^{+\infin}x_k[n]e^{-j\omega n}\\ &=\sum_{r=-\infin}^{+\infin}x_k[rk]e^{-j\omega rk}\\ &=\sum_{r=-\infin}^{+\infin}x[\frac{rk}{k}]e^{-j\omega rk}\\ &=\sum_{r=-\infin}^{+\infin}x[r]e^{-jk\omega r}\\ &=X(e^{jk\omega}) \end{aligned}

# 频域微分

jnx[n]DTFTdX(ejω)dω-jnx[n]\stackrel{DTFT}{\longleftrightarrow}\frac{dX(e^{j\omega})}{d\omega}

# Parseval 定理

n=+x[n]2=12π2πX(ejω)2dω\sum_{n=-\infin}^{+\infin}|x[n]|^2=\frac{1}{2\pi}\int_{2\pi}|X(e^{j\omega})|^2d\omega

# 卷积特性

x[n]DTFTX(ejω),h[n]DTFTH(ejω)x[n]h[n]DTFTX(ejω)H(ejω)x[n]\stackrel{DTFT}{\longleftrightarrow}X(e^{j\omega})\ \ ,\ \ h[n]\stackrel{DTFT}{\longleftrightarrow}H(e^{j\omega})\\ \dArr\\ x[n]*h[n]\stackrel{DTFT}{\longleftrightarrow}X(e^{j\omega})H(e^{j\omega})

该卷积性质使离散时间 LTI 系统的频域分析非常便利。本质上,卷积性质的成立仍是因为复指数信号 e^{j𝜔n} 是一切离散时间 LTI 系统的特征函数,H(ejω)H(e^{j\omega}) 则是对应的特征值。

# 相乘特性

如果:

y[n]=x1[n]x2[n]y[n]=x_1[n]\cdot x_2[n]

则:

Y(ejω)=12π2πX1(ejθ)X2(ej(ωθ))dθ=12πX1(ejω)X2(ejω)\begin{aligned} Y(e^{j\omega}) &=\frac{1}{2\pi}\int_{2\pi}X_1(e^{j\theta})X_2(e^{j(\omega-\theta)})d\theta\\ &=\frac{1}{2\pi}X_1(e^{j\omega})\otimes X_2(e^{j\omega}) \end{aligned}

因此上述卷积称为周期卷积,因为 X1(ejω)X_1(e^{j\omega})X2(ejω)X_2(e^{j\omega}) 都是以 2π2\pi 为周期的

# 离散时间 LTI 系统的分析

# 频域分析法

⚠️并非所有的 LTI 系统都存在频率响应!一般只考虑稳定的 LTI 系统的频率响应,因为此时 h[n]h[n] 绝对可和,离散时间傅里叶变换(即频率响应)H(ejω)H(e^{j\omega}) 存在。

与连续时间 LTI 系统的频域分析法基本一致

根据卷积特性,可以对 LTI 系统进行频域分析,其过程为:

  1. 求出(或已知、根据系统描述直接得出)系统单位冲激响应 h[n]h[n]
  2. 求输入 x[n]x[n] 的傅里叶正变换:x[n]DTFTX(ejω)x[n]\stackrel{DTFT}{\longleftrightarrow}X(e^{j\omega})
  3. 求单位冲激响应 h[n]h[n] 的傅里叶正变换:h[n]DTFTH(ejω)h[n]\stackrel{DTFT}{\longleftrightarrow}H(e^{j\omega})
  4. 若需要求 Y(ejω)Y(e^{j\omega}) ,由傅里叶变换卷积特性得:Y(ejω)=X(ejω)H(ejω)Y(e^{j\omega})=X(e^{j\omega})H(e^{j\omega})
  5. 若需要求 y[n]y[n]
    • x[n]x[n] 是非周期的(或非周期部分):
      • 往往由傅里叶反变换求得:y[n]=F1{Y(ejω)}=12π+Y(ejω)ejωtdωy[n]=\mathscr{F}^{-1}\{Y(e^{j\omega})\}=\frac{1}{2\pi}\int_{-\infin}^{+\infin} Y(e^{j\omega}) e^{j\omega t}d\omega
      • 对有理函数求傅里叶反变换通常采用部分分式展开和利用常用变换对进行
    • x[n]x[n] 是周期的(或周期部分):
      • Y(ejω)=X(ejω)×H(ejω)|Y(e^{j\omega})|=|X(e^{j\omega})|\times|H(e^{j\omega})|
      • argY(ejω)=argX(ejω)+argH(ejω)\text{arg}Y(e^{j\omega})=\text{arg}X(e^{j\omega})+\text{arg}H(e^{j\omega})

# 线性常差分方程

* 线性常系数差分方程

对于由线性常差分方程描述的 LTI 系统:

k=0Naky[nk]=k=0Mbkx[nk]\sum_{k=0}^{N}a_ky[n-k]=\sum_{k=0}^{M}b_kx[n-k]

对方程两边进行傅里叶变换,有:

k=0NakejkωY(ejω)=k=0MbkejkωX(ejω)Y(ejω)k=0Nakejkω=X(ejω)k=0MbkejkωY(ejω)X(ejω)=k=0Mbkejkωk=0Nakejkω\begin{aligned} \sum_{k=0}^{N}a_{k}e^{-jk\omega}Y(e^{j\omega}) &= \sum_{k=0}^{M}b_{k}e^{-jk\omega}X(e^{j\omega})\\ Y(e^{j\omega})\sum_{k=0}^{N}a_{k}e^{-jk\omega} &= X(e^{j\omega})\sum_{k=0}^{M}b_{k}e^{-jk\omega}\\ {Y(e^{j\omega})\over X(e^{j\omega})} &= {\sum_{k=0}^{M}b_{k}e^{-jk\omega}\over\sum_{k=0}^{N}a_{k}e^{-jk\omega}} \end{aligned}

由 DTFT 卷积特性有:

Y(ejω)=X(ejω)H(ejω)Y(e^{j\omega})=X(e^{j\omega})H(e^{j\omega})

可得:

H(ejω)=Y(ejω)X(ejω)=k=0Mbkejkωk=0NakejkωH(e^{j\omega})={Y(e^{j\omega})\over X(e^{j\omega})}={\sum_{k=0}^{M}b_{k}e^{-jk\omega}\over\sum_{k=0}^{N}a_{k}e^{-jk\omega}}

可见由线性常系数差分方程描述的 LTI 系统的频率响应是一个有理函数。

若要求 h[n]h[n] ,也就是系统的单位冲激响应,则往往可以对有理函数(有理分式)形式的 H(ejω)H(e^{j\omega}) 变形化得到常用变换对的表示形式,再利用常用变换对反变换得到 h[t]h[t]


反之,若已知一个 LTI 系统的频率响应 H(ejω)=Y(ejω)X(ejω)H(e^{j\omega})={Y(e^{j\omega})\over X(e^{j\omega})} ,则可以列出两侧分别是关于 Y(ejω)Y(e^{j\omega})X(ejω)X(e^{j\omega}) 的方程,两侧同时进行傅里叶反变换,(注意将 ejωe^{j\omega} 视为一个整体)则可得到描述该 LTI 系统的线性常系数微分方程

\ No newline at end of file diff --git a/ie/signals-and-systems/FS/index.html b/ie/signals-and-systems/FS/index.html index d2e52651..ffb0f8c5 100644 --- a/ie/signals-and-systems/FS/index.html +++ b/ie/signals-and-systems/FS/index.html @@ -1,4 +1,4 @@ -周期信号的傅里叶级数表示 - 信号与系统 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 连续时间周期信号的傅里叶级数表示

# 连续时间傅里叶级数

谐波关系的复指数信号集:ejkω0t,k=0,±1,±2,e^{jk\omega_0 t},\ \ \ k=0,\pm 1,\pm 2,\cdots ,满足:

  • 每个信号周期为:2πω=2πkω0\frac{2\pi}{|\omega|}=\frac{2\pi}{|k\omega_0|}
  • 公共周期为:T=2πω0T=\frac{2\pi}{|\omega_0|}
  • 各信号彼此独立

这些信号的线性组合称为 (连续) 傅里叶级数

x(t)=k=+akejkω0t,k=0,±1,±2,x(t)=\sum_{k=-\infin}^{+\infin}a_k e^{jk\omega_0 t},\ \ \ k=0,\pm 1,\pm 2,\cdots

则有:

  • 基波频率 ω0\omega_0,即 k=1k=1 时的频率 ω=kω0\omega=k\omega_0
  • (基波) 周期: T=2πω0T=\frac{2\pi}{|\omega_0|}
  • aka_k 称为傅立叶级数的系数
  • k = 0 对应直流分量
  • k = ±1 对应一次谐波
  • k = ±2 对应二次谐波

# 频谱图

在傅里叶级数中,各个信号分量(谐波分量)间的区别仅仅是系数频率不同。

因此,可以用线段来表示分量的系数,用线段的位置表示相应的频率(谐波次数)

实系数傅里叶级数

x(t)=k=+akejkω0t,k=0,±1,±2,,akRx(t)=\sum_{k=-\infin}^{+\infin}a_k e^{jk\omega_0 t},\ \ \ k=0,\pm 1,\pm 2,\cdots,\ \ \ a_k\in\mathbb{R}

可以表示为:

频谱图1

akCa_k\in\mathbb{C} 为复系数傅里叶级数时,通常分幅度与相位分别作图:

频谱图2

# 确定系数

如果周期信号 x (t) 可以表示为傅里叶级数:

x(t)=k=+akejkω0t,k=0,±1,±2,,ω0=2πTx(t)=\sum_{k=-\infin}^{+\infin}a_k e^{jk\omega_0 t},\ \ \ k=0,\pm 1,\pm 2,\cdots,\ \ \ \omega_0=\frac{2\pi}{T}

则有:

x(t)ejnω0t=k=+akej(kn)ω0tx(t) e^{-jn\omega_0 t} = \sum_{k=-\infin}^{+\infin}a_k e^{j(k-n)\omega_0 t}

对两边同时在一个周期内积分,有:

0Tx(t)ejnω0tdy=k=+ak0Tej(kn)ω0tdt\begin{aligned} \int_{0}^{T}x(t) e^{-jn\omega_0 t}dy &= \sum_{k=-\infin}^{+\infin} a_k \int_{0}^{T} e^{j(k-n)\omega_0 t}dt \end{aligned}

其中:

0Tej(kn)ω0tdt=0Tcos((kn)ω0t)dt+j0Tsin((kn)ω0t)dt={0,knT,k=n\begin{aligned} \int_{0}^{T} e^{j(k-n)\omega_0 t}dt &=\int_{0}^{T}cos((k-n)\omega_0 t)dt+j\int_{0}^{T}sin((k-n)\omega_0 t)dt\\ &= \begin{cases} 0,\ \ \ k\neq n\\ T,\ \ \ k=n \end{cases} \end{aligned}

所以:

0Tx(t)ejnω0tdt=k=+ak0Tej(kn)ω0tdt=anT\begin{aligned} \int_{0}^{T}x(t) e^{-jn\omega_0 t}dt &= \sum_{k=-\infin}^{+\infin} a_k \int_{0}^{T} e^{j(k-n)\omega_0 t}dt\\ &= a_n T \end{aligned}

可得 ana_n

an=1T0Tx(t)ejnω0tdt\begin{aligned} a_n &= \frac{1}{T}\int_{0}^{T}x(t) e^{-jn\omega_0 t}dt \end{aligned}

在确定此积分时,只要积分区间是一个周期即可,对积分区间的起止并无特别要求,因此可表示为:

ak=1TTx(t)ejkω0tdt=1TTx(t)[cos(kω0t)jsin(kω0t)]dt\begin{aligned} a_k &= \frac{1}{T}{\int}_{T} x(t) e^{-jk\omega_0 t}dt\\ &= \frac{1}{T}{\int}_{T} x(t) [\text{cos}(k\omega_0t)-j\ \text{sin}(k\omega_0t)]dt \end{aligned}

n=0n=0 时信号在一个周期的平均值,通常称直流分量

a0=1TTx(t)dt\begin{aligned} a_0 &= \frac{1}{T}{\int}_{T} x(t) dt \end{aligned}

# 周期性矩形脉冲信号

周期性矩形脉冲信号

ak=1TTx(t)ejkω0tdt=1TT1T1ejkω0tdt=1jkω0Tejkω0tT1T1=2sin(kω0T1)kω0T=2T1T2sin(kω0T1)kω0T1(ω0=2πT)=2T1TSa(kπ2T1T)\begin{aligned} a_k &= \frac{1}{T}{\int}_{T} x(t) e^{-jk\omega_0 t}dt\\ &= \frac{1}{T}{\int}_{-T_1}^{T_1}e^{-jk\omega_0 t}dt\\ &= -\frac{1}{jk\omega_0 T} e^{-jk\omega_0t}|_{-T_1}^{T_1}\\ &= \frac{2\text{sin}(k\omega_0 T_1)}{k\omega_0 T}\\ &= \frac{2T_1}{T}\frac{2\text{sin}(k\omega_0 T_1)}{k\omega_0 T_1}\\ (\omega_0=\frac{2\pi}{T}) &= \frac{2T_1}{T}\text{Sa}(k\pi\frac{2T_1}{T}) \end{aligned}

其中 Sa(...)\text{Sa}(...) 是抽样信号:

Sa(x)=sinxx\text{Sa}(x)=\frac{\text{sin}x}{x}

基波频率为:ω0=2πT\omega_0=\frac{2\pi}{T}

类似地:

sinc(x)=sinπxπx\text{sinc}(x)=\frac{\text{sin}\pi x}{\pi x}

抽样信号

不同占空比的周期性矩形脉冲信号的傅里叶级数表示:

不同占空比的周期性矩形脉冲信号的傅里叶级数表示

# 收敛性

x(t)x(t) 以 T 为周期,用有限项级数:

xN(t)=k=NNakejkω0tx_N(t)=\sum_{k=-N}^{N}a_k e^{jk\omega_0 t}

近似 x(t)x(t) 时,定义误差:

eN(t)=x(t)xN(t)=x(t)k=NNakejkω0te_N(t)=x(t)-x_N(t)=x(t)-\sum_{k=-N}^{N}a_k e^{jk\omega_0 t}

误差在一个周期内的能量为:

EN=TeN(t)2dtE_N=\int_{T}|e_N(t)|^2dt

可以证明,要使 ENE_N 最小,应有:

ak=1TTx(t)ejkω0tdta_k= \frac{1}{T}{\int}_{T} x(t) e^{-jk\omega_0 t}dt

结论:在误差能量ENE_N 最小的准则下,傅里叶级数是对周期信号的最佳近似

# 收敛的充分条件

两组条件并不完全等价。它们都是傅里叶级数收敛的充分条件。

相当广泛的信号都能满足这两组条件中的一组,因而用傅里叶级数表示周期信号具有相当的普遍适用性

# 平方可积条件

如果:

Tx(t)2dt<\int_{T}|x(t)|^2dt \lt \infin

aka_k 必存在。

此时 x (t) 与其傅里叶级数表示之间没有能量上的区别

# Dirichlet 条件

(1)x(t)x(t) 在任何周期内信号绝对可积,即:

Tx(t)dt<\int_{T}|x(t)|dt \lt \infin

(2)在任何有限区间内,只有有限个极值点,且极值为有限值

(3)在任何有限区间内,只有有限个间断点,且在这些间断点上,函数值有限

Dirichlet 条件保证在间断点之外 x(t)x(t) 等于它的傅里叶级数;而在间断点上,该无穷级数收敛于间断点两边值的平均值

# 实信号的傅里叶级数其他形式 (如考)

x(t)x(t) 是实信号,则有 :

x(t)=x(t)x(t)=x^*(t)

从而有:

x(t)=[k=+akejkω0t]x^*(t)=[\sum_{k=-\infin}^{+\infin}a_k e^{jk\omega_0 t}]^*


# Gibbs 现象

满足 Dirichlet 条件的信号,其傅里叶级数是如何收敛于 x(t)x(t) 的?特别当 x(t)x(t) 具有间断点时,在间断点附近,如何收敛于 x(t)x(t) ?

Gibbs 现象表明:

用有限项傅里叶级数表示有间断点的信号时,在间断点附近不可避免的会出现振荡和超量。超量的幅度不会随所取项数的增加而减小。只是随着项数的增多,振荡频率变高,并向间断点处压缩,从而使它所占有的能量减少


# 离散时间周期信号的傅里叶级数表示

# 离散时间傅里叶级数

谐波关系的复指数信号集:Φk[n]={ej2πNkt},k=0,±1,±2,\Phi_k[n]=\{e^{j\frac{2\pi}{N}kt}\},\ \ \ k=0,\pm 1,\pm 2,\cdots ,满足:

  • 每个信号周期为:Nk\frac{N}{k}
  • 公共周期为:NN
  • 各信号彼此独立

这些信号的线性组合称为离散傅里叶级数

x[n]=k=Nakej2πNkn,k=0,±1,±2,x[n]=\sum_{k=\langle N\rangle}a_k e^{j\frac{2\pi}{N}kn},\ \ \ k=0,\pm 1,\pm 2,\cdots

⭐️其中 N\langle N\rangle 表示一个总共 NN 个的连续序列,起始和结束没有要求。

则有:

  • 基波频率 ω0=2πN\omega_0=\frac{2\pi}{N},即 k=1k=1 时的频率 ω=kω0=2kπN\omega=k\omega_0=\frac{2k\pi}{N}
  • (基波) 周期:NN
  • aka_k 为傅立叶级数的系数,也称为 x[n]x[n]频谱系数

# 确定系数

x[n]=k=Nakej2πNktx[n]=\sum_{k=\langle N\rangle}a_{k}e^{j\frac{2\pi}{N}kt} 两边同时乘 ej2πNrne^{-j\frac{2\pi}{N}rn} ,可得:

x[n]ej2πNrn=k=Nakej2πN(kr)nx[n]e^{-j\frac{2\pi}{N}rn}=\sum_{k=\langle N\rangle}a_k e^{j\frac{2\pi}{N}(k-r)n}

显然 x[n]ej2πNrnx[n]e^{-j\frac{2\pi}{N}rn} 仍然是以 N 为周期的,对两边求和:

n=Nx[n]ej2πNrn=n=Nk=Nakej2πN(kr)n=k=Nakn=Nej2πN(kr)n\sum_{n=\langle N\rangle}x[n]e^{-j\frac{2\pi}{N}rn} =\sum_{n=\langle N\rangle}\sum_{k=\langle N\rangle}a_k e^{j\frac{2\pi}{N}(k-r)n} =\sum_{k=\langle N\rangle}a_k \sum_{n=\langle N\rangle}e^{j\frac{2\pi}{N}(k-r)n}

其中:

n=Nej2πN(kr)n=n=0N1ej2πN(kr)n=1ej(kr)2π1ej(kr)2πN={0,krN,k=r\begin{aligned} \sum_{n=\langle N\rangle}e^{j\frac{2\pi}{N}(k-r)n} &= \sum_{n=0}^{N-1}e^{j\frac{2\pi}{N}(k-r)n}\\ &= \frac{1-e^{j(k-r)2\pi}}{1-e^{j(k-r)\frac{2\pi}{N}}}\\ &= \begin{cases} 0,\ \ \ k\neq r\\ N,\ \ \ k=r \end{cases} \end{aligned}

从而:

n=Nx[n]ej2πNrn=Nar\sum_{n=\langle N\rangle}x[n]e^{-j\frac{2\pi}{N}rn}=Na_r

即可得:(r 换成了 k)

ak=1Nn=Nx[n]ej2πNkna_k=\frac{1}{N}\sum_{n=\langle N\rangle}x[n]e^{-j\frac{2\pi}{N}kn}

显然上式满足 ak+N=aka_{k+N}=a_k ,即也是以 NN 为周期的,或者说 aka_k 中只有 NN 个是独立的

# 周期性方波序列

周期性方波序列

ak=1Nn=Nx[n]ej2πNkn=1Nn=N1N1ej2πNkn=1Nej2πNkN1ej2πNk(N1+1)1ej2πNk=1NejπNkejπNkej2πNk(N1+12)ej2πNk(N1+12)ejπNkejπNk=1NsinπNk(2N1+1)sinπNk,k0,±N,±2N,=1Nsinkω0(N1+12)sinkω02,k0,±N,±2N,\begin{aligned} a_k &= \frac{1}{N}\sum_{n=\langle N\rangle}x[n]e^{-j\frac{2\pi}{N}kn} \\ &= \frac{1}{N}\sum_{n=-N_1}^{N_1}e^{-j\frac{2\pi}{N}kn} \\ &= \frac{1}{N}\frac {e^{j\frac{2\pi}{N}kN_1}-e^{-j\frac{2\pi}{N}k(N_1+1)}} {1-e^{-j\frac{2\pi}{N}k}} \\ &= \frac{1}{N}\frac{e^{-j\frac{\pi}{N}k}}{e^{-j\frac{\pi}{N}k}}\frac {e^{j\frac{2\pi}{N}k(N_1+\frac{1}{2})}-e^{-j\frac{2\pi}{N}k(N_1+\frac{1}{2})}} {e^{j\frac{\pi}{N}k}-e^{-j\frac{\pi}{N}k}} \\ &= \frac{1}{N}\frac{\text{sin}\frac{\pi}{N}k(2N_1+1)}{\text{sin}\frac{\pi}{N}k},\ \ \ \ k\neq 0,\pm N,\pm 2N,\cdots\\ &= \frac{1}{N}\frac{\text{sin}k\omega_0(N_1+\frac{1}{2})}{\text{sin}\frac{k\omega_0}{2}},\ \ \ \ k\neq 0,\pm N,\pm 2N,\cdots \end{aligned}

ak=2N1+1N,k=rNa_k = \frac{2N_1+1}{N},\ \ \ \ k=rN

# 收敛性

离散时间傅里叶级数是一个有限项的级数,确定 aka_k 的关系式也是有限项的和式,因而不存在收敛问题,也不会产生 Gibbs 现象

# LTI 系统对复指数信号的响应

# 特征函数与特征值

考查 LTI 系统对复指数信号 este^{st} 作为输入时的响应

连续复指数信号输入

y(t)=+es(tτ)h(τ)dτ=est+esτh(τ)dτ=estH(s)\begin{aligned} y(t) &=\int_{-\infin}^{+\infin}e^{s(t-\tau)}h(\tau)d\tau \\ &= e^{st}\int_{-\infin}^{+\infin}e^{-s\tau}h(\tau)d\tau \\ &= e^{st}H(s) \end{aligned}

其中:

H(s)=+esτh(τ)dτH(s) = \int_{-\infin}^{+\infin}e^{-s\tau}h(\tau)d\tau

考查 LTI 系统对复指数信号 znz^n 作为输入时的响应

离散复指数信号输入

y[n]=k=+znkh[k]=znk=+zkh[k]=znH(z)\begin{aligned} y[n] &=\sum_{k=-\infin}^{+\infin}z^{n-k}h[k] \\ &=z^{n}\sum_{k=-\infin}^{+\infin}z^{-k}h[k] \\ &= z^{n}H(z) \end{aligned}

其中:

H(z)=k=+zkh[k]H(z) = \sum_{k=-\infin}^{+\infin}z^{-k}h[k]

如果系统对某一信号的响应是该信号乘以一个常数,则称该信号是这个系统的特征函数,称该常数为系统与特征函数相对应的特征值

类比线性代数中的特征向量和特征值

复指数函数 este^{st}znz^n一切 LTI 系统的特征函数H(s)H(s)H(z)H(z) 分别是 LTI 系统与复指数信号相对应的特征值。这为后面的 =

# 频率响应

对时域的任何一个信号 x(t)x(t) 或者 x[n]x[n],若能将其表示为下列形式:

x(t)=kakesktx[n]=kakzknx(t) = \sum_{k}a_k\ e^{s_k t}\\ x[n] = \sum_{k}a_k\ z_{k}^{n}

s=jωs=j\omega ,考虑形如 ejωte^{j\omega t} 的基本信号,则有连续时间傅里叶级数与傅里叶级数变换:

H(jω)H(j\omega) 被称为连续时间 LTI 系统的频率响应

H(jω)=+h(t)ejωtdtH(j\omega) = \int_{-\infin}^{+\infin}h(t)e^{-j\omega t}dt

z=ejωz=e^{j\omega} ,考虑形如 ejωne^{j\omega n} 的基本信号,则有离散时间傅里叶级数与傅里叶级数变换;

H(ejω)H(e^{j\omega}) 称为离散时间 LTI 系统的频率响应

H(ejω)=n=+h[n]ejωnH(e^{j\omega}) = \sum_{n=-\infin}^{+\infin}h[n]e^{-j\omega n}

利用 LTI 系统的特征函数以及齐次性与叠加性,则有:

输入响应\text{输入}\to\text{响应}

ejωtejωtH(jω)x(t)=kakejkω0ty(t)=kakejkω0tH(jkω0)e^{j\omega t}\to e^{j\omega t}\ H(j\omega ) \\ x(t)= \sum_{k}a_k\ e^{jk\omega_0 t}\to y(t)= \sum_{k}a_k\ e^{jk\omega_0 t}\ H(jk\omega_0)

ejωnejωnH(ejω)x[n]=kakej2πNkny[n]=kakej2πNknH(ej2πNk)e^{j\omega n}\to e^{j\omega n}\ H(e^{j\omega})\\ x[n] = \sum_{k}a_k\ e^{j\frac{2\pi}{N}kn}\to y[n]=\sum_{k}a_k\ e^{j\frac{2\pi}{N}kn}\ H(e^{j\frac{2\pi}{N}k})

有的题目里会有ω=kω0\omega=k\omega_0 关系,直接给出H(jω)H(j\omega)H(ejω)H(e^{j\omega})

LTI 系统对周期信号的响应仍是一个周期信号;

LTI 系统频率响应的意义在于对各个谐波频率的信号分量进行不同的加权处理.

# 滤波

滤波:改变信号中各频率分量的相对大小或消除某些频率分量的过程。

  • 频率成形滤波器:改变信号频谱形状的滤波器
  • 频率选择性滤波器:基本上无失真地通过某些频率,而显著地衰减或消除另一些频率的滤波器

# 微分器

属于频率成形滤波器

H(jω)=+u1(t)ejωtdt=jωH(j\omega) = \int_{-\infin}^{+\infin}u_1(t)e^{-j\omega t}dt=j\omega

幅度特性:

幅度特性

相位特性:

相位特性

# 低通滤波器 LPF

Lowpass filter,通过低频分量,衰减或阻止高频分量

# 高通滤波器 HPF

Highpass filter,通过高频而衰减或阻止低频

# 带通滤波器 BPF

Bandpass filter,通过一频带范围,衰减或阻止这一频带之外的频率分量

# 带阻滤波器

Band-stop filter 或 band-rejection filter

# 微分方程描述的连续时间滤波器

# RC 低通滤波器

RC-C电压的响应

频率响应 H(jω)H(j\omega),设系统初始松弛,则该系统为 LTI 系统,输入 vs(t)=ejωtv_s(t) = e^{jωt} 将产生输出 vc(t)=H(jω)ejωtv_c(t) = H(j\omega) e^{jωt} ,因此:

RCddtvc(t)+vc(t)=vs(t)RCddt[H(jω)ejωt]+H(jω)ejωt=ejωt\begin{aligned} RC\frac{d}{dt}v_c(t)+v_c(t)&=v_s(t)\\ RC\frac{d}{dt}[H(j\omega)e^{j\omega t}]+H(j\omega)e^{j\omega t}&=e^{j\omega t} \end{aligned}

可得:

H(jω)=11+RCjωH(jω)=1s1+(RCω)2H(jω)=arctan(RCω)\begin{aligned} H(j\omega)&=\frac{1}{1+RCj\omega} \\ |H(j\omega)|&=\frac{1}{s\sqrt{1+(RC\omega)^2}}\\ \angle H(j\omega)&=-\text{arctan}(RC\omega) \end{aligned}

# 连续时间周期信号的傅里叶级数表示

# 连续时间傅里叶级数

谐波关系的复指数信号集:ejkω0t,k=0,±1,±2,e^{jk\omega_0 t},\ \ \ k=0,\pm 1,\pm 2,\cdots ,满足:

  • 每个信号周期为:2πω=2πkω0\frac{2\pi}{|\omega|}=\frac{2\pi}{|k\omega_0|}
  • 公共周期为:T=2πω0T=\frac{2\pi}{|\omega_0|}
  • 各信号彼此独立

这些信号的线性组合称为 (连续) 傅里叶级数

x(t)=k=+akejkω0t,k=0,±1,±2,x(t)=\sum_{k=-\infin}^{+\infin}a_k e^{jk\omega_0 t},\ \ \ k=0,\pm 1,\pm 2,\cdots

则有:

  • 基波频率 ω0\omega_0,即 k=1k=1 时的频率 ω=kω0\omega=k\omega_0
  • (基波) 周期: T=2πω0T=\frac{2\pi}{|\omega_0|}
  • aka_k 称为傅立叶级数的系数
  • k = 0 对应直流分量
  • k = ±1 对应一次谐波
  • k = ±2 对应二次谐波

# 频谱图

在傅里叶级数中,各个信号分量(谐波分量)间的区别仅仅是系数频率不同。

因此,可以用线段来表示分量的系数,用线段的位置表示相应的频率(谐波次数)

实系数傅里叶级数

x(t)=k=+akejkω0t,k=0,±1,±2,,akRx(t)=\sum_{k=-\infin}^{+\infin}a_k e^{jk\omega_0 t},\ \ \ k=0,\pm 1,\pm 2,\cdots,\ \ \ a_k\in\mathbb{R}

可以表示为:

频谱图1

akCa_k\in\mathbb{C} 为复系数傅里叶级数时,通常分幅度与相位分别作图:

频谱图2

# 确定系数

如果周期信号 x (t) 可以表示为傅里叶级数:

x(t)=k=+akejkω0t,k=0,±1,±2,,ω0=2πTx(t)=\sum_{k=-\infin}^{+\infin}a_k e^{jk\omega_0 t},\ \ \ k=0,\pm 1,\pm 2,\cdots,\ \ \ \omega_0=\frac{2\pi}{T}

则有:

x(t)ejnω0t=k=+akej(kn)ω0tx(t) e^{-jn\omega_0 t} = \sum_{k=-\infin}^{+\infin}a_k e^{j(k-n)\omega_0 t}

对两边同时在一个周期内积分,有:

0Tx(t)ejnω0tdy=k=+ak0Tej(kn)ω0tdt\begin{aligned} \int_{0}^{T}x(t) e^{-jn\omega_0 t}dy &= \sum_{k=-\infin}^{+\infin} a_k \int_{0}^{T} e^{j(k-n)\omega_0 t}dt \end{aligned}

其中:

0Tej(kn)ω0tdt=0Tcos((kn)ω0t)dt+j0Tsin((kn)ω0t)dt={0,knT,k=n\begin{aligned} \int_{0}^{T} e^{j(k-n)\omega_0 t}dt &=\int_{0}^{T}cos((k-n)\omega_0 t)dt+j\int_{0}^{T}sin((k-n)\omega_0 t)dt\\ &= \begin{cases} 0,\ \ \ k\neq n\\ T,\ \ \ k=n \end{cases} \end{aligned}

所以:

0Tx(t)ejnω0tdt=k=+ak0Tej(kn)ω0tdt=anT\begin{aligned} \int_{0}^{T}x(t) e^{-jn\omega_0 t}dt &= \sum_{k=-\infin}^{+\infin} a_k \int_{0}^{T} e^{j(k-n)\omega_0 t}dt\\ &= a_n T \end{aligned}

可得 ana_n

an=1T0Tx(t)ejnω0tdt\begin{aligned} a_n &= \frac{1}{T}\int_{0}^{T}x(t) e^{-jn\omega_0 t}dt \end{aligned}

在确定此积分时,只要积分区间是一个周期即可,对积分区间的起止并无特别要求,因此可表示为:

ak=1TTx(t)ejkω0tdt=1TTx(t)[cos(kω0t)jsin(kω0t)]dt\begin{aligned} a_k &= \frac{1}{T}{\int}_{T} x(t) e^{-jk\omega_0 t}dt\\ &= \frac{1}{T}{\int}_{T} x(t) [\text{cos}(k\omega_0t)-j\ \text{sin}(k\omega_0t)]dt \end{aligned}

n=0n=0 时信号在一个周期的平均值,通常称直流分量

a0=1TTx(t)dt\begin{aligned} a_0 &= \frac{1}{T}{\int}_{T} x(t) dt \end{aligned}

# 周期性矩形脉冲信号

周期性矩形脉冲信号

ak=1TTx(t)ejkω0tdt=1TT1T1ejkω0tdt=1jkω0Tejkω0tT1T1=2sin(kω0T1)kω0T=2T1T2sin(kω0T1)kω0T1(ω0=2πT)=2T1TSa(kπ2T1T)\begin{aligned} a_k &= \frac{1}{T}{\int}_{T} x(t) e^{-jk\omega_0 t}dt\\ &= \frac{1}{T}{\int}_{-T_1}^{T_1}e^{-jk\omega_0 t}dt\\ &= -\frac{1}{jk\omega_0 T} e^{-jk\omega_0t}|_{-T_1}^{T_1}\\ &= \frac{2\text{sin}(k\omega_0 T_1)}{k\omega_0 T}\\ &= \frac{2T_1}{T}\frac{2\text{sin}(k\omega_0 T_1)}{k\omega_0 T_1}\\ (\omega_0=\frac{2\pi}{T}) &= \frac{2T_1}{T}\text{Sa}(k\pi\frac{2T_1}{T}) \end{aligned}

其中 Sa(...)\text{Sa}(...) 是抽样信号:

Sa(x)=sinxx\text{Sa}(x)=\frac{\text{sin}x}{x}

基波频率为:ω0=2πT\omega_0=\frac{2\pi}{T}

类似地:

sinc(x)=sinπxπx\text{sinc}(x)=\frac{\text{sin}\pi x}{\pi x}

抽样信号

不同占空比的周期性矩形脉冲信号的傅里叶级数表示:

不同占空比的周期性矩形脉冲信号的傅里叶级数表示

# 收敛性

x(t)x(t) 以 T 为周期,用有限项级数:

xN(t)=k=NNakejkω0tx_N(t)=\sum_{k=-N}^{N}a_k e^{jk\omega_0 t}

近似 x(t)x(t) 时,定义误差:

eN(t)=x(t)xN(t)=x(t)k=NNakejkω0te_N(t)=x(t)-x_N(t)=x(t)-\sum_{k=-N}^{N}a_k e^{jk\omega_0 t}

误差在一个周期内的能量为:

EN=TeN(t)2dtE_N=\int_{T}|e_N(t)|^2dt

可以证明,要使 ENE_N 最小,应有:

ak=1TTx(t)ejkω0tdta_k= \frac{1}{T}{\int}_{T} x(t) e^{-jk\omega_0 t}dt

结论:在误差能量ENE_N 最小的准则下,傅里叶级数是对周期信号的最佳近似

# 收敛的充分条件

两组条件并不完全等价。它们都是傅里叶级数收敛的充分条件。

相当广泛的信号都能满足这两组条件中的一组,因而用傅里叶级数表示周期信号具有相当的普遍适用性

# 平方可积条件

如果:

Tx(t)2dt<\int_{T}|x(t)|^2dt \lt \infin

aka_k 必存在。

此时 x (t) 与其傅里叶级数表示之间没有能量上的区别

# Dirichlet 条件

(1)x(t)x(t) 在任何周期内信号绝对可积,即:

Tx(t)dt<\int_{T}|x(t)|dt \lt \infin

(2)在任何有限区间内,只有有限个极值点,且极值为有限值

(3)在任何有限区间内,只有有限个间断点,且在这些间断点上,函数值有限

Dirichlet 条件保证在间断点之外 x(t)x(t) 等于它的傅里叶级数;而在间断点上,该无穷级数收敛于间断点两边值的平均值

# 实信号的傅里叶级数其他形式 (如考)

x(t)x(t) 是实信号,则有 :

x(t)=x(t)x(t)=x^*(t)

从而有:

x(t)=[k=+akejkω0t]x^*(t)=[\sum_{k=-\infin}^{+\infin}a_k e^{jk\omega_0 t}]^*


# Gibbs 现象

满足 Dirichlet 条件的信号,其傅里叶级数是如何收敛于 x(t)x(t) 的?特别当 x(t)x(t) 具有间断点时,在间断点附近,如何收敛于 x(t)x(t) ?

Gibbs 现象表明:

用有限项傅里叶级数表示有间断点的信号时,在间断点附近不可避免的会出现振荡和超量。超量的幅度不会随所取项数的增加而减小。只是随着项数的增多,振荡频率变高,并向间断点处压缩,从而使它所占有的能量减少


# 离散时间周期信号的傅里叶级数表示

# 离散时间傅里叶级数

谐波关系的复指数信号集:Φk[n]={ej2πNkt},k=0,±1,±2,\Phi_k[n]=\{e^{j\frac{2\pi}{N}kt}\},\ \ \ k=0,\pm 1,\pm 2,\cdots ,满足:

  • 每个信号周期为:Nk\frac{N}{k}
  • 公共周期为:NN
  • 各信号彼此独立

这些信号的线性组合称为离散傅里叶级数

x[n]=k=Nakej2πNkn,k=0,±1,±2,x[n]=\sum_{k=\langle N\rangle}a_k e^{j\frac{2\pi}{N}kn},\ \ \ k=0,\pm 1,\pm 2,\cdots

⭐️其中 N\langle N\rangle 表示一个总共 NN 个的连续序列,起始和结束没有要求。

则有:

  • 基波频率 ω0=2πN\omega_0=\frac{2\pi}{N},即 k=1k=1 时的频率 ω=kω0=2kπN\omega=k\omega_0=\frac{2k\pi}{N}
  • (基波) 周期:NN
  • aka_k 为傅立叶级数的系数,也称为 x[n]x[n]频谱系数

# 确定系数

x[n]=k=Nakej2πNktx[n]=\sum_{k=\langle N\rangle}a_{k}e^{j\frac{2\pi}{N}kt} 两边同时乘 ej2πNrne^{-j\frac{2\pi}{N}rn} ,可得:

x[n]ej2πNrn=k=Nakej2πN(kr)nx[n]e^{-j\frac{2\pi}{N}rn}=\sum_{k=\langle N\rangle}a_k e^{j\frac{2\pi}{N}(k-r)n}

显然 x[n]ej2πNrnx[n]e^{-j\frac{2\pi}{N}rn} 仍然是以 N 为周期的,对两边求和:

n=Nx[n]ej2πNrn=n=Nk=Nakej2πN(kr)n=k=Nakn=Nej2πN(kr)n\sum_{n=\langle N\rangle}x[n]e^{-j\frac{2\pi}{N}rn} =\sum_{n=\langle N\rangle}\sum_{k=\langle N\rangle}a_k e^{j\frac{2\pi}{N}(k-r)n} =\sum_{k=\langle N\rangle}a_k \sum_{n=\langle N\rangle}e^{j\frac{2\pi}{N}(k-r)n}

其中:

n=Nej2πN(kr)n=n=0N1ej2πN(kr)n=1ej(kr)2π1ej(kr)2πN={0,krN,k=r\begin{aligned} \sum_{n=\langle N\rangle}e^{j\frac{2\pi}{N}(k-r)n} &= \sum_{n=0}^{N-1}e^{j\frac{2\pi}{N}(k-r)n}\\ &= \frac{1-e^{j(k-r)2\pi}}{1-e^{j(k-r)\frac{2\pi}{N}}}\\ &= \begin{cases} 0,\ \ \ k\neq r\\ N,\ \ \ k=r \end{cases} \end{aligned}

从而:

n=Nx[n]ej2πNrn=Nar\sum_{n=\langle N\rangle}x[n]e^{-j\frac{2\pi}{N}rn}=Na_r

即可得:(r 换成了 k)

ak=1Nn=Nx[n]ej2πNkna_k=\frac{1}{N}\sum_{n=\langle N\rangle}x[n]e^{-j\frac{2\pi}{N}kn}

显然上式满足 ak+N=aka_{k+N}=a_k ,即也是以 NN 为周期的,或者说 aka_k 中只有 NN 个是独立的

# 周期性方波序列

周期性方波序列

ak=1Nn=Nx[n]ej2πNkn=1Nn=N1N1ej2πNkn=1Nej2πNkN1ej2πNk(N1+1)1ej2πNk=1NejπNkejπNkej2πNk(N1+12)ej2πNk(N1+12)ejπNkejπNk=1NsinπNk(2N1+1)sinπNk,k0,±N,±2N,=1Nsinkω0(N1+12)sinkω02,k0,±N,±2N,\begin{aligned} a_k &= \frac{1}{N}\sum_{n=\langle N\rangle}x[n]e^{-j\frac{2\pi}{N}kn} \\ &= \frac{1}{N}\sum_{n=-N_1}^{N_1}e^{-j\frac{2\pi}{N}kn} \\ &= \frac{1}{N}\frac {e^{j\frac{2\pi}{N}kN_1}-e^{-j\frac{2\pi}{N}k(N_1+1)}} {1-e^{-j\frac{2\pi}{N}k}} \\ &= \frac{1}{N}\frac{e^{-j\frac{\pi}{N}k}}{e^{-j\frac{\pi}{N}k}}\frac {e^{j\frac{2\pi}{N}k(N_1+\frac{1}{2})}-e^{-j\frac{2\pi}{N}k(N_1+\frac{1}{2})}} {e^{j\frac{\pi}{N}k}-e^{-j\frac{\pi}{N}k}} \\ &= \frac{1}{N}\frac{\text{sin}\frac{\pi}{N}k(2N_1+1)}{\text{sin}\frac{\pi}{N}k},\ \ \ \ k\neq 0,\pm N,\pm 2N,\cdots\\ &= \frac{1}{N}\frac{\text{sin}k\omega_0(N_1+\frac{1}{2})}{\text{sin}\frac{k\omega_0}{2}},\ \ \ \ k\neq 0,\pm N,\pm 2N,\cdots \end{aligned}

ak=2N1+1N,k=rNa_k = \frac{2N_1+1}{N},\ \ \ \ k=rN

# 收敛性

离散时间傅里叶级数是一个有限项的级数,确定 aka_k 的关系式也是有限项的和式,因而不存在收敛问题,也不会产生 Gibbs 现象

# LTI 系统对复指数信号的响应

# 特征函数与特征值

考查 LTI 系统对复指数信号 este^{st} 作为输入时的响应

连续复指数信号输入

y(t)=+es(tτ)h(τ)dτ=est+esτh(τ)dτ=estH(s)\begin{aligned} y(t) &=\int_{-\infin}^{+\infin}e^{s(t-\tau)}h(\tau)d\tau \\ &= e^{st}\int_{-\infin}^{+\infin}e^{-s\tau}h(\tau)d\tau \\ &= e^{st}H(s) \end{aligned}

其中:

H(s)=+esτh(τ)dτH(s) = \int_{-\infin}^{+\infin}e^{-s\tau}h(\tau)d\tau

考查 LTI 系统对复指数信号 znz^n 作为输入时的响应

离散复指数信号输入

y[n]=k=+znkh[k]=znk=+zkh[k]=znH(z)\begin{aligned} y[n] &=\sum_{k=-\infin}^{+\infin}z^{n-k}h[k] \\ &=z^{n}\sum_{k=-\infin}^{+\infin}z^{-k}h[k] \\ &= z^{n}H(z) \end{aligned}

其中:

H(z)=k=+zkh[k]H(z) = \sum_{k=-\infin}^{+\infin}z^{-k}h[k]

如果系统对某一信号的响应是该信号乘以一个常数,则称该信号是这个系统的特征函数,称该常数为系统与特征函数相对应的特征值

类比线性代数中的特征向量和特征值

复指数函数 este^{st}znz^n一切 LTI 系统的特征函数H(s)H(s)H(z)H(z) 分别是 LTI 系统与复指数信号相对应的特征值。这为后面的 =

# 频率响应

对时域的任何一个信号 x(t)x(t) 或者 x[n]x[n],若能将其表示为下列形式:

x(t)=kakesktx[n]=kakzknx(t) = \sum_{k}a_k\ e^{s_k t}\\ x[n] = \sum_{k}a_k\ z_{k}^{n}

s=jωs=j\omega ,考虑形如 ejωte^{j\omega t} 的基本信号,则有连续时间傅里叶级数与傅里叶级数变换:

H(jω)H(j\omega) 被称为连续时间 LTI 系统的频率响应

H(jω)=+h(t)ejωtdtH(j\omega) = \int_{-\infin}^{+\infin}h(t)e^{-j\omega t}dt

z=ejωz=e^{j\omega} ,考虑形如 ejωne^{j\omega n} 的基本信号,则有离散时间傅里叶级数与傅里叶级数变换;

H(ejω)H(e^{j\omega}) 称为离散时间 LTI 系统的频率响应

H(ejω)=n=+h[n]ejωnH(e^{j\omega}) = \sum_{n=-\infin}^{+\infin}h[n]e^{-j\omega n}

利用 LTI 系统的特征函数以及齐次性与叠加性,则有:

输入响应\text{输入}\to\text{响应}

ejωtejωtH(jω)x(t)=kakejkω0ty(t)=kakejkω0tH(jkω0)e^{j\omega t}\to e^{j\omega t}\ H(j\omega ) \\ x(t)= \sum_{k}a_k\ e^{jk\omega_0 t}\to y(t)= \sum_{k}a_k\ e^{jk\omega_0 t}\ H(jk\omega_0)

ejωnejωnH(ejω)x[n]=kakej2πNkny[n]=kakej2πNknH(ej2πNk)e^{j\omega n}\to e^{j\omega n}\ H(e^{j\omega})\\ x[n] = \sum_{k}a_k\ e^{j\frac{2\pi}{N}kn}\to y[n]=\sum_{k}a_k\ e^{j\frac{2\pi}{N}kn}\ H(e^{j\frac{2\pi}{N}k})

有的题目里会有ω=kω0\omega=k\omega_0 关系,直接给出H(jω)H(j\omega)H(ejω)H(e^{j\omega})

LTI 系统对周期信号的响应仍是一个周期信号;

LTI 系统频率响应的意义在于对各个谐波频率的信号分量进行不同的加权处理.

# 滤波

滤波:改变信号中各频率分量的相对大小或消除某些频率分量的过程。

  • 频率成形滤波器:改变信号频谱形状的滤波器
  • 频率选择性滤波器:基本上无失真地通过某些频率,而显著地衰减或消除另一些频率的滤波器

# 微分器

属于频率成形滤波器

H(jω)=+u1(t)ejωtdt=jωH(j\omega) = \int_{-\infin}^{+\infin}u_1(t)e^{-j\omega t}dt=j\omega

幅度特性:

幅度特性

相位特性:

相位特性

# 低通滤波器 LPF

Lowpass filter,通过低频分量,衰减或阻止高频分量

# 高通滤波器 HPF

Highpass filter,通过高频而衰减或阻止低频

# 带通滤波器 BPF

Bandpass filter,通过一频带范围,衰减或阻止这一频带之外的频率分量

# 带阻滤波器

Band-stop filter 或 band-rejection filter

# 微分方程描述的连续时间滤波器

# RC 低通滤波器

RC-C电压的响应

频率响应 H(jω)H(j\omega),设系统初始松弛,则该系统为 LTI 系统,输入 vs(t)=ejωtv_s(t) = e^{jωt} 将产生输出 vc(t)=H(jω)ejωtv_c(t) = H(j\omega) e^{jωt} ,因此:

RCddtvc(t)+vc(t)=vs(t)RCddt[H(jω)ejωt]+H(jω)ejωt=ejωt\begin{aligned} RC\frac{d}{dt}v_c(t)+v_c(t)&=v_s(t)\\ RC\frac{d}{dt}[H(j\omega)e^{j\omega t}]+H(j\omega)e^{j\omega t}&=e^{j\omega t} \end{aligned}

可得:

H(jω)=11+RCjωH(jω)=1s1+(RCω)2H(jω)=arctan(RCω)\begin{aligned} H(j\omega)&=\frac{1}{1+RCj\omega} \\ |H(j\omega)|&=\frac{1}{s\sqrt{1+(RC\omega)^2}}\\ \angle H(j\omega)&=-\text{arctan}(RC\omega) \end{aligned}

RC高通

# 差分方程描述的离散时间滤波器

这一部分在我刚学这门课时觉得比较难,但还是记了这些笔记。

但后面学了 CTFT、DTFT、LT、zT 后运用后面的方法会发现这里的分析其实很简单,不必按照这里的方法分析。

# 一阶递归离散时间滤波器

对于由一阶差分方程描述的 LTI 系统

y[n]ay[n1]=x[n]y[n]-ay[n-1]=x[n]

输入 x[n]=ejωnx[n] = e^{j\omega n} 将产生输出 y[n]=H(ejω)ejωny[n] = H(e^{j\omega}) e^{j\omega n} ,因此:

H(ejω)ejωnaH(ejω)ejω(n1)=ejωnH(e^{j\omega}) e^{j\omega n}-a H(e^{j\omega}) e^{jω(n-1)}=e^{j\omega n}

H(ejω)=11aejωH(e^{j\omega})=\frac{1}{1-ae^{-j\omega}}

# 非递归离散时间滤波器

# 移动均值滤波器

输出信号 = 输入信号的时移和

# 三点

三点移动均值滤波器中,输入与输出的关系是:

y[n]=13(x[n1]+x[n]+x[n+1])y[n]=\frac{1}{3}(x[n-1]+x[n]+x[n+1])

单位脉冲响应为:

h[n]=13(δ[n1]+δ[n]+δ[n+1])h[n]=\frac{1}{3}(\delta[n-1]+\delta[n]+\delta[n+1])

则频率响应为:

H(ejω)=n=+h[n]ejωn=13[ejω+1+ejω]=13+23cosω\begin{aligned} H(e^{j\omega}) &= \sum_{n=-\infin}^{+\infin}h[n]e^{-j\omega n} \\ &= \frac{1}{3}[e^{-j\omega}+1+e^{j\omega}] \\ &= \frac{1}{3}+\frac{2}{3}\text{cos}\omega \end{aligned}

# N+M+1 点

N+M+1 移动均值滤波器中,输入与输出的关系是:

y[n]=1N+M+1k=NMx[nk]y[n]=\frac{1}{N+M+1}\sum_{k=-N}^{M}x[n-k]

单位脉冲响应为:

h[n]=1N+M+1k=NMδ[nk]h[n]=\frac{1}{N+M+1}\sum_{k=-N}^{M}\delta[n-k]

则频率响应为:

H(ejω)=1N+M+1n=+k=NMδ[nk]ejωn=1N+M+1k=NMn=+δ[nk]ejωn=1N+M+1k=NMδ[nk]ejωk=1N+M+1ejωNM2sinω(N+M+1)2sin(ω2)\begin{aligned} H(e^{j\omega}) &= \frac{1}{N+M+1}\sum_{n=-\infin}^{+\infin}\sum_{k=-N}^{M}\delta[n-k]e^{-j\omega n} \\ &= \frac{1}{N+M+1}\sum_{k=-N}^{M}\sum_{n=-\infin}^{+\infin}\delta[n-k]e^{-j\omega n} \\ &= \frac{1}{N+M+1}\sum_{k=-N}^{M}\delta[n-k]e^{-j\omega k} \\ &= \frac{1}{N+M+1}e^{j\omega\frac{N-M}{2}}\frac{\text{sin}\frac{\omega(N+M+1)}{2}}{\sin(\frac{\omega}{2})} \\ \end{aligned}

# 差分滤波器

这个名字是我乱起的,为了和移动均值滤波器 “对偶” 也好分类

输出信号 = 输入信号的时移差,也就是输出信号 = 输入信号的差分

# (两点)

两点差分滤波器这个名字也是我乱起的

输入与输出的关系是:

y[n]=12(x[n]x[n1])y[n]=\frac{1}{2}(x[n]-x[n-1])

单位脉冲响应为:

h[n]=12(δ[n]δ[n1])h[n]=\frac{1}{2}(\delta[n]-\delta[n-1])

则频率响应为:

H(ejω)=n=+h[n]ejωn=12[1ejω]=je12jωsin(ω2)\begin{aligned} H(e^{j\omega}) &= \sum_{n=-\infin}^{+\infin}h[n]e^{-j\omega n} \\ &= \frac{1}{2}[1-e^{-j\omega}] \\ &= je^{-\frac{1}{2}j\omega}\sin(\frac{\omega}{2}) \end{aligned}

H(ejω)=sin(ω2)|H(e^{j\omega})|=|\sin(\frac{\omega}{2})|

两点差分滤波器

\ No newline at end of file +M1001 80h400000v40h-400000z"/>RCω=arctan(RCω1)

RC高通

# 差分方程描述的离散时间滤波器

这一部分在我刚学这门课时觉得比较难,但还是记了这些笔记。

但后面学了 CTFT、DTFT、LT、zT 后运用后面的方法会发现这里的分析其实很简单,不必按照这里的方法分析。

# 一阶递归离散时间滤波器

对于由一阶差分方程描述的 LTI 系统

y[n]ay[n1]=x[n]y[n]-ay[n-1]=x[n]

输入 x[n]=ejωnx[n] = e^{j\omega n} 将产生输出 y[n]=H(ejω)ejωny[n] = H(e^{j\omega}) e^{j\omega n} ,因此:

H(ejω)ejωnaH(ejω)ejω(n1)=ejωnH(e^{j\omega}) e^{j\omega n}-a H(e^{j\omega}) e^{jω(n-1)}=e^{j\omega n}

H(ejω)=11aejωH(e^{j\omega})=\frac{1}{1-ae^{-j\omega}}

# 非递归离散时间滤波器

# 移动均值滤波器

输出信号 = 输入信号的时移和

# 三点

三点移动均值滤波器中,输入与输出的关系是:

y[n]=13(x[n1]+x[n]+x[n+1])y[n]=\frac{1}{3}(x[n-1]+x[n]+x[n+1])

单位脉冲响应为:

h[n]=13(δ[n1]+δ[n]+δ[n+1])h[n]=\frac{1}{3}(\delta[n-1]+\delta[n]+\delta[n+1])

则频率响应为:

H(ejω)=n=+h[n]ejωn=13[ejω+1+ejω]=13+23cosω\begin{aligned} H(e^{j\omega}) &= \sum_{n=-\infin}^{+\infin}h[n]e^{-j\omega n} \\ &= \frac{1}{3}[e^{-j\omega}+1+e^{j\omega}] \\ &= \frac{1}{3}+\frac{2}{3}\text{cos}\omega \end{aligned}

# N+M+1 点

N+M+1 移动均值滤波器中,输入与输出的关系是:

y[n]=1N+M+1k=NMx[nk]y[n]=\frac{1}{N+M+1}\sum_{k=-N}^{M}x[n-k]

单位脉冲响应为:

h[n]=1N+M+1k=NMδ[nk]h[n]=\frac{1}{N+M+1}\sum_{k=-N}^{M}\delta[n-k]

则频率响应为:

H(ejω)=1N+M+1n=+k=NMδ[nk]ejωn=1N+M+1k=NMn=+δ[nk]ejωn=1N+M+1k=NMδ[nk]ejωk=1N+M+1ejωNM2sinω(N+M+1)2sin(ω2)\begin{aligned} H(e^{j\omega}) &= \frac{1}{N+M+1}\sum_{n=-\infin}^{+\infin}\sum_{k=-N}^{M}\delta[n-k]e^{-j\omega n} \\ &= \frac{1}{N+M+1}\sum_{k=-N}^{M}\sum_{n=-\infin}^{+\infin}\delta[n-k]e^{-j\omega n} \\ &= \frac{1}{N+M+1}\sum_{k=-N}^{M}\delta[n-k]e^{-j\omega k} \\ &= \frac{1}{N+M+1}e^{j\omega\frac{N-M}{2}}\frac{\text{sin}\frac{\omega(N+M+1)}{2}}{\sin(\frac{\omega}{2})} \\ \end{aligned}

# 差分滤波器

这个名字是我乱起的,为了和移动均值滤波器 “对偶” 也好分类

输出信号 = 输入信号的时移差,也就是输出信号 = 输入信号的差分

# (两点)

两点差分滤波器这个名字也是我乱起的

输入与输出的关系是:

y[n]=12(x[n]x[n1])y[n]=\frac{1}{2}(x[n]-x[n-1])

单位脉冲响应为:

h[n]=12(δ[n]δ[n1])h[n]=\frac{1}{2}(\delta[n]-\delta[n-1])

则频率响应为:

H(ejω)=n=+h[n]ejωn=12[1ejω]=je12jωsin(ω2)\begin{aligned} H(e^{j\omega}) &= \sum_{n=-\infin}^{+\infin}h[n]e^{-j\omega n} \\ &= \frac{1}{2}[1-e^{-j\omega}] \\ &= je^{-\frac{1}{2}j\omega}\sin(\frac{\omega}{2}) \end{aligned}

H(ejω)=sin(ω2)|H(e^{j\omega})|=|\sin(\frac{\omega}{2})|

两点差分滤波器

\ No newline at end of file diff --git a/ie/signals-and-systems/LT/index.html b/ie/signals-and-systems/LT/index.html index 7f314c67..f9f8956c 100644 --- a/ie/signals-and-systems/LT/index.html +++ b/ie/signals-and-systems/LT/index.html @@ -1,4 +1,4 @@ -拉普拉斯变换 - 信号与系统 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 公式表

# 基本变换对

基本变换对

# 性质表

性质表

# 双边拉普拉斯变换

# 定义

X(s)=+x(t)estdtX(s)=\int_{-\infin}^{+\infin}x(t)e^{-st}dt

称为 x(t)x(t) 的拉普拉斯变换,后面简记为 LT,其中 s=σ+jωs=\sigma+j\omega 为复数。

σ=0\sigma=0s=jωs=j\omega 为纯虚数则为傅里叶变换,也就是说连续时间傅里叶变换是双边拉普拉斯变换在 𝜎=0 或是在 jωj\omega 轴上的特例,即 X(s)s=jω=X(jω)X(s)|_{s=j\omega}=X(j\omega)

# LT 与 CTFT 的关系

X(s)=+x(t)eσtejωtdt=+[x(t)eσt]ejωtdt=F{x(t)eσt}\begin{aligned} X(s)&=\int_{-\infin}^{+\infin}x(t)e^{-\sigma t}e^{-j\omega t}dt\\ &=\int_{-\infin}^{+\infin}[x(t)e^{-\sigma t}]e^{-j\omega t}dt\\ &=\mathscr{F}\{x(t)e^{-\sigma t}\} \end{aligned}

所以 x(t)x(t) 的 LT 就是 x(t)eσtx(t)e^{-\sigma t} 的 CTFT 。

⭐️ 当拉普拉斯变换的收敛域包含 jωj\omega 时,拉普拉斯变换和傅里叶变换都存在,并且:

X(jω)=X(s)s=jωX(j\omega)=X(s)|_{s=j\omega}

# 零极点图

X(s)X(s) 是有理函数:

X(s)=N(s)D(s)=Mi(sβi)i(sαi)X(s)=\frac{N(s)}{D(s)}=M\frac{\prod_i(s-\beta_i)}{\prod_i(s-\alpha_i)}

  • 分子多项式的根称为零点,画为圆圈 ⭕️
  • 分母多项式的根称为极点,画为交叉 ❌

X(s)X(s) 的全部零点极点表示在 ss 平面上,就构成了零极点图

零极点图及其收敛域可以表示一个 X(s)X(s) ,最多与真实的 X(s)X(s) 相差一个常数因子 𝑀𝑀

# ROC

⚠️不同的信号可能会有完全相同的拉普拉斯变换表达式,只是它们的收敛域不同。拉普拉斯变换的表达式只有连同相应的收敛域,才能和信号建立一一对应的关系。

常见的 x(t)=ektu(at+b)x(t)=e^{kt}u(at+b) 收敛域:

X(s)=ba+e(ks)tdt,a>0X(s)=bae(ks)tdt,a<0X(s)=\int_{-\frac{b}{a}}^{+\infin}e^{(k-s)t}dt,\ \ \ a>0\\ X(s)=\int^{-\frac{b}{a}}_{-\infin}e^{(k-s)t}dt,\ \ \ a<0

tt 积分到 ++\infin 时,tt 前的系数的实部需要小于零,该积分收敛域为 Re{ks}<0\text{Re}\{k-s\}<0

tt 积分到 -\infin 时,tt 前的系数的实部需要大于零,该积分收敛域为 Re{ks}>0\text{Re}\{k-s\}>0

并非 ss 平面上的任何复数都能使拉普拉斯变换 X(s)X(s) 收敛,也不是任何信号的拉普拉斯变换 X(s)X(s) 都存在。

使拉普拉斯变换 X(s)X(s) 收敛的复数 ss 的集合,称为拉普拉斯变换 (LT) 的收敛域ROC,Region of Convergence)

x(t)x(t) 可以写为若干部分的线性组合,各个部分分别进行 LT 有各自的收敛域,则 X(s)X(s) 的收敛域是各个收敛域的交集

  • ROC 总是以平行于 jωj\omega 轴的直线作为边界的
  • ROC 的边界总是与 X(s)X(s) 的分母的根 (极点) 相对应
  • (因为)有理拉普拉斯变换在其 ROC 内无任何极点
  • 绝对可积的时限信号其 ROC 是整个 ss 平面

按照 ROC 在 ss 平面上的分布可以分为:

  • 右边信号的 ROC 位于 ss 平面内一条平行于 jωj\omega 轴的直线的右边
  • 左边信号的 ROC 位于 ss 平面内一条平行于 jωj\omega 轴的直线的左边
  • 双边信号的 ROC 如果存在,一定是 ss 平面内平行于 jωj\omega 轴的带形区域

# 拉普拉斯反变换

# 定义

利用 LT 和 CTFT 的关系、CTFT 的反变换可以得到 LT 的反变换。

(LT 和 CTFT 的关系:)

X(s)=+x(t)estdtX(σ+jω)=+x(t)eσtejωtdt=F{x(t)eσt}\begin{aligned} X(s)&=\int_{-\infin}^{+\infin}x(t)e^{-st}dt\\ X(\sigma+j\omega)&=\int_{-\infin}^{+\infin}x(t)e^{-\sigma t}e^{-j\omega t}dt\\ &=\mathscr{F}\{x(t)e^{-\sigma t}\} \end{aligned}

进而由 CTFT 的反变换有:

x(t)eσt=12π+X(σ+jω)ejωtdωx(t)=12π+X(σ+jω)eσtejωtdωx(t)=12π+X(s)estdω\begin{aligned} x(t)e^{-\sigma t}&=\frac{1}{2\pi}\int_{-\infin}^{+\infin}X(\sigma+j\omega)e^{j\omega t}d\omega\\ x(t)&=\frac{1}{2\pi}\int_{-\infin}^{+\infin}X(\sigma+j\omega)e^{\sigma t}e^{j\omega t}d\omega\\ x(t)&=\frac{1}{2\pi}\int_{-\infin}^{+\infin}X(s)e^{st}d\omega \end{aligned}

s=σ+jωs=\sigma+j\omega 两侧同时微分得到:ds=jdωds=jd\omega ;同时,当 ω\omega+-\infin\to+\infin 时,ssσjσ+j\sigma-j\infin\to\sigma+j\infin ,所以可得到拉普拉斯反变换为

x(t)=12πjσjσ+jX(s)estdsx(t)=\frac{1}{2\pi j}\int_{\sigma-j\infin}^{\sigma+j\infin}X(s)e^{st}ds

# 部分分式展开法

  1. X(s)X(s) 展开为部分分式
  2. 根据 X(s)X(s) 的 ROC ,确定每一项的 ROC
  3. 利用常用信号变换对与拉普拉斯变换性质,对每一项进行反变换

# LT 的几何求值

# 单零点

X(s)=saX(s)=s-a

有唯一一个零点:s=as=a

单零点

s1a\vec{s_1}-\vec{a}

# 公式表

# 基本变换对

基本变换对

# 性质表

性质表

# 双边拉普拉斯变换

# 定义

X(s)=+x(t)estdtX(s)=\int_{-\infin}^{+\infin}x(t)e^{-st}dt

称为 x(t)x(t) 的拉普拉斯变换,后面简记为 LT,其中 s=σ+jωs=\sigma+j\omega 为复数。

σ=0\sigma=0s=jωs=j\omega 为纯虚数则为傅里叶变换,也就是说连续时间傅里叶变换是双边拉普拉斯变换在 𝜎=0 或是在 jωj\omega 轴上的特例,即 X(s)s=jω=X(jω)X(s)|_{s=j\omega}=X(j\omega)

# LT 与 CTFT 的关系

X(s)=+x(t)eσtejωtdt=+[x(t)eσt]ejωtdt=F{x(t)eσt}\begin{aligned} X(s)&=\int_{-\infin}^{+\infin}x(t)e^{-\sigma t}e^{-j\omega t}dt\\ &=\int_{-\infin}^{+\infin}[x(t)e^{-\sigma t}]e^{-j\omega t}dt\\ &=\mathscr{F}\{x(t)e^{-\sigma t}\} \end{aligned}

所以 x(t)x(t) 的 LT 就是 x(t)eσtx(t)e^{-\sigma t} 的 CTFT 。

⭐️ 当拉普拉斯变换的收敛域包含 jωj\omega 时,拉普拉斯变换和傅里叶变换都存在,并且:

X(jω)=X(s)s=jωX(j\omega)=X(s)|_{s=j\omega}

# 零极点图

X(s)X(s) 是有理函数:

X(s)=N(s)D(s)=Mi(sβi)i(sαi)X(s)=\frac{N(s)}{D(s)}=M\frac{\prod_i(s-\beta_i)}{\prod_i(s-\alpha_i)}

  • 分子多项式的根称为零点,画为圆圈 ⭕️
  • 分母多项式的根称为极点,画为交叉 ❌

X(s)X(s) 的全部零点极点表示在 ss 平面上,就构成了零极点图

零极点图及其收敛域可以表示一个 X(s)X(s) ,最多与真实的 X(s)X(s) 相差一个常数因子 𝑀𝑀

# ROC

⚠️不同的信号可能会有完全相同的拉普拉斯变换表达式,只是它们的收敛域不同。拉普拉斯变换的表达式只有连同相应的收敛域,才能和信号建立一一对应的关系。

常见的 x(t)=ektu(at+b)x(t)=e^{kt}u(at+b) 收敛域:

X(s)=ba+e(ks)tdt,a>0X(s)=bae(ks)tdt,a<0X(s)=\int_{-\frac{b}{a}}^{+\infin}e^{(k-s)t}dt,\ \ \ a>0\\ X(s)=\int^{-\frac{b}{a}}_{-\infin}e^{(k-s)t}dt,\ \ \ a<0

tt 积分到 ++\infin 时,tt 前的系数的实部需要小于零,该积分收敛域为 Re{ks}<0\text{Re}\{k-s\}<0

tt 积分到 -\infin 时,tt 前的系数的实部需要大于零,该积分收敛域为 Re{ks}>0\text{Re}\{k-s\}>0

并非 ss 平面上的任何复数都能使拉普拉斯变换 X(s)X(s) 收敛,也不是任何信号的拉普拉斯变换 X(s)X(s) 都存在。

使拉普拉斯变换 X(s)X(s) 收敛的复数 ss 的集合,称为拉普拉斯变换 (LT) 的收敛域ROC,Region of Convergence)

x(t)x(t) 可以写为若干部分的线性组合,各个部分分别进行 LT 有各自的收敛域,则 X(s)X(s) 的收敛域是各个收敛域的交集

  • ROC 总是以平行于 jωj\omega 轴的直线作为边界的
  • ROC 的边界总是与 X(s)X(s) 的分母的根 (极点) 相对应
  • (因为)有理拉普拉斯变换在其 ROC 内无任何极点
  • 绝对可积的时限信号其 ROC 是整个 ss 平面

按照 ROC 在 ss 平面上的分布可以分为:

  • 右边信号的 ROC 位于 ss 平面内一条平行于 jωj\omega 轴的直线的右边
  • 左边信号的 ROC 位于 ss 平面内一条平行于 jωj\omega 轴的直线的左边
  • 双边信号的 ROC 如果存在,一定是 ss 平面内平行于 jωj\omega 轴的带形区域

# 拉普拉斯反变换

# 定义

利用 LT 和 CTFT 的关系、CTFT 的反变换可以得到 LT 的反变换。

(LT 和 CTFT 的关系:)

X(s)=+x(t)estdtX(σ+jω)=+x(t)eσtejωtdt=F{x(t)eσt}\begin{aligned} X(s)&=\int_{-\infin}^{+\infin}x(t)e^{-st}dt\\ X(\sigma+j\omega)&=\int_{-\infin}^{+\infin}x(t)e^{-\sigma t}e^{-j\omega t}dt\\ &=\mathscr{F}\{x(t)e^{-\sigma t}\} \end{aligned}

进而由 CTFT 的反变换有:

x(t)eσt=12π+X(σ+jω)ejωtdωx(t)=12π+X(σ+jω)eσtejωtdωx(t)=12π+X(s)estdω\begin{aligned} x(t)e^{-\sigma t}&=\frac{1}{2\pi}\int_{-\infin}^{+\infin}X(\sigma+j\omega)e^{j\omega t}d\omega\\ x(t)&=\frac{1}{2\pi}\int_{-\infin}^{+\infin}X(\sigma+j\omega)e^{\sigma t}e^{j\omega t}d\omega\\ x(t)&=\frac{1}{2\pi}\int_{-\infin}^{+\infin}X(s)e^{st}d\omega \end{aligned}

s=σ+jωs=\sigma+j\omega 两侧同时微分得到:ds=jdωds=jd\omega ;同时,当 ω\omega+-\infin\to+\infin 时,ssσjσ+j\sigma-j\infin\to\sigma+j\infin ,所以可得到拉普拉斯反变换为

x(t)=12πjσjσ+jX(s)estdsx(t)=\frac{1}{2\pi j}\int_{\sigma-j\infin}^{\sigma+j\infin}X(s)e^{st}ds

# 部分分式展开法

  1. X(s)X(s) 展开为部分分式
  2. 根据 X(s)X(s) 的 ROC ,确定每一项的 ROC
  3. 利用常用信号变换对与拉普拉斯变换性质,对每一项进行反变换

# LT 的几何求值

# 单零点

X(s)=saX(s)=s-a

有唯一一个零点:s=as=a

单零点

s1a\vec{s_1}-\vec{a}

从所有零点向 ss 点作零点矢量,从所有极点向 ss 点作极点矢量:

  • 所有零点矢量的长度之积 (不存在则为 1) 除以所有极点矢量的长度之积即为 X(s)|X(s)|
  • 所有零点矢量的幅角之和 (不存在则为 0) 减去所有极点矢量的幅角之和即为 X(s)\angle X(s)

ss 取为 jωj\omega 轴上的点时,即为傅里叶变换的几何求值。考查 ssjωj\omega 轴上移动时所有零、极点矢量的长度和幅角的变化,即可得出 X(jω)X(j\omega) 的幅频特性和相频特性

# 全通系统

全通系统被广泛用于对系统进行相位均衡,它满足:

  • 零点和极点分布关于 jωj\omega 轴对称、成对分布;
  • H(jω)|H(j\omega)| 在任何时候都等于 11

一般还称具有 nn 对零点和极点的全通系统为 nn 阶全通系统。

# LT 性质

LT 具有很多与 FT 相似的重要性质,主要不同是这里需要考虑 ROC

# 线性

x1(t)LTX1(s),ROC:R1x2(t)LTX2(s),ROC:R2ax1(t)+bx2(t)LTaX1(s)+bX2(s)x_1(t)\stackrel{LT}{\longleftrightarrow}X_1(s),\ \ \text{ROC}:R_1\\ x_2(t)\stackrel{LT}{\longleftrightarrow}X_2(s),\ \ \text{ROC}:R_2\\ \dArr\\ ax_1(t)+bx_2(t)\stackrel{LT}{\longleftrightarrow}aX_1(s)+bX_2(s)

后者的 ROC 至少R1R2R_1\cap R_2 ,否则若 R1R2=R_1\cap R_2=\varnothing ,则 ax1(t)+bx2(t)ax_1(t)+bx_2(t) 的 LT 不存在。

ROC 也有可能扩大:X1(s)X_1(s)X2(s)X_2(s) 线性组合时,若发生了零极点相抵消的现象,且当被抵消的极点恰好在 ROC 的边界上时,就会使 ROC 扩大。

# 时移特性

x(t)LTX(s),ROC:Rx(tt0)LTX(s)est0,ROC:Rx(t)\stackrel{LT}{\longleftrightarrow}X(s),\ \ \text{ROC}:R\\ \dArr\\ x(t-t_0)\stackrel{LT}{\longleftrightarrow}X(s)e^{-st_0},\ \ \text{ROC}:R

# s 域平移

x(t)LTX(t),ROC:Rx(t)esotLTX(ss0),ROC:R+Re[s0]x(t)\stackrel{LT}{\longleftrightarrow}X(t),\ \ \text{ROC}:R\\ \dArr\\ x(t)e^{s_o t}\stackrel{LT}{\longleftrightarrow}X(s-s_0),\ \ \text{ROC}:R+\text{Re}[s_0]

⚠️这里 R+Re[s0]R+\text{Re}[s_0] 的意思是将 RR 平移了一个 Re[s0]\text{Re}[s_0]⚠️,与时域平移不同,ss 域平移的时候收敛域 ROC 也发生了平移。

  • 加法➕是 ROC 向右平移
  • 剑法➖是 ROC 向左平移

# 时域尺度变换

若信号在时域尺度变换,其 LT 的 ROC 在 ss 平面上作相反的尺度变换。

x(t)LTX(s),ROC:Rx(at)LT1aX(sa),ROC:aRx(t)\stackrel{LT}{\longleftrightarrow}X(s),\ \ \text{ROC}:R\\ \dArr\\ x(at)\stackrel{LT}{\longleftrightarrow}\frac{1}{|a|}X(\frac{s}{a}),\ \ \text{ROC}:aR

ROC 的推导比较简单:sRs\in RX(s)X(s) 收敛,所以 s/aRs/a\in RX(sa)X(\frac{s}{a}) 收敛。

⚠️这里 aRaR 的意思是将 RR 线性伸缩了 aa 倍⚠️

# 共轭对称性

x(t)LTX(s),ROC:Rx(t)LTX(s),ROC:Rx(t)\stackrel{LT}{\longleftrightarrow}X(s),\ \ \text{ROC}:R\\ \dArr\\ x^*(t)\stackrel{LT}{\longleftrightarrow}X^*(s^*),\ \ \text{ROC}:R

这里可以结合 X(s)=X(s)|X(s)|=|X(s^*)| 理解,模相同意味着二者总是零点极点相同......

特别地,当 x(t)x(t)实信号时,有:

x(t)=x(t)LTX(s)=X(s)=X(s)=X(s)x^*(t)=x(t)\stackrel{LT}{\longleftrightarrow} X^*(s^*)=X(s)=X^*(s)=X(s^*)

这里 X(s)=X(s)X^*(s^*)=X(s) 等价于 X(s)=X(s)X^*(s)=X(s^*)

因此,如果 x(t)x(t) 是实信号,且 X(s)X(s)s0s_0 有极点 (或零点),则 X(s)X(s) 一定在 s0s_0^* 也有极点 (或零点)。即实信号的拉普拉斯变换其零、极点必共轭成对出现

# 卷积性质

x1(t)LTX1(s),ROC:R1x2(t)LTX2(s),ROC:R2x1(t)x2(t)LTX1(s)X2(s)x_1(t)\stackrel{LT}{\longleftrightarrow}X_1(s),\ \ \text{ROC}:R_1\\ x_2(t)\stackrel{LT}{\longleftrightarrow}X_2(s),\ \ \text{ROC}:R_2\\ \dArr\\ x_1(t)*x_2(t)\stackrel{LT}{\longleftrightarrow}X_1(s)X_2(s)

类似线性性质中,后者的 ROC 包括 R1R2R_1\cap R_2 ,否则若 R1R2=R_1\cap R_2=\varnothing ,则 x1(t)x2(t)x_1(t)*x_2(t) 的 LT 不存在。

ROC 也有可能扩大:X1(s)X_1(s)X2(s)X_2(s) 相乘时,若发生了零极点相抵消的现象,且当被抵消的极点恰好在 ROC 的边界上时,就会使 ROC 扩大。

# 时域微分

x(t)LTX(s),ROC:Rddtx(t)LTsX(s)x(t)\stackrel{LT}{\longleftrightarrow}X(s),\ \ \text{ROC}:R\\ \dArr\\ \frac{d}{dt}x(t)\stackrel{LT}{\longleftrightarrow}sX(s)

后者的 ROC 包括 R1R2R_1\cap R_2 ,有可能扩大。

证明可由 LT 逆变换两侧同时对 tt 微分得到。

# s 域微分

x(t)LTX(s),ROC:Rtx(t)LTddsX(s),ROC:Rx(t)\stackrel{LT}{\longleftrightarrow}X(s),\ \ \text{ROC}:R\\ \dArr\\ -tx(t)\stackrel{LT}{\longleftrightarrow}\frac{d}{ds}X(s),\ \ \text{ROC}:R\\

# 时域积分

x(t)LTX(s),ROC:Rtx(τ)dτLT1sX(s)x(t)\stackrel{LT}{\longleftrightarrow}X(s),\ \ \text{ROC}:R\\ \dArr\\ \int_{-\infin}^{t}x(\tau)d\tau\stackrel{LT}{\longleftrightarrow}\frac{1}{s}X(s)

后者的 ROC 包括 R{sRe[s]>0}R\cap\{s|\text{Re}[s]>0\} ,也就是包括 RRssjωj\omega 轴右侧的部分 (ss 平面的右半部分)。这是因为:

tx(τ)dτ=x(t)u(t)\int_{-\infin}^{t}x(\tau)d\tau=x(t)*u(t)

# 初值与终值定理

# 初值定理

如果 x(t)x(t) 是因果信号,且在 t=0t=0 不包含奇异函数,则有初值定理

x(0+)=limssX(s)x(0^+)=\lim_{s\to\infin}sX(s)


证明

t<0t<0x(t)=0x(t)=0x=0x=0 时不为奇异函数,则有: x(t)=x(t)u(t)x(t)=x(t)u(t)

x(t)=[x(0+)+x(0+)t+x(0+)t22++x(n)(0+)tnn!]u(t)\begin{aligned} x(t)&=[x(0^+)+x'(0^+)t+x''(0^+)\frac{t^2}{2}+\cdots+x^{(n)}(0^+)\frac{t^n}{n!}]u(t) \end{aligned}

作 LT 可得:

X(s)=[1sx(0+)+1s2x(0+)+1s3x(0+)++1sn+1x(n)(0+)]u(t)=n=0+1sn+1x(n)(0+)\begin{aligned} X(s)&=[\frac{1}{s}x(0^+)+\frac{1}{s^2}x'(0^+)+\frac{1}{s^3}x''(0^+)+\cdots+\frac{1}{s^{n+1}}x^{(n)}(0^+)]u(t)\\ &=\sum_{n=0}^{+\infin}\frac{1}{s^{n+1}}\cdot x^{(n)}(0^+) \end{aligned}

那么:

sX(s)=sn=0+1sn+1x(n)(0+)=x(0+)+n=1+1snx(n)(0+)limssX(s)=x(0+)\begin{aligned} sX(s)&=s\sum_{n=0}^{+\infin}\frac{1}{s^{n+1}}\cdot x^{(n)}(0^+)\\ &=x(0^+)+\sum_{n=1}^{+\infin}\frac{1}{s^{n}}\cdot x^{(n)}(0^+)\\ \lim_{s\to\infin}sX(s)&=x(0^+) \end{aligned}

# 终值定理

如果 x(t)x(t) 是因果信号,且在 t=0t=0 不包含奇异函数,X(s)X(s) 除了在 s=0s=0 可以有单阶极点外,其余极点均在 ss 平面的左半边 (Re[s]<0\text{Re}[s]<0​)

上述条件的目的在于保证终值存在

则有终值定理

limtx(t)=lims0sX(s)\lim_{t\to\infin}x(t)=\lim_{s\to0}sX(s)


证明

x(t)x(t) 是因果信号,且在 t=0t=0 不包含奇异函数,则有:

0+estddtx(t)dt=x(t)est0++s0+estx(t)dt=x(t)est0++sX(s)\begin{aligned} \int_{0^+}^{\infin}e^{-st}\frac{d}{dt}x(t)dt &=x(t)e^{-st}\big|_{0^+}^{\infin}+s\int_{0^+}^{\infin}e^{-st}x(t)dt\\ &=x(t)e^{-st}\big|_{0^+}^{\infin}+sX(s) \end{aligned}

X(s)X(s) 除了在 s=0s=0 可以有单阶极点外,其余极点均在 ss 平面的左半边 (Re[s]<0\text{Re}[s]<0) ,所以 sX(s)sX(s) 的 ROC 中必包含正实数轴。

x(t)est0+=x(0+)x(t)e^{-st}\big|_{0^+}^{\infin}=-x(0^+)

于是:

0+estddtx(t)dt=x(0+)+sX(s)\begin{aligned} \int_{0^+}^{\infin}e^{-st}\frac{d}{dt}x(t)dt &=-x(0^+)+sX(s) \end{aligned}

两侧同时令 s0+s\to0^+ ,可得:

lims0+0+estddtx(t)dt=x(0+)+lims0+sX(s)0+ddtx(t)dt=x(0+)+lims0+sX(s)0+dx(t)=x(0+)+lims0+sX(s)limtx(t)x(0+)=x(0+)+lims0+sX(s)limtx(t)=lims0+sX(s)\begin{aligned} \lim_{s\to0^+}\int_{0^+}^{\infin}e^{-st}\frac{d}{dt}x(t)dt &=-x(0^+)+\lim_{s\to0^+}sX(s)\\ \int_{0^+}^{\infin}\frac{d}{dt}x(t)dt &=-x(0^+)+\lim_{s\to0^+}sX(s)\\ \int_{0^+}^{\infin}dx(t) &=-x(0^+)+\lim_{s\to0^+}sX(s)\\ \lim_{t\to\infin}x(t)-x(0^+) &=-x(0^+)+\lim_{s\to0^+}sX(s)\\ \lim_{t\to\infin}x(t) &=\lim_{s\to0^+}sX(s)\\ \end{aligned}

# LT 分析 LTI 系统

以卷积特性为基础,可建立 LTI 系统的拉普拉斯变换分析方法,即:

Y(s)=X(s)H(s)Y(s)=X(s)\cdot H(s)

其中 H(s)H(s)h(t)h(t) 的拉普拉斯变换,称为系统函数转移函数传递函数

这些方法成立的本质原因在于复指数函数 este^{st} 是一切 LTI 系统的特征函数。

# 特征函数

x(t)=es0tx(t)=e^{s_0t} 时,响应为:

y(t)=H(s0)es0ty(t)=H(s_0)e^{s_0t}

# 因果性

  • 如果 t<0t<0h(t)=0h(t)=0,则系统是因果的;
  • 如果 t>0t>0h(t)=0h(t)=0,则系统是反因果的;

因果系统的 h(t)h(t) 是右边信号,其 H(s)H(s) 的 ROC 必是最右边极点的右边;当 H(s)H(s) 是有理函数时,逆命题成立。

  • ⚠️但是当 H(s)H(s) 不是有理函数时, H(s)H(s) 的 ROC 是最右边极点的右边不能推出 h(t)h(t) 不是因果的

反因果系统的 h(t)h(t) 是左边信号,H(s)H(s) 的 ROC 必是最左边极点的左边;当 H(s)H(s) 是有理函数时,逆命题成立。

# 稳定性

LTI 系统稳定的充要条件是其 H(s)H(s) 收敛域包括 jωj\omega 轴。

因果稳定系统的 H(s)H(s) 收敛域为包括 jωj\omega 轴的 ss 右半平面。

# 线性常微分方程

* 线性常系数微分方程

如果由线性常系数微分方程描述的系统满足初始松弛条件,则系统是因果 LTI 的,其 H(s)H(s) 的 ROC 必是最右边极点的右边。

对于由线性常系数微分方程描述的 LTI 系统:

k=0Nakdky(t)dtk=k=0Mbkdkx(t)dtk\sum_{k=0}^{N}a_k\frac{d^ky(t)}{dt^k}=\sum_{k=0}^{M}b_k\frac{d^kx(t)}{dt^k}

两边进行拉普拉斯变换,可得:

H(s)=Y(s)X(s)=k=0Mbkskk=0NakskH(s)={Y(s)\over X(s)}={\sum_{k=0}^{M}b_{k}s^{k}\over\sum_{k=0}^{N}a_{k}s^{k}}

可得到 H(s)H(s) 是一个有理函数。系统的单位冲激响应 h(t)h(t) 可由 H(s)H(s) 反变换获得。

# 单边拉普拉斯变换

Unilateral Laplace Transform

单边拉普拉斯变换是仅考虑 00^- 之后部分信号的双边拉普拉斯变换:

χ(s)=0+x(t)estdt\chi(s)=\int_{0^-}^{+\infin}x(t)e^{-st}dt

单边拉普拉斯变换的反变换与同 ROC 的双边拉普拉斯变换的反变换相同:

x(t)=12πjσjσ+jχ(s)estdsx(t)=\frac{1}{2\pi j}\int_{\sigma-j\infin}^{\sigma+j\infin}\chi(s)e^{st}ds

X(s)X(s)χ(s)\chi(s) 不同,是因为 x(t)x(t)t<0t<0 的部分对 X(s)X(s) 有作用,而对 χ(s)\chi(s) 没有任何作用所致。

由于单边拉普拉斯变换不存在类似双边拉普拉斯变换中与 ROC 相关的多义性,一般不再强调其 ROC ,任何单边拉普拉斯变换的收敛域总是某一右半平面。

单边拉普拉斯变换的 ROC 位于最右边极点右边。

因果信号的双边拉普拉斯变换和单边拉普拉斯变换完全相同。⭐️从而可以利用双边 LT 的基本变换对。

# 性质

由于单边拉普拉斯变换是特殊的双边拉普拉斯变换,因此其大部分性质与双边拉普拉斯变换相同,但也有一些区别:

# 共轭对称性

x(t)ULTχ(s)x(t)ULTχ(s)x(t)\stackrel{ULT}{\longleftrightarrow}\chi(s)\\ \dArr\\ x^*(t)\stackrel{ULT}{\longleftrightarrow}\chi^*(s)

# 时域尺度变换

x(at)x(at) 中的 aa 需要满足 a>0a\gt0

x(t)ULTχ(s)x(at)ULT1aχ(sa)x(t)\stackrel{ULT}{\longleftrightarrow}\chi(s)\\ \dArr\\ x(at)\stackrel{ULT}{\longleftrightarrow}\frac{1}{a}\chi(\frac{s}{a})

# 时域微分

x(t)ULTχ(s)ddtx(t)ULTsχ(s)x(0)d2dt2x(t)ULTs2χ(s)sx(0)ddtx(0)d3dt3x(t)ULTs3χ(s)s2x(0)sddtx(0)d2dt2x(0)......x(n)(t)ULTsnχ(s)sn1x(0)sn2x(0)sn3x(0)x(n1)(0)x(t)\stackrel{ULT}{\longleftrightarrow}\chi(s)\\ \dArr\\ \frac{d}{dt}x(t)\stackrel{ULT}{\longleftrightarrow}s\chi(s)-x(0^-)\\ \frac{d^2}{dt^2}x(t)\stackrel{ULT}{\longleftrightarrow}s^2\chi(s)-sx(0^-)-\frac{d}{dt}x(0^-)\\ \frac{d^3}{dt^3}x(t)\stackrel{ULT}{\longleftrightarrow}s^3\chi(s)-s^2x(0^-)-s\frac{d}{dt}x(0^-)-\frac{d^2}{dt^2}x(0^-)\\ ......\\ x^{(n)}(t)\stackrel{ULT}{\longleftrightarrow}s^{n}\chi(s)-s^{n-1}x(0^-)-s^{n-2}x'(0^-)-s^{n-3}x''(0^-)-\cdots-x^{(n-1)}(0^-)

# 线性常微分方程

单边拉普拉斯变换特别适合于求解具有非零初始条件的线性常系数微分方程(增量线性系统)。

往往假定系统为因果系统。该条件下得到的结果在进行单边拉普拉斯反变换的时候可以确定为右边信号

以二阶为例(最高二阶微分),将初始条件带入后,整理得到如下形式:

Aγ(s)=By(0)+Cy(0)+Dχ(s)γ(s)=BAy(0)+CAy(0)+DAχ(s)\begin{aligned} A\gamma(s)&=By(0^-)+Cy'(0^-)+D\chi(s)\\ \gamma(s)&=\frac{B}{A}y(0^-)+\frac{C}{A}y'(0^-)+\frac{D}{A}\chi(s) \end{aligned}

其中 DAχ(s)\frac{D}{A}\chi(s)零状态响应BAy(0)+CAy(0)\frac{B}{A}y(0^-)+\frac{C}{A}y'(0^-)零输入响应

γ(s)=k01s+k11s+1+k21s+2+\begin{aligned} \gamma(s)=k_0\frac{1}{s}+k_1\frac{1}{s+1}+k_2\frac{1}{s+2}+\cdots \end{aligned}

其中 k01sk_0\frac{1}{s}强迫响应k0k_0 为常数,也就是对应的单边拉普拉斯反变换为 k0u(t)k_0u(t) 形式的才是强迫响应;;k11s+1+k21s+2+k_1\frac{1}{s+1}+k_2\frac{1}{s+2}+\cdots自然响应

\ No newline at end of file +c-16-25.333-24-45-24-59z"/>)

从所有零点向 ss 点作零点矢量,从所有极点向 ss 点作极点矢量:

  • 所有零点矢量的长度之积 (不存在则为 1) 除以所有极点矢量的长度之积即为 X(s)|X(s)|
  • 所有零点矢量的幅角之和 (不存在则为 0) 减去所有极点矢量的幅角之和即为 X(s)\angle X(s)

ss 取为 jωj\omega 轴上的点时,即为傅里叶变换的几何求值。考查 ssjωj\omega 轴上移动时所有零、极点矢量的长度和幅角的变化,即可得出 X(jω)X(j\omega) 的幅频特性和相频特性

# 全通系统

全通系统被广泛用于对系统进行相位均衡,它满足:

  • 零点和极点分布关于 jωj\omega 轴对称、成对分布;
  • H(jω)|H(j\omega)| 在任何时候都等于 11

一般还称具有 nn 对零点和极点的全通系统为 nn 阶全通系统。

# LT 性质

LT 具有很多与 FT 相似的重要性质,主要不同是这里需要考虑 ROC

# 线性

x1(t)LTX1(s),ROC:R1x2(t)LTX2(s),ROC:R2ax1(t)+bx2(t)LTaX1(s)+bX2(s)x_1(t)\stackrel{LT}{\longleftrightarrow}X_1(s),\ \ \text{ROC}:R_1\\ x_2(t)\stackrel{LT}{\longleftrightarrow}X_2(s),\ \ \text{ROC}:R_2\\ \dArr\\ ax_1(t)+bx_2(t)\stackrel{LT}{\longleftrightarrow}aX_1(s)+bX_2(s)

后者的 ROC 至少R1R2R_1\cap R_2 ,否则若 R1R2=R_1\cap R_2=\varnothing ,则 ax1(t)+bx2(t)ax_1(t)+bx_2(t) 的 LT 不存在。

ROC 也有可能扩大:X1(s)X_1(s)X2(s)X_2(s) 线性组合时,若发生了零极点相抵消的现象,且当被抵消的极点恰好在 ROC 的边界上时,就会使 ROC 扩大。

# 时移特性

x(t)LTX(s),ROC:Rx(tt0)LTX(s)est0,ROC:Rx(t)\stackrel{LT}{\longleftrightarrow}X(s),\ \ \text{ROC}:R\\ \dArr\\ x(t-t_0)\stackrel{LT}{\longleftrightarrow}X(s)e^{-st_0},\ \ \text{ROC}:R

# s 域平移

x(t)LTX(t),ROC:Rx(t)esotLTX(ss0),ROC:R+Re[s0]x(t)\stackrel{LT}{\longleftrightarrow}X(t),\ \ \text{ROC}:R\\ \dArr\\ x(t)e^{s_o t}\stackrel{LT}{\longleftrightarrow}X(s-s_0),\ \ \text{ROC}:R+\text{Re}[s_0]

⚠️这里 R+Re[s0]R+\text{Re}[s_0] 的意思是将 RR 平移了一个 Re[s0]\text{Re}[s_0]⚠️,与时域平移不同,ss 域平移的时候收敛域 ROC 也发生了平移。

  • 加法➕是 ROC 向右平移
  • 剑法➖是 ROC 向左平移

# 时域尺度变换

若信号在时域尺度变换,其 LT 的 ROC 在 ss 平面上作相反的尺度变换。

x(t)LTX(s),ROC:Rx(at)LT1aX(sa),ROC:aRx(t)\stackrel{LT}{\longleftrightarrow}X(s),\ \ \text{ROC}:R\\ \dArr\\ x(at)\stackrel{LT}{\longleftrightarrow}\frac{1}{|a|}X(\frac{s}{a}),\ \ \text{ROC}:aR

ROC 的推导比较简单:sRs\in RX(s)X(s) 收敛,所以 s/aRs/a\in RX(sa)X(\frac{s}{a}) 收敛。

⚠️这里 aRaR 的意思是将 RR 线性伸缩了 aa 倍⚠️

# 共轭对称性

x(t)LTX(s),ROC:Rx(t)LTX(s),ROC:Rx(t)\stackrel{LT}{\longleftrightarrow}X(s),\ \ \text{ROC}:R\\ \dArr\\ x^*(t)\stackrel{LT}{\longleftrightarrow}X^*(s^*),\ \ \text{ROC}:R

这里可以结合 X(s)=X(s)|X(s)|=|X(s^*)| 理解,模相同意味着二者总是零点极点相同......

特别地,当 x(t)x(t)实信号时,有:

x(t)=x(t)LTX(s)=X(s)=X(s)=X(s)x^*(t)=x(t)\stackrel{LT}{\longleftrightarrow} X^*(s^*)=X(s)=X^*(s)=X(s^*)

这里 X(s)=X(s)X^*(s^*)=X(s) 等价于 X(s)=X(s)X^*(s)=X(s^*)

因此,如果 x(t)x(t) 是实信号,且 X(s)X(s)s0s_0 有极点 (或零点),则 X(s)X(s) 一定在 s0s_0^* 也有极点 (或零点)。即实信号的拉普拉斯变换其零、极点必共轭成对出现

# 卷积性质

x1(t)LTX1(s),ROC:R1x2(t)LTX2(s),ROC:R2x1(t)x2(t)LTX1(s)X2(s)x_1(t)\stackrel{LT}{\longleftrightarrow}X_1(s),\ \ \text{ROC}:R_1\\ x_2(t)\stackrel{LT}{\longleftrightarrow}X_2(s),\ \ \text{ROC}:R_2\\ \dArr\\ x_1(t)*x_2(t)\stackrel{LT}{\longleftrightarrow}X_1(s)X_2(s)

类似线性性质中,后者的 ROC 包括 R1R2R_1\cap R_2 ,否则若 R1R2=R_1\cap R_2=\varnothing ,则 x1(t)x2(t)x_1(t)*x_2(t) 的 LT 不存在。

ROC 也有可能扩大:X1(s)X_1(s)X2(s)X_2(s) 相乘时,若发生了零极点相抵消的现象,且当被抵消的极点恰好在 ROC 的边界上时,就会使 ROC 扩大。

# 时域微分

x(t)LTX(s),ROC:Rddtx(t)LTsX(s)x(t)\stackrel{LT}{\longleftrightarrow}X(s),\ \ \text{ROC}:R\\ \dArr\\ \frac{d}{dt}x(t)\stackrel{LT}{\longleftrightarrow}sX(s)

后者的 ROC 包括 R1R2R_1\cap R_2 ,有可能扩大。

证明可由 LT 逆变换两侧同时对 tt 微分得到。

# s 域微分

x(t)LTX(s),ROC:Rtx(t)LTddsX(s),ROC:Rx(t)\stackrel{LT}{\longleftrightarrow}X(s),\ \ \text{ROC}:R\\ \dArr\\ -tx(t)\stackrel{LT}{\longleftrightarrow}\frac{d}{ds}X(s),\ \ \text{ROC}:R\\

# 时域积分

x(t)LTX(s),ROC:Rtx(τ)dτLT1sX(s)x(t)\stackrel{LT}{\longleftrightarrow}X(s),\ \ \text{ROC}:R\\ \dArr\\ \int_{-\infin}^{t}x(\tau)d\tau\stackrel{LT}{\longleftrightarrow}\frac{1}{s}X(s)

后者的 ROC 包括 R{sRe[s]>0}R\cap\{s|\text{Re}[s]>0\} ,也就是包括 RRssjωj\omega 轴右侧的部分 (ss 平面的右半部分)。这是因为:

tx(τ)dτ=x(t)u(t)\int_{-\infin}^{t}x(\tau)d\tau=x(t)*u(t)

# 初值与终值定理

# 初值定理

如果 x(t)x(t) 是因果信号,且在 t=0t=0 不包含奇异函数,则有初值定理

x(0+)=limssX(s)x(0^+)=\lim_{s\to\infin}sX(s)


证明

t<0t<0x(t)=0x(t)=0x=0x=0 时不为奇异函数,则有: x(t)=x(t)u(t)x(t)=x(t)u(t)

x(t)=[x(0+)+x(0+)t+x(0+)t22++x(n)(0+)tnn!]u(t)\begin{aligned} x(t)&=[x(0^+)+x'(0^+)t+x''(0^+)\frac{t^2}{2}+\cdots+x^{(n)}(0^+)\frac{t^n}{n!}]u(t) \end{aligned}

作 LT 可得:

X(s)=[1sx(0+)+1s2x(0+)+1s3x(0+)++1sn+1x(n)(0+)]u(t)=n=0+1sn+1x(n)(0+)\begin{aligned} X(s)&=[\frac{1}{s}x(0^+)+\frac{1}{s^2}x'(0^+)+\frac{1}{s^3}x''(0^+)+\cdots+\frac{1}{s^{n+1}}x^{(n)}(0^+)]u(t)\\ &=\sum_{n=0}^{+\infin}\frac{1}{s^{n+1}}\cdot x^{(n)}(0^+) \end{aligned}

那么:

sX(s)=sn=0+1sn+1x(n)(0+)=x(0+)+n=1+1snx(n)(0+)limssX(s)=x(0+)\begin{aligned} sX(s)&=s\sum_{n=0}^{+\infin}\frac{1}{s^{n+1}}\cdot x^{(n)}(0^+)\\ &=x(0^+)+\sum_{n=1}^{+\infin}\frac{1}{s^{n}}\cdot x^{(n)}(0^+)\\ \lim_{s\to\infin}sX(s)&=x(0^+) \end{aligned}

# 终值定理

如果 x(t)x(t) 是因果信号,且在 t=0t=0 不包含奇异函数,X(s)X(s) 除了在 s=0s=0 可以有单阶极点外,其余极点均在 ss 平面的左半边 (Re[s]<0\text{Re}[s]<0​)

上述条件的目的在于保证终值存在

则有终值定理

limtx(t)=lims0sX(s)\lim_{t\to\infin}x(t)=\lim_{s\to0}sX(s)


证明

x(t)x(t) 是因果信号,且在 t=0t=0 不包含奇异函数,则有:

0+estddtx(t)dt=x(t)est0++s0+estx(t)dt=x(t)est0++sX(s)\begin{aligned} \int_{0^+}^{\infin}e^{-st}\frac{d}{dt}x(t)dt &=x(t)e^{-st}\big|_{0^+}^{\infin}+s\int_{0^+}^{\infin}e^{-st}x(t)dt\\ &=x(t)e^{-st}\big|_{0^+}^{\infin}+sX(s) \end{aligned}

X(s)X(s) 除了在 s=0s=0 可以有单阶极点外,其余极点均在 ss 平面的左半边 (Re[s]<0\text{Re}[s]<0) ,所以 sX(s)sX(s) 的 ROC 中必包含正实数轴。

x(t)est0+=x(0+)x(t)e^{-st}\big|_{0^+}^{\infin}=-x(0^+)

于是:

0+estddtx(t)dt=x(0+)+sX(s)\begin{aligned} \int_{0^+}^{\infin}e^{-st}\frac{d}{dt}x(t)dt &=-x(0^+)+sX(s) \end{aligned}

两侧同时令 s0+s\to0^+ ,可得:

lims0+0+estddtx(t)dt=x(0+)+lims0+sX(s)0+ddtx(t)dt=x(0+)+lims0+sX(s)0+dx(t)=x(0+)+lims0+sX(s)limtx(t)x(0+)=x(0+)+lims0+sX(s)limtx(t)=lims0+sX(s)\begin{aligned} \lim_{s\to0^+}\int_{0^+}^{\infin}e^{-st}\frac{d}{dt}x(t)dt &=-x(0^+)+\lim_{s\to0^+}sX(s)\\ \int_{0^+}^{\infin}\frac{d}{dt}x(t)dt &=-x(0^+)+\lim_{s\to0^+}sX(s)\\ \int_{0^+}^{\infin}dx(t) &=-x(0^+)+\lim_{s\to0^+}sX(s)\\ \lim_{t\to\infin}x(t)-x(0^+) &=-x(0^+)+\lim_{s\to0^+}sX(s)\\ \lim_{t\to\infin}x(t) &=\lim_{s\to0^+}sX(s)\\ \end{aligned}

# LT 分析 LTI 系统

以卷积特性为基础,可建立 LTI 系统的拉普拉斯变换分析方法,即:

Y(s)=X(s)H(s)Y(s)=X(s)\cdot H(s)

其中 H(s)H(s)h(t)h(t) 的拉普拉斯变换,称为系统函数转移函数传递函数

这些方法成立的本质原因在于复指数函数 este^{st} 是一切 LTI 系统的特征函数。

# 特征函数

x(t)=es0tx(t)=e^{s_0t} 时,响应为:

y(t)=H(s0)es0ty(t)=H(s_0)e^{s_0t}

# 因果性

  • 如果 t<0t<0h(t)=0h(t)=0,则系统是因果的;
  • 如果 t>0t>0h(t)=0h(t)=0,则系统是反因果的;

因果系统的 h(t)h(t) 是右边信号,其 H(s)H(s) 的 ROC 必是最右边极点的右边;当 H(s)H(s) 是有理函数时,逆命题成立。

  • ⚠️但是当 H(s)H(s) 不是有理函数时, H(s)H(s) 的 ROC 是最右边极点的右边不能推出 h(t)h(t) 不是因果的

反因果系统的 h(t)h(t) 是左边信号,H(s)H(s) 的 ROC 必是最左边极点的左边;当 H(s)H(s) 是有理函数时,逆命题成立。

# 稳定性

LTI 系统稳定的充要条件是其 H(s)H(s) 收敛域包括 jωj\omega 轴。

因果稳定系统的 H(s)H(s) 收敛域为包括 jωj\omega 轴的 ss 右半平面。

# 线性常微分方程

* 线性常系数微分方程

如果由线性常系数微分方程描述的系统满足初始松弛条件,则系统是因果 LTI 的,其 H(s)H(s) 的 ROC 必是最右边极点的右边。

对于由线性常系数微分方程描述的 LTI 系统:

k=0Nakdky(t)dtk=k=0Mbkdkx(t)dtk\sum_{k=0}^{N}a_k\frac{d^ky(t)}{dt^k}=\sum_{k=0}^{M}b_k\frac{d^kx(t)}{dt^k}

两边进行拉普拉斯变换,可得:

H(s)=Y(s)X(s)=k=0Mbkskk=0NakskH(s)={Y(s)\over X(s)}={\sum_{k=0}^{M}b_{k}s^{k}\over\sum_{k=0}^{N}a_{k}s^{k}}

可得到 H(s)H(s) 是一个有理函数。系统的单位冲激响应 h(t)h(t) 可由 H(s)H(s) 反变换获得。

# 单边拉普拉斯变换

Unilateral Laplace Transform

单边拉普拉斯变换是仅考虑 00^- 之后部分信号的双边拉普拉斯变换:

χ(s)=0+x(t)estdt\chi(s)=\int_{0^-}^{+\infin}x(t)e^{-st}dt

单边拉普拉斯变换的反变换与同 ROC 的双边拉普拉斯变换的反变换相同:

x(t)=12πjσjσ+jχ(s)estdsx(t)=\frac{1}{2\pi j}\int_{\sigma-j\infin}^{\sigma+j\infin}\chi(s)e^{st}ds

X(s)X(s)χ(s)\chi(s) 不同,是因为 x(t)x(t)t<0t<0 的部分对 X(s)X(s) 有作用,而对 χ(s)\chi(s) 没有任何作用所致。

由于单边拉普拉斯变换不存在类似双边拉普拉斯变换中与 ROC 相关的多义性,一般不再强调其 ROC ,任何单边拉普拉斯变换的收敛域总是某一右半平面。

单边拉普拉斯变换的 ROC 位于最右边极点右边。

因果信号的双边拉普拉斯变换和单边拉普拉斯变换完全相同。⭐️从而可以利用双边 LT 的基本变换对。

# 性质

由于单边拉普拉斯变换是特殊的双边拉普拉斯变换,因此其大部分性质与双边拉普拉斯变换相同,但也有一些区别:

# 共轭对称性

x(t)ULTχ(s)x(t)ULTχ(s)x(t)\stackrel{ULT}{\longleftrightarrow}\chi(s)\\ \dArr\\ x^*(t)\stackrel{ULT}{\longleftrightarrow}\chi^*(s)

# 时域尺度变换

x(at)x(at) 中的 aa 需要满足 a>0a\gt0

x(t)ULTχ(s)x(at)ULT1aχ(sa)x(t)\stackrel{ULT}{\longleftrightarrow}\chi(s)\\ \dArr\\ x(at)\stackrel{ULT}{\longleftrightarrow}\frac{1}{a}\chi(\frac{s}{a})

# 时域微分

x(t)ULTχ(s)ddtx(t)ULTsχ(s)x(0)d2dt2x(t)ULTs2χ(s)sx(0)ddtx(0)d3dt3x(t)ULTs3χ(s)s2x(0)sddtx(0)d2dt2x(0)......x(n)(t)ULTsnχ(s)sn1x(0)sn2x(0)sn3x(0)x(n1)(0)x(t)\stackrel{ULT}{\longleftrightarrow}\chi(s)\\ \dArr\\ \frac{d}{dt}x(t)\stackrel{ULT}{\longleftrightarrow}s\chi(s)-x(0^-)\\ \frac{d^2}{dt^2}x(t)\stackrel{ULT}{\longleftrightarrow}s^2\chi(s)-sx(0^-)-\frac{d}{dt}x(0^-)\\ \frac{d^3}{dt^3}x(t)\stackrel{ULT}{\longleftrightarrow}s^3\chi(s)-s^2x(0^-)-s\frac{d}{dt}x(0^-)-\frac{d^2}{dt^2}x(0^-)\\ ......\\ x^{(n)}(t)\stackrel{ULT}{\longleftrightarrow}s^{n}\chi(s)-s^{n-1}x(0^-)-s^{n-2}x'(0^-)-s^{n-3}x''(0^-)-\cdots-x^{(n-1)}(0^-)

# 线性常微分方程

单边拉普拉斯变换特别适合于求解具有非零初始条件的线性常系数微分方程(增量线性系统)。

往往假定系统为因果系统。该条件下得到的结果在进行单边拉普拉斯反变换的时候可以确定为右边信号

以二阶为例(最高二阶微分),将初始条件带入后,整理得到如下形式:

Aγ(s)=By(0)+Cy(0)+Dχ(s)γ(s)=BAy(0)+CAy(0)+DAχ(s)\begin{aligned} A\gamma(s)&=By(0^-)+Cy'(0^-)+D\chi(s)\\ \gamma(s)&=\frac{B}{A}y(0^-)+\frac{C}{A}y'(0^-)+\frac{D}{A}\chi(s) \end{aligned}

其中 DAχ(s)\frac{D}{A}\chi(s)零状态响应BAy(0)+CAy(0)\frac{B}{A}y(0^-)+\frac{C}{A}y'(0^-)零输入响应

γ(s)=k01s+k11s+1+k21s+2+\begin{aligned} \gamma(s)=k_0\frac{1}{s}+k_1\frac{1}{s+1}+k_2\frac{1}{s+2}+\cdots \end{aligned}

其中 k01sk_0\frac{1}{s}强迫响应k0k_0 为常数,也就是对应的单边拉普拉斯反变换为 k0u(t)k_0u(t) 形式的才是强迫响应;;k11s+1+k21s+2+k_1\frac{1}{s+1}+k_2\frac{1}{s+2}+\cdots自然响应

\ No newline at end of file diff --git a/ie/signals-and-systems/communication/index.html b/ie/signals-and-systems/communication/index.html index 1a939af0..2c4fb6ca 100644 --- a/ie/signals-and-systems/communication/index.html +++ b/ie/signals-and-systems/communication/index.html @@ -1 +1 @@ -通信系统 - 信号与系统 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

there are still some bugs rendering katex here...

LTI 系统对输入信号所起的作用包括两个方面:

  • 改变输入信号各频率分量的幅度
  • 改变输入信号各频率分量的相对相位

Y(jω)=X(jω)H(jω)Y(jω)=X(jω)H(jω)Y(jω)=X(jω)+H(jω)\begin{aligned} Y(j\omega)&=X(j\omega)H(j\omega)\\ |Y(j\omega)|&=|X(j\omega)|\cdot|H(j\omega)|\\ \angle Y(j\omega)&=\angle X(j\omega)+\angle H(j\omega) \end{aligned}

线性与非线性相位

信号在传输过程中,相位特性或幅度特性发生改变都可能引起信号波形的改变,即发生失真

当相位特性仅仅是产生一个线性相移时,只引起信号在时间上的平移。如连续时间 LTI 系统,信号的时移会导致其频谱产生一个线性相移

x(t)FX(jω)x(tt0)FX(jω)ejωt0x(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\\ \dArr\\ x(t-t_0)\stackrel{F}{\longleftrightarrow}X(j\omega)e^{-j\omega t_0}

此时信号波形不发生改变,只是发生时间上的延迟,因此未丢失信号所携带的任何信息。

如果系统的相位特性是非线性的,由于不同频率分量所产生的时移不同,叠加起来会变成一个与原来信号不相同的信号波形。

系统响应与输入信号满足:

y(t)=kx(tt0)y[n]=kx[nn0]y(t)=kx(t-t_0)\ \ \ y[n]=kx[n-n_0]

也就是:

则可视为在传输中未发生失真

H(jω)=k,H(jω)=ωt0|H(j\omega)|=k,\ \ \angle H(j\omega)=-\omega t_0

在传输信号的带宽范围内

理想滤波器

  • 非因果系统,因而是物理不可实现
  • h(t)h(t) 存在震荡

# 采样

# 采样的概念

在某些离散的时间点上提取连续时间信号值的过程就是采样(sampling)

与之相对应的,从离散时间信号等间隔地提取信号,则叫做抽取(decimation)

一般情况下,从连续时间信号采样所得到的样本序列不能唯一地代表原来的连续时间信号,决定是否能从采样结果恢复原信号的关键在于采样定理

# 采样的数学模型

采样的数学模型

在时域:

xp(t)=x(t)p(t)x_p(t)=x(t)\cdot p(t)

在频域:

Xp(jω)=12πX(jω)P(jω)X_p(j\omega)=\frac{1}{2\pi}X(j\omega)*P(j\omega)

# 冲激串采样 (理想采样)

TT 为采样间隔的脉冲采样信号为:

p(t)=n=+δ(tnT)p(t)=\sum_{n=-\infin}^{+\infin}\delta(t-nT)

  • p(t)p(t)采样函数
  • p(t)p(t) 的基波周期 TT采样周期
  • p(t)p(t) 的基波频率 ωs=2πT\omega_s=\frac{2\pi}{T}采样频率

采样结果为:

xp(t)=x(t)p(t)=n=+x(nT)δ(tnT)x_p(t)=x(t)\cdot p(t)=\sum_{n=-\infin}^{+\infin}x(nT)\delta(t-nT)

这样的采样就是理想采样,也就是冲激串采样

理想采样

由 CTFT 在频域有:

p(t)CTFTP(jω)=2πTn=+δ(ω2πTk)p(t)\stackrel{CTFT}{\longleftrightarrow}P(j\omega)=\frac{2\pi}{T}\sum_{n=-\infin}^{+\infin}\delta(\omega-\frac{2\pi}{T}k)

从而可得到 Xp(jω)X_p(j\omega)

Xp(jω)=12πX(jω)P(jω)=12πX(jω)2πTn=+δ(ω2πTk)=1Tn=+X(j(ω2πTk))=1Tn=+X(j(ωkωs))\begin{aligned} X_p(j\omega) &=\frac{1}{2\pi}X(j\omega)*P(j\omega)\\ &=\frac{1}{2\pi}X(j\omega)*\frac{2\pi}{T}\sum_{n=-\infin}^{+\infin}\delta(\omega-\frac{2\pi}{T}k)\\ &=\frac{1}{T}\sum_{n=-\infin}^{+\infin}X(j(\omega-\frac{2\pi}{T}k))\\ &=\frac{1}{T}\sum_{n=-\infin}^{+\infin}X(j(\omega-k\omega_s)) \end{aligned}

可见,在时域对连续时间信号进行理想采样,就相当于在频域将连续时间信号的频谱以 ωs=2πT\omega_s=\frac{2\pi}{T} 为周期进行延拓。

# 采样定理

要想使采样后的信号样本能完全代表原来的信号,就意味着要能够从 X𝑝(jω)X_𝑝(j\omega)不失真地分离X(jω)X(j\omega) 。这就要求 X𝑝(jω)X_𝑝(j\omega) 在周期性延拓时不能发生频谱的混叠,因此:

  1. x(t)x(t) 必须是带限的,设最高频率分量为 ωM\omega_M
  2. 采样间隔(周期)不能是任意的,必须保持采样频率 ωs=2πT>2ωM\omega_s=\frac{2\pi}{T}\gt 2\omega_M
  3. 采样频率也不能过大,不能导致周期延拓后频谱发生混叠(补充)

采样频率的下限 2ωM2\omega_M 也叫做奈奎斯特率(Nyquist rate)

在满足上述条件时,就可以通过理想低通滤波器从 X𝑝(jω)X_𝑝(j\omega) 中不失真地分离出 X(jω)X(j\omega)

# 理想低通滤波器

低通滤波器频域

若要满足采样定理,低通滤波器截止频率 ωc\omega_c 必须满足:ωM<ωc<ωsωM\omega_M\lt\omega_c\lt\omega_s-\omega_M

为补偿采样导致的频谱幅度减小,滤波器在通带内应具有 TT 倍增益。

# Nyquist 采样定理

对带限于最高频率 ω𝑀\omega_𝑀 的连续时间信号 x(t)x(t) ,如果以 ωs>2ω𝑀\omega_s>2\omega_𝑀 的频率进行理想采样,则 x(t)x(t) 可以唯一地由其样本 x(nT)x(nT) 来确定。

这里的 TT 也是采样周期,对应采样频率 ωs\omega_s

# 零阶保持采样

零阶保持采样相当于理想采样后,再级联一个零阶保持系统,是最简单的一种恢复重建采样前原信号的方法。

如果由零阶保持所给出的粗糙内插令人不够满意,则可以使用各种更为平滑的內插手段,其中的一些合起来统称为高阶保持 (higher order hold)

零阶保持采样

零阶保持采样结果

为了能从 x0(t)x_0(t) 恢复 x(t)x(t) ,零阶保持后要再级(串,卷积)联一个系统 H𝑟(jω)H_𝑟(j\omega) ,使得:

H0(jω)Hr(jω)=H(jω)={T,ω<ωc0,ω>ωcH_0(j\omega)H_r(j\omega)=H(j\omega)= \begin{cases} T,&|\omega|\lt\omega_c\\ 0,&|\omega|\gt\omega_c \end{cases}

其中 ωM<ωc<ωsωM\omega_M\lt\omega_c\lt\omega_s-\omega_M ;图像如下:

零阶保持采样最终输出

零阶保持系统的单位冲激响应 h0(t)h_0(t) 是矩形方波信号(经过了一定的时移),利用基本 CTFT 变换对和时移特性可得到:

H0(jω)=2ωsin(ω2T)ejω2TH_0(j\omega)=\frac{2}{\omega}\sin(\frac{\omega}{2}T)e^{-j\frac{\omega}{2}T}

零阶保持系统频域

H(jω)H(j\omega)H0(jω)H_0(j\omega) 可得到 H𝑟(jω)H_𝑟(j\omega)

H𝑟(jω)=H(jω)H0(jω)=2ωH(jω)sin(ω2T)ejω2TH_𝑟(j\omega)=\frac{H(j\omega)}{H_0(j\omega)}=\frac{2}{\omega}\frac{H(j\omega)}{\sin(\frac{\omega}{2}T)}e^{j\frac{\omega}{2}T}

Hr的模Hr的幅度

# 内插

# 理想内插

也称为时域带限内插

h(t)h(t) 为理想低通滤波器的单位冲激响应,则

xr(t)=x𝑝(t)h(t)=n=+x(nT)δ(tnT)h(t)=n=+x(nT)h(tnT)\begin{aligned} x_r(t) &=x_𝑝(t)*h(t)\\ &=\sum_{n=-∞}^{+∞}x(nT)\delta(t-nT)*h(t)\\ &=\sum_{n=-∞}^{+∞}x(nT)h(t - nT) \end{aligned}

这里利用了单位冲激响应的卷积特性(定义):

x(h(g(t)))=x(h(t))δ(g(t))x(h(g(t)))=x(h(t))*\delta(g(t))

表明:理想内插以理想低通滤波器的单位冲激响应作为内插函数。

当理想低通滤波器的截止频率为 ωc=12ωs=πT\omega_c=\frac{1}{2}\omega_s=\frac{\pi}{T} 时有:

\begin{aligned} h(t)=T\frac{\sin \omega_c t}{\pit}\text{Sa}(\omega_ct)=\text{Sa}(\omega_ct) \end{aligned}

则有:

xr(t)=n=+x(nT)Sa[ωc(tnT)]x_r(t)=\sum_{n=-∞}^{+\infin}x(nT)\cdot Sa[\omega_c(t-nT)]

按照这个过程,就得到了原始信号 x(t)x(t) 的重建信号 xr(t)x_r(t)。只要采样过程满足采样定理,那么这个重建就完全恢复了 x(t)x(t)

# 调制与调解

Modulation & Demodulation

利用傅里叶变换的相乘特性:两个信号在时域相乘,可以看成是由一个信号控制另一个信号的幅度,这就是幅度调制。其中前者为调制信号,后者为载波

WIKI:调制调解

# 正弦幅度调制

正弦幅度调制等效于在频域将调制信号的频谱搬移到载频位置

调制信号 s(t)CTFTS(jω)s(t)\stackrel{CTFT}{\longleftrightarrow}S(j\omega)

s正弦幅度调制信号的频域

载波信号 p(t)CTFTP(jω)p(t)\stackrel{CTFT}{\longleftrightarrow}P(j\omega)

p余弦信号的频域

输入乘法器,输出调制后的信号:

正弦幅度调制

调制后的信号 r(t)CTFTR(jω)r(t)\stackrel{CTFT}{\longleftrightarrow}R(j\omega)

正弦幅度调制结果

# 同步调解

必须要求调制和解调时所使用的载波不仅要严格同频,而且要同相。因此这种解调方法称为同步解调。

r(t)cosω0tF12πR(jω)π[δ(ωω0)+δ(ω+ω0)]=12S(jω)+14S[j(ω2ω0)]+14S[j(ω+2ω0)]\begin{aligned} r(t)cos\omega_0t\stackrel{F}{\longleftrightarrow} &\ \frac{1}{2\pi}R(j\omega)*\pi[\delta(\omega-\omega_0)+\delta(\omega+\omega_0)]\\ =&\ \frac{1}{2}S(j\omega)+\frac{1}{4}S[j(\omega-2\omega_0)]+\frac{1}{4}S[j(\omega+2\omega_0)] \end{aligned}

同步调解结果

\ No newline at end of file +通信系统 - 信号与系统 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

there are still some bugs rendering katex here...

LTI 系统对输入信号所起的作用包括两个方面:

  • 改变输入信号各频率分量的幅度
  • 改变输入信号各频率分量的相对相位

Y(jω)=X(jω)H(jω)Y(jω)=X(jω)H(jω)Y(jω)=X(jω)+H(jω)\begin{aligned} Y(j\omega)&=X(j\omega)H(j\omega)\\ |Y(j\omega)|&=|X(j\omega)|\cdot|H(j\omega)|\\ \angle Y(j\omega)&=\angle X(j\omega)+\angle H(j\omega) \end{aligned}

线性与非线性相位

信号在传输过程中,相位特性或幅度特性发生改变都可能引起信号波形的改变,即发生失真

当相位特性仅仅是产生一个线性相移时,只引起信号在时间上的平移。如连续时间 LTI 系统,信号的时移会导致其频谱产生一个线性相移

x(t)FX(jω)x(tt0)FX(jω)ejωt0x(t)\stackrel{F}{\longleftrightarrow}X(j\omega)\\ \dArr\\ x(t-t_0)\stackrel{F}{\longleftrightarrow}X(j\omega)e^{-j\omega t_0}

此时信号波形不发生改变,只是发生时间上的延迟,因此未丢失信号所携带的任何信息。

如果系统的相位特性是非线性的,由于不同频率分量所产生的时移不同,叠加起来会变成一个与原来信号不相同的信号波形。

系统响应与输入信号满足:

y(t)=kx(tt0)y[n]=kx[nn0]y(t)=kx(t-t_0)\ \ \ y[n]=kx[n-n_0]

也就是:

则可视为在传输中未发生失真

H(jω)=k,H(jω)=ωt0|H(j\omega)|=k,\ \ \angle H(j\omega)=-\omega t_0

在传输信号的带宽范围内

理想滤波器

  • 非因果系统,因而是物理不可实现
  • h(t)h(t) 存在震荡

# 采样

# 采样的概念

在某些离散的时间点上提取连续时间信号值的过程就是采样(sampling)

与之相对应的,从离散时间信号等间隔地提取信号,则叫做抽取(decimation)

一般情况下,从连续时间信号采样所得到的样本序列不能唯一地代表原来的连续时间信号,决定是否能从采样结果恢复原信号的关键在于采样定理

# 采样的数学模型

采样的数学模型

在时域:

xp(t)=x(t)p(t)x_p(t)=x(t)\cdot p(t)

在频域:

Xp(jω)=12πX(jω)P(jω)X_p(j\omega)=\frac{1}{2\pi}X(j\omega)*P(j\omega)

# 冲激串采样 (理想采样)

TT 为采样间隔的脉冲采样信号为:

p(t)=n=+δ(tnT)p(t)=\sum_{n=-\infin}^{+\infin}\delta(t-nT)

  • p(t)p(t)采样函数
  • p(t)p(t) 的基波周期 TT采样周期
  • p(t)p(t) 的基波频率 ωs=2πT\omega_s=\frac{2\pi}{T}采样频率

采样结果为:

xp(t)=x(t)p(t)=n=+x(nT)δ(tnT)x_p(t)=x(t)\cdot p(t)=\sum_{n=-\infin}^{+\infin}x(nT)\delta(t-nT)

这样的采样就是理想采样,也就是冲激串采样

理想采样

由 CTFT 在频域有:

p(t)CTFTP(jω)=2πTn=+δ(ω2πTk)p(t)\stackrel{CTFT}{\longleftrightarrow}P(j\omega)=\frac{2\pi}{T}\sum_{n=-\infin}^{+\infin}\delta(\omega-\frac{2\pi}{T}k)

从而可得到 Xp(jω)X_p(j\omega)

Xp(jω)=12πX(jω)P(jω)=12πX(jω)2πTn=+δ(ω2πTk)=1Tn=+X(j(ω2πTk))=1Tn=+X(j(ωkωs))\begin{aligned} X_p(j\omega) &=\frac{1}{2\pi}X(j\omega)*P(j\omega)\\ &=\frac{1}{2\pi}X(j\omega)*\frac{2\pi}{T}\sum_{n=-\infin}^{+\infin}\delta(\omega-\frac{2\pi}{T}k)\\ &=\frac{1}{T}\sum_{n=-\infin}^{+\infin}X(j(\omega-\frac{2\pi}{T}k))\\ &=\frac{1}{T}\sum_{n=-\infin}^{+\infin}X(j(\omega-k\omega_s)) \end{aligned}

可见,在时域对连续时间信号进行理想采样,就相当于在频域将连续时间信号的频谱以 ωs=2πT\omega_s=\frac{2\pi}{T} 为周期进行延拓。

# 采样定理

要想使采样后的信号样本能完全代表原来的信号,就意味着要能够从 X𝑝(jω)X_𝑝(j\omega)不失真地分离X(jω)X(j\omega) 。这就要求 X𝑝(jω)X_𝑝(j\omega) 在周期性延拓时不能发生频谱的混叠,因此:

  1. x(t)x(t) 必须是带限的,设最高频率分量为 ωM\omega_M
  2. 采样间隔(周期)不能是任意的,必须保持采样频率 ωs=2πT>2ωM\omega_s=\frac{2\pi}{T}\gt 2\omega_M
  3. 采样频率也不能过大,不能导致周期延拓后频谱发生混叠(补充)

采样频率的下限 2ωM2\omega_M 也叫做奈奎斯特率(Nyquist rate)

在满足上述条件时,就可以通过理想低通滤波器从 X𝑝(jω)X_𝑝(j\omega) 中不失真地分离出 X(jω)X(j\omega)

# 理想低通滤波器

低通滤波器频域

若要满足采样定理,低通滤波器截止频率 ωc\omega_c 必须满足:ωM<ωc<ωsωM\omega_M\lt\omega_c\lt\omega_s-\omega_M

为补偿采样导致的频谱幅度减小,滤波器在通带内应具有 TT 倍增益。

# Nyquist 采样定理

对带限于最高频率 ω𝑀\omega_𝑀 的连续时间信号 x(t)x(t) ,如果以 ωs>2ω𝑀\omega_s>2\omega_𝑀 的频率进行理想采样,则 x(t)x(t) 可以唯一地由其样本 x(nT)x(nT) 来确定。

这里的 TT 也是采样周期,对应采样频率 ωs\omega_s

# 零阶保持采样

零阶保持采样相当于理想采样后,再级联一个零阶保持系统,是最简单的一种恢复重建采样前原信号的方法。

如果由零阶保持所给出的粗糙内插令人不够满意,则可以使用各种更为平滑的內插手段,其中的一些合起来统称为高阶保持 (higher order hold)

零阶保持采样

零阶保持采样结果

为了能从 x0(t)x_0(t) 恢复 x(t)x(t) ,零阶保持后要再级(串,卷积)联一个系统 H𝑟(jω)H_𝑟(j\omega) ,使得:

H0(jω)Hr(jω)=H(jω)={T,ω<ωc0,ω>ωcH_0(j\omega)H_r(j\omega)=H(j\omega)= \begin{cases} T,&|\omega|\lt\omega_c\\ 0,&|\omega|\gt\omega_c \end{cases}

其中 ωM<ωc<ωsωM\omega_M\lt\omega_c\lt\omega_s-\omega_M ;图像如下:

零阶保持采样最终输出

零阶保持系统的单位冲激响应 h0(t)h_0(t) 是矩形方波信号(经过了一定的时移),利用基本 CTFT 变换对和时移特性可得到:

H0(jω)=2ωsin(ω2T)ejω2TH_0(j\omega)=\frac{2}{\omega}\sin(\frac{\omega}{2}T)e^{-j\frac{\omega}{2}T}

零阶保持系统频域

H(jω)H(j\omega)H0(jω)H_0(j\omega) 可得到 H𝑟(jω)H_𝑟(j\omega)

H𝑟(jω)=H(jω)H0(jω)=2ωH(jω)sin(ω2T)ejω2TH_𝑟(j\omega)=\frac{H(j\omega)}{H_0(j\omega)}=\frac{2}{\omega}\frac{H(j\omega)}{\sin(\frac{\omega}{2}T)}e^{j\frac{\omega}{2}T}

Hr的模Hr的幅度

# 内插

# 理想内插

也称为时域带限内插

h(t)h(t) 为理想低通滤波器的单位冲激响应,则

xr(t)=x𝑝(t)h(t)=n=+x(nT)δ(tnT)h(t)=n=+x(nT)h(tnT)\begin{aligned} x_r(t) &=x_𝑝(t)*h(t)\\ &=\sum_{n=-∞}^{+∞}x(nT)\delta(t-nT)*h(t)\\ &=\sum_{n=-∞}^{+∞}x(nT)h(t - nT) \end{aligned}

这里利用了单位冲激响应的卷积特性(定义):

x(h(g(t)))=x(h(t))δ(g(t))x(h(g(t)))=x(h(t))*\delta(g(t))

表明:理想内插以理想低通滤波器的单位冲激响应作为内插函数。

当理想低通滤波器的截止频率为 ωc=12ωs=πT\omega_c=\frac{1}{2}\omega_s=\frac{\pi}{T} 时有:

\begin{aligned} h(t)=T\frac{\sin \omega_c t}{\pit}\text{Sa}(\omega_ct)=\text{Sa}(\omega_ct) \end{aligned}

则有:

xr(t)=n=+x(nT)Sa[ωc(tnT)]x_r(t)=\sum_{n=-∞}^{+\infin}x(nT)\cdot Sa[\omega_c(t-nT)]

按照这个过程,就得到了原始信号 x(t)x(t) 的重建信号 xr(t)x_r(t)。只要采样过程满足采样定理,那么这个重建就完全恢复了 x(t)x(t)

# 调制与调解

Modulation & Demodulation

利用傅里叶变换的相乘特性:两个信号在时域相乘,可以看成是由一个信号控制另一个信号的幅度,这就是幅度调制。其中前者为调制信号,后者为载波

WIKI:调制调解

# 正弦幅度调制

正弦幅度调制等效于在频域将调制信号的频谱搬移到载频位置

调制信号 s(t)CTFTS(jω)s(t)\stackrel{CTFT}{\longleftrightarrow}S(j\omega)

s正弦幅度调制信号的频域

载波信号 p(t)CTFTP(jω)p(t)\stackrel{CTFT}{\longleftrightarrow}P(j\omega)

p余弦信号的频域

输入乘法器,输出调制后的信号:

正弦幅度调制

调制后的信号 r(t)CTFTR(jω)r(t)\stackrel{CTFT}{\longleftrightarrow}R(j\omega)

正弦幅度调制结果

# 同步调解

必须要求调制和解调时所使用的载波不仅要严格同频,而且要同相。因此这种解调方法称为同步解调。

r(t)cosω0tF12πR(jω)π[δ(ωω0)+δ(ω+ω0)]=12S(jω)+14S[j(ω2ω0)]+14S[j(ω+2ω0)]\begin{aligned} r(t)cos\omega_0t\stackrel{F}{\longleftrightarrow} &\ \frac{1}{2\pi}R(j\omega)*\pi[\delta(\omega-\omega_0)+\delta(\omega+\omega_0)]\\ =&\ \frac{1}{2}S(j\omega)+\frac{1}{4}S[j(\omega-2\omega_0)]+\frac{1}{4}S[j(\omega+2\omega_0)] \end{aligned}

同步调解结果

\ No newline at end of file diff --git a/ie/signals-and-systems/duality/index.html b/ie/signals-and-systems/duality/index.html index 0d4313e2..9aabc4d2 100644 --- a/ie/signals-and-systems/duality/index.html +++ b/ie/signals-and-systems/duality/index.html @@ -1 +1 @@ -离散 / 连续时间傅里叶系数 / 变换的对偶关系 - 信号与系统 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 归纳总结

缩写:

  • CTFS—— 连续时间傅里叶级数
  • DTFS—— 离散时间傅里叶级数
  • CTFT—— 连续时间傅里叶变换
  • DTFT—— 离散时间傅里叶变换

一图归纳:

归纳

信号在时域的特性和在频域的特性之间存在以下对应关系:

  • 时域的周期性 —— 频域的离散性
  • 时域的非周期性 —— 频域的连续性
  • 时域的离散性 —— 频域的周期性
  • 时域的连续性 —— 频域的非周期性

# CTFT 的对偶

x(t)CTFTX(jω)x(t)\stackrel{CTFT}{\longleftrightarrow}X(j\omega) ,则有:

x(t)=12π+X(jω)ejωtdω2πx(t)=+X(jω)ejωtdω2πx(ω)=+X(jt)ejωtdt2πx(ω)=+X(jt)ejωtdt\begin{aligned} x(t) &=\frac{1}{2\pi} \int_{-\infin}^{+\infin} X(j\omega) e^{j\omega t}d\omega\\ 2\pi x(t) &=\int_{-\infin}^{+\infin} X(j\omega) e^{j\omega t}d\omega\\ 2\pi x(\omega) &=\int_{-\infin}^{+\infin} X(jt) e^{j\omega t}dt\\ 2\pi x(-\omega) &=\int_{-\infin}^{+\infin} X(jt) e^{-j\omega t}dt\\ \end{aligned}

可得到对偶关系:

x(t)CTFTX(jω)X(jt)CTFT2πx(ω)x(t)\stackrel{CTFT}{\longleftrightarrow}X(j\omega)\\\\ X(jt)\stackrel{CTFT}{\longleftrightarrow}2\pi x(-\omega)

利用这一对偶关系,可以将 CTFT 时域的某些特性对偶到频域,或者反之。

# DFS 的对偶

ak=1Nn=Nx[n]ej2πNkna_k=\frac{1}{N}\sum_{n=\langle N\rangle}x[n]e^{-j\frac{2\pi}{N}kn}

aka_k 本身也是以 NN 为周期的序列,用 n-n 变量代换 nn ,则可以将 aka_k 写为离散时间傅里叶级数(DFS)的形式:

ak=n=N1Nx[n]ej2πNkna_k=\sum_{n=\langle N\rangle}\frac{1}{N}x[-n]\cdot e^{j\frac{2\pi}{N}kn}

也就是(将 kknn 变量交换):

an=k=N1Nx[k]ej2πNkna_n=\sum_{k=\langle N\rangle}\frac{1}{N}x[-k]\cdot e^{j\frac{2\pi}{N}kn}

可以得到对偶关系;

x[n]DFSakanDFS1Nx[k]\begin{aligned} x[n]&\stackrel{DFS}{\longleftrightarrow}a_k\\\\ a_n&\stackrel{DFS}{\longleftrightarrow}\frac{1}{N}x[-k] \end{aligned}

利用这一对偶关系,可以将 DFS 在时域的性质推广至频域,或者反之。

# DTFT 与 CFS 间的对偶

x[n]x[n] 的离散时间傅里叶正变换(DTFT)X(ejω)X(e^{j\omega}) 是以 2π2\pi 为周期的连续函数。如果将其视为连续时间信号 X(ejt)X(e^{jt}) ,则可以表示为连续时间傅里叶级数(CFS)的形式:

X(ejt)=n=+x[n]ejtn=k=+x[k]ejkt\begin{aligned} X(e^{jt}) &=\sum_{n=-\infin}^{+\infin}x[n]\cdot e^{-jtn}\\ &=\sum_{k=-\infin}^{+\infin}x[-k]\cdot e^{jkt} \end{aligned}

于是就有对偶关系:

x[n]DTFTX(ejω)X(ejt)DFSx[k]\begin{aligned} x[n]&\stackrel{DTFT}{\longleftrightarrow}X(e^{j\omega})\\\\ X(e^{jt})&\stackrel{DFS}{\longleftrightarrow}x[-k] \end{aligned}

利用这一对偶关系,可以将 DTFT 的若干特性对偶到 CFS 中去,或者反之。

\ No newline at end of file +离散 / 连续时间傅里叶系数 / 变换的对偶关系 - 信号与系统 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 归纳总结

缩写:

  • CTFS—— 连续时间傅里叶级数
  • DTFS—— 离散时间傅里叶级数
  • CTFT—— 连续时间傅里叶变换
  • DTFT—— 离散时间傅里叶变换

一图归纳:

归纳

信号在时域的特性和在频域的特性之间存在以下对应关系:

  • 时域的周期性 —— 频域的离散性
  • 时域的非周期性 —— 频域的连续性
  • 时域的离散性 —— 频域的周期性
  • 时域的连续性 —— 频域的非周期性

# CTFT 的对偶

x(t)CTFTX(jω)x(t)\stackrel{CTFT}{\longleftrightarrow}X(j\omega) ,则有:

x(t)=12π+X(jω)ejωtdω2πx(t)=+X(jω)ejωtdω2πx(ω)=+X(jt)ejωtdt2πx(ω)=+X(jt)ejωtdt\begin{aligned} x(t) &=\frac{1}{2\pi} \int_{-\infin}^{+\infin} X(j\omega) e^{j\omega t}d\omega\\ 2\pi x(t) &=\int_{-\infin}^{+\infin} X(j\omega) e^{j\omega t}d\omega\\ 2\pi x(\omega) &=\int_{-\infin}^{+\infin} X(jt) e^{j\omega t}dt\\ 2\pi x(-\omega) &=\int_{-\infin}^{+\infin} X(jt) e^{-j\omega t}dt\\ \end{aligned}

可得到对偶关系:

x(t)CTFTX(jω)X(jt)CTFT2πx(ω)x(t)\stackrel{CTFT}{\longleftrightarrow}X(j\omega)\\\\ X(jt)\stackrel{CTFT}{\longleftrightarrow}2\pi x(-\omega)

利用这一对偶关系,可以将 CTFT 时域的某些特性对偶到频域,或者反之。

# DFS 的对偶

ak=1Nn=Nx[n]ej2πNkna_k=\frac{1}{N}\sum_{n=\langle N\rangle}x[n]e^{-j\frac{2\pi}{N}kn}

aka_k 本身也是以 NN 为周期的序列,用 n-n 变量代换 nn ,则可以将 aka_k 写为离散时间傅里叶级数(DFS)的形式:

ak=n=N1Nx[n]ej2πNkna_k=\sum_{n=\langle N\rangle}\frac{1}{N}x[-n]\cdot e^{j\frac{2\pi}{N}kn}

也就是(将 kknn 变量交换):

an=k=N1Nx[k]ej2πNkna_n=\sum_{k=\langle N\rangle}\frac{1}{N}x[-k]\cdot e^{j\frac{2\pi}{N}kn}

可以得到对偶关系;

x[n]DFSakanDFS1Nx[k]\begin{aligned} x[n]&\stackrel{DFS}{\longleftrightarrow}a_k\\\\ a_n&\stackrel{DFS}{\longleftrightarrow}\frac{1}{N}x[-k] \end{aligned}

利用这一对偶关系,可以将 DFS 在时域的性质推广至频域,或者反之。

# DTFT 与 CFS 间的对偶

x[n]x[n] 的离散时间傅里叶正变换(DTFT)X(ejω)X(e^{j\omega}) 是以 2π2\pi 为周期的连续函数。如果将其视为连续时间信号 X(ejt)X(e^{jt}) ,则可以表示为连续时间傅里叶级数(CFS)的形式:

X(ejt)=n=+x[n]ejtn=k=+x[k]ejkt\begin{aligned} X(e^{jt}) &=\sum_{n=-\infin}^{+\infin}x[n]\cdot e^{-jtn}\\ &=\sum_{k=-\infin}^{+\infin}x[-k]\cdot e^{jkt} \end{aligned}

于是就有对偶关系:

x[n]DTFTX(ejω)X(ejt)DFSx[k]\begin{aligned} x[n]&\stackrel{DTFT}{\longleftrightarrow}X(e^{j\omega})\\\\ X(e^{jt})&\stackrel{DFS}{\longleftrightarrow}x[-k] \end{aligned}

利用这一对偶关系,可以将 DTFT 的若干特性对偶到 CFS 中去,或者反之。

\ No newline at end of file diff --git a/ie/signals-and-systems/lti/index.html b/ie/signals-and-systems/lti/index.html index b48126aa..c3a2e31e 100644 --- a/ie/signals-and-systems/lti/index.html +++ b/ie/signals-and-systems/lti/index.html @@ -1 +1 @@ -卷积と线性时不变系统 - 信号与系统 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

Linear Time Invariant 线性时不变

基本信号应具有以下特点:

  • 本身尽可能简单,并且用它们的线性组合能够表示尽可能广泛的信号
  • LTI 系统对这种信号的响应易于计算且有利于对系统的深入理解

两类有用的基本信号:

  • 复指数信号
  • 单位冲激信号

本章主要考虑以单位冲激信号为基本信号进行信号与系统分析

summary

# 卷积和

# 定义

对于任意一个离散时间系统:

离散时间系统

设离散时间系统为 LTI 的,定义单位脉冲响应 h[n]h[n] 为以单位冲激信号 δ[n]\delta[n] 为输入时的输出:

δ[n]h[n]\delta[n]\to h[n]

由 LTI 时不变性有:

δ[nk]h[nk]\delta[n-k]\to h[n-k]

由 LTI 线性有:

x[n]=k=+x[k]δ[nk]y[n]=k=+x[k]h[nk]x[n]=\sum_{k=-\infin}^{+\infin}x[k]\delta[n-k]\to y[n]=\sum_{k=-\infin}^{+\infin}x[k]h[n-k]

这种求得系统响应的运算关系称为卷积和,即离散时间 LTI 系统的响应可以用卷积和表示为:

y[n]=x[n]h[n]=k=+x[k]h[nk]y[n]=x[n]*h[n]=\sum_{k=-\infin}^{+\infin}x[k]h[n-k]

⭐️更一般的形式:

x[nn0n1]=x[nn0]h[nn1]x[n-n_0-n_1]=x[n-n_0]*h[n-n_1]

⭐️只要得到了 LTI 系统对 δ[n]\delta[n] 的 响 应 h[n]h[n] —— 单位脉冲响应,就可以得到 LTI 系统对任何输入信号 x[n]x[n] 的响应。

换言之,一个 LTI 系统可以完全由它的单位脉冲响应 h[n]h[n] 来表征。

# 特殊离散 LTI 系统

# 延时器

h[n]=δ[nn0]h[n]=\delta[n-n_0]

具有该单位脉冲响应的系统一般情况下存在多种可能性,但是对应的 LTI 系统只有一个:

y[n]=x[nn0]=x[n]δ[nn0]y[n]=x[n-n_0]=x[n]*\delta[n-n_0]

# 累加器

h[n]=k=nδ[k]=u[n]h[n]=\sum_{k=-\infin}^{n}\delta[k]=u[n]

对应的 LTI 系统:

y[n]=x[n]u[n]=k=nx[k]y[n]=x[n]*u[n]=\sum_{k=-\infin}^{n}x[k]

# 计算

选择 nn 值并固定,求和项视为 kk 的函数,步骤如下:

  1. x[n]x[n]h[n]h[n] 变为 x[k]x[k]h[k]h[k] ,以 kk 为求和变量
  2. h[k]h[k] 翻转变为 h[k]h[-k]
  3. h[k]h[-k] 平移 nn,变为 h[nk]h[n - k]
  4. x[k]x[k]h[nk]h[n-k] 相乘;
  5. 对乘积 x[k]h[nk]x[k]h[n-k]kZk\in \mathbb{Z} 取和;
    • 一般都转化为只对非 0 区间积分。注意非 0 区间上下限!!!
  6. 改变 nn 值并重复 3–5 步,直到 nn 超过了 x[n]x[n] 非零部分定义域

注意很多题目最后答案会加上一个 u(n)u(n) ,是因为只求定义域在 [0,+)[0,+\infin) 的部分

# 卷积积分

# 定义

类似积分思想,转化为无限多的离散和的极限

用冲激信号表示连续时间信号:

将输入信号 x(t)x(t) 近似表示为移位、放缩后的脉冲之和

脉冲和近似表示输入信号

xΔ(t)=x(kΔ),kΔ<t<(k+1)Δx_{\Delta}(t)=x(k\Delta)\ ,\ k\Delta\lt t\lt(k+1)\Delta

阶梯近似表达过程:

设连续时间系统为 LTI 的,定义(名字待补,与卷积和中的单位脉冲响应对应) hΔ(n)h_{\Delta}(n) 为以单位冲激信号 δΔ(n)\delta_{\Delta}(n) 为输入时的输出:

δΔ(n)hΔ(n)\delta_{\Delta}(n)\to h_{\Delta}(n)

阶梯近似表达

由 LTI 时不变性有:

δΔ(nkΔ)hΔ(nkΔ)\delta_{\Delta}(n-k\Delta)\to h_{\Delta}(n-k\Delta)

由 LTI 线性齐次性尺度调整:

x(kΔ)δΔ(nkΔ)x(kΔ)hΔ(nkΔ)x(k\Delta)\delta_{\Delta}(n-k\Delta)\to x(k\Delta)h_{\Delta}(n-k\Delta)

阶梯近似表达2

由 LTI 线性叠加性有:

k=+x(kΔ)δΔ(nkΔ)Δk=+x(kΔ)hΔ(nkΔ)ΔxΔ(t)yΔ(t)\sum_{k=-\infin}^{+\infin}x(k\Delta)\delta_{\Delta}(n-k\Delta)\Delta\to \sum_{k=-\infin}^{+\infin}x(k\Delta)h_{\Delta}(n-k\Delta)\Delta\\ x_{\Delta}(t)\to y_{\Delta}(t)

当 Δ → 0 时 :

  • xΔ(t)x(t)x_Δ(t) → x(t)
  • yΔ(t)y(t)y_Δ(t) → y(t)
  • kΔτkΔ → \tau
  • ΔdτΔ → d\tau
  • δΔ(tkΔ)δ(tτ)\delta_Δ(t - kΔ) → \delta(t - \tau)
  • hΔ(tkΔ)h(tτ)h_Δ(t - kΔ) → h(t - \tau)
  • \sum\to\int

从而得到:

x(t)=+x(τ)δ(tτ)dτ=x(t)δ(t)y(t)=+x(τ)h(tτ)dτ=x(t)h(t)x(t)=\int_{-\infin}^{+\infin}x(\tau)\delta(t-\tau)d\tau=x(t)*\delta(t)\\ y(t)=\int_{-\infin}^{+\infin}x(\tau)h(t-\tau)d\tau=x(t)*h(t)

  • 其中第一个式子意义是:用位移的单位冲激信号表示任意的连续时间信号
  • 其中第一个式子意义是:用卷积积分表示连续时间 LTI 系统的响应

阶梯近似图解过程:

阶梯近似图解过程

# 计算

求卷积积分 x(t)h(t)=+x(τ)h(tτ)dτx(t) * h(t) = \int_{-∞}^{+∞}x(\tau)h(t - \tau)d\tau 的过程与卷积和计算过程相似。卷积积分的计算步骤如下:

  1. x(t)x(t)h(t)h(t) 变为 x(τ)x(\tau)h(τ)h(\tau) ,以 τ\tau 为积分变量;
  2. h(τ)h(\tau) 翻转变为 h(τ)h(-\tau)
  3. h(τ)h(-\tau) 平移 tt ,变为 h(tτ)h(t - \tau)
  4. x(τ)x(\tau)h(tτ)h(t-\tau) 相乘;
  5. 求区间 (,+)(-\infin,+\infin) 上乘积 x(τ)h(tτ)x(\tau)h(t-\tau) 下的面积;
    • 一般都转化为只对非 0 区间积分。注意非 0 区间上下限!!!
  6. 改变 tt 值并重复 3–5 步。

# 特殊连续 LTI 系统

# 积分器

单位冲激信号为输入下系统的响应为:

h(t)=u(t)h(t)=u(t)

对任意激励信号 x(t)x(t) ,系统响应为:

y(t)=x(t)h(t)=+x(τ)h(tτ)dτ=tx(τ)dτy(t)=x(t)*h(t)=\int_{-\infin}^{+\infin}x(\tau)h(t-\tau)d\tau = \int_{-\infin}^{t}x(\tau)d\tau

# 卷积和与卷积积分的性质

# 交换律

变量替换:

x[n]h[n]=k=+x[k]h[nk]=l=+x[nl]h[l]=h[n]x[n]x[n]*h[n]=\sum_{k=-\infin}^{+\infin}x[k]h[n-k]=\sum_{l=-\infin}^{+\infin}x[n-l]h[l]=h[n]*x[n]

x(n)h(n)=+x(τ)h(tτ)dτ=+x(tτ)h(τ)dτ=h(t)x(t)x(n)*h(n)=\int_{-\infin}^{+\infin}x(\tau)h(t-\tau)d\tau=\int_{-\infin}^{+\infin}x(t-\tau')h(\tau')d\tau'=h(t)*x(t)

交换律

s[n]=u[n]h[n]=h[n]u[n]=k=nh[k]s[n]=u[n]*h[n]=h[n]*u[n]=\sum_{k=-\infin}^{n}h[k]

利用 u[n]u[n] 是累加器的单位脉冲响应以及交换律可以得到:

该系统的单位脉冲响应是 h[n]h[n]u[n]u[n] 单位阶跃信号作为输入,则其单位阶跃响应 s[n]s[n] 等价于 以 h[n]h[n] 作为输入时,累加器的响应

# 分配律

x[n](h1[n]+h2[n])=x[n]h1[n]+x[n]h2[n]x(t)(h1(t)+h2(t))=x(t)h1(t)+x(t)h2(t)x[n] * (h_1[n] + h_2[n]) = x[n] * h_1[n] + x[n] * h_2[n]\\ x(t) * (h_1(t) + h_2(t)) = x(t) * h_1(t) + x(t) * h_2(t)

分配律

# 结合律

(x[n]h1[n])h2[n]=x[n](h1[n]h2[n])(x(t)h1(t))h2(t)=x(t)(h1(t)h2(t))(x[n] * h_1 [n] ) * h_2[n] = x[n] * (h_1 [n] * h_2[n])\\ (x(t) * h_1 (t) ) * h_2(t) = x(t) * (h_1(t)* h_2 (t))

结合律

级联的 LTI 系统其总的单位冲激 (脉冲) 响应等于各子系统单位冲激 (脉冲) 响应的卷积

# 级联可交换

卷积运算满足结合律和交换律,因此,系统级联的先后次序可以调换。

x[n]h1[n]h2[n]=x[n]h2[n]h1[n]x(t)h1(t)h2(t)=x(t)h2(t)h1(t)x[n] * h_1[n] * h_2[n] = x[n] * h_2[n] * h_1[n]\\ x(t) * h_1(t) * h_2(t) = x(t) * h_2(t) * h_1(t)

级联可交换

级联次序可交换的前提条件:

  • 系统是 LTI 的
  • 所有涉及到的卷积运算必须收敛

# 微分、积分及时移特性

卷积积分满足微分、积分及时移特性。若 x(t)h(t)=y(t)x(t)*h(t)=y(t),则:

# 微分特性

x(t)h(t)=x(t)h(t)=y(t)x'(t) * h(t) = x(t) * h'(t) = y'(t)

x(m)(t)h(n)(t)=y(m+n)(t)x^{(m)}(t) * h^{(n)}(t) = y^{(m+n)}(t)

tt 求导而不是对 τ\tau 求导

# 积分特性

(tx(τ)dτ)h(t)=+(τ1x(τ)dτ)h(tτ1)dτ1=x(t)(th(τ)dτ)=ty(τ)dτ\begin{aligned} \big(\int_{-\infin}^{t}x(\tau)d\tau\big)*h(t)&= \int_{-\infin}^{+\infin}\big(\int_{-\infin}^{\tau_1}x(\tau)d\tau\big)h(t-\tau_1)d\tau_1\\ &=x(t)*\big(\int_{-\infin}^{t}h(\tau)d\tau\big)\\ &=\int_{-\infin}^{t}y(\tau)d\tau \end{aligned}

# 时移特性

x(tt0)h(tt1)=x(tt1)h(tt0)=y(tt0t1)x(t - t_0) * h(t-t_1) = x(t-t_1) * h(t - t_0) = y(t - t_0-t_1)

# 差分、求和及时移特性

卷积和满足差分、求和及时移特性。若 x [n] * h [n] = y [n],则:

# 差分特性

x[n]x[n1]h[n]=x[n](h[n]h[n1])=y[n]y[n1]x[n]- x[n- 1] * h[n]= x[n]* (h[n]- h[n - 1])= y[n] - y[n - 1]

# 求和特性

(k=nx[k])h[n]=x[n](k=nh[k])=k=ny[k](\sum_{k=-∞}^{n}x[k] )* h[n] = x[n] * (\sum_{k=-∞}^{n}h[k] )=\sum_{k=-∞}^{n}y[k]

# 时移特性

x[tt0]h[tt1]=x[tt1]h[tt0]=y[tt0t1]x[t - t_0] * h[t-t_1] = x[t-t_1]* h[t - t_0]= y[t - t_0-t_1]

# LTI 系统的性质

# 记忆性

对于离散时间 LTI 系统:

y[n]=k=+x[k]h[nk]y[n]=\sum_{k=-\infin}^{+\infin}x[k]h[n-k]

如果系统是无记忆的,则在任何时刻 nny[n]y[n] 都只能和 nn 时刻的输入有关,等式右边的和式中只能有 k=nk=n 时的一项非零,即必须有 h[nk]=0h[n-k]=0knk≠n,也即:

h[n]=0,n0h[n] = 0 ,\ \ \ n\neq0

所以,离散时间无记忆系统的单位脉冲响应为:

h[n]=kδ[n]h[n]=k\delta[n]

即为离散时间系统无记忆充要条件

类似地,连续时间系统无记忆的充要条件为:

h(t)=kδ(t)h(t)=k\delta(t)

k=1k=1 时系统是恒等系统。

# 可逆性

如果 LTI 系统是可逆的,则其逆系统也是 LTI 系统。

互逆的两个系统的满足(充要条件卷积和等于单位冲激信号

h(t)g(t)=δ(t)h[n]g[n]=δ[n]\begin{aligned} h(t) * g(t) =\delta(t)\\ h[n] * g[n] =\delta[n] \end{aligned}

从而有:

x(t)h(t)g(t)=x(t)δ(t)=x(t)x[t]h[n]g[n]=x[t]δ[n]=x[t]\begin{aligned} x(t)*h(t)*g(t)=x(t)*\delta(t)=x(t)\\ x[t]*h[n]*g[n]=x[t]*\delta[n]=x[t] \end{aligned}

可逆性

例如:延时器是可逆的 LTI 系统,h (t) = \delta (t - t0),其逆系统是 g (t) = \delta (t + t0),显然有:

h(t)g(t)=(tt0)δ(t+t0)=δ(t)h(t) * g(t) = (t - t_0) * \delta(t + t_0) = \delta(t)

又如:累加器是可逆的 LTI 系统,其 h [n] = u [n],其逆系统是 g [n] = \delta [n] - \delta [n - 1],显然也有:

h[n]g[n]=u[n](δ[n]δ[n1])=u[n]u[n1]=δ[n]\begin{aligned} h[n] * g[n] &= u[n] * (\delta[n] - \delta[n - 1])\\ &= u[n] - u[n - 1] = \delta[n] \end{aligned}

# 因果性

对于离散时间 LTI 系统:

y[n]=k=+x[k]h[nk]y[n]=\sum_{k=-\infin}^{+\infin}x[k]h[n-k]

因果性意味着上式等号右边和式中所有 k > n 的项都必须为零,即 h [n - k] = 0,k > n,也即:

h[n]=0,n<0h[n] = 0,\ \ \ n < 0

同理对连续时间因果系统有:

h(t)=0,t<0h(t) = 0, \ \ \ t < 0

即为 LTI 系统具有因果性的充要条件

对于线性系统而言,因果性与初始松弛条件等价。所谓系统满足初始松弛条件是指该系统具有如下表现:对于任意时刻,只要该时刻之前系统的输入为 0,则该时刻之前系统的输出也必然为 0。

(参考教材习题 1.44 (a))

– 该等价性的前提是系统为线性的。否则不一定成立。例如 y n = 2x n + 3 是因果的,但显然不满足初始松弛条件。

# 稳定性

稳定性意味着有界输入必然产生有界输出。以离散时间 LTI 系统为例,设 |x [n]| 有界,| x [n - k]| ≤ A。有:

y[n]=k=+h[k]x[nk]k=+h[k]x[nk]Ak=+h[k]|y[n]| = |\sum_{k=-∞}^{+∞}h[k]x[n - k]| ≤ \sum_{k=-∞}^{+∞} |h[k]| |x[n - k]| ≤ A \sum_{k=-∞}^{+∞}|h[k]|

离散 LTI 系统稳定的充分必要条件为:

n=+h[n]<+\sum_{n=-\infin}^{+\infin}|h[n]|\lt +\infin

类似地有连续 LTI 系统稳定的充分必要条件为:

+h(t)dt<+\int_{-\infin}^{+\infin}|h(t)|dt \lt +\infin

# 单位阶跃响应

在工程实际中,也常用单位阶跃响应来描述 LTI 系统。单位阶跃响应就是系统对 u (t) 或 u [n] 所产生的响应,记为 s (t) 或 s [n]。因此有:

s[n]=u[n]h[n]=k=nh[k]s[n] = u[n] * h[n] = \sum_{k=-∞}^n h[k]

h[n]=s[n]s[n1]h[n] = s[n] - s[n - 1]

s(t)=u(t)h(t)=th(τ)dτs(t) = u(t) * h(t) = \int_{-\infin}^{t}h(\tau)d\tau

h(t)=ds(t)dt=s(t)h(t) =\frac{ds(t)}{dt}= s'(t)

# 用微分和差分方程描述的因果 LTI 系统

在工程实际中有相当普遍的一类系统,其数学模型可以用线性常系数微分方程或线性常系数差分方程来描述。

在时域内分析这类 LTI 系统,就是要求解线性常系数微分方程或差分方程。

# 线性常系数微分方程

一般情况 NMN\geq M , N 阶非其次常系数微分方程的一般形式:

k=0Nakdky(t)dtk=k=0Mbkdky(t)dtk\sum_{k=0}^{N}a_k\frac{d^ky(t)}{dt^k}=\sum_{k=0}^{M}b_k\frac{d^ky(t)}{dt^k}

其中 ak, bk 均为常数

求解该微分方程(求 y (t) 的显式表达)的步骤:

  1. 求出齐次解通解)yh (t) ,也称为系统的自然响应自由响应
    1. 建立特征方程求出特征根 𝜆k
    2. 根据特征根得到齐次解形式
    3. 根据附加条件确定齐次解形式中的待定常数 Ck
  2. 特解 y𝑝(t),也称系统的受迫响应强迫响应,其形式与输入信号有关
    1. 根据输入信号形式得到特解形式
    2. 将输入信号与特解代入微分方程确定特解形式中的待定常数
  3. 得到完全解 y (t) = yh(t) + y𝑝(t)

附加条件常给出为初始松弛条件,即 t<0t\lt 0 时若 x(t)=0x(t)=0 则有 y(t)=0y(t)=0 ,或 n<0n\lt 0 时若 x[n]=0x[n]=0 则有 y[n]=0y[n]=0

对于线性系统,初始松弛条件与满足因果性是等价的

解题时,可以直接认为就是有 y(0)=0y(0)=0x[0]=0x[0]=0

# 线性常系数差分方程

一般情况 NMN\geq MNN 阶非其次常系数差分方程的一般形式

k=0Naky[nk]=k=0Mbkx[nk]\sum_{k=0}^{N}a_k y[n-k]=\sum_{k=0}^{M}b_k x[n-k]

其中 ak, bk 均为常数

还可以将其改写为 ==(正向) 递归形式 ==:

y[n]=1a0(k=0Mbkx[nk]k=0Naky[nk])y[n]=\frac{1}{a_0}(\sum_{k=0}^{M}b_k x[n-k]-\sum_{k=0}^{N}a_k y[n-k])

还可将差分方程改写反向递归求解形式

y[nN]=1aN(k=0Mbkx[nk]k=0N1aky[nk])y[n-N]=\frac{1}{a_N}(\sum_{k=0}^{M}b_k x[n-k]-\sum_{k=0}^{N-1}a_k y[n-k])

ak=0,k0a_k =0,k\neq 0 时,差分方程变为一个卷积和的形式即非递归方程

y[n]=k=0Mbka0x[nk]=+h[n]x[nk]y[n]=\sum_{k=0}^{M}\frac{b_k}{a_0}x[n-k]=\sum_{-\infin}^{+\infin}h[n]\ x[n-k]

其中:

h[n]={bna0,0nM0,othersh[n]= \begin{cases} \frac{b_n}{a_0},\ \ 0\leq n\leq M \\ 0,\ \ \ \ \text{others} \end{cases}

  • 由于 h [n] 是有限长的,当 ak=0,k0a_k =0,k\neq 0非递归方程描述的系统称为有限脉冲响应( Finite Impulse Response,FIR)系统

  • 而其他情况下递归方程描述的系统结合初始松弛条件具有无限长的单位脉冲响应,因而称为无限脉冲响应(Infinite Impulse Response,IIR)系统

  • 与微分方程类似,差分方程的齐次解通解)与输入信号的形式无关,称为系统的自然响应自由响应

  • 特解具有与输入信号相同的函数形式,称为受迫响应强迫响应

具有非零起始状态的线性常系数微分或差分方程对应增量线性系统,其响应由两部分组成:

  • 零输入响应,与输入信号无关,属于自然响应
  • 零状态响应,既与输入信号有关,也与系统特性有关,它包含了一部分受迫响应,也包含有一部分自然响应

# 方框图表示

# 差分方程描述系统

对于正向递归形式的 LTI 系统差分方程,其方程中包括三种基本运算:

  • 移位(延迟)—— 对应延迟器
  • 乘系数 —— 对应数乘器
  • 相加 —— 对应加法器

令:

w[n]=k=0Mbkx[nk]w[n]=\sum_{k=0}^{M}b_k x[n-k]

正向递归形式可写为:

y[n]=1a0(w[n]k=0Naky[nk])y[n]=\frac{1}{a_0}(w[n]-\sum_{k=0}^{N}a_k y[n-k])

差分-直接I型

将其级联起来,就成为线性常系数差分方程描述的系统,它具有与差分方程完全相同的运算功能。可以调换级联次序,并将移位单元合并,于是得到直接 II 型

差分-直接II型

# 微分方程描述系统

微分方程也包括三种基本运算:

  • 微分
  • 乘系数
  • 相加

但微分器不仅在工程实现上有困难,而且对误差及噪声极为敏感,因此,通常使用积分器而不用微分器

N 阶微分方程两边同时积分 N 次,即可得到对应 N 阶积分方程:

k=0Naky(Nk)(t)=k=0Mbkx(Nk)(t)\sum_{k=0}^{N}a_k\ y_{(N-k)}(t)=\sum_{k=0}^{M}b_k\ x_{(N-k)}(t)

对此积分方程完全按照差分方程的办法有其递归方程:

y(t)=1a0(k=0Mbkx(Nk)(t)k=0Naky(Nk)(t))y(t)=\frac{1}{a_0}(\sum_{k=0}^{M}b_k x_{(N-k)}(t)-\sum_{k=0}^{N}a_k y_{(N-k)}(t))

令:

w(t)=k=0Mbkx(Nk)(t)w(t)=\sum_{k=0}^{M}b_k x_{(N-k)}(t)

可得:

y(t)=1a0(w(t)k=0Naky(Nk)(t))y(t)=\frac{1}{a_0}(w(t)-\sum_{k=0}^{N}a_k y_{(N-k)}(t))

积分-直接I型

通过交换级联次序,合并积分器可得直接 Ⅱ 型

积分-直接II型

# 卷积定义奇异函数

# 单位冲激信号u0(t)u_0(t)

δ(t)=ddtu(t)\delta(t)=\frac{d}{dt}u(t) 定义下的单位冲激。这是不严密的,因为 u(t)u(t) 在 t=0 处不连续。

进而采用极限的观点,将 δ(t)\delta(t) 视为 δΔ(t)\delta_Δ (t)Δ0Δ → 0 时的极限。但这种定义或描述 \delta (t) 的方法在数学上仍然是不严格的,因为存在无穷多个不同的函数在 Δ0Δ → 0 时都表现为与δΔ(t)\delta_Δ (t) 有相同的特性。

极限定义举例1

极限定义举例2

上述现象出现的原因在于 \delta (t) 是一个理想化的非常规函数,被称为奇异函数,通常采用卷积或积分运算下表现的特性来定义奇异函数

从系统的角度,将 δ(t)\delta(t) 定义为恒等系统单位冲激响应,也就是通过卷积定义 δ(t)\delta(t) ,对任意 x(t)x(t)δ(t)\delta(t) 应满足:

x(t)=x(t)δ(t)x(t)=x(t)*\delta (t)

单位冲激函数相当于卷积运算系统的单位元

根据定义可以得出 δ(t)\delta(t) 的如下性质:

1=1δ(t)=+δ(τ)dτ1=1*\delta (t) = \int_{-\infin}^{+\infin}\delta(\tau)d\tau

卷积定义还有一个等价版本 —— 积分定义

g(t)=g(t)δ(t)=+g(tτ)δ(τ)dτg(0)=+g(t)δ(τ)dτg(t)=g(t)*\delta(t)=\int_{-\infin}^{+\infin}g(t-\tau)\delta(\tau)d\tau\\ g(0)=\int_{-\infin}^{+\infin}g(t)\delta(\tau)d\tau

# 偶函数

单位冲激信号 δ(t)\delta(t) 是偶函数:

δ(t)=δ(t)\delta(t)=\delta(-t)

证明:

+δ(t)f(t)dt=+δ(τ)f(τ)d(τ)=+δ(τ)f(τ)dτ=f(0)\begin{aligned} \int_{-\infin}^{+\infin}\delta(-t)f(t)dt &=\int_{-\infin}^{+\infin}\delta(\tau)f(-\tau)d(-\tau)\\ &=\int_{-\infin}^{+\infin}\delta(\tau)f(-\tau)d\tau\\ &=f(0) \end{aligned}

# 时间尺度变换

δ(at)=1aδ(t)\delta(at)=\frac{1}{|a|}\delta(t)

验证信号下方面积:

a>0a\gt 0 时 :

+δ(aτ)dτ=1a+δ(aτ)d(aτ)=1a=1a\int_{-\infin}^{+\infin}\delta(a\tau)d\tau=\frac{1}{a}\int_{-\infin}^{+\infin}\delta(a\tau)d(a\tau)=\frac{1}{a}=\frac{1}{|a|}

a<0a\lt 0 时 :

+δ(aτ)dτ=1a+δ(aτ)d(aτ)=1a+δ(t)dt=1a+δ(t)dt=1a=1a\begin{aligned} \int_{-\infin}^{+\infin}\delta(a\tau)d\tau &= \frac{1}{a}\int_{-\infin}^{+\infin}\delta(a\tau)d(a\tau)\\ &= \frac{1}{a}\int_{+\infin}^{-\infin}\delta(t)dt \\ &= -\frac{1}{a}\int_{-\infin}^{+\infin}\delta(t)dt \\ &= -\frac{1}{a} \\ &= |\frac{1}{a}| \end{aligned}

# 单位冲激偶u1(t)u_1(t)

系统角度定义为理想微分器单位冲激响应,即 δ(t)\delta(t) 的微分:

u1(t)=ddtδ(t)u_1(t)=\frac{d}{dt}\delta(t)

微分器

单位冲激偶

卷积定义,从 LTI 系统分析的角度有:

x(t)u1(t)=ddtx(t)x(t)*u_1 (t)=\frac{d}{dt}x(t)

该信号可视为短脉冲求导的理想化结果。

短脉冲求导的理想化

# 积分性质

令输入 x(t)=1x(t)=1 有:

+u1(τ)dτ=+x(tτ)u1(τ)dτ=x(t)u1(t)=ddtx(t)=0\int_{-\infin}^{+\infin}u_1(\tau)d\tau=\int_{-\infin}^{+\infin}x(t-\tau)u_1(\tau)d\tau=x(t)*u_1(t)=\frac{d}{dt}x(t)=0

# 积分意义下的定义

+g(τt)u1(τ)dτ=g(t)u1(t)=ddtg(t)\int_{-\infin}^{+\infin}g(\tau-t)u_1(\tau)d\tau=g(-t)*u_1(t)=-\frac{d}{dt}g(-t)

t=0t=0 有:

g(0)=+g(τ)u1(τ)dτ-g'(0)=\int_{-\infin}^{+\infin}g(\tau)u_1(\tau)d\tau

该积分即可作为 u1(t)u_1(t) 在积分意义下的定义

# δ(t)\delta(t) 的积分u1(t)u_{-1}(t)

从系统的角度,定义 u1(t)u_{-1}(t)理想积分器单位冲激响应

u1(t)=tδ(τ)dτ=u(t)u_{-1}(t)=\int_{-\infin}^{t}\delta(\tau)d\tau=u(t)

运算定义为:

x(t)u1(t)=tx(τ)dτx(t)*u_{-1}(t)=\int_{-\infin}^{t}x(\tau)d\tau

# 单位斜坡函数u2(t)u_{-2}(t)

系统的角度,可以定义为:(卷积)

u2(t)=u1(t)u1(t)=tu(t)dt=tu(t)u_{-2}(t)=u_{-1}(t)*u_{-1}(t)=\int_{-\infin}^{t}u(t)dt=tu(t)

运算定义为二重积分:

x(t)u2(t)=x(t)u2(t)=x(t)u1(t)u1(t)=(tu(σ)dσ)u1(t)=t(τu(σ)dσ)dτ=tτu(σ)dσdτ\begin{aligned} x(t)*u_{-2}(t) &= x(t)*u_{-2}(t)\\ &= x(t)*u_{-1}(t)*u_{-1}(t) \\ &= \big(\int_{-\infin}^{t}u(\sigma)d\sigma\large)*u_{-1}(t) \\ &= \int_{-\infin}^{t}\big(\int_{-\infin}^{\tau}u(\sigma)d\sigma\big)d\tau \\ &= \int_{-\infin}^{t}\int_{-\infin}^{\tau}u(\sigma)\ d\sigma d\tau \end{aligned}

# 卷积定义推广

例如 u2(t)u_2(t) 可以定义为:u2(t)=u1(t)u1(t)u_2(t)=u_1(t)*u_1(t) :

x(t)u2(t)=d2dt2x(t)=x(t)u1(t)u1(t)x(t)*u_2(t)=\frac{d^2}{dt^2}x(t)=x(t)*u_1(t)*u_1(t)

以此类推:

u2(t)=u1(t)u1(t)u2(t)=u1(t)u1(t)u1(t)......uk(t)=u1(t)u1(t)...u1(t)k个\begin{aligned} u_2(t) &= u_1(t)*u_1(t) \\ u_2(t) &= u_1(t)*u_1(t)*u_1(t)\\ &......\\ u_k(t)\over &{=\over} {u_1(t)*u_1(t)*...*u_1(t)\over \text{k个}} \end{aligned}

单位阶跃函数的高阶积分推广:

u3(t)=u1(t)u1(t)u1(t)=12t2u(t)u4(t)=u1(t)u1(t)u1(t)u1(t)=16t3u(t)......uk(t)=u1(t)u1(t)...u1(t)k个=tk1(k1)!u(t)\begin{aligned} u_{-3}(t) &= u_{-1}(t)*u_{-1}(t)*u_{-1}(t)=\frac{1}{2}t^2 u(t) \\ u_{-4}(t) &= u_{-1}(t)*u_{-1}(t)*u_{-1}(t)*u_{-1}(t)=\frac{1}{6}t^3 u(t)\\ &......\\ u_{-k}(t)\over &{=\over} {u_{-1}(t)*u_{-1}(t)*...*u_{-1}(t)\over \text{k个}}{=\over}{\frac{t^{k-1}}{(k-1)!}u(t)\over} \end{aligned}

实际上, \delta (t) 的各次积分已经是常规函数了

\ No newline at end of file +卷积と线性时不变系统 - 信号与系统 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

Linear Time Invariant 线性时不变

基本信号应具有以下特点:

  • 本身尽可能简单,并且用它们的线性组合能够表示尽可能广泛的信号
  • LTI 系统对这种信号的响应易于计算且有利于对系统的深入理解

两类有用的基本信号:

  • 复指数信号
  • 单位冲激信号

本章主要考虑以单位冲激信号为基本信号进行信号与系统分析

summary

# 卷积和

# 定义

对于任意一个离散时间系统:

离散时间系统

设离散时间系统为 LTI 的,定义单位脉冲响应 h[n]h[n] 为以单位冲激信号 δ[n]\delta[n] 为输入时的输出:

δ[n]h[n]\delta[n]\to h[n]

由 LTI 时不变性有:

δ[nk]h[nk]\delta[n-k]\to h[n-k]

由 LTI 线性有:

x[n]=k=+x[k]δ[nk]y[n]=k=+x[k]h[nk]x[n]=\sum_{k=-\infin}^{+\infin}x[k]\delta[n-k]\to y[n]=\sum_{k=-\infin}^{+\infin}x[k]h[n-k]

这种求得系统响应的运算关系称为卷积和,即离散时间 LTI 系统的响应可以用卷积和表示为:

y[n]=x[n]h[n]=k=+x[k]h[nk]y[n]=x[n]*h[n]=\sum_{k=-\infin}^{+\infin}x[k]h[n-k]

⭐️更一般的形式:

x[nn0n1]=x[nn0]h[nn1]x[n-n_0-n_1]=x[n-n_0]*h[n-n_1]

⭐️只要得到了 LTI 系统对 δ[n]\delta[n] 的 响 应 h[n]h[n] —— 单位脉冲响应,就可以得到 LTI 系统对任何输入信号 x[n]x[n] 的响应。

换言之,一个 LTI 系统可以完全由它的单位脉冲响应 h[n]h[n] 来表征。

# 特殊离散 LTI 系统

# 延时器

h[n]=δ[nn0]h[n]=\delta[n-n_0]

具有该单位脉冲响应的系统一般情况下存在多种可能性,但是对应的 LTI 系统只有一个:

y[n]=x[nn0]=x[n]δ[nn0]y[n]=x[n-n_0]=x[n]*\delta[n-n_0]

# 累加器

h[n]=k=nδ[k]=u[n]h[n]=\sum_{k=-\infin}^{n}\delta[k]=u[n]

对应的 LTI 系统:

y[n]=x[n]u[n]=k=nx[k]y[n]=x[n]*u[n]=\sum_{k=-\infin}^{n}x[k]

# 计算

选择 nn 值并固定,求和项视为 kk 的函数,步骤如下:

  1. x[n]x[n]h[n]h[n] 变为 x[k]x[k]h[k]h[k] ,以 kk 为求和变量
  2. h[k]h[k] 翻转变为 h[k]h[-k]
  3. h[k]h[-k] 平移 nn,变为 h[nk]h[n - k]
  4. x[k]x[k]h[nk]h[n-k] 相乘;
  5. 对乘积 x[k]h[nk]x[k]h[n-k]kZk\in \mathbb{Z} 取和;
    • 一般都转化为只对非 0 区间积分。注意非 0 区间上下限!!!
  6. 改变 nn 值并重复 3–5 步,直到 nn 超过了 x[n]x[n] 非零部分定义域

注意很多题目最后答案会加上一个 u(n)u(n) ,是因为只求定义域在 [0,+)[0,+\infin) 的部分

# 卷积积分

# 定义

类似积分思想,转化为无限多的离散和的极限

用冲激信号表示连续时间信号:

将输入信号 x(t)x(t) 近似表示为移位、放缩后的脉冲之和

脉冲和近似表示输入信号

xΔ(t)=x(kΔ),kΔ<t<(k+1)Δx_{\Delta}(t)=x(k\Delta)\ ,\ k\Delta\lt t\lt(k+1)\Delta

阶梯近似表达过程:

设连续时间系统为 LTI 的,定义(名字待补,与卷积和中的单位脉冲响应对应) hΔ(n)h_{\Delta}(n) 为以单位冲激信号 δΔ(n)\delta_{\Delta}(n) 为输入时的输出:

δΔ(n)hΔ(n)\delta_{\Delta}(n)\to h_{\Delta}(n)

阶梯近似表达

由 LTI 时不变性有:

δΔ(nkΔ)hΔ(nkΔ)\delta_{\Delta}(n-k\Delta)\to h_{\Delta}(n-k\Delta)

由 LTI 线性齐次性尺度调整:

x(kΔ)δΔ(nkΔ)x(kΔ)hΔ(nkΔ)x(k\Delta)\delta_{\Delta}(n-k\Delta)\to x(k\Delta)h_{\Delta}(n-k\Delta)

阶梯近似表达2

由 LTI 线性叠加性有:

k=+x(kΔ)δΔ(nkΔ)Δk=+x(kΔ)hΔ(nkΔ)ΔxΔ(t)yΔ(t)\sum_{k=-\infin}^{+\infin}x(k\Delta)\delta_{\Delta}(n-k\Delta)\Delta\to \sum_{k=-\infin}^{+\infin}x(k\Delta)h_{\Delta}(n-k\Delta)\Delta\\ x_{\Delta}(t)\to y_{\Delta}(t)

当 Δ → 0 时 :

  • xΔ(t)x(t)x_Δ(t) → x(t)
  • yΔ(t)y(t)y_Δ(t) → y(t)
  • kΔτkΔ → \tau
  • ΔdτΔ → d\tau
  • δΔ(tkΔ)δ(tτ)\delta_Δ(t - kΔ) → \delta(t - \tau)
  • hΔ(tkΔ)h(tτ)h_Δ(t - kΔ) → h(t - \tau)
  • \sum\to\int

从而得到:

x(t)=+x(τ)δ(tτ)dτ=x(t)δ(t)y(t)=+x(τ)h(tτ)dτ=x(t)h(t)x(t)=\int_{-\infin}^{+\infin}x(\tau)\delta(t-\tau)d\tau=x(t)*\delta(t)\\ y(t)=\int_{-\infin}^{+\infin}x(\tau)h(t-\tau)d\tau=x(t)*h(t)

  • 其中第一个式子意义是:用位移的单位冲激信号表示任意的连续时间信号
  • 其中第一个式子意义是:用卷积积分表示连续时间 LTI 系统的响应

阶梯近似图解过程:

阶梯近似图解过程

# 计算

求卷积积分 x(t)h(t)=+x(τ)h(tτ)dτx(t) * h(t) = \int_{-∞}^{+∞}x(\tau)h(t - \tau)d\tau 的过程与卷积和计算过程相似。卷积积分的计算步骤如下:

  1. x(t)x(t)h(t)h(t) 变为 x(τ)x(\tau)h(τ)h(\tau) ,以 τ\tau 为积分变量;
  2. h(τ)h(\tau) 翻转变为 h(τ)h(-\tau)
  3. h(τ)h(-\tau) 平移 tt ,变为 h(tτ)h(t - \tau)
  4. x(τ)x(\tau)h(tτ)h(t-\tau) 相乘;
  5. 求区间 (,+)(-\infin,+\infin) 上乘积 x(τ)h(tτ)x(\tau)h(t-\tau) 下的面积;
    • 一般都转化为只对非 0 区间积分。注意非 0 区间上下限!!!
  6. 改变 tt 值并重复 3–5 步。

# 特殊连续 LTI 系统

# 积分器

单位冲激信号为输入下系统的响应为:

h(t)=u(t)h(t)=u(t)

对任意激励信号 x(t)x(t) ,系统响应为:

y(t)=x(t)h(t)=+x(τ)h(tτ)dτ=tx(τ)dτy(t)=x(t)*h(t)=\int_{-\infin}^{+\infin}x(\tau)h(t-\tau)d\tau = \int_{-\infin}^{t}x(\tau)d\tau

# 卷积和与卷积积分的性质

# 交换律

变量替换:

x[n]h[n]=k=+x[k]h[nk]=l=+x[nl]h[l]=h[n]x[n]x[n]*h[n]=\sum_{k=-\infin}^{+\infin}x[k]h[n-k]=\sum_{l=-\infin}^{+\infin}x[n-l]h[l]=h[n]*x[n]

x(n)h(n)=+x(τ)h(tτ)dτ=+x(tτ)h(τ)dτ=h(t)x(t)x(n)*h(n)=\int_{-\infin}^{+\infin}x(\tau)h(t-\tau)d\tau=\int_{-\infin}^{+\infin}x(t-\tau')h(\tau')d\tau'=h(t)*x(t)

交换律

s[n]=u[n]h[n]=h[n]u[n]=k=nh[k]s[n]=u[n]*h[n]=h[n]*u[n]=\sum_{k=-\infin}^{n}h[k]

利用 u[n]u[n] 是累加器的单位脉冲响应以及交换律可以得到:

该系统的单位脉冲响应是 h[n]h[n]u[n]u[n] 单位阶跃信号作为输入,则其单位阶跃响应 s[n]s[n] 等价于 以 h[n]h[n] 作为输入时,累加器的响应

# 分配律

x[n](h1[n]+h2[n])=x[n]h1[n]+x[n]h2[n]x(t)(h1(t)+h2(t))=x(t)h1(t)+x(t)h2(t)x[n] * (h_1[n] + h_2[n]) = x[n] * h_1[n] + x[n] * h_2[n]\\ x(t) * (h_1(t) + h_2(t)) = x(t) * h_1(t) + x(t) * h_2(t)

分配律

# 结合律

(x[n]h1[n])h2[n]=x[n](h1[n]h2[n])(x(t)h1(t))h2(t)=x(t)(h1(t)h2(t))(x[n] * h_1 [n] ) * h_2[n] = x[n] * (h_1 [n] * h_2[n])\\ (x(t) * h_1 (t) ) * h_2(t) = x(t) * (h_1(t)* h_2 (t))

结合律

级联的 LTI 系统其总的单位冲激 (脉冲) 响应等于各子系统单位冲激 (脉冲) 响应的卷积

# 级联可交换

卷积运算满足结合律和交换律,因此,系统级联的先后次序可以调换。

x[n]h1[n]h2[n]=x[n]h2[n]h1[n]x(t)h1(t)h2(t)=x(t)h2(t)h1(t)x[n] * h_1[n] * h_2[n] = x[n] * h_2[n] * h_1[n]\\ x(t) * h_1(t) * h_2(t) = x(t) * h_2(t) * h_1(t)

级联可交换

级联次序可交换的前提条件:

  • 系统是 LTI 的
  • 所有涉及到的卷积运算必须收敛

# 微分、积分及时移特性

卷积积分满足微分、积分及时移特性。若 x(t)h(t)=y(t)x(t)*h(t)=y(t),则:

# 微分特性

x(t)h(t)=x(t)h(t)=y(t)x'(t) * h(t) = x(t) * h'(t) = y'(t)

x(m)(t)h(n)(t)=y(m+n)(t)x^{(m)}(t) * h^{(n)}(t) = y^{(m+n)}(t)

tt 求导而不是对 τ\tau 求导

# 积分特性

(tx(τ)dτ)h(t)=+(τ1x(τ)dτ)h(tτ1)dτ1=x(t)(th(τ)dτ)=ty(τ)dτ\begin{aligned} \big(\int_{-\infin}^{t}x(\tau)d\tau\big)*h(t)&= \int_{-\infin}^{+\infin}\big(\int_{-\infin}^{\tau_1}x(\tau)d\tau\big)h(t-\tau_1)d\tau_1\\ &=x(t)*\big(\int_{-\infin}^{t}h(\tau)d\tau\big)\\ &=\int_{-\infin}^{t}y(\tau)d\tau \end{aligned}

# 时移特性

x(tt0)h(tt1)=x(tt1)h(tt0)=y(tt0t1)x(t - t_0) * h(t-t_1) = x(t-t_1) * h(t - t_0) = y(t - t_0-t_1)

# 差分、求和及时移特性

卷积和满足差分、求和及时移特性。若 x [n] * h [n] = y [n],则:

# 差分特性

x[n]x[n1]h[n]=x[n](h[n]h[n1])=y[n]y[n1]x[n]- x[n- 1] * h[n]= x[n]* (h[n]- h[n - 1])= y[n] - y[n - 1]

# 求和特性

(k=nx[k])h[n]=x[n](k=nh[k])=k=ny[k](\sum_{k=-∞}^{n}x[k] )* h[n] = x[n] * (\sum_{k=-∞}^{n}h[k] )=\sum_{k=-∞}^{n}y[k]

# 时移特性

x[tt0]h[tt1]=x[tt1]h[tt0]=y[tt0t1]x[t - t_0] * h[t-t_1] = x[t-t_1]* h[t - t_0]= y[t - t_0-t_1]

# LTI 系统的性质

# 记忆性

对于离散时间 LTI 系统:

y[n]=k=+x[k]h[nk]y[n]=\sum_{k=-\infin}^{+\infin}x[k]h[n-k]

如果系统是无记忆的,则在任何时刻 nny[n]y[n] 都只能和 nn 时刻的输入有关,等式右边的和式中只能有 k=nk=n 时的一项非零,即必须有 h[nk]=0h[n-k]=0knk≠n,也即:

h[n]=0,n0h[n] = 0 ,\ \ \ n\neq0

所以,离散时间无记忆系统的单位脉冲响应为:

h[n]=kδ[n]h[n]=k\delta[n]

即为离散时间系统无记忆充要条件

类似地,连续时间系统无记忆的充要条件为:

h(t)=kδ(t)h(t)=k\delta(t)

k=1k=1 时系统是恒等系统。

# 可逆性

如果 LTI 系统是可逆的,则其逆系统也是 LTI 系统。

互逆的两个系统的满足(充要条件卷积和等于单位冲激信号

h(t)g(t)=δ(t)h[n]g[n]=δ[n]\begin{aligned} h(t) * g(t) =\delta(t)\\ h[n] * g[n] =\delta[n] \end{aligned}

从而有:

x(t)h(t)g(t)=x(t)δ(t)=x(t)x[t]h[n]g[n]=x[t]δ[n]=x[t]\begin{aligned} x(t)*h(t)*g(t)=x(t)*\delta(t)=x(t)\\ x[t]*h[n]*g[n]=x[t]*\delta[n]=x[t] \end{aligned}

可逆性

例如:延时器是可逆的 LTI 系统,h (t) = \delta (t - t0),其逆系统是 g (t) = \delta (t + t0),显然有:

h(t)g(t)=(tt0)δ(t+t0)=δ(t)h(t) * g(t) = (t - t_0) * \delta(t + t_0) = \delta(t)

又如:累加器是可逆的 LTI 系统,其 h [n] = u [n],其逆系统是 g [n] = \delta [n] - \delta [n - 1],显然也有:

h[n]g[n]=u[n](δ[n]δ[n1])=u[n]u[n1]=δ[n]\begin{aligned} h[n] * g[n] &= u[n] * (\delta[n] - \delta[n - 1])\\ &= u[n] - u[n - 1] = \delta[n] \end{aligned}

# 因果性

对于离散时间 LTI 系统:

y[n]=k=+x[k]h[nk]y[n]=\sum_{k=-\infin}^{+\infin}x[k]h[n-k]

因果性意味着上式等号右边和式中所有 k > n 的项都必须为零,即 h [n - k] = 0,k > n,也即:

h[n]=0,n<0h[n] = 0,\ \ \ n < 0

同理对连续时间因果系统有:

h(t)=0,t<0h(t) = 0, \ \ \ t < 0

即为 LTI 系统具有因果性的充要条件

对于线性系统而言,因果性与初始松弛条件等价。所谓系统满足初始松弛条件是指该系统具有如下表现:对于任意时刻,只要该时刻之前系统的输入为 0,则该时刻之前系统的输出也必然为 0。

(参考教材习题 1.44 (a))

– 该等价性的前提是系统为线性的。否则不一定成立。例如 y n = 2x n + 3 是因果的,但显然不满足初始松弛条件。

# 稳定性

稳定性意味着有界输入必然产生有界输出。以离散时间 LTI 系统为例,设 |x [n]| 有界,| x [n - k]| ≤ A。有:

y[n]=k=+h[k]x[nk]k=+h[k]x[nk]Ak=+h[k]|y[n]| = |\sum_{k=-∞}^{+∞}h[k]x[n - k]| ≤ \sum_{k=-∞}^{+∞} |h[k]| |x[n - k]| ≤ A \sum_{k=-∞}^{+∞}|h[k]|

离散 LTI 系统稳定的充分必要条件为:

n=+h[n]<+\sum_{n=-\infin}^{+\infin}|h[n]|\lt +\infin

类似地有连续 LTI 系统稳定的充分必要条件为:

+h(t)dt<+\int_{-\infin}^{+\infin}|h(t)|dt \lt +\infin

# 单位阶跃响应

在工程实际中,也常用单位阶跃响应来描述 LTI 系统。单位阶跃响应就是系统对 u (t) 或 u [n] 所产生的响应,记为 s (t) 或 s [n]。因此有:

s[n]=u[n]h[n]=k=nh[k]s[n] = u[n] * h[n] = \sum_{k=-∞}^n h[k]

h[n]=s[n]s[n1]h[n] = s[n] - s[n - 1]

s(t)=u(t)h(t)=th(τ)dτs(t) = u(t) * h(t) = \int_{-\infin}^{t}h(\tau)d\tau

h(t)=ds(t)dt=s(t)h(t) =\frac{ds(t)}{dt}= s'(t)

# 用微分和差分方程描述的因果 LTI 系统

在工程实际中有相当普遍的一类系统,其数学模型可以用线性常系数微分方程或线性常系数差分方程来描述。

在时域内分析这类 LTI 系统,就是要求解线性常系数微分方程或差分方程。

# 线性常系数微分方程

一般情况 NMN\geq M , N 阶非其次常系数微分方程的一般形式:

k=0Nakdky(t)dtk=k=0Mbkdky(t)dtk\sum_{k=0}^{N}a_k\frac{d^ky(t)}{dt^k}=\sum_{k=0}^{M}b_k\frac{d^ky(t)}{dt^k}

其中 ak, bk 均为常数

求解该微分方程(求 y (t) 的显式表达)的步骤:

  1. 求出齐次解通解)yh (t) ,也称为系统的自然响应自由响应
    1. 建立特征方程求出特征根 𝜆k
    2. 根据特征根得到齐次解形式
    3. 根据附加条件确定齐次解形式中的待定常数 Ck
  2. 特解 y𝑝(t),也称系统的受迫响应强迫响应,其形式与输入信号有关
    1. 根据输入信号形式得到特解形式
    2. 将输入信号与特解代入微分方程确定特解形式中的待定常数
  3. 得到完全解 y (t) = yh(t) + y𝑝(t)

附加条件常给出为初始松弛条件,即 t<0t\lt 0 时若 x(t)=0x(t)=0 则有 y(t)=0y(t)=0 ,或 n<0n\lt 0 时若 x[n]=0x[n]=0 则有 y[n]=0y[n]=0

对于线性系统,初始松弛条件与满足因果性是等价的

解题时,可以直接认为就是有 y(0)=0y(0)=0x[0]=0x[0]=0

# 线性常系数差分方程

一般情况 NMN\geq MNN 阶非其次常系数差分方程的一般形式

k=0Naky[nk]=k=0Mbkx[nk]\sum_{k=0}^{N}a_k y[n-k]=\sum_{k=0}^{M}b_k x[n-k]

其中 ak, bk 均为常数

还可以将其改写为 ==(正向) 递归形式 ==:

y[n]=1a0(k=0Mbkx[nk]k=0Naky[nk])y[n]=\frac{1}{a_0}(\sum_{k=0}^{M}b_k x[n-k]-\sum_{k=0}^{N}a_k y[n-k])

还可将差分方程改写反向递归求解形式

y[nN]=1aN(k=0Mbkx[nk]k=0N1aky[nk])y[n-N]=\frac{1}{a_N}(\sum_{k=0}^{M}b_k x[n-k]-\sum_{k=0}^{N-1}a_k y[n-k])

ak=0,k0a_k =0,k\neq 0 时,差分方程变为一个卷积和的形式即非递归方程

y[n]=k=0Mbka0x[nk]=+h[n]x[nk]y[n]=\sum_{k=0}^{M}\frac{b_k}{a_0}x[n-k]=\sum_{-\infin}^{+\infin}h[n]\ x[n-k]

其中:

h[n]={bna0,0nM0,othersh[n]= \begin{cases} \frac{b_n}{a_0},\ \ 0\leq n\leq M \\ 0,\ \ \ \ \text{others} \end{cases}

  • 由于 h [n] 是有限长的,当 ak=0,k0a_k =0,k\neq 0非递归方程描述的系统称为有限脉冲响应( Finite Impulse Response,FIR)系统

  • 而其他情况下递归方程描述的系统结合初始松弛条件具有无限长的单位脉冲响应,因而称为无限脉冲响应(Infinite Impulse Response,IIR)系统

  • 与微分方程类似,差分方程的齐次解通解)与输入信号的形式无关,称为系统的自然响应自由响应

  • 特解具有与输入信号相同的函数形式,称为受迫响应强迫响应

具有非零起始状态的线性常系数微分或差分方程对应增量线性系统,其响应由两部分组成:

  • 零输入响应,与输入信号无关,属于自然响应
  • 零状态响应,既与输入信号有关,也与系统特性有关,它包含了一部分受迫响应,也包含有一部分自然响应

# 方框图表示

# 差分方程描述系统

对于正向递归形式的 LTI 系统差分方程,其方程中包括三种基本运算:

  • 移位(延迟)—— 对应延迟器
  • 乘系数 —— 对应数乘器
  • 相加 —— 对应加法器

令:

w[n]=k=0Mbkx[nk]w[n]=\sum_{k=0}^{M}b_k x[n-k]

正向递归形式可写为:

y[n]=1a0(w[n]k=0Naky[nk])y[n]=\frac{1}{a_0}(w[n]-\sum_{k=0}^{N}a_k y[n-k])

差分-直接I型

将其级联起来,就成为线性常系数差分方程描述的系统,它具有与差分方程完全相同的运算功能。可以调换级联次序,并将移位单元合并,于是得到直接 II 型

差分-直接II型

# 微分方程描述系统

微分方程也包括三种基本运算:

  • 微分
  • 乘系数
  • 相加

但微分器不仅在工程实现上有困难,而且对误差及噪声极为敏感,因此,通常使用积分器而不用微分器

N 阶微分方程两边同时积分 N 次,即可得到对应 N 阶积分方程:

k=0Naky(Nk)(t)=k=0Mbkx(Nk)(t)\sum_{k=0}^{N}a_k\ y_{(N-k)}(t)=\sum_{k=0}^{M}b_k\ x_{(N-k)}(t)

对此积分方程完全按照差分方程的办法有其递归方程:

y(t)=1a0(k=0Mbkx(Nk)(t)k=0Naky(Nk)(t))y(t)=\frac{1}{a_0}(\sum_{k=0}^{M}b_k x_{(N-k)}(t)-\sum_{k=0}^{N}a_k y_{(N-k)}(t))

令:

w(t)=k=0Mbkx(Nk)(t)w(t)=\sum_{k=0}^{M}b_k x_{(N-k)}(t)

可得:

y(t)=1a0(w(t)k=0Naky(Nk)(t))y(t)=\frac{1}{a_0}(w(t)-\sum_{k=0}^{N}a_k y_{(N-k)}(t))

积分-直接I型

通过交换级联次序,合并积分器可得直接 Ⅱ 型

积分-直接II型

# 卷积定义奇异函数

# 单位冲激信号u0(t)u_0(t)

δ(t)=ddtu(t)\delta(t)=\frac{d}{dt}u(t) 定义下的单位冲激。这是不严密的,因为 u(t)u(t) 在 t=0 处不连续。

进而采用极限的观点,将 δ(t)\delta(t) 视为 δΔ(t)\delta_Δ (t)Δ0Δ → 0 时的极限。但这种定义或描述 \delta (t) 的方法在数学上仍然是不严格的,因为存在无穷多个不同的函数在 Δ0Δ → 0 时都表现为与δΔ(t)\delta_Δ (t) 有相同的特性。

极限定义举例1

极限定义举例2

上述现象出现的原因在于 \delta (t) 是一个理想化的非常规函数,被称为奇异函数,通常采用卷积或积分运算下表现的特性来定义奇异函数

从系统的角度,将 δ(t)\delta(t) 定义为恒等系统单位冲激响应,也就是通过卷积定义 δ(t)\delta(t) ,对任意 x(t)x(t)δ(t)\delta(t) 应满足:

x(t)=x(t)δ(t)x(t)=x(t)*\delta (t)

单位冲激函数相当于卷积运算系统的单位元

根据定义可以得出 δ(t)\delta(t) 的如下性质:

1=1δ(t)=+δ(τ)dτ1=1*\delta (t) = \int_{-\infin}^{+\infin}\delta(\tau)d\tau

卷积定义还有一个等价版本 —— 积分定义

g(t)=g(t)δ(t)=+g(tτ)δ(τ)dτg(0)=+g(t)δ(τ)dτg(t)=g(t)*\delta(t)=\int_{-\infin}^{+\infin}g(t-\tau)\delta(\tau)d\tau\\ g(0)=\int_{-\infin}^{+\infin}g(t)\delta(\tau)d\tau

# 偶函数

单位冲激信号 δ(t)\delta(t) 是偶函数:

δ(t)=δ(t)\delta(t)=\delta(-t)

证明:

+δ(t)f(t)dt=+δ(τ)f(τ)d(τ)=+δ(τ)f(τ)dτ=f(0)\begin{aligned} \int_{-\infin}^{+\infin}\delta(-t)f(t)dt &=\int_{-\infin}^{+\infin}\delta(\tau)f(-\tau)d(-\tau)\\ &=\int_{-\infin}^{+\infin}\delta(\tau)f(-\tau)d\tau\\ &=f(0) \end{aligned}

# 时间尺度变换

δ(at)=1aδ(t)\delta(at)=\frac{1}{|a|}\delta(t)

验证信号下方面积:

a>0a\gt 0 时 :

+δ(aτ)dτ=1a+δ(aτ)d(aτ)=1a=1a\int_{-\infin}^{+\infin}\delta(a\tau)d\tau=\frac{1}{a}\int_{-\infin}^{+\infin}\delta(a\tau)d(a\tau)=\frac{1}{a}=\frac{1}{|a|}

a<0a\lt 0 时 :

+δ(aτ)dτ=1a+δ(aτ)d(aτ)=1a+δ(t)dt=1a+δ(t)dt=1a=1a\begin{aligned} \int_{-\infin}^{+\infin}\delta(a\tau)d\tau &= \frac{1}{a}\int_{-\infin}^{+\infin}\delta(a\tau)d(a\tau)\\ &= \frac{1}{a}\int_{+\infin}^{-\infin}\delta(t)dt \\ &= -\frac{1}{a}\int_{-\infin}^{+\infin}\delta(t)dt \\ &= -\frac{1}{a} \\ &= |\frac{1}{a}| \end{aligned}

# 单位冲激偶u1(t)u_1(t)

系统角度定义为理想微分器单位冲激响应,即 δ(t)\delta(t) 的微分:

u1(t)=ddtδ(t)u_1(t)=\frac{d}{dt}\delta(t)

微分器

单位冲激偶

卷积定义,从 LTI 系统分析的角度有:

x(t)u1(t)=ddtx(t)x(t)*u_1 (t)=\frac{d}{dt}x(t)

该信号可视为短脉冲求导的理想化结果。

短脉冲求导的理想化

# 积分性质

令输入 x(t)=1x(t)=1 有:

+u1(τ)dτ=+x(tτ)u1(τ)dτ=x(t)u1(t)=ddtx(t)=0\int_{-\infin}^{+\infin}u_1(\tau)d\tau=\int_{-\infin}^{+\infin}x(t-\tau)u_1(\tau)d\tau=x(t)*u_1(t)=\frac{d}{dt}x(t)=0

# 积分意义下的定义

+g(τt)u1(τ)dτ=g(t)u1(t)=ddtg(t)\int_{-\infin}^{+\infin}g(\tau-t)u_1(\tau)d\tau=g(-t)*u_1(t)=-\frac{d}{dt}g(-t)

t=0t=0 有:

g(0)=+g(τ)u1(τ)dτ-g'(0)=\int_{-\infin}^{+\infin}g(\tau)u_1(\tau)d\tau

该积分即可作为 u1(t)u_1(t) 在积分意义下的定义

# δ(t)\delta(t) 的积分u1(t)u_{-1}(t)

从系统的角度,定义 u1(t)u_{-1}(t)理想积分器单位冲激响应

u1(t)=tδ(τ)dτ=u(t)u_{-1}(t)=\int_{-\infin}^{t}\delta(\tau)d\tau=u(t)

运算定义为:

x(t)u1(t)=tx(τ)dτx(t)*u_{-1}(t)=\int_{-\infin}^{t}x(\tau)d\tau

# 单位斜坡函数u2(t)u_{-2}(t)

系统的角度,可以定义为:(卷积)

u2(t)=u1(t)u1(t)=tu(t)dt=tu(t)u_{-2}(t)=u_{-1}(t)*u_{-1}(t)=\int_{-\infin}^{t}u(t)dt=tu(t)

运算定义为二重积分:

x(t)u2(t)=x(t)u2(t)=x(t)u1(t)u1(t)=(tu(σ)dσ)u1(t)=t(τu(σ)dσ)dτ=tτu(σ)dσdτ\begin{aligned} x(t)*u_{-2}(t) &= x(t)*u_{-2}(t)\\ &= x(t)*u_{-1}(t)*u_{-1}(t) \\ &= \big(\int_{-\infin}^{t}u(\sigma)d\sigma\large)*u_{-1}(t) \\ &= \int_{-\infin}^{t}\big(\int_{-\infin}^{\tau}u(\sigma)d\sigma\big)d\tau \\ &= \int_{-\infin}^{t}\int_{-\infin}^{\tau}u(\sigma)\ d\sigma d\tau \end{aligned}

# 卷积定义推广

例如 u2(t)u_2(t) 可以定义为:u2(t)=u1(t)u1(t)u_2(t)=u_1(t)*u_1(t) :

x(t)u2(t)=d2dt2x(t)=x(t)u1(t)u1(t)x(t)*u_2(t)=\frac{d^2}{dt^2}x(t)=x(t)*u_1(t)*u_1(t)

以此类推:

u2(t)=u1(t)u1(t)u2(t)=u1(t)u1(t)u1(t)......uk(t)=u1(t)u1(t)...u1(t)k个\begin{aligned} u_2(t) &= u_1(t)*u_1(t) \\ u_2(t) &= u_1(t)*u_1(t)*u_1(t)\\ &......\\ u_k(t)\over &{=\over} {u_1(t)*u_1(t)*...*u_1(t)\over \text{k个}} \end{aligned}

单位阶跃函数的高阶积分推广:

u3(t)=u1(t)u1(t)u1(t)=12t2u(t)u4(t)=u1(t)u1(t)u1(t)u1(t)=16t3u(t)......uk(t)=u1(t)u1(t)...u1(t)k个=tk1(k1)!u(t)\begin{aligned} u_{-3}(t) &= u_{-1}(t)*u_{-1}(t)*u_{-1}(t)=\frac{1}{2}t^2 u(t) \\ u_{-4}(t) &= u_{-1}(t)*u_{-1}(t)*u_{-1}(t)*u_{-1}(t)=\frac{1}{6}t^3 u(t)\\ &......\\ u_{-k}(t)\over &{=\over} {u_{-1}(t)*u_{-1}(t)*...*u_{-1}(t)\over \text{k个}}{=\over}{\frac{t^{k-1}}{(k-1)!}u(t)\over} \end{aligned}

实际上, \delta (t) 的各次积分已经是常规函数了

\ No newline at end of file diff --git a/ie/signals-and-systems/signals-concepts/index.html b/ie/signals-and-systems/signals-concepts/index.html index 536de6a7..b9e29821 100644 --- a/ie/signals-and-systems/signals-concepts/index.html +++ b/ie/signals-and-systems/signals-concepts/index.html @@ -1,4 +1,4 @@ -信号基本概念 - 信号与系统 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 能量 / 功率 信号

能量功率信号.png

# 能量信号

能量为一有界值,即 0 < E < + ∞,此时 P = 0

有时求 P 不好求,但是 E 好求,可以证明 E 为有界的,从而得到 P = 0

# 功率信号

功率为一有界值,即 0 < P < + ∞ ,此时 E = ∞

有时求 E 不好求,但是 P 好求,可以证明 P 为有界的,从而得到 E = ∞

# 信号的分解

# 偶部与奇部

f(t)=fe(t)+fo(t)f(t)=f_e(t)+f_o(t)

偶部:

fe(t)=12[f(t)+f(t)]f_e(t)=\frac{1}{2}[f(t)+f(-t)]

奇部:

fo(t)=12[f(t)f(t)]f_o(t)=\frac{1}{2}[f(t)-f(-t)]

# 实部与虚部

针对复函数而言

f(t)=Re{f(t)}+Im{f(t)}f(t)=Re\{f(t)\}+Im\{f(t)\}

实部:

Re{f(t)}Re\{f(t)\}

虚部:

Im{f(t)}Im\{f(t)\}

# 连续 / 离散 (时间) 信号

区分 模拟 / 数字 信号,模拟 / 数字 信号的划分是依据 “值域” 是否连续,而 连续 / 离散 时间信号的划分是依据定义域是否连续

连续时间信号 包含 模拟信号 和 数字 (量化) 信号

# 周期信号定义

  • 连续周期信号 : f(t+mT)=f(t)f(t+mT)=f(t) , T 为周期 m = 0,±1,±2,±3...
  • 离散周期信号 : f(k+mN)=f(k)f(k+mN) = f(k) , N 为周期 m = 0,±1,±2,±3...

T N 趋于⽆无穷时,周期信号变为⾮非周期信号。

# 连续时间信号

定义域连续

在一定时间范围内,除若⼲不连续点之外,对任意时刻函数都有确定的函数值。 “连续” 的含义指定义域连续,⽽连续信号中可以含有不连续点。

# 普通连续信号

普通连续信号是指函数的定义域和值域没有不连续点 (即跳变点) 的信号。

# (实) 指数信号

f(t)=Keαtf (t) = Ke^{αt}

指数函数求导、积分后仍为指数函数。

# 正弦信号

利用正弦函数与余弦函数表示的信号统称为正弦信号,可表示为

f(t)=Acos(ωtθ)f(t)=A\cos(\omega t-\theta)

正弦信号求导、积分后仍然为正弦信号。

指数信号可以转化为正弦信号:

ejωt=cosωt+jsinωtejωt=cosωtjsinωte^{j\omega t}=\cos\ \omega t+j\ \sin\ \omega t \\ e^{-j\omega t}=\cos\ \omega t-j\ \sin\ \omega t

指数信号可以转化为正弦信号:

sinωt=12j(ejωtejωt)cosωt=12(ejωt+ejωt)\sin\ \omega t = \frac{1}{2j}( e^{j\omega t} - e^{-j\omega t})\\ \cos\ \omega t = \frac{1}{2}( e^{j\omega t} + e^{-j\omega t})

# 复指数信号

f(t)=Kest=Ke(σ+jω)t=Keσt(cosωt+jsinωt)f (t) = Ke^{st} = Ke^{(σ+j\omega)t} = Ke^{σt}(\cos\ ωt + j\ \sin\ ωt),

其中 s=σ+jω0s=σ+j\omega_0 为复数

复指数信号中,σ\sigma 决定增长衰减,ω0\omega_0 决定震荡快慢;

σ\sigma 的大小ω0\omega_0 的大小最终结果
σ=1\sigma=1ω00\omega_0\neq0实部虚部等幅震荡
σ>1\sigma>1ω00\omega_0\neq0实部虚部增⻓震荡
σ<1\sigma<1ω00\omega_0\neq0实部虚部衰减震荡
\sigma≠0ω0=0\omega_0=0实部虚部为指数信号
σ=0\sigma=0ω0=0\omega_0=0为直流信号
# 连续复指数信号的周期性

复指数信号是周期信号当且仅当 σ\sigma = 1 且 ω00\omega_0\neq 0

基波周期:T=2πω0T=|\frac{2\pi}{\omega_0}|

基波频率:ω0\omega_0

# 成谐波关系的连续复指数信号集

{φk(t)}={ejkω0t}k=0,±1,±2......\{\varphi_k(t) \}=\{ e^{jk\omega_0 t} \}\\ k=0,\pm1,\pm2......

一般假设 ω0>0\omega_0 \gt 0 ,该集合中的每个信号都是周期的,它们的基波频率分别为 kω0k\omega_0 ,都是 ω0\omega_0 的整数倍,因而称它们是成谐波关系的。

各次谐波的基波周期分别为 Tk=2πkω0T_k =\frac{2\pi}{|k\omega_0|} ,它们的公共周期是 T0=2πω0T_0=\frac{2\pi}{\omega_0}

  • k=0k=0 称为直流分量
  • k=±1k=\pm1 称为基波分量
  • k=±2k=\pm2 称为二次谐波分量
  • ... 等等...
# 一般连续复指数信号

f(t)=Kest=Kejθe(σ+jω0)t=Keσtej(ω0+θ)f (t) = Ke^{st} = |K|e^{j\theta}e^{(σ+j\omega_0)t} = Ke^{σt}e^{j(\omega_0+\theta)},

其中 s=σ+jω0s=σ+j\omega_0K=KejθK=|K|e^{j\theta} 为复数

该信号可看成是振幅按实指数信号规律变化的周期性复指数信号。它的实部与虚部都是振幅呈实指数规律变化的正弦振荡。

# 抽样信号

Sa(t)=sinttlimtSa(t)=0;limt0Sa(t)=10+Sa(t)dt=π2;+Sa(t)dt=πSa(t)=\frac{\sin\ t}{t} \\ \lim_{t\to \infin}Sa(t)=0 \ \ ;\ \ \lim_{t\to 0}Sa(t)=1 \\ \int_{0}^{+\infin}Sa(t)\ d\ t=\frac{\pi}{2}\ \ ;\ \ \int_{-\infin}^{+\infin}Sa(t)\ d\ t=\pi

# 高斯函数 “钟形信号”

即正态分布 PDF

φ(t)=1σ2πe(tμ)22σ2\varphi(t) = \frac{1}{\sigma\sqrt{2\pi}}e^{-\frac{(t-\mu)^2}{2\sigma^2}}

# 能量 / 功率 信号

能量功率信号.png

# 能量信号

能量为一有界值,即 0 < E < + ∞,此时 P = 0

有时求 P 不好求,但是 E 好求,可以证明 E 为有界的,从而得到 P = 0

# 功率信号

功率为一有界值,即 0 < P < + ∞ ,此时 E = ∞

有时求 E 不好求,但是 P 好求,可以证明 P 为有界的,从而得到 E = ∞

# 信号的分解

# 偶部与奇部

f(t)=fe(t)+fo(t)f(t)=f_e(t)+f_o(t)

偶部:

fe(t)=12[f(t)+f(t)]f_e(t)=\frac{1}{2}[f(t)+f(-t)]

奇部:

fo(t)=12[f(t)f(t)]f_o(t)=\frac{1}{2}[f(t)-f(-t)]

# 实部与虚部

针对复函数而言

f(t)=Re{f(t)}+Im{f(t)}f(t)=Re\{f(t)\}+Im\{f(t)\}

实部:

Re{f(t)}Re\{f(t)\}

虚部:

Im{f(t)}Im\{f(t)\}

# 连续 / 离散 (时间) 信号

区分 模拟 / 数字 信号,模拟 / 数字 信号的划分是依据 “值域” 是否连续,而 连续 / 离散 时间信号的划分是依据定义域是否连续

连续时间信号 包含 模拟信号 和 数字 (量化) 信号

# 周期信号定义

  • 连续周期信号 : f(t+mT)=f(t)f(t+mT)=f(t) , T 为周期 m = 0,±1,±2,±3...
  • 离散周期信号 : f(k+mN)=f(k)f(k+mN) = f(k) , N 为周期 m = 0,±1,±2,±3...

T N 趋于⽆无穷时,周期信号变为⾮非周期信号。

# 连续时间信号

定义域连续

在一定时间范围内,除若⼲不连续点之外,对任意时刻函数都有确定的函数值。 “连续” 的含义指定义域连续,⽽连续信号中可以含有不连续点。

# 普通连续信号

普通连续信号是指函数的定义域和值域没有不连续点 (即跳变点) 的信号。

# (实) 指数信号

f(t)=Keαtf (t) = Ke^{αt}

指数函数求导、积分后仍为指数函数。

# 正弦信号

利用正弦函数与余弦函数表示的信号统称为正弦信号,可表示为

f(t)=Acos(ωtθ)f(t)=A\cos(\omega t-\theta)

正弦信号求导、积分后仍然为正弦信号。

指数信号可以转化为正弦信号:

ejωt=cosωt+jsinωtejωt=cosωtjsinωte^{j\omega t}=\cos\ \omega t+j\ \sin\ \omega t \\ e^{-j\omega t}=\cos\ \omega t-j\ \sin\ \omega t

指数信号可以转化为正弦信号:

sinωt=12j(ejωtejωt)cosωt=12(ejωt+ejωt)\sin\ \omega t = \frac{1}{2j}( e^{j\omega t} - e^{-j\omega t})\\ \cos\ \omega t = \frac{1}{2}( e^{j\omega t} + e^{-j\omega t})

# 复指数信号

f(t)=Kest=Ke(σ+jω)t=Keσt(cosωt+jsinωt)f (t) = Ke^{st} = Ke^{(σ+j\omega)t} = Ke^{σt}(\cos\ ωt + j\ \sin\ ωt),

其中 s=σ+jω0s=σ+j\omega_0 为复数

复指数信号中,σ\sigma 决定增长衰减,ω0\omega_0 决定震荡快慢;

σ\sigma 的大小ω0\omega_0 的大小最终结果
σ=1\sigma=1ω00\omega_0\neq0实部虚部等幅震荡
σ>1\sigma>1ω00\omega_0\neq0实部虚部增⻓震荡
σ<1\sigma<1ω00\omega_0\neq0实部虚部衰减震荡
\sigma≠0ω0=0\omega_0=0实部虚部为指数信号
σ=0\sigma=0ω0=0\omega_0=0为直流信号
# 连续复指数信号的周期性

复指数信号是周期信号当且仅当 σ\sigma = 1 且 ω00\omega_0\neq 0

基波周期:T=2πω0T=|\frac{2\pi}{\omega_0}|

基波频率:ω0\omega_0

# 成谐波关系的连续复指数信号集

{φk(t)}={ejkω0t}k=0,±1,±2......\{\varphi_k(t) \}=\{ e^{jk\omega_0 t} \}\\ k=0,\pm1,\pm2......

一般假设 ω0>0\omega_0 \gt 0 ,该集合中的每个信号都是周期的,它们的基波频率分别为 kω0k\omega_0 ,都是 ω0\omega_0 的整数倍,因而称它们是成谐波关系的。

各次谐波的基波周期分别为 Tk=2πkω0T_k =\frac{2\pi}{|k\omega_0|} ,它们的公共周期是 T0=2πω0T_0=\frac{2\pi}{\omega_0}

  • k=0k=0 称为直流分量
  • k=±1k=\pm1 称为基波分量
  • k=±2k=\pm2 称为二次谐波分量
  • ... 等等...
# 一般连续复指数信号

f(t)=Kest=Kejθe(σ+jω0)t=Keσtej(ω0+θ)f (t) = Ke^{st} = |K|e^{j\theta}e^{(σ+j\omega_0)t} = Ke^{σt}e^{j(\omega_0+\theta)},

其中 s=σ+jω0s=σ+j\omega_0K=KejθK=|K|e^{j\theta} 为复数

该信号可看成是振幅按实指数信号规律变化的周期性复指数信号。它的实部与虚部都是振幅呈实指数规律变化的正弦振荡。

# 抽样信号

Sa(t)=sinttlimtSa(t)=0;limt0Sa(t)=10+Sa(t)dt=π2;+Sa(t)dt=πSa(t)=\frac{\sin\ t}{t} \\ \lim_{t\to \infin}Sa(t)=0 \ \ ;\ \ \lim_{t\to 0}Sa(t)=1 \\ \int_{0}^{+\infin}Sa(t)\ d\ t=\frac{\pi}{2}\ \ ;\ \ \int_{-\infin}^{+\infin}Sa(t)\ d\ t=\pi

# 高斯函数 “钟形信号”

即正态分布 PDF

φ(t)=1σ2πe(tμ)22σ2\varphi(t) = \frac{1}{\sigma\sqrt{2\pi}}e^{-\frac{(t-\mu)^2}{2\sigma^2}}

# 奇异信号

奇异信号是指函数本身或其导数与积分不连续点 (即跳变点) 的信号。

# 单位斜坡信号 (ramp)

r(t)={tt00t<0\begin{aligned} r(t) = \begin{cases} t & t \geq 0 \\ 0 & t \lt 0 \end{cases} \end{aligned}

# 符号函数 (signal)

sig(t)={1t>00t=01t<0\begin{aligned} sig(t) = \begin{cases} 1 & t \gt 0 \\ 0 & t = 0 \\ -1 & t \lt 0 \end{cases} \end{aligned}

# 单位阶跃信号

u(t)=ε(t)={1t>0undifinedt=00t<0\begin{aligned} u(t)=\varepsilon(t) = \begin{cases} 1 & t \gt 0 \\ \text{undifined} & t = 0 \\ 0 & t \lt 0 \end{cases} \end{aligned}

t = 0 处函数无定义 (部分教材规定 t = 0 时取 12\frac{1}{2})

有的教材用 u(t)u(t) 也有的教材用 ε(t)\varepsilon(t)

# 单位延迟阶跃信号

ε(tt0)={1t>t0undifinedt=t00t<t0\begin{aligned} \varepsilon(t-t_0) = \begin{cases} 1 & t \gt t_0 \\ \text{undifined} & t = t_0 \\ 0 & t \lt t_0 \end{cases} \end{aligned}

# 物理意义
  • ε(t) 表示信号 f (t) = 1 在 t = 0 时刻接⼊系统。
  • f (t) ε(t) 表示信号 f (t) 在 t = 0 时刻接入系统。
  • f (t) ε(t - t0 ) 表示信号 f (t) 在 t = t0 时刻接⼊系统。
# 与斜坡信号的关系

r(t)=tε(t)dr(t)dt=ε(t)tε(τ)dτ=r(t)r(t)=t\ \varepsilon(t)\\ \frac{d\ r(t)}{d\ t}=\varepsilon(t) \\ \int_{-\infin}^{t}\varepsilon(\tau)\ d\ \tau=r(t)

# (单位) 冲激信号

# 物理定义

δ(t)=limτ01τ[ε(t+τ2)ε(tτ2)]δ(tt0)=limτt01τ[ε(t+τ2t0)ε(tτ2t0)]\delta(t)=\lim_{\tau\to 0}\frac{1}{\tau}[\varepsilon(t+\frac{\tau}{2})-\varepsilon(t-\frac{\tau}{2})] \\ \delta(t-t_0)=\lim_{\tau\to t_0}\frac{1}{\tau}[\varepsilon(t+\frac{\tau}{2}-t_0)-\varepsilon(t-\frac{\tau}{2}-t_0)]

# 狄拉克定义

δ(t)={+δ(t)dt=1δ(t)=0,t0\delta (t)= \begin{cases} \int_{-\infin}^{+\infin}\delta (t)\ d\ t=1 \\ \delta (t)=0,t\neq 0 \end{cases}

δ(tt0)={+δ(tt0)dt=1δ(t)=0,tt0\delta (t-t_0)= \begin{cases} \int_{-\infin}^{+\infin}\delta (t-t_0)\ d\ t=1 \\ \delta (t)=0,t\neq t_0 \end{cases}

# 广义函数定义

+δ(t)φ(t)dt=φ(0)+δ(tt0)φ(t)dt=φ(t0)\int_{-\infin}^{+\infin}\delta (t)\ \varphi(t)\ d\ t =\varphi (0) \\ \int_{-\infin}^{+\infin}\delta (t-t_0)\ \varphi(t)\ d\ t =\varphi (t_0)

# 取样性

即广义函数定义,注意在有限区间同样有取样性

# 尺度变化特性

δ(at)=1aδ(t)δ(att0)=1aδ(tt0a)+f(t)δ(att0)=1af(t0a)a0\delta (a\ t)=\frac{1}{|a|}\delta (t) \\ \delta (a\ t-t_0)=\frac{1}{|a|}\delta (t-\frac{t_0}{a}) \\ \int_{-\infin}^{+\infin}f(t)\ \delta (a\ t-t_0)=\frac{1}{|a|}f(\frac{t_0}{a}) \\ a\neq 0

# 与普通函数相乘

f(t)δ(t)=f(0)δ(t)f(t)δ(tt0)=f(t0)δ(tt0)f(t)\ \delta(t)=f(0)\ \delta(t) \\ f(t)\ \delta(t-t_0)=f(t_0)\ \delta(t-t_0)

# 与阶跃信号的关系

ddtε(t)=δ(t)\frac{d}{d\ t}\varepsilon(t)=\delta(t)

若信号的函数值有跳变,则信号在跳变点处的导数为冲激信号,其中冲击强度为信号在跳变点的跳跃值

# (单位) 冲激偶信号

# 定义

单位冲激信号的 “奇函数版本”,且是单位冲激信号的导函数

δ(t)=ddtδ(t)\delta '(t)=\frac{d}{d\ t}\delta (t)

单位冲激信号是偶函数;单位冲激偶信号是奇函数!!

二者通过积分和求导可相互转化

# 与普通函数相乘

f(t)δ(t)=f(0)δ(t)f(0)δ(t)f(t)δ(tt0)=f(0)δ(tt0)f(0)δ(tt0)f(t)\delta'(t)=f(0)\delta'(t)-f'(0)\delta(t) \\ f(t)\delta'(t-t_0)=f(0)\delta'(t-t_0)-f'(0)\delta(t-t_0)

# 筛选特性

+f(t)δ(t)dt=f(0)+f(t)δ(tt0)dt=f(t0)\int_{-\infin}^{+\infin}f(t)\delta'(t)d\ t=-f'(0) \\ \int_{-\infin}^{+\infin}f(t)\delta'(t-t_0)d\ t=-f'(t_0)

# 尺度变化特性

δ(at)=1aaδ(t)a0\delta'(a\ t)=\frac{1}{a|a|}\delta'(t) \\ a\neq 0

# 离散时间信号

定义域离散

仅在一些离散时刻才有意义,⽽而在其他时刻⽆无定义。离散时间⼀一般为均匀间隔,“离散” 是指信号的定义域是离散的。

# 基本离散信号

# 单位序列

单位序列列 δ(k) 亦称单位样值序列列,类似于连续时间信号中的 δ(t)

δ(k)={1k=00k0\delta (k)= \begin{cases} 1 & k=0 \\ 0 & k\neq 0 \end{cases}

δ(ki)={1k=i0ki\delta (k-i)= \begin{cases} 1 & k=i \\ 0 & k\neq i \end{cases}

# 单位阶跃序列

单位阶跃序列 ε(k) 类似于连续时间信号中的单位阶跃函数 ε(t)

ε(k)={1k00k<0\varepsilon (k)= \begin{cases} 1 & k \geq 0 \\ 0 & k \lt 0 \end{cases}

ε(ki)={1ki0k<i\varepsilon (k-i)= \begin{cases} 1 & k \geq i \\ 0 & k \lt i \end{cases}

# 单位序列 δ(k) 转化为单位阶跃序列 ε(k)

ε(k)=j=0+δ(kj)\varepsilon (k)=\sum_{j=0}^{+\infin}\delta(k-j)

# 单位阶跃序列 ε(k) 转化为单位序列 δ(k)

δ(k)=ε(k)ε(k1)\delta(k)=\varepsilon(k)-\varepsilon(k-1)

# 单边指数序列

f(k)=αkε(k),kzf (k) = \alpha^{k}\varepsilon(k)\ ,\ \ k \in z

当 |α| > 1 时,序列列发散,|α| < 1 时,序列列收敛;

α > 0 时,序列列恒正, α < 0 时,序列列正负交错。

# 正弦序列

f(k)=cosω0k,kzf (k) = \cos\ \omega_0\ k\ ,\ \ k \in z

ω0\omega_0 为数字角频率,其与连续正弦信号的⻆频率不同,详见数字信号处理

不是所有的正弦序列都是周期序列,因为正弦序列为连续正弦信号的抽样

# 离散正弦序列的周期性

正弦序列是周期序列当且仅当

kz,ω02kπ\exist k\in z\ \ ,\ \ \omega_0 | 2k\pi

# 复指数序列

f(k)=e(α+jω0)k=eαkejω0k=eαk(cosω0k+jsinω0k)kzf (k) = e^{(\alpha +j\omega_0)k} = e^{\alpha k}e^{j\omega_0 k}=e^{\alpha k}(\cos\ \omega_0k +j\ \sin\ \omega_0k)\\ k \in z

α 的大小ω0 的大小最终结果
α = 0ω00\omega_0\neq 0实部虚部均等幅正弦序列
α > 0ω00\omega_0\neq 0实部虚部均增幅正弦序列
α < 0ω00\omega_0\neq 0实部虚部均减幅正弦序列
α ≠ 0ω0=0\omega_0 = 0为指数序列
α = 0ω0=0\omega_0 = 0为常数序列
# 离散复指数序列的周期性

α=0\alpha=0ω00\omega_0\neq0 时实部虚部均等幅正弦序列,对应连续复指数信号是周期信号,离散复指数序列才有可能是周期序列,因为离散复指数序列为连续复指数信号的抽样

复指数序列是周期序列当且仅当

N,mz2πω0=Nmejω0N=1ejω0n=ejω0nejω0N=ejω0(n+N)x[k]=x[k+N]\exist N,m\in z\\ \frac{2\pi}{\omega_0}=\frac{N}{m} \\ \lrArr e^{j\omega_0N} = 1\\ \lrArr e^{j\omega_0n} = e^{j\omega_0n}\cdot e^{j\omega_0N} = e^{j\omega_0(n+N)} \\ \lrArr x[k]=x[k+N]

也就是当且仅当 ω0=qπ\omega_0=q\pi 其中 qq 为有理数时复指数序列为周期序列。

NNmm 互质(无公因子)时:

基波周期:N=2πω0mN=\frac{2π}{\omega_0}m

基波频率为:ω=2πN=ω0m\omega=\frac{2π}{N}=\frac{\omega_0}{m}

# 成谐波关系的离散复指数信号集

{Φk[n]}={ej2πNkn}k=0,±1,±2......\{\varPhi_k[n] \}=\{ e^{j\frac{2\pi}{N}kn} \}\\ k=0,\pm1,\pm2......

该信号集中的每一个信号都是以 NN 为公共周期的,频率是 2π 的整数倍。

与连续时间情况不同,该信号集中的信号并不都是彼此独立的。显然有:

Φk+N[n]=Φk[n]\varPhi_{k+N}[n] = \varPhi_k[n]

该信号集中只有 N 个信号是独立的。即当 k 取相连的 NN 个整数时所对应的各个谐波才是彼此独立的。

根据集合定义,那么实际上这个信号集的元素个数是 NN 个。

这里 “相互独立” 的意思是互不相等

# 信号的基本运算

# 平移与反转

连续信号和离散信号的运算一致

  • 沿横轴向左平移:f(t)f(t+t0)f(t) \to f(t+t_0)
  • 沿横轴向右平移:f(t)f(tt0)f(t) \to f(t-t_0)
  • 沿纵轴镜像翻转:f(t)f(t)f(t) \to f(-t)

# 尺度变换

对于离散信号,⼀般不做尺度变换,因为可能丢失序列信息,只对连续信号尺度变换

f(t)f(at)f(t) \to f(a\ t)

横轴变为原来的 1a\frac{1}{a}

# 连续信号的求导与积分

# 离散信号的差分与求和

好离散信号的向 (一阶) 差分

Δf(k)=f(k+1)f(k)\Delta f(k)=f(k+1)-f(k)

好离散信号的向 (一阶) 差分

f(k)=f(k)f(k1)\nabla f(k)=f(k)-f(k-1)

# 信号的运算的综合运⽤

平移、反折、压缩等各种运算均对独⽴、单一的变量 t 计算,⽽不是对 atat + b 整体计算

对于 f (t) → f(at + b) 先平移,后尺度 (含反折),即 f (t) → f(t + b) → f(at + b)

对于 f (at + b) → f(t) 先尺度 (含反折),后平移,即 f (at + b) → f(t + b) → f(t)

\ No newline at end of file +M834 80h400000v40h-400000z"/>1e2σ2(tμ)2

# 奇异信号

奇异信号是指函数本身或其导数与积分不连续点 (即跳变点) 的信号。

# 单位斜坡信号 (ramp)

r(t)={tt00t<0\begin{aligned} r(t) = \begin{cases} t & t \geq 0 \\ 0 & t \lt 0 \end{cases} \end{aligned}

# 符号函数 (signal)

sig(t)={1t>00t=01t<0\begin{aligned} sig(t) = \begin{cases} 1 & t \gt 0 \\ 0 & t = 0 \\ -1 & t \lt 0 \end{cases} \end{aligned}

# 单位阶跃信号

u(t)=ε(t)={1t>0undifinedt=00t<0\begin{aligned} u(t)=\varepsilon(t) = \begin{cases} 1 & t \gt 0 \\ \text{undifined} & t = 0 \\ 0 & t \lt 0 \end{cases} \end{aligned}

t = 0 处函数无定义 (部分教材规定 t = 0 时取 12\frac{1}{2})

有的教材用 u(t)u(t) 也有的教材用 ε(t)\varepsilon(t)

# 单位延迟阶跃信号

ε(tt0)={1t>t0undifinedt=t00t<t0\begin{aligned} \varepsilon(t-t_0) = \begin{cases} 1 & t \gt t_0 \\ \text{undifined} & t = t_0 \\ 0 & t \lt t_0 \end{cases} \end{aligned}

# 物理意义
  • ε(t) 表示信号 f (t) = 1 在 t = 0 时刻接⼊系统。
  • f (t) ε(t) 表示信号 f (t) 在 t = 0 时刻接入系统。
  • f (t) ε(t - t0 ) 表示信号 f (t) 在 t = t0 时刻接⼊系统。
# 与斜坡信号的关系

r(t)=tε(t)dr(t)dt=ε(t)tε(τ)dτ=r(t)r(t)=t\ \varepsilon(t)\\ \frac{d\ r(t)}{d\ t}=\varepsilon(t) \\ \int_{-\infin}^{t}\varepsilon(\tau)\ d\ \tau=r(t)

# (单位) 冲激信号

# 物理定义

δ(t)=limτ01τ[ε(t+τ2)ε(tτ2)]δ(tt0)=limτt01τ[ε(t+τ2t0)ε(tτ2t0)]\delta(t)=\lim_{\tau\to 0}\frac{1}{\tau}[\varepsilon(t+\frac{\tau}{2})-\varepsilon(t-\frac{\tau}{2})] \\ \delta(t-t_0)=\lim_{\tau\to t_0}\frac{1}{\tau}[\varepsilon(t+\frac{\tau}{2}-t_0)-\varepsilon(t-\frac{\tau}{2}-t_0)]

# 狄拉克定义

δ(t)={+δ(t)dt=1δ(t)=0,t0\delta (t)= \begin{cases} \int_{-\infin}^{+\infin}\delta (t)\ d\ t=1 \\ \delta (t)=0,t\neq 0 \end{cases}

δ(tt0)={+δ(tt0)dt=1δ(t)=0,tt0\delta (t-t_0)= \begin{cases} \int_{-\infin}^{+\infin}\delta (t-t_0)\ d\ t=1 \\ \delta (t)=0,t\neq t_0 \end{cases}

# 广义函数定义

+δ(t)φ(t)dt=φ(0)+δ(tt0)φ(t)dt=φ(t0)\int_{-\infin}^{+\infin}\delta (t)\ \varphi(t)\ d\ t =\varphi (0) \\ \int_{-\infin}^{+\infin}\delta (t-t_0)\ \varphi(t)\ d\ t =\varphi (t_0)

# 取样性

即广义函数定义,注意在有限区间同样有取样性

# 尺度变化特性

δ(at)=1aδ(t)δ(att0)=1aδ(tt0a)+f(t)δ(att0)=1af(t0a)a0\delta (a\ t)=\frac{1}{|a|}\delta (t) \\ \delta (a\ t-t_0)=\frac{1}{|a|}\delta (t-\frac{t_0}{a}) \\ \int_{-\infin}^{+\infin}f(t)\ \delta (a\ t-t_0)=\frac{1}{|a|}f(\frac{t_0}{a}) \\ a\neq 0

# 与普通函数相乘

f(t)δ(t)=f(0)δ(t)f(t)δ(tt0)=f(t0)δ(tt0)f(t)\ \delta(t)=f(0)\ \delta(t) \\ f(t)\ \delta(t-t_0)=f(t_0)\ \delta(t-t_0)

# 与阶跃信号的关系

ddtε(t)=δ(t)\frac{d}{d\ t}\varepsilon(t)=\delta(t)

若信号的函数值有跳变,则信号在跳变点处的导数为冲激信号,其中冲击强度为信号在跳变点的跳跃值

# (单位) 冲激偶信号

# 定义

单位冲激信号的 “奇函数版本”,且是单位冲激信号的导函数

δ(t)=ddtδ(t)\delta '(t)=\frac{d}{d\ t}\delta (t)

单位冲激信号是偶函数;单位冲激偶信号是奇函数!!

二者通过积分和求导可相互转化

# 与普通函数相乘

f(t)δ(t)=f(0)δ(t)f(0)δ(t)f(t)δ(tt0)=f(0)δ(tt0)f(0)δ(tt0)f(t)\delta'(t)=f(0)\delta'(t)-f'(0)\delta(t) \\ f(t)\delta'(t-t_0)=f(0)\delta'(t-t_0)-f'(0)\delta(t-t_0)

# 筛选特性

+f(t)δ(t)dt=f(0)+f(t)δ(tt0)dt=f(t0)\int_{-\infin}^{+\infin}f(t)\delta'(t)d\ t=-f'(0) \\ \int_{-\infin}^{+\infin}f(t)\delta'(t-t_0)d\ t=-f'(t_0)

# 尺度变化特性

δ(at)=1aaδ(t)a0\delta'(a\ t)=\frac{1}{a|a|}\delta'(t) \\ a\neq 0

# 离散时间信号

定义域离散

仅在一些离散时刻才有意义,⽽而在其他时刻⽆无定义。离散时间⼀一般为均匀间隔,“离散” 是指信号的定义域是离散的。

# 基本离散信号

# 单位序列

单位序列列 δ(k) 亦称单位样值序列列,类似于连续时间信号中的 δ(t)

δ(k)={1k=00k0\delta (k)= \begin{cases} 1 & k=0 \\ 0 & k\neq 0 \end{cases}

δ(ki)={1k=i0ki\delta (k-i)= \begin{cases} 1 & k=i \\ 0 & k\neq i \end{cases}

# 单位阶跃序列

单位阶跃序列 ε(k) 类似于连续时间信号中的单位阶跃函数 ε(t)

ε(k)={1k00k<0\varepsilon (k)= \begin{cases} 1 & k \geq 0 \\ 0 & k \lt 0 \end{cases}

ε(ki)={1ki0k<i\varepsilon (k-i)= \begin{cases} 1 & k \geq i \\ 0 & k \lt i \end{cases}

# 单位序列 δ(k) 转化为单位阶跃序列 ε(k)

ε(k)=j=0+δ(kj)\varepsilon (k)=\sum_{j=0}^{+\infin}\delta(k-j)

# 单位阶跃序列 ε(k) 转化为单位序列 δ(k)

δ(k)=ε(k)ε(k1)\delta(k)=\varepsilon(k)-\varepsilon(k-1)

# 单边指数序列

f(k)=αkε(k),kzf (k) = \alpha^{k}\varepsilon(k)\ ,\ \ k \in z

当 |α| > 1 时,序列列发散,|α| < 1 时,序列列收敛;

α > 0 时,序列列恒正, α < 0 时,序列列正负交错。

# 正弦序列

f(k)=cosω0k,kzf (k) = \cos\ \omega_0\ k\ ,\ \ k \in z

ω0\omega_0 为数字角频率,其与连续正弦信号的⻆频率不同,详见数字信号处理

不是所有的正弦序列都是周期序列,因为正弦序列为连续正弦信号的抽样

# 离散正弦序列的周期性

正弦序列是周期序列当且仅当

kz,ω02kπ\exist k\in z\ \ ,\ \ \omega_0 | 2k\pi

# 复指数序列

f(k)=e(α+jω0)k=eαkejω0k=eαk(cosω0k+jsinω0k)kzf (k) = e^{(\alpha +j\omega_0)k} = e^{\alpha k}e^{j\omega_0 k}=e^{\alpha k}(\cos\ \omega_0k +j\ \sin\ \omega_0k)\\ k \in z

α 的大小ω0 的大小最终结果
α = 0ω00\omega_0\neq 0实部虚部均等幅正弦序列
α > 0ω00\omega_0\neq 0实部虚部均增幅正弦序列
α < 0ω00\omega_0\neq 0实部虚部均减幅正弦序列
α ≠ 0ω0=0\omega_0 = 0为指数序列
α = 0ω0=0\omega_0 = 0为常数序列
# 离散复指数序列的周期性

α=0\alpha=0ω00\omega_0\neq0 时实部虚部均等幅正弦序列,对应连续复指数信号是周期信号,离散复指数序列才有可能是周期序列,因为离散复指数序列为连续复指数信号的抽样

复指数序列是周期序列当且仅当

N,mz2πω0=Nmejω0N=1ejω0n=ejω0nejω0N=ejω0(n+N)x[k]=x[k+N]\exist N,m\in z\\ \frac{2\pi}{\omega_0}=\frac{N}{m} \\ \lrArr e^{j\omega_0N} = 1\\ \lrArr e^{j\omega_0n} = e^{j\omega_0n}\cdot e^{j\omega_0N} = e^{j\omega_0(n+N)} \\ \lrArr x[k]=x[k+N]

也就是当且仅当 ω0=qπ\omega_0=q\pi 其中 qq 为有理数时复指数序列为周期序列。

NNmm 互质(无公因子)时:

基波周期:N=2πω0mN=\frac{2π}{\omega_0}m

基波频率为:ω=2πN=ω0m\omega=\frac{2π}{N}=\frac{\omega_0}{m}

# 成谐波关系的离散复指数信号集

{Φk[n]}={ej2πNkn}k=0,±1,±2......\{\varPhi_k[n] \}=\{ e^{j\frac{2\pi}{N}kn} \}\\ k=0,\pm1,\pm2......

该信号集中的每一个信号都是以 NN 为公共周期的,频率是 2π 的整数倍。

与连续时间情况不同,该信号集中的信号并不都是彼此独立的。显然有:

Φk+N[n]=Φk[n]\varPhi_{k+N}[n] = \varPhi_k[n]

该信号集中只有 N 个信号是独立的。即当 k 取相连的 NN 个整数时所对应的各个谐波才是彼此独立的。

根据集合定义,那么实际上这个信号集的元素个数是 NN 个。

这里 “相互独立” 的意思是互不相等

# 信号的基本运算

# 平移与反转

连续信号和离散信号的运算一致

  • 沿横轴向左平移:f(t)f(t+t0)f(t) \to f(t+t_0)
  • 沿横轴向右平移:f(t)f(tt0)f(t) \to f(t-t_0)
  • 沿纵轴镜像翻转:f(t)f(t)f(t) \to f(-t)

# 尺度变换

对于离散信号,⼀般不做尺度变换,因为可能丢失序列信息,只对连续信号尺度变换

f(t)f(at)f(t) \to f(a\ t)

横轴变为原来的 1a\frac{1}{a}

# 连续信号的求导与积分

# 离散信号的差分与求和

好离散信号的向 (一阶) 差分

Δf(k)=f(k+1)f(k)\Delta f(k)=f(k+1)-f(k)

好离散信号的向 (一阶) 差分

f(k)=f(k)f(k1)\nabla f(k)=f(k)-f(k-1)

# 信号的运算的综合运⽤

平移、反折、压缩等各种运算均对独⽴、单一的变量 t 计算,⽽不是对 atat + b 整体计算

对于 f (t) → f(at + b) 先平移,后尺度 (含反折),即 f (t) → f(t + b) → f(at + b)

对于 f (at + b) → f(t) 先尺度 (含反折),后平移,即 f (at + b) → f(t + b) → f(t)

\ No newline at end of file diff --git a/ie/signals-and-systems/systems-concepts/index.html b/ie/signals-and-systems/systems-concepts/index.html index a87eb304..4dce81a1 100644 --- a/ie/signals-and-systems/systems-concepts/index.html +++ b/ie/signals-and-systems/systems-concepts/index.html @@ -1 +1 @@ -系统基本概念 - 信号与系统 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 系统的描述

# 连续 / 离散 时间系统

# 连续时间系统

输入信号与输出响应都是连续时间信号的系统。

连续时间系统

eg: 机械系统、电路系统

# 离散时间系统

输入信号与输出响应都是离散时间信号的系统。

离散时间系统

eg: 人口问题

# 两种描述方法

# 输入输出描述法 (微分方程、差分⽅程)

着眼于系统输入与输出的关系,适⽤用于单输入 — 单输出系统。

# 状态变量描述法 (状态⽅程、输出方程)

即可描述输入与输出的关系,还可以描述系统的内部状态 既可⽤用于单输入 — 单输出系统,⼜可⽤于多输⼊ — 多输出系统。

# 系统的互联

现实中的系统是各式各样的,其复杂程度也大相径庭。但许多系统都可以分解为若干个简单系统的组合。这一思想对系统分析系统综合十分重要。

  • 可以通过对简单系统(子系统)的分析并通过子系统互联而达到分析复杂系统的目的。
  • 也可以通过将若干个简单子系统互联起来而实现一个相对复杂的系统。

# 级联

级联

# 并联

并联

# 反馈联结

反馈联结

# 系统的组成

⼀个系统由若⼲个基本单元组成, 其中的基本组成单元包括:

# 加法器

加法器

# 数乘器

数乘器

# 积分器

积分器

# 单位延时器

单位延时器

# 延时器

延时器

# 系统的基本性质

# 记忆性

在任何时刻,系统的输出都只与当前时刻的输入有关,而与该时刻以外的输入无关,则称该系统是无记忆系统,也叫即时系统。否则就是记忆系统,也叫动态系统

注意一个特例 —— 恒等系统:任何时刻系统的输出响应与输入信号都相同,即有 y(t) = x(t)y[n] = x[n]

包含积分器、微分器的系统就是记忆系统

# 可逆性

如果一个系统对任何不同的输入都能产生不同的输出,即输入与输出是一一对应,则称该系统是可逆系统。反之,称为不可逆系统

一个可逆系统与另一个系统级联后构成一个恒等系统,则称后者是前者的逆系统

逆系统

# 因果性

如果系统在任何时刻的输出只与当前时刻及此前的输入有关,而和此后的输入无关,就称该系统是因果的。否则就是非因果的。

一般说来,实时的物理系统都是因果的,因为时间是单向变化的,结果发生于原因之后。

但对非实时处理信号的离散时间系统,或信号的自变量并不具有时间概念的情况,因果性并不一定成为系统能否物理实现的先决条件。

  • 因果系统:响应后于激励
  • 非因果系统:响应先于激励

由定义显然可见:非记忆性系统一定是因果的;非因果系统一定是记忆性的。

# 稳定性

如果一个系统对任意有界输入都产生有界输出,则该系统是稳定系统。否则,就是不稳定系统

即当 e(.)<|e(.)|\lt\infin时yzs(.)<|y_{zs}(.)|\lt\infin

工程实际中通常希望所设计的系统是稳定的。因此稳定性对系统设计来说是一个重要的考虑因素。

# 时不变性

时不变性质只对零状态响应 yzs(.)y_{zs}( . ) 讨论

e(.)e(.)x(.)x(.) 表示输入信号,或者说激励

yzs(.)y_{zs}(.) 表示零状态响应,zs 即 zero status 零状态

yzi(.)y_{zi}(.) 表示零输入响应,zi 即 zero input 零输入

全响应 = 零状态响应 + 零输入响应:y(.)=yzx(.)+yzi(.)y(.)=y_{zx}(.)+y_{zi}(.)

当输入信号有一个时移时,系统的输出响应也产生相同时移,此外无其它变化,则称该系统是时不变的。否则就是时变的。

若对任意 x(t)y(t)x(t) → y(t)x(tt0)y(tt0)x(t - t0) → y(t - t0) ,则系统是时不变的。

⭐️ 检验一个系统时不变性的步骤(以连续时间为例,离散时间可类推)

  1. 令输入为 x1(t)x_1(t) ,根据系统描述确定对应输出 y1(t)y_1(t) ;
  2. 将输入变为 x2(t)=x1(tt0)x_2(t) = x_1(t - t_0) ,再根据系统描述确定输出 y2(t)y_2(t) ;
  3. 根据自变量变换,检验 y2(t)y_2(t) 是否等于 y1(tt0)y_1(t - t_0)

# 线性 linear

# 定义

连续时间线性系统定义

对任意 x1(t)y1(t)x1(t) → y1(t)x2(t)y2(t)x2(t) → y2(t) ,总有 ax1(t)+bx2(t)ay1(t)+by2(t)ax_1(t) + bx_2(t) → ay_1(t) + by_2(t) ,其中 a 与 b 是任意常数。

连续线性时间系统

离散时间线性系统同理。

实际上线性等价于以下两个性质之和:

x1(t)+x2(t)y1(t)+y2(t)x_1(t) + x_2(t) → y_1(t) + y_2(t)(可加性 / 叠加性)

ax1(t)ay1(t)ax_1(t) → ay_1(t)(齐次性 / 均匀性)

# 零输入 — 零输出特性

根据线性系统的齐次性,可得出:线性系统当输入为零(即没有输入)时,系统的输出响应也必然为零(即没有输出响应)。这就是所谓线性系统的零输入 — 零输出特性

# 非线性系统举例

eg1 : 满足可加性,但不满足齐次性

y(t)=Re{x(t)}y(t) = Re\{x(t)\}

eg2 : 满足齐次性但不满足可加性

y(t)=[x(t)]2x(t)y(t) = \frac{[x'(t)]^2}{x(t)}

# 线性系统的分解特性

如果一个系统是线性的,则只要我们能够把输入信号分解成若干个简单信号的线性组合,且知道该系统对每一个简单信号的响应,就可以很方便地通过线性组合而得到系统对原输入信号的响应。即:

{x(t)=kakxk(t)xk(t)yk(t)y(t)=kakyk(t)\begin{cases} x(t)=\sum_k a_k x_k (t)\\ x_k(t)\to y_k(t) \end{cases} \rArr y(t)=\sum_k a_k y_k (t)

这一思想是信号与系统分析理论和方法的基础

# 特殊系统

# 增量线性系统

在工程实际中,有一类系统并不满足线性系统的要求。但是这类系统的输出响应的增量与输入信号的增量之间满足线性特性。这类系统称为增量线性系统

eg:考虑系统 y(t)=x(t)+2y(t) = x(t) + 2 ,由于:

x1(t)y1(t)=x1(t)+2x2(t)y2(t)=x2(t)+2x_1(t) → y_1(t) = x_1(t) + 2\\ x_2(t) → y_2(t) = x_2(t) + 2

该系统既不满足齐次性,也不满足可加性,但当考查输入的增量与输出的增量之间的关系时,有

Δy(t)=y1(t)y2(t)=x1(t)x2(t)=Δx(t)Δy(t) = y_1(t) - y_2(t) = x_1(t) - x_2(t) = Δx(t)

可见输入的增量与输出的增量之间是满足线性关系的,它是一个增量线性系统。

增量线性系统可以等效为一个线性系统再加上一部分与输入无关的响应。

线性增量系统

增量线性系统的响应包括:

  • 零状态响应:当 y0(t)=0y_0(t) = 0 时,y(t)=y1(t)y(t) = y_1(t) 。此时系统处于零初始状态,故将 y1(t)y_1(t) 称为系统的零状态响应。
  • 零输入响应:当 x(t)=0x(t) = 0 时,有 y1(t)=0y_1(t) = 0y(t)=y0(t)y(t) = y_0(t) ,因此将 y0(t)y_0(t) 称为系统的零输入响应。

# 线性时不变系统(LTI)

线性 + 时不变性 = LTI

基本事实:如果知道线性时不变系统对某些输入信号的响应,则可以知道该系统对许多其它输入信号的响应。

线性时不变(LTI)系统是本课程主要关注的系统

# 线性性质

# 根据系统框图描述建立微分方程

# 对于连续系统

步骤如下

  1. 首先判断其阶数,阶数 = 积分器个数
  2. 设信号传递 ** 最后一个积分器输出为 x(t)x(t) ** ,则各积分器的输入输出均可确定
  3. 对每个加法器列⽅程:输入和 = 输出和
  4. 联立方程消去中间变量 x(t)x(t) ,得到关于输出信号 y(t) 的微分方程

# 对于离散系统

步骤如下

  1. 首先判断其阶数,阶数 = 延时单元个数
  2. 设信号传递第一个延时单元输入为 x(k) ,则各延时单元的输入输出均可确定
  3. 对每个加法器列⽅程:输入和 = 输出和
  4. 联立方程消去中间变量 x(t)x(t) ,得到关于输出信号 y(t) 的微分方程
\ No newline at end of file +系统基本概念 - 信号与系统 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 系统的描述

# 连续 / 离散 时间系统

# 连续时间系统

输入信号与输出响应都是连续时间信号的系统。

连续时间系统

eg: 机械系统、电路系统

# 离散时间系统

输入信号与输出响应都是离散时间信号的系统。

离散时间系统

eg: 人口问题

# 两种描述方法

# 输入输出描述法 (微分方程、差分⽅程)

着眼于系统输入与输出的关系,适⽤用于单输入 — 单输出系统。

# 状态变量描述法 (状态⽅程、输出方程)

即可描述输入与输出的关系,还可以描述系统的内部状态 既可⽤用于单输入 — 单输出系统,⼜可⽤于多输⼊ — 多输出系统。

# 系统的互联

现实中的系统是各式各样的,其复杂程度也大相径庭。但许多系统都可以分解为若干个简单系统的组合。这一思想对系统分析系统综合十分重要。

  • 可以通过对简单系统(子系统)的分析并通过子系统互联而达到分析复杂系统的目的。
  • 也可以通过将若干个简单子系统互联起来而实现一个相对复杂的系统。

# 级联

级联

# 并联

并联

# 反馈联结

反馈联结

# 系统的组成

⼀个系统由若⼲个基本单元组成, 其中的基本组成单元包括:

# 加法器

加法器

# 数乘器

数乘器

# 积分器

积分器

# 单位延时器

单位延时器

# 延时器

延时器

# 系统的基本性质

# 记忆性

在任何时刻,系统的输出都只与当前时刻的输入有关,而与该时刻以外的输入无关,则称该系统是无记忆系统,也叫即时系统。否则就是记忆系统,也叫动态系统

注意一个特例 —— 恒等系统:任何时刻系统的输出响应与输入信号都相同,即有 y(t) = x(t)y[n] = x[n]

包含积分器、微分器的系统就是记忆系统

# 可逆性

如果一个系统对任何不同的输入都能产生不同的输出,即输入与输出是一一对应,则称该系统是可逆系统。反之,称为不可逆系统

一个可逆系统与另一个系统级联后构成一个恒等系统,则称后者是前者的逆系统

逆系统

# 因果性

如果系统在任何时刻的输出只与当前时刻及此前的输入有关,而和此后的输入无关,就称该系统是因果的。否则就是非因果的。

一般说来,实时的物理系统都是因果的,因为时间是单向变化的,结果发生于原因之后。

但对非实时处理信号的离散时间系统,或信号的自变量并不具有时间概念的情况,因果性并不一定成为系统能否物理实现的先决条件。

  • 因果系统:响应后于激励
  • 非因果系统:响应先于激励

由定义显然可见:非记忆性系统一定是因果的;非因果系统一定是记忆性的。

# 稳定性

如果一个系统对任意有界输入都产生有界输出,则该系统是稳定系统。否则,就是不稳定系统

即当 e(.)<|e(.)|\lt\infin时yzs(.)<|y_{zs}(.)|\lt\infin

工程实际中通常希望所设计的系统是稳定的。因此稳定性对系统设计来说是一个重要的考虑因素。

# 时不变性

时不变性质只对零状态响应 yzs(.)y_{zs}( . ) 讨论

e(.)e(.)x(.)x(.) 表示输入信号,或者说激励

yzs(.)y_{zs}(.) 表示零状态响应,zs 即 zero status 零状态

yzi(.)y_{zi}(.) 表示零输入响应,zi 即 zero input 零输入

全响应 = 零状态响应 + 零输入响应:y(.)=yzx(.)+yzi(.)y(.)=y_{zx}(.)+y_{zi}(.)

当输入信号有一个时移时,系统的输出响应也产生相同时移,此外无其它变化,则称该系统是时不变的。否则就是时变的。

若对任意 x(t)y(t)x(t) → y(t)x(tt0)y(tt0)x(t - t0) → y(t - t0) ,则系统是时不变的。

⭐️ 检验一个系统时不变性的步骤(以连续时间为例,离散时间可类推)

  1. 令输入为 x1(t)x_1(t) ,根据系统描述确定对应输出 y1(t)y_1(t) ;
  2. 将输入变为 x2(t)=x1(tt0)x_2(t) = x_1(t - t_0) ,再根据系统描述确定输出 y2(t)y_2(t) ;
  3. 根据自变量变换,检验 y2(t)y_2(t) 是否等于 y1(tt0)y_1(t - t_0)

# 线性 linear

# 定义

连续时间线性系统定义

对任意 x1(t)y1(t)x1(t) → y1(t)x2(t)y2(t)x2(t) → y2(t) ,总有 ax1(t)+bx2(t)ay1(t)+by2(t)ax_1(t) + bx_2(t) → ay_1(t) + by_2(t) ,其中 a 与 b 是任意常数。

连续线性时间系统

离散时间线性系统同理。

实际上线性等价于以下两个性质之和:

x1(t)+x2(t)y1(t)+y2(t)x_1(t) + x_2(t) → y_1(t) + y_2(t)(可加性 / 叠加性)

ax1(t)ay1(t)ax_1(t) → ay_1(t)(齐次性 / 均匀性)

# 零输入 — 零输出特性

根据线性系统的齐次性,可得出:线性系统当输入为零(即没有输入)时,系统的输出响应也必然为零(即没有输出响应)。这就是所谓线性系统的零输入 — 零输出特性

# 非线性系统举例

eg1 : 满足可加性,但不满足齐次性

y(t)=Re{x(t)}y(t) = Re\{x(t)\}

eg2 : 满足齐次性但不满足可加性

y(t)=[x(t)]2x(t)y(t) = \frac{[x'(t)]^2}{x(t)}

# 线性系统的分解特性

如果一个系统是线性的,则只要我们能够把输入信号分解成若干个简单信号的线性组合,且知道该系统对每一个简单信号的响应,就可以很方便地通过线性组合而得到系统对原输入信号的响应。即:

{x(t)=kakxk(t)xk(t)yk(t)y(t)=kakyk(t)\begin{cases} x(t)=\sum_k a_k x_k (t)\\ x_k(t)\to y_k(t) \end{cases} \rArr y(t)=\sum_k a_k y_k (t)

这一思想是信号与系统分析理论和方法的基础

# 特殊系统

# 增量线性系统

在工程实际中,有一类系统并不满足线性系统的要求。但是这类系统的输出响应的增量与输入信号的增量之间满足线性特性。这类系统称为增量线性系统

eg:考虑系统 y(t)=x(t)+2y(t) = x(t) + 2 ,由于:

x1(t)y1(t)=x1(t)+2x2(t)y2(t)=x2(t)+2x_1(t) → y_1(t) = x_1(t) + 2\\ x_2(t) → y_2(t) = x_2(t) + 2

该系统既不满足齐次性,也不满足可加性,但当考查输入的增量与输出的增量之间的关系时,有

Δy(t)=y1(t)y2(t)=x1(t)x2(t)=Δx(t)Δy(t) = y_1(t) - y_2(t) = x_1(t) - x_2(t) = Δx(t)

可见输入的增量与输出的增量之间是满足线性关系的,它是一个增量线性系统。

增量线性系统可以等效为一个线性系统再加上一部分与输入无关的响应。

线性增量系统

增量线性系统的响应包括:

  • 零状态响应:当 y0(t)=0y_0(t) = 0 时,y(t)=y1(t)y(t) = y_1(t) 。此时系统处于零初始状态,故将 y1(t)y_1(t) 称为系统的零状态响应。
  • 零输入响应:当 x(t)=0x(t) = 0 时,有 y1(t)=0y_1(t) = 0y(t)=y0(t)y(t) = y_0(t) ,因此将 y0(t)y_0(t) 称为系统的零输入响应。

# 线性时不变系统(LTI)

线性 + 时不变性 = LTI

基本事实:如果知道线性时不变系统对某些输入信号的响应,则可以知道该系统对许多其它输入信号的响应。

线性时不变(LTI)系统是本课程主要关注的系统

# 线性性质

# 根据系统框图描述建立微分方程

# 对于连续系统

步骤如下

  1. 首先判断其阶数,阶数 = 积分器个数
  2. 设信号传递 ** 最后一个积分器输出为 x(t)x(t) ** ,则各积分器的输入输出均可确定
  3. 对每个加法器列⽅程:输入和 = 输出和
  4. 联立方程消去中间变量 x(t)x(t) ,得到关于输出信号 y(t) 的微分方程

# 对于离散系统

步骤如下

  1. 首先判断其阶数,阶数 = 延时单元个数
  2. 设信号传递第一个延时单元输入为 x(k) ,则各延时单元的输入输出均可确定
  3. 对每个加法器列⽅程:输入和 = 输出和
  4. 联立方程消去中间变量 x(t)x(t) ,得到关于输出信号 y(t) 的微分方程
\ No newline at end of file diff --git a/ie/signals-and-systems/zT/index.html b/ie/signals-and-systems/zT/index.html index e9f94445..d904933e 100644 --- a/ie/signals-and-systems/zT/index.html +++ b/ie/signals-and-systems/zT/index.html @@ -1,4 +1,4 @@ -z 变换 - 信号与系统 - 电子信息 | Balloon Party = 風船のパーティー = fuusen no party

# 公式表

# 基本变换对

常用 (双边) z 变换对:

常用z变换对

# 二阶系统

二阶系统

# 性质表

双边 z 变换的性质:

z变换性质

单边 z 变换的性质:

单边z变换性质

# 双边 z 变换

# 定义

X(z)=n=+x[n]znX(z)=\sum_{n=-\infin}^{+\infin}x[n]z^{-n}

称为 x[n]x[n] 的 z 变换,后面简记为 zT,其中 z=rejωz=re^{j\omega} 为复数。

r=1r=1z=ejωz=e^{j\omega} 位于单位圆上,则为 DTFT(离散时间傅里叶变换),也就是说 DTFT 是双边 z 变换在 r=1r=1 或者说是在单位圆上的特例,即 X(z)r=1=X(ejω)X(z)|_{r=1}=X(e^{j\omega})

# zT 与 DTFT 的关系

X(z)=X(rejω)=n=+x[n]rnejωn=n=+[x[n]rn]ejωn=F{x[n]rn}\begin{aligned} X(z)=X(re^{j\omega})&=\sum_{n=-\infin}^{+\infin}x[n]r^{-n}e^{-j\omega n}\\ &=\sum_{n=-\infin}^{+\infin}\big[x[n]r^{-n}\big]e^{-j\omega n}\\ &=\mathscr{F}\{x[n]r^{-n}\} \end{aligned}

所以 x[n]x[n] 的 zT 就是 x[n]rnx[n]r^{-n} 的 DTFT 。

# 零极点图

X(z)X(z) 是有理函数:

X(z)=N(z)D(z)=Mi(sβi)i(sαi)X(z)=\frac{N(z)}{D(z)}=M\frac{\prod_{i}(s-\beta_i)}{\prod_{i}(s-\alpha_i)}

  • 分子多项式的根称为零点,画为圆圈 ⭕️
  • 分母多项式的根称为极点,画为交叉 ❌

X(z)X(z) 的全部零点极点表示在 ss 平面上,就构成了零极点图

零极点图上标出收敛域,可以唯一确定一个 X(z)X(z) ,最多与真实的 X(z)X(z) 相差一个常数因子 𝑀𝑀

# ROC

⚠️不同的信号可能会有完全相同的 z 变换表达式,只是它们的收敛域不同。z 变换的表达式只有连同相应的收敛域,才能和信号建立一一对应的关系。

并非 zz 平面上的任何复数都能使 z 变换 X(z)X(z) 收敛,也不是任何信号的 z 变换都存在。

和拉普拉斯变换一样,使 z 变换收敛的复数 zz 的集合,称为 z 变换 (zT) 的收敛域ROC,Region of Convergence)

x[n]x[n] 可以写为若干部分的线性组合,各个部分分别进行 zT 有各自的收敛域,则 X(z)X(z) 的收敛域是各个收敛域的交集

  • ROC 总是 z 平面上以原点为中心的环形区域
  • ROC 的边界总是与 X(z)X(z) 的分母的根 (极点) 相对应
  • (因为)有理 z 变换在其 ROC 内无任何极点

⭐️按照 ROC 在 zz 平面上的分布可以分为:

  • 右边序列的 ROC 是某个圆的外部,但可能不包括 z=z=\infin

    • x[n]x[n] 左边界 <0\lt0 时,z=|z|=\infin 不在 ROC 内
    • 当且仅当 z=z=\infin 在 ROC 内时,x[n]x[n]n<0n\lt0 时总为 00x[n]x[n]因果序列
  • 左边序列的 ROC 是某个圆的内部,但可能不包括 z=0z=0

    • x[n]x[n] 右边界 >0\gt0 时,z=0|z|=0 不在 ROC 内
    • 当且仅当 z=0z=0 在 ROC 内时,x[n]x[n]n>0n\gt0 时总为 00x[n]x[n]反因果序列
  • 双边序列的 ROC 如果存在,一定是一个环形区域

  • 有限长序列的 ROC 是整个 z 平面

    • x[n]x[n] 左边界 <0\lt0 时,z=|z|=\infin 不在 ROC 内
    • x[n]x[n] 右边界 >0\gt0 时,z=0|z|=0 不在 ROC 内

# 有限长序列

x[n]x[n] 是有限长序列,定义于 [N1,N2][N_1,N_2] ,则有其 z 变换:

X(z)=n=N1N2x[n]znX(z)=\sum_{n=N_1}^{N_2}x[n]z^{-n}

此时既然是有限项求和,当 z 不等于零或无穷大时,和式中的每一项都是有限的,那么显然整个 z 平面上都是收敛的。

如果 N1<0N_1\lt0,那么 x[n]x[n]n<0n<0 一定会有非零值,和式中包括 z 的正幂次项。当 z|z|\to\infin 时,涉及 z 的正幂次的那些项就成为无界的,因此收敛域不包括 z=|z|=\infin

如果 N2>0N_2\gt0,那么 x[n]x[n]n>0n>0 一定会有非零值,和式中包括 z 的负幂次项。当 z0|z|\to0 时,涉及 z 的负幂次的那些项就成为无界的,因此收敛域不包括 z=0|z|=0

# 右边序列

x[n]x[n] 是右边序列,定义于 [N1,+)[N_1,+\infin) ,则有其 z 变换:

X(z)=n=N1+x[n]znX(z)=\sum_{n=N_1}^{+\infin}x[n]z^{-n}

z=r0ROC|z|=r_0\in\text{ROC} ,则有 X(z)X(z) 收敛:

n=N1+x[n]zn=n=N1+x[n]r0n<\sum_{n=N_1}^{+\infin}|x[n]z^{-n}|=\sum_{n=N_1}^{+\infin}|x[n]r_0^{-n}|\lt\infin

对任意 r1>r0r_1\gt r_0 有:

n=N1+x[n]r1n=n=N1+x[n]r0n(r0r1)nn=N1+x[n]r0n(r0r1)N1<\sum_{n=N_1}^{+\infin}|x[n]r_1^{-n}|=\sum_{n=N_1}^{+\infin}|x[n]r_0^{-n}|\cdot(\frac{r_0}{r_1})^n\leq\sum_{n=N_1}^{+\infin}|x[n]r_0^{-n}|\cdot(\frac{r_0}{r_1})^{N_1}\lt\infin

如果 N1<0N_1\lt0,那么 x[n]x[n]n<0n<0 一定会有非零值,和式中包括 z 的正幂次项。当 z|z|\to\infin 时,涉及 z 的正幂次的那些项就成为无界的,因此收敛域不包括 z=|z|=\infin

于是就可得:

  • X(z)X(z) 为有理函数,则 ROC 必位于最外极点之外
  • N1<0N_1\lt0 时,z=|z|=\infin 不在 ROC 内
  • 当且仅当 z=z=\infin 在 ROC 内时,x[n]x[n] 为因果序列

# 左边序列

x[n]x[n] 是左边序列,定义于 (,N1](-\infin,N_1] ,则有其 z 变换:

X(z)=n=N1x[n]znX(z)=\sum_{n=-\infin}^{N_1}x[n]z^{-n}

z=r0ROC|z|=r_0\in\text{ROC} ,则有 X(z)X(z) 收敛:

n=N1x[n]zn=n=N1x[n]r0n<\sum_{n=-\infin}^{N_1}|x[n]z^{-n}|=\sum_{n=-\infin}^{N_1}|x[n]r_0^{-n}|\lt\infin

对任意 r1<r0r_1\lt r_0 有:

n=N1x[n]r1n=n=N1x[n]r0n(r0r1)nn=N1x[n]r0n(r0r1)N1<\sum_{n=-\infin}^{N_1}|x[n]r_1^{-n}|=\sum_{n=-\infin}^{N_1}|x[n]r_0^{-n}|\cdot(\frac{r_0}{r_1})^n\leq\sum_{n=-\infin}^{N_1}|x[n]r_0^{-n}|\cdot(\frac{r_0}{r_1})^{N_1}\lt\infin

如果 N1>0N_1\gt0,那么 x[n]x[n]n>0n>0 一定会有非零值,和式中包括 z 的负幂次项。当 z0|z|\to0 时,涉及 z 的负幂次的那些项就成为无界的,因此收敛域不包括 z=0|z|=0

于是就可得:

  • X(z)X(z) 为有理函数,则 ROC 必位于最内极点之内内
  • N1>0N_1\gt0 时,z=0|z|=0 不在 ROC 内
  • 当且仅当 z=0z=0 在 ROC 内时,x[n]x[n] 为反因果序列

# 双边序列

x[n]x[n] 是双边序列,定义于 (,+)(-\infin,+\infin) ,则有其 z 变换:

X(z)=n=+x[n]znX(z)=\sum_{n=\infin}^{+\infin}x[n]z^{-n}

和有限长序列相反,此时收敛域不包括 z=|z|=\infin 也不包括 z=0|z|=0。此时的收敛域是 z 平面上的环形区域

zN=aNz^N=a^N 的解为:z=aej2πNkz=ae^{j\frac{2\pi}{N}k}。均匀分布在半径为 aa 的圆上

# z 反变换

# 定义

利用 zT 和 DTFT 的关系、DTFT 的反变换可以得到 zT 的反变换。

(zT 和 DTFT 的关系:)

X(z)=n=+x[n]rnejωnX(rejω)=n=+[x[n]rn]ejωn=F{x[n]rn}\begin{aligned} X(z)&=\sum_{n=-\infin}^{+\infin}x[n]r^{-n}e^{-j\omega n}\\ X(re^{j\omega})&=\sum_{n=-\infin}^{+\infin}\big[x[n]r^{-n}\big]e^{-j\omega n}\\ &=\mathscr{F}\{x[n]r^{-n}\} \end{aligned}

进而由 DTFT 的反变换有:

x[n]rn=12π2πX(rejω)ejωndωx[n]=12π2πX(rejω)rnejωndωx[n]=12π2πX(z)zndω\begin{aligned} x[n]r^{-n}&=\frac{1}{2\pi}\int_{2\pi}X(re^{j\omega})e^{j\omega n}d\omega\\ x[n]&=\frac{1}{2\pi}\int_{2\pi}X(re^{j\omega})r^ne^{j\omega n}d\omega\\ x[n]&=\frac{1}{2\pi}\int_{2\pi}X(z)z^{n}d\omega \end{aligned}

z=rejωz=re^{j\omega} 两侧同时微分得到:dz=jrejωdω=jzdωdz=jre^{j\omega}d\omega=jzd\omega ;同时,当 ω\omega02π0\to2\pi 时,zz 沿着 ROC 内半径为 rr 的圆积分一周 ,所以可得到 z 反变换为

x[n]=12πjX(z)zn1dzx[n]=\frac{1}{2\pi j}\oint X(z)z^{n-1}dz

式中 \oint 记为在半径为 rr,以原点为中心的封闭圆上沿逆时针方向环绕 一周的积分。rr 的值可选为使 X(z)X(z) 收敛的任 何值也就是使 z=r|z|=r 的积分围线位于收敛域内的任何值。

# 部分分式展开法

  1. X(z)X(z) 展开为部分分式
  2. 根据 X(z)X(z) 的 ROC ,确定每一项的 ROC
  3. 利用常用信号变换对与拉普拉斯变换性质,对每一项进行反变换

# 幂级数展开法

X(z)X(z) 的定义,将其展开为幂级数,有

X(z)=+x[n]zn++x[2]z2+x[1]z+x[0]+x[1]z1+x[2]z2++x[n]zn+\begin{aligned} X(z)=&\cdots+x[-n]z^n+\cdots+x[-2]z^{2}+x[-1]z\\ &+x[0]+\\ &x[1]z^{-1}+x[2]z^{-2}+\cdots+x[n]z^{-n}+\cdots \end{aligned}

展开式中 znz^{-n} 项的系数即为 x[n]x[n]

泰勒级数展开法适合用来求解非有理函数形式 X(z)X(z) 的反变换。

⭐️当 X(z)X(z) 是有理函数时,可以通过长除的方法将其展开为幂级数:(但可能不易获得闭式表达)

  • 右边序列的展开式中应包含无限个 zz 的负幂项,所以要按降幂长除
  • 左边序列的展开式中应包含无限个 zz 的正幂项,要按升幂长除
  • 双边序列,先要将其分成对应信号的右边和左边的两部分,再分别按上述原则长除。

# zT 的几何求值

其方法与拉普拉斯变换时完全类似

考查动点在单位圆上移动一周时,各极点矢量和零点矢量的长度与幅角变化的情况,即可反映频率特性。

# 一般情况

对有理函数形式的 X(z)X(z)

X(z)=N(z)D(z)=Mi(sβi)i(sαi)X(z)=\frac{N(z)}{D(z)}=M\frac{\prod_i(s-\beta_i)}{\prod_i(s-\alpha_i)}

可得:

X(z)=MisβiisαiX(z)=i(sβi)i(sαi)\begin{aligned} |X(z)|&=|M|\frac{\prod_i|\vec{s}-\vec{\beta_i}|}{\prod_i|\vec{s}-\vec{\alpha_i}|}\\ \angle X(z)&=\sum_i\angle(\vec{s}-\vec{\beta_i})-\sum_i\angle(\vec{s}-\vec{\alpha_i}) \end{aligned}

# 公式表

# 基本变换对

常用 (双边) z 变换对:

常用z变换对

# 二阶系统

二阶系统

# 性质表

双边 z 变换的性质:

z变换性质

单边 z 变换的性质:

单边z变换性质

# 双边 z 变换

# 定义

X(z)=n=+x[n]znX(z)=\sum_{n=-\infin}^{+\infin}x[n]z^{-n}

称为 x[n]x[n] 的 z 变换,后面简记为 zT,其中 z=rejωz=re^{j\omega} 为复数。

r=1r=1z=ejωz=e^{j\omega} 位于单位圆上,则为 DTFT(离散时间傅里叶变换),也就是说 DTFT 是双边 z 变换在 r=1r=1 或者说是在单位圆上的特例,即 X(z)r=1=X(ejω)X(z)|_{r=1}=X(e^{j\omega})

# zT 与 DTFT 的关系

X(z)=X(rejω)=n=+x[n]rnejωn=n=+[x[n]rn]ejωn=F{x[n]rn}\begin{aligned} X(z)=X(re^{j\omega})&=\sum_{n=-\infin}^{+\infin}x[n]r^{-n}e^{-j\omega n}\\ &=\sum_{n=-\infin}^{+\infin}\big[x[n]r^{-n}\big]e^{-j\omega n}\\ &=\mathscr{F}\{x[n]r^{-n}\} \end{aligned}

所以 x[n]x[n] 的 zT 就是 x[n]rnx[n]r^{-n} 的 DTFT 。

# 零极点图

X(z)X(z) 是有理函数:

X(z)=N(z)D(z)=Mi(sβi)i(sαi)X(z)=\frac{N(z)}{D(z)}=M\frac{\prod_{i}(s-\beta_i)}{\prod_{i}(s-\alpha_i)}

  • 分子多项式的根称为零点,画为圆圈 ⭕️
  • 分母多项式的根称为极点,画为交叉 ❌

X(z)X(z) 的全部零点极点表示在 ss 平面上,就构成了零极点图

零极点图上标出收敛域,可以唯一确定一个 X(z)X(z) ,最多与真实的 X(z)X(z) 相差一个常数因子 𝑀𝑀

# ROC

⚠️不同的信号可能会有完全相同的 z 变换表达式,只是它们的收敛域不同。z 变换的表达式只有连同相应的收敛域,才能和信号建立一一对应的关系。

并非 zz 平面上的任何复数都能使 z 变换 X(z)X(z) 收敛,也不是任何信号的 z 变换都存在。

和拉普拉斯变换一样,使 z 变换收敛的复数 zz 的集合,称为 z 变换 (zT) 的收敛域ROC,Region of Convergence)

x[n]x[n] 可以写为若干部分的线性组合,各个部分分别进行 zT 有各自的收敛域,则 X(z)X(z) 的收敛域是各个收敛域的交集

  • ROC 总是 z 平面上以原点为中心的环形区域
  • ROC 的边界总是与 X(z)X(z) 的分母的根 (极点) 相对应
  • (因为)有理 z 变换在其 ROC 内无任何极点

⭐️按照 ROC 在 zz 平面上的分布可以分为:

  • 右边序列的 ROC 是某个圆的外部,但可能不包括 z=z=\infin

    • x[n]x[n] 左边界 <0\lt0 时,z=|z|=\infin 不在 ROC 内
    • 当且仅当 z=z=\infin 在 ROC 内时,x[n]x[n]n<0n\lt0 时总为 00x[n]x[n]因果序列
  • 左边序列的 ROC 是某个圆的内部,但可能不包括 z=0z=0

    • x[n]x[n] 右边界 >0\gt0 时,z=0|z|=0 不在 ROC 内
    • 当且仅当 z=0z=0 在 ROC 内时,x[n]x[n]n>0n\gt0 时总为 00x[n]x[n]反因果序列
  • 双边序列的 ROC 如果存在,一定是一个环形区域

  • 有限长序列的 ROC 是整个 z 平面

    • x[n]x[n] 左边界 <0\lt0 时,z=|z|=\infin 不在 ROC 内
    • x[n]x[n] 右边界 >0\gt0 时,z=0|z|=0 不在 ROC 内

# 有限长序列

x[n]x[n] 是有限长序列,定义于 [N1,N2][N_1,N_2] ,则有其 z 变换:

X(z)=n=N1N2x[n]znX(z)=\sum_{n=N_1}^{N_2}x[n]z^{-n}

此时既然是有限项求和,当 z 不等于零或无穷大时,和式中的每一项都是有限的,那么显然整个 z 平面上都是收敛的。

如果 N1<0N_1\lt0,那么 x[n]x[n]n<0n<0 一定会有非零值,和式中包括 z 的正幂次项。当 z|z|\to\infin 时,涉及 z 的正幂次的那些项就成为无界的,因此收敛域不包括 z=|z|=\infin

如果 N2>0N_2\gt0,那么 x[n]x[n]n>0n>0 一定会有非零值,和式中包括 z 的负幂次项。当 z0|z|\to0 时,涉及 z 的负幂次的那些项就成为无界的,因此收敛域不包括 z=0|z|=0

# 右边序列

x[n]x[n] 是右边序列,定义于 [N1,+)[N_1,+\infin) ,则有其 z 变换:

X(z)=n=N1+x[n]znX(z)=\sum_{n=N_1}^{+\infin}x[n]z^{-n}

z=r0ROC|z|=r_0\in\text{ROC} ,则有 X(z)X(z) 收敛:

n=N1+x[n]zn=n=N1+x[n]r0n<\sum_{n=N_1}^{+\infin}|x[n]z^{-n}|=\sum_{n=N_1}^{+\infin}|x[n]r_0^{-n}|\lt\infin

对任意 r1>r0r_1\gt r_0 有:

n=N1+x[n]r1n=n=N1+x[n]r0n(r0r1)nn=N1+x[n]r0n(r0r1)N1<\sum_{n=N_1}^{+\infin}|x[n]r_1^{-n}|=\sum_{n=N_1}^{+\infin}|x[n]r_0^{-n}|\cdot(\frac{r_0}{r_1})^n\leq\sum_{n=N_1}^{+\infin}|x[n]r_0^{-n}|\cdot(\frac{r_0}{r_1})^{N_1}\lt\infin

如果 N1<0N_1\lt0,那么 x[n]x[n]n<0n<0 一定会有非零值,和式中包括 z 的正幂次项。当 z|z|\to\infin 时,涉及 z 的正幂次的那些项就成为无界的,因此收敛域不包括 z=|z|=\infin

于是就可得:

  • X(z)X(z) 为有理函数,则 ROC 必位于最外极点之外
  • N1<0N_1\lt0 时,z=|z|=\infin 不在 ROC 内
  • 当且仅当 z=z=\infin 在 ROC 内时,x[n]x[n] 为因果序列

# 左边序列

x[n]x[n] 是左边序列,定义于 (,N1](-\infin,N_1] ,则有其 z 变换:

X(z)=n=N1x[n]znX(z)=\sum_{n=-\infin}^{N_1}x[n]z^{-n}

z=r0ROC|z|=r_0\in\text{ROC} ,则有 X(z)X(z) 收敛:

n=N1x[n]zn=n=N1x[n]r0n<\sum_{n=-\infin}^{N_1}|x[n]z^{-n}|=\sum_{n=-\infin}^{N_1}|x[n]r_0^{-n}|\lt\infin

对任意 r1<r0r_1\lt r_0 有:

n=N1x[n]r1n=n=N1x[n]r0n(r0r1)nn=N1x[n]r0n(r0r1)N1<\sum_{n=-\infin}^{N_1}|x[n]r_1^{-n}|=\sum_{n=-\infin}^{N_1}|x[n]r_0^{-n}|\cdot(\frac{r_0}{r_1})^n\leq\sum_{n=-\infin}^{N_1}|x[n]r_0^{-n}|\cdot(\frac{r_0}{r_1})^{N_1}\lt\infin

如果 N1>0N_1\gt0,那么 x[n]x[n]n>0n>0 一定会有非零值,和式中包括 z 的负幂次项。当 z0|z|\to0 时,涉及 z 的负幂次的那些项就成为无界的,因此收敛域不包括 z=0|z|=0

于是就可得:

  • X(z)X(z) 为有理函数,则 ROC 必位于最内极点之内内
  • N1>0N_1\gt0 时,z=0|z|=0 不在 ROC 内
  • 当且仅当 z=0z=0 在 ROC 内时,x[n]x[n] 为反因果序列

# 双边序列

x[n]x[n] 是双边序列,定义于 (,+)(-\infin,+\infin) ,则有其 z 变换:

X(z)=n=+x[n]znX(z)=\sum_{n=\infin}^{+\infin}x[n]z^{-n}

和有限长序列相反,此时收敛域不包括 z=|z|=\infin 也不包括 z=0|z|=0。此时的收敛域是 z 平面上的环形区域

zN=aNz^N=a^N 的解为:z=aej2πNkz=ae^{j\frac{2\pi}{N}k}。均匀分布在半径为 aa 的圆上

# z 反变换

# 定义

利用 zT 和 DTFT 的关系、DTFT 的反变换可以得到 zT 的反变换。

(zT 和 DTFT 的关系:)

X(z)=n=+x[n]rnejωnX(rejω)=n=+[x[n]rn]ejωn=F{x[n]rn}\begin{aligned} X(z)&=\sum_{n=-\infin}^{+\infin}x[n]r^{-n}e^{-j\omega n}\\ X(re^{j\omega})&=\sum_{n=-\infin}^{+\infin}\big[x[n]r^{-n}\big]e^{-j\omega n}\\ &=\mathscr{F}\{x[n]r^{-n}\} \end{aligned}

进而由 DTFT 的反变换有:

x[n]rn=12π2πX(rejω)ejωndωx[n]=12π2πX(rejω)rnejωndωx[n]=12π2πX(z)zndω\begin{aligned} x[n]r^{-n}&=\frac{1}{2\pi}\int_{2\pi}X(re^{j\omega})e^{j\omega n}d\omega\\ x[n]&=\frac{1}{2\pi}\int_{2\pi}X(re^{j\omega})r^ne^{j\omega n}d\omega\\ x[n]&=\frac{1}{2\pi}\int_{2\pi}X(z)z^{n}d\omega \end{aligned}

z=rejωz=re^{j\omega} 两侧同时微分得到:dz=jrejωdω=jzdωdz=jre^{j\omega}d\omega=jzd\omega ;同时,当 ω\omega02π0\to2\pi 时,zz 沿着 ROC 内半径为 rr 的圆积分一周 ,所以可得到 z 反变换为

x[n]=12πjX(z)zn1dzx[n]=\frac{1}{2\pi j}\oint X(z)z^{n-1}dz

式中 \oint 记为在半径为 rr,以原点为中心的封闭圆上沿逆时针方向环绕 一周的积分。rr 的值可选为使 X(z)X(z) 收敛的任 何值也就是使 z=r|z|=r 的积分围线位于收敛域内的任何值。

# 部分分式展开法

  1. X(z)X(z) 展开为部分分式
  2. 根据 X(z)X(z) 的 ROC ,确定每一项的 ROC
  3. 利用常用信号变换对与拉普拉斯变换性质,对每一项进行反变换

# 幂级数展开法

X(z)X(z) 的定义,将其展开为幂级数,有

X(z)=+x[n]zn++x[2]z2+x[1]z+x[0]+x[1]z1+x[2]z2++x[n]zn+\begin{aligned} X(z)=&\cdots+x[-n]z^n+\cdots+x[-2]z^{2}+x[-1]z\\ &+x[0]+\\ &x[1]z^{-1}+x[2]z^{-2}+\cdots+x[n]z^{-n}+\cdots \end{aligned}

展开式中 znz^{-n} 项的系数即为 x[n]x[n]

泰勒级数展开法适合用来求解非有理函数形式 X(z)X(z) 的反变换。

⭐️当 X(z)X(z) 是有理函数时,可以通过长除的方法将其展开为幂级数:(但可能不易获得闭式表达)

  • 右边序列的展开式中应包含无限个 zz 的负幂项,所以要按降幂长除
  • 左边序列的展开式中应包含无限个 zz 的正幂项,要按升幂长除
  • 双边序列,先要将其分成对应信号的右边和左边的两部分,再分别按上述原则长除。

# zT 的几何求值

其方法与拉普拉斯变换时完全类似

考查动点在单位圆上移动一周时,各极点矢量和零点矢量的长度与幅角变化的情况,即可反映频率特性。

# 一般情况

对有理函数形式的 X(z)X(z)

X(z)=N(z)D(z)=Mi(sβi)i(sαi)X(z)=\frac{N(z)}{D(z)}=M\frac{\prod_i(s-\beta_i)}{\prod_i(s-\alpha_i)}

可得:

X(z)=MisβiisαiX(z)=i(sβi)i(sαi)\begin{aligned} |X(z)|&=|M|\frac{\prod_i|\vec{s}-\vec{\beta_i}|}{\prod_i|\vec{s}-\vec{\alpha_i}|}\\ \angle X(z)&=\sum_i\angle(\vec{s}-\vec{\beta_i})-\sum_i\angle(\vec{s}-\vec{\alpha_i}) \end{aligned}

从所有零点向 ss 点作零点矢量,从所有极点向 ss 点作极点矢量:

  • 所有零点矢量的长度之积 (不存在则为 1) 除以所有极点矢量的长度之积即为 X(z)|X(z)|
  • 所有零点矢量的幅角之和 (不存在则为 0) 减去所有极点矢量的幅角之和即为 \ang X(z);

ss 取为单位元上的点时,即为傅里叶变换的几何求值。考查 ss 在单位圆上移动时所有零、极点矢量的长度和幅角的变化,即可得出 X(ejω)X(e^{j\omega}) 的幅频特性和相频特性

⭐️ ROC 包括单位圆,则说明 x[n]x[n] 对应的傅里叶变换存在⚠️

# zT 性质

与 s 变换类似,在讨论 z 变换的许多性质时我们都要考虑其 ROC 的变化。

# 线性

x1[n]zTX1(z),ROC:R1x2[n]zTX2(z),ROC:R2ax1[n]+bx2[n]zTaX1(z)+bX2(z)x_1[n]\stackrel{zT}{\longleftrightarrow}X_1(z),\ \ \text{ROC}:R_1\\ x_2[n]\stackrel{zT}{\longleftrightarrow}X_2(z),\ \ \text{ROC}:R_2\\ \dArr\\ ax_1[n]+bx_2[n]\stackrel{zT}{\longleftrightarrow}aX_1(z)+bX_2(z)

后者的 ROC 至少R1R2R_1\cap R_2 ,否则若 R1R2=R_1\cap R_2=\varnothing ,则 ax1[n]+bx2[n]ax_1[n]+bx_2[n] 的 LT 不存在。

ROC 也有可能扩大:X1(z)X_1(z)X2(z)X_2(z) 线性组合时,若发生了零极点相抵消的现象,且当被抵消的极点恰好在 ROC 的边界上时,就会使 ROC 扩大。

# 时移特性

x[n]zTX(z),ROC:Rx[nn0]zTX(z)zn0x[n]\stackrel{zT}{\longleftrightarrow}X(z),\ \ \text{ROC}:R\\ \dArr\\ x[n-n_0]\stackrel{zT}{\longleftrightarrow}X(z)z^{-n_0}

后者的 ROC 为 RR ,但是在 z=0z=0z=z=∞ 可能会有增删,这是由于 x[n]x[n] 的平移可能改变其在 xx 轴正半轴、负半轴的取值情况,信号时移可能会改变其因果性。

# z 域尺度变换

x[n]zTX[n],ROC:Rx[n]z0nzTX(zz0),ROC:z0Rx[n]\stackrel{zT}{\longleftrightarrow}X[n],\ \ \text{ROC}:R\\ \dArr\\ x[n]z_0^{n}\stackrel{zT}{\longleftrightarrow}X\big(\frac{z}{z_0}\big),\ \ \text{ROC}:|z_0|R

⚠️这里 z0R|z_0|R 的意思是将 RR 的边界缩放为 z0z_0 倍⚠️,也就是整体的模缩放为 z0z_0 倍。实际上 ROC 还会有一个 ω0\omega_0 的角度偏移(z0=z0ejω0z_0=|z_0|e^{j\omega_0}),所以零点和极点位置发生缩放和旋转。

特别地,当 z0=ejω0z_0=e^{j\omega_0} 时,有 z0R=R|z_0|R=R,只有旋转没有缩放。在公式表中这一项被单独列出。

连续时间的时域尺度变换的概念不能直接推广到离散时间中,因为离散时间变量仅仅定义在整数值上。相对应的,z 变换有时域反转、时域扩展这两个性质

# 时域反转

若信号在时域尺度变换,其 LT 的 ROC 在 ss 平面上作相反的尺度变换。

x[n]zTX(z),ROC:Rx[n]zTX(z1),ROC:1Rx[n]\stackrel{zT}{\longleftrightarrow}X(z),\ \ \text{ROC}:R\\ \dArr\\ x[-n]\stackrel{zT}{\longleftrightarrow}X(z^{-1}),\ \ \text{ROC}:\frac{1}{R}

⚠️这里 1R\frac{1}{R} 的意思是 RR 收敛域边界倒置⚠️,零点、极点也将变为倒数。

# 时域扩展

定义在原有序列 x[n]x[n] 的各连续值之间插入 k1k-1 个零值序列:

x(k)[n]={x[nk],nk的整数倍0,n不是k的整数倍x_{(k)}[n]=\begin{cases} x[\frac{n}{k}],&n\text{是}k\text{的整数倍}\\ 0,&n\text{不是}k\text{的整数倍} \end{cases}

于是有:

x[n]zTX(z),ROC:Rx(k)[n]zTX(zk),ROC:R1kx[n]\stackrel{zT}{\longleftrightarrow}X(z),\ \ \text{ROC}:R\\ \dArr\\ x_{(k)}[n]\stackrel{zT}{\longleftrightarrow}X(z^{k}),\ \ \text{ROC}:R^{\frac{1}{k}}

⚠️这里 R1kR^{\frac{1}{k}} 的意思与前面相似...

# 共轭对称性

x[n]zTX(z),ROC:Rx[n]zTX(z),ROC:Rx[n]\stackrel{zT}{\longleftrightarrow}X(z),\ \ \text{ROC}:R\\ \dArr\\ x^*[n]\stackrel{zT}{\longleftrightarrow}X^*(z^*),\ \ \text{ROC}:R

这里可以结合 X(z)=X(z)|X(z)|=|X(z^*)| 理解,模相同意味着二者总是零点极点相同......

特别地,当 x[n]x[n]实信号时,有:

x[n]=x[n]zTX(z)=X(z)=X(z)=X(z)x^*[n]=x[n]\stackrel{zT}{\longleftrightarrow} X^*(z^*)=X(z)=X^*(z)=X(z^*)

这里 X(z)=X(z)X^*(z^*)=X(z) 等价于 X(z)=X(z)X^*(z)=X(z^*)

因此,如果 x[n]x[n] 是实信号,且 X(z)X(z)z0z_0 有极点 (或零点),则 X(z)X(z) 一定在 z0z_0^* 也有极点 (或零点)。即实信号的 z 变换其零、极点必共轭成对出现

# 卷积性质

x1[n]zTX1(z),ROC:R1x2[n]zTX2(z),ROC:R2x1[n]x2[n]zTX1(z)X2(z)x_1[n]\stackrel{zT}{\longleftrightarrow}X_1(z),\ \ \text{ROC}:R_1\\ x_2[n]\stackrel{zT}{\longleftrightarrow}X_2(z),\ \ \text{ROC}:R_2\\ \dArr\\ x_1[n]*x_2[n]\stackrel{zT}{\longleftrightarrow}X_1(z)X_2(z)

类似线性性质中,后者的 ROC 包括 R1R2R_1\cap R_2 ,否则若 R1R2=R_1\cap R_2=\varnothing ,则 x1[n]x2[n]x_1[n]*x_2[n] 的 LT 不存在。

ROC 也有可能扩大:X1(z)X_1(z)X2(z)X_2(z) 相乘时,若发生了零极点相抵消的现象,且当被抵消的极点恰好在 ROC 的边界上时,就会使 ROC 扩大。

# 时域差分

y[n]=x[n]x[n1]=(δ[n]δ[n1])x[n]y[n]=x[n]-x[n-1]=\big(\delta[n]-\delta[n-1]\big)*x[n]

y[n]y[n]x[n]x[n] 的的一次差分。可以认为是离散时间情况下的 “微分”。

x[n]zTX(z),ROC:Rx[n]x[n1]zT(1z1)X(z)x[n]\stackrel{zT}{\longleftrightarrow}X(z),\ \ \text{ROC}:R\\ \dArr\\ x[n]-x[n-1]\stackrel{zT}{\longleftrightarrow}(1-z^{-1})X(z)

后者的 ROC 至少是 RRz>0|z|>0 的相交。

# z 域微分

x[n]zTX(z),ROC:Rnx[n]zTzddzX(z),ROC:Rx[n]\stackrel{zT}{\longleftrightarrow}X(z),\ \ \text{ROC}:R\\ \dArr\\ nx[n]\stackrel{zT}{\longleftrightarrow}-z\frac{d}{dz}X(z),\ \ \text{ROC}:R\\

# 时域累加

w[n]=k=nx[k]=u[n]x[n]w[n]=\sum_{k=-\infin}^{n}x[k]=u[n]*x[n]

w[n]w[n]x[n]x[n] 的的累加 / 求和。可以认为是离散时间情况下的 “积分”。

x[n]zTX(z),ROC:Rk=nx[k]zT11z1X(z)x[n]\stackrel{zT}{\longleftrightarrow}X(z),\ \ \text{ROC}:R\\ \dArr\\ \sum_{k=-\infin}^{n}x[k]\stackrel{zT}{\longleftrightarrow}\frac{1}{1-z^{-1}}X(z)

后者的 ROC 至少是 RRz>1|z|>1 的相交,也就是包括 RR 在单位圆外侧的部分。这是因为:

k=nx[k]=x[n]u[n]\sum_{k=-\infin}^{n}x[k]=x[n]*u[n]

# 初值与终值定理

# 初值定理

如果 x(t)x(t) 是因果信号,也就是 n<0n<0x[n]=0x[n]=0,则有初值定理

x[0]=limzX(z)x[0]=\lim_{z\to\infin}X(z)

或者非因果信号可以用单边 z 变换表示:

x[0]=limzχ(z)x[0]=\lim_{z\to\infin}\chi(z)


证明

X(z)X(z) 按照定义式展开有:

X(z)=x(0)+x(1)z1+x(2)z2++x(n)zn+\begin{aligned} X(z)=x(0)+x(1)z^{-1}+x(2)z^{-2}+\cdots+x(n)z^{-n}+\cdots \end{aligned}

显然就有 x[0]=limzX(z)x[0]=\lim_{z\to\infin}X(z)

# 终值定理

如果 x[n]x[n] 是因果信号,X(z)X(z) 除了在 z=1z=1 可以有单阶极点外,其余极点均在单位圆内

上述条件的目的在于保证终值存在

则有终值定理

limnx[n]=limz1(z1)X(z)\lim_{n\to\infin}x[n]=\lim_{z\to1}(z-1)X(z)


证明

limz1(z1)X(z)=limz1n=1(x[n+1]x[n])zn=limmn=1m(x[n+1]x[n])=limmn=1m(x[0]x[1]+x[1]x[0]++x[m+1]x[m])=limmx[m+1]=limnx[n]\begin{aligned} \lim_{z\to1}(z-1)X(z) &=\lim_{z\to1}\sum_{n=-1}^{\infin}\big(x[n+1]-x[n]\big)z^{-n}\\ &=\lim_{m\to\infin}\sum_{n=-1}^{m}\big(x[n+1]-x[n]\big)\\ &=\lim_{m\to\infin}\sum_{n=-1}^{m}\big(x[0]-x[-1]+x[1]-x[0]+\cdots+x[m+1]-x[m]\big)\\ &=\lim_{m\to\infin}x[m+1]\\ &=\lim_{n\to\infin}x[n] \end{aligned}

# zT 分析 LTI 系统

以卷积特性为基础,可建立 LTI 系统的 z 变换分析方法,即:

Y(z)=X(z)H(z)Y(z)=X(z)\cdot H(z)

设离散时间 LTI 系统的单位脉冲响应为 h[n]h[n],则 h[n]h[n] 的 z 变换 H(z)H(z) 称为系统函数或转移函数,它描述了一个离散时间 LTI 系统并体现其系统特性。其中 H(z)H(z)h[n]h[n] 的 z 变换,称为系统函数转移函数传递函数

# 特征函数

x[n]=ez0tx[n]=e^{z_0t} 时,响应为:

y[n]=H(z0)ez0ty[n]=H(z_0)e^{z_0t}

# 因果性

  • 系统是因果的当且仅当:如果 n<0n<0h[n]=0h[n]=0,则 H(z)H(z) 的 ROC 是最外部极点的外部,并且包括 z=z=\infin
  • 系统是反因果的当且仅当:如果 n>0n>0h[n]=0h[n]=0,则 H(z)H(z) 的 ROC 是最内部极点的内部,并且包括 z=0z=0

对于 H(z)H(z) 表达式已知,判断因果性、反因果性与否可以直接看 limz0H(z)\lim_{z\to0}H(z)limzH(z)\lim_{z\to\infin}H(z) 是否收敛存在。

# 稳定性

LTI 系统若稳定,即 n=h[n]<\sum_{n=-\infin}^{\infin}|h[n]|\lt\infin,也即 h[n]h[n] 的 DTFT 存在,则 H(z)H(z) 的 ROC 必包括单位圆;反之亦然。所以 LTI 系统稳定的充要条件是 ROC 包含单位圆。

对于因果稳定的 LTI 系统,其系统函数 H(z)H(z) 如果存在极点,则全部极点必须位于单位圆内。

# 线性常微分方程

* 线性常系数微分方程

如果由线性常系数微分方程描述的系统满足初始松弛条件,则系统是因果 LTI 的,其 H(z)H(z) 的 ROC 必是最外侧极点的外部。

对于由线性常系数微分方程描述的 LTI 系统:

k=0Naky[nk]=k=0Mbkx[nk]\sum_{k=0}^{N}a_k\cdot y[n-k]=\sum_{k=0}^{M}b_k\cdot x[n-k]

两边进行 z 变换,可得:

k=0NakzkY(z)=k=0MbkzkX(z)Y(z)k=0Nakzk=X(z)k=0Mbkzk\sum_{k=0}^{N}a_k\cdot z^{-k}\cdot Y(z)=\sum_{k=0}^{M}b_k\cdot z^{-k}\cdot X(z)\\ Y(z)\sum_{k=0}^{N}a_k\cdot z^{-k}=X(z)\sum_{k=0}^{M}b_k\cdot z^{-k}

所以:

H(z)=Y(z)X(z)=k=0Mbkzkk=0NakzkH(z)={Y(z)\over X(z)}={\sum_{k=0}^{M}b_{k}z^{-k}\over\sum_{k=0}^{N}a_{k}z^{-k}}

可得到 H(z)H(z) 是一个有理函数。系统的单位冲激响应 h[n]h[n] 可由 H(z)H(z) 反变换获得。

# 因果 LTI 系统的方框图表示

  • 级联
  • 并联
  • 反馈联接

# 直接型表示

# 级联型表示

H(z)H(z) 因式分解,在无重阶极点时可得:

H(z)=k=0Mbkzkk=0Nakzk=b0a0k=1M(1+μkz1)k=1N(1+ηkzk)H(z)={\sum_{k=0}^{M}b_{k}z^{-k}\over\sum_{k=0}^{N}a_{k}z^{-k}} =\frac{b_0}{a_0}{\sum_{k=1}^{M}(1+\mu_k z^{-1})\over\sum_{k=1}^{N}(1+\eta_kz^{-k})}

M=NM=N 为偶数时,可得:

H(z)=b0a0k=1N21+β1kz1+β2kz21+α1kz1+α2kz2=b0a0k=1N2Hk(z)H(z)=\frac{b_0}{a_0}\sum_{k=1}^{\frac{N}{2}}{1+\beta_{1k} z^{-1}+\beta_{2k}z^{-2}\over1+\alpha_{1k}z^{-1}+\alpha_{2k}z^{-2}} =\frac{b_0}{a_0}\sum_{k=1}^{\frac{N}{2}}H_k(z)

其中 Hk(z)H_k(z) 是二阶子系统。系统级联表示为 N2\frac{N}{2} 个二阶子系统的级联如下:

级联表示

# 并联型表示

H(z)H(z) 展开为部分分式,在无重阶极点时可得:

H(z)=b0a0+k=1NAk1+ηkz1H(z)=\frac{b_0}{a_0}+\sum_{k=1}^{N}\frac{A_k}{1+\eta_kz^{-1}}

M=NM=N 为偶数时,可得:

H(z)=b0a0+k=1N2r0k+r1kz11+α1kz1+α2kz2=b0a0+k=1N2Hk(z)H(z)=\frac{b_0}{a_0}+\sum_{k=1}^{\frac{N}{2}}{r_{0k}+r_{1k} z^{-1}\over1+\alpha_{1k}z^{-1}+\alpha_{2k}z^{-2}} =\frac{b_0}{a_0}+\sum_{k=1}^{\frac{N}{2}}H_k'(z)

其中 Hk(z)H_k'(z) 是二阶子系统。系统级联表示为 N2\frac{N}{2} 个二阶子系统的并联如下:

并联表示

# 单边 z 变换

Unilateral z Transform

单边 z 变换是仅考虑大于 1-1 之后部分信号的双边 z 变换,也就是 x[n]u[n]x[n]\cdot u[n] 的双边 z 变换:

χ(z)=n=0+x[n]zn\chi(z)=\sum_{n=0}^{+\infin}x[n]z^{-n}

单边 z 变换的反变换与同 ROC 的双边 z 变换的反变换相同:

x[n]=12πjX(z)zn1dz,n0x[n]=\frac{1}{2\pi j}\oint X(z)z^{n-1}dz,\ \ n\geq0

X(z)X(z)χ(z)\chi(z) 不同,是因为 x[n]x[n]n<0n<0 的部分对 X(z)X(z) 有作用,而对 χ(z)\chi(z) 没有任何作用所致。

由于单边拉普拉斯变换不存在类似双边拉普拉斯变换中与 ROC 相关的多义性,一般不再强调其 ROC ,任何单边 z 变换的 ROC 一定是最外侧极点的外部。

因果信号的双边 z 变换和单边 z 变换完全相同。⭐️从而可以利用双边 LT 的基本变换对。

# 性质

由于单边拉普拉斯变换是特殊的双边拉普拉斯变换,因此其大部分性质与双边拉普拉斯变换相同,主要的不同是时移特性,分为:

  • 时移特性
    • 时延
    • 时间超前

# 时延

x[n]UzTχ(z)x[n1]UzTz1χ(z)+x[1]x[n2]UzTz2χ(z)+x[1]z1+x[2]......x[n]\stackrel{UzT}{\longleftrightarrow}\chi(z)\\ \dArr\\ \begin{aligned} x[n-1]&\stackrel{UzT}{\longleftrightarrow}z^{-1}\chi(z)+x[-1]\\ x[n-2]&\stackrel{UzT}{\longleftrightarrow}z^{-2}\chi(z)+x[-1]z^{-1}+x[-2]\\ &...... \end{aligned}

# 时间超前

x[n]UzTχ(z)x[n+1]UzTz(χ(z)x[0])x[n]\stackrel{UzT}{\longleftrightarrow}\chi(z)\\ \dArr\\ x[n+1]\stackrel{UzT}{\longleftrightarrow}z\big(\chi(z)-x[0]\big)

# 差分方程

利用单边 z 变换和时延性质来解具有非零初始条件的线性常系数差分方程,单边 z 变换在将线性常系数差分方程变换为 z 域代数方程时,可以自动将方程的初始条件引入,因而在解决增量线性系统问题时特别有用。

往往假定系统为因果系统。该条件下得到的结果在进行单边 z 反变换的时候可以确定为右边信号

以二阶为例(最高二阶差分),将初始条件带入后,整理得到如下形式:

Aγ(z)=By[1]+Cy[2]+Dχ(z)γ(z)=BAy[1]+CAy[2]+DAχ(z)\begin{aligned} A\gamma(z)&=By[-1]+Cy[-2]+D\chi(z)\\ \gamma(z)&=\frac{B}{A}y[-1]+\frac{C}{A}y[-2]+\frac{D}{A}\chi(z) \end{aligned}

其中 DAχ(z)\frac{D}{A}\chi(z) 对应的单边 z 反变换为零状态响应BAy[1]+CAy[2]\frac{B}{A}y[-1]+\frac{C}{A}y[-2] 对应的单边 z 反变换为零输入响应

γ(z)=k111z1+\begin{aligned} \gamma(z)=k_1\frac{1}{1-z^{-1}}+\cdots \end{aligned}

其中 k111z1k_1\frac{1}{1-z^{-1}}强迫响应k1k_1 为常数,也就是对应的单边 z 反变换为 k1u[n]k_1u[n] 形式的才是强迫响应;其他都是自然响应

\ No newline at end of file +c-16-25.333-24-45-24-59z"/>)

从所有零点向 ss 点作零点矢量,从所有极点向 ss 点作极点矢量:

  • 所有零点矢量的长度之积 (不存在则为 1) 除以所有极点矢量的长度之积即为 X(z)|X(z)|
  • 所有零点矢量的幅角之和 (不存在则为 0) 减去所有极点矢量的幅角之和即为 \ang X(z);

ss 取为单位元上的点时,即为傅里叶变换的几何求值。考查 ss 在单位圆上移动时所有零、极点矢量的长度和幅角的变化,即可得出 X(ejω)X(e^{j\omega}) 的幅频特性和相频特性

⭐️ ROC 包括单位圆,则说明 x[n]x[n] 对应的傅里叶变换存在⚠️

# zT 性质

与 s 变换类似,在讨论 z 变换的许多性质时我们都要考虑其 ROC 的变化。

# 线性

x1[n]zTX1(z),ROC:R1x2[n]zTX2(z),ROC:R2ax1[n]+bx2[n]zTaX1(z)+bX2(z)x_1[n]\stackrel{zT}{\longleftrightarrow}X_1(z),\ \ \text{ROC}:R_1\\ x_2[n]\stackrel{zT}{\longleftrightarrow}X_2(z),\ \ \text{ROC}:R_2\\ \dArr\\ ax_1[n]+bx_2[n]\stackrel{zT}{\longleftrightarrow}aX_1(z)+bX_2(z)

后者的 ROC 至少R1R2R_1\cap R_2 ,否则若 R1R2=R_1\cap R_2=\varnothing ,则 ax1[n]+bx2[n]ax_1[n]+bx_2[n] 的 LT 不存在。

ROC 也有可能扩大:X1(z)X_1(z)X2(z)X_2(z) 线性组合时,若发生了零极点相抵消的现象,且当被抵消的极点恰好在 ROC 的边界上时,就会使 ROC 扩大。

# 时移特性

x[n]zTX(z),ROC:Rx[nn0]zTX(z)zn0x[n]\stackrel{zT}{\longleftrightarrow}X(z),\ \ \text{ROC}:R\\ \dArr\\ x[n-n_0]\stackrel{zT}{\longleftrightarrow}X(z)z^{-n_0}

后者的 ROC 为 RR ,但是在 z=0z=0z=z=∞ 可能会有增删,这是由于 x[n]x[n] 的平移可能改变其在 xx 轴正半轴、负半轴的取值情况,信号时移可能会改变其因果性。

# z 域尺度变换

x[n]zTX[n],ROC:Rx[n]z0nzTX(zz0),ROC:z0Rx[n]\stackrel{zT}{\longleftrightarrow}X[n],\ \ \text{ROC}:R\\ \dArr\\ x[n]z_0^{n}\stackrel{zT}{\longleftrightarrow}X\big(\frac{z}{z_0}\big),\ \ \text{ROC}:|z_0|R

⚠️这里 z0R|z_0|R 的意思是将 RR 的边界缩放为 z0z_0 倍⚠️,也就是整体的模缩放为 z0z_0 倍。实际上 ROC 还会有一个 ω0\omega_0 的角度偏移(z0=z0ejω0z_0=|z_0|e^{j\omega_0}),所以零点和极点位置发生缩放和旋转。

特别地,当 z0=ejω0z_0=e^{j\omega_0} 时,有 z0R=R|z_0|R=R,只有旋转没有缩放。在公式表中这一项被单独列出。

连续时间的时域尺度变换的概念不能直接推广到离散时间中,因为离散时间变量仅仅定义在整数值上。相对应的,z 变换有时域反转、时域扩展这两个性质

# 时域反转

若信号在时域尺度变换,其 LT 的 ROC 在 ss 平面上作相反的尺度变换。

x[n]zTX(z),ROC:Rx[n]zTX(z1),ROC:1Rx[n]\stackrel{zT}{\longleftrightarrow}X(z),\ \ \text{ROC}:R\\ \dArr\\ x[-n]\stackrel{zT}{\longleftrightarrow}X(z^{-1}),\ \ \text{ROC}:\frac{1}{R}

⚠️这里 1R\frac{1}{R} 的意思是 RR 收敛域边界倒置⚠️,零点、极点也将变为倒数。

# 时域扩展

定义在原有序列 x[n]x[n] 的各连续值之间插入 k1k-1 个零值序列:

x(k)[n]={x[nk],nk的整数倍0,n不是k的整数倍x_{(k)}[n]=\begin{cases} x[\frac{n}{k}],&n\text{是}k\text{的整数倍}\\ 0,&n\text{不是}k\text{的整数倍} \end{cases}

于是有:

x[n]zTX(z),ROC:Rx(k)[n]zTX(zk),ROC:R1kx[n]\stackrel{zT}{\longleftrightarrow}X(z),\ \ \text{ROC}:R\\ \dArr\\ x_{(k)}[n]\stackrel{zT}{\longleftrightarrow}X(z^{k}),\ \ \text{ROC}:R^{\frac{1}{k}}

⚠️这里 R1kR^{\frac{1}{k}} 的意思与前面相似...

# 共轭对称性

x[n]zTX(z),ROC:Rx[n]zTX(z),ROC:Rx[n]\stackrel{zT}{\longleftrightarrow}X(z),\ \ \text{ROC}:R\\ \dArr\\ x^*[n]\stackrel{zT}{\longleftrightarrow}X^*(z^*),\ \ \text{ROC}:R

这里可以结合 X(z)=X(z)|X(z)|=|X(z^*)| 理解,模相同意味着二者总是零点极点相同......

特别地,当 x[n]x[n]实信号时,有:

x[n]=x[n]zTX(z)=X(z)=X(z)=X(z)x^*[n]=x[n]\stackrel{zT}{\longleftrightarrow} X^*(z^*)=X(z)=X^*(z)=X(z^*)

这里 X(z)=X(z)X^*(z^*)=X(z) 等价于 X(z)=X(z)X^*(z)=X(z^*)

因此,如果 x[n]x[n] 是实信号,且 X(z)X(z)z0z_0 有极点 (或零点),则 X(z)X(z) 一定在 z0z_0^* 也有极点 (或零点)。即实信号的 z 变换其零、极点必共轭成对出现

# 卷积性质

x1[n]zTX1(z),ROC:R1x2[n]zTX2(z),ROC:R2x1[n]x2[n]zTX1(z)X2(z)x_1[n]\stackrel{zT}{\longleftrightarrow}X_1(z),\ \ \text{ROC}:R_1\\ x_2[n]\stackrel{zT}{\longleftrightarrow}X_2(z),\ \ \text{ROC}:R_2\\ \dArr\\ x_1[n]*x_2[n]\stackrel{zT}{\longleftrightarrow}X_1(z)X_2(z)

类似线性性质中,后者的 ROC 包括 R1R2R_1\cap R_2 ,否则若 R1R2=R_1\cap R_2=\varnothing ,则 x1[n]x2[n]x_1[n]*x_2[n] 的 LT 不存在。

ROC 也有可能扩大:X1(z)X_1(z)X2(z)X_2(z) 相乘时,若发生了零极点相抵消的现象,且当被抵消的极点恰好在 ROC 的边界上时,就会使 ROC 扩大。

# 时域差分

y[n]=x[n]x[n1]=(δ[n]δ[n1])x[n]y[n]=x[n]-x[n-1]=\big(\delta[n]-\delta[n-1]\big)*x[n]

y[n]y[n]x[n]x[n] 的的一次差分。可以认为是离散时间情况下的 “微分”。

x[n]zTX(z),ROC:Rx[n]x[n1]zT(1z1)X(z)x[n]\stackrel{zT}{\longleftrightarrow}X(z),\ \ \text{ROC}:R\\ \dArr\\ x[n]-x[n-1]\stackrel{zT}{\longleftrightarrow}(1-z^{-1})X(z)

后者的 ROC 至少是 RRz>0|z|>0 的相交。

# z 域微分

x[n]zTX(z),ROC:Rnx[n]zTzddzX(z),ROC:Rx[n]\stackrel{zT}{\longleftrightarrow}X(z),\ \ \text{ROC}:R\\ \dArr\\ nx[n]\stackrel{zT}{\longleftrightarrow}-z\frac{d}{dz}X(z),\ \ \text{ROC}:R\\

# 时域累加

w[n]=k=nx[k]=u[n]x[n]w[n]=\sum_{k=-\infin}^{n}x[k]=u[n]*x[n]

w[n]w[n]x[n]x[n] 的的累加 / 求和。可以认为是离散时间情况下的 “积分”。

x[n]zTX(z),ROC:Rk=nx[k]zT11z1X(z)x[n]\stackrel{zT}{\longleftrightarrow}X(z),\ \ \text{ROC}:R\\ \dArr\\ \sum_{k=-\infin}^{n}x[k]\stackrel{zT}{\longleftrightarrow}\frac{1}{1-z^{-1}}X(z)

后者的 ROC 至少是 RRz>1|z|>1 的相交,也就是包括 RR 在单位圆外侧的部分。这是因为:

k=nx[k]=x[n]u[n]\sum_{k=-\infin}^{n}x[k]=x[n]*u[n]

# 初值与终值定理

# 初值定理

如果 x(t)x(t) 是因果信号,也就是 n<0n<0x[n]=0x[n]=0,则有初值定理

x[0]=limzX(z)x[0]=\lim_{z\to\infin}X(z)

或者非因果信号可以用单边 z 变换表示:

x[0]=limzχ(z)x[0]=\lim_{z\to\infin}\chi(z)


证明

X(z)X(z) 按照定义式展开有:

X(z)=x(0)+x(1)z1+x(2)z2++x(n)zn+\begin{aligned} X(z)=x(0)+x(1)z^{-1}+x(2)z^{-2}+\cdots+x(n)z^{-n}+\cdots \end{aligned}

显然就有 x[0]=limzX(z)x[0]=\lim_{z\to\infin}X(z)

# 终值定理

如果 x[n]x[n] 是因果信号,X(z)X(z) 除了在 z=1z=1 可以有单阶极点外,其余极点均在单位圆内

上述条件的目的在于保证终值存在

则有终值定理

limnx[n]=limz1(z1)X(z)\lim_{n\to\infin}x[n]=\lim_{z\to1}(z-1)X(z)


证明

limz1(z1)X(z)=limz1n=1(x[n+1]x[n])zn=limmn=1m(x[n+1]x[n])=limmn=1m(x[0]x[1]+x[1]x[0]++x[m+1]x[m])=limmx[m+1]=limnx[n]\begin{aligned} \lim_{z\to1}(z-1)X(z) &=\lim_{z\to1}\sum_{n=-1}^{\infin}\big(x[n+1]-x[n]\big)z^{-n}\\ &=\lim_{m\to\infin}\sum_{n=-1}^{m}\big(x[n+1]-x[n]\big)\\ &=\lim_{m\to\infin}\sum_{n=-1}^{m}\big(x[0]-x[-1]+x[1]-x[0]+\cdots+x[m+1]-x[m]\big)\\ &=\lim_{m\to\infin}x[m+1]\\ &=\lim_{n\to\infin}x[n] \end{aligned}

# zT 分析 LTI 系统

以卷积特性为基础,可建立 LTI 系统的 z 变换分析方法,即:

Y(z)=X(z)H(z)Y(z)=X(z)\cdot H(z)

设离散时间 LTI 系统的单位脉冲响应为 h[n]h[n],则 h[n]h[n] 的 z 变换 H(z)H(z) 称为系统函数或转移函数,它描述了一个离散时间 LTI 系统并体现其系统特性。其中 H(z)H(z)h[n]h[n] 的 z 变换,称为系统函数转移函数传递函数

# 特征函数

x[n]=ez0tx[n]=e^{z_0t} 时,响应为:

y[n]=H(z0)ez0ty[n]=H(z_0)e^{z_0t}

# 因果性

  • 系统是因果的当且仅当:如果 n<0n<0h[n]=0h[n]=0,则 H(z)H(z) 的 ROC 是最外部极点的外部,并且包括 z=z=\infin
  • 系统是反因果的当且仅当:如果 n>0n>0h[n]=0h[n]=0,则 H(z)H(z) 的 ROC 是最内部极点的内部,并且包括 z=0z=0

对于 H(z)H(z) 表达式已知,判断因果性、反因果性与否可以直接看 limz0H(z)\lim_{z\to0}H(z)limzH(z)\lim_{z\to\infin}H(z) 是否收敛存在。

# 稳定性

LTI 系统若稳定,即 n=h[n]<\sum_{n=-\infin}^{\infin}|h[n]|\lt\infin,也即 h[n]h[n] 的 DTFT 存在,则 H(z)H(z) 的 ROC 必包括单位圆;反之亦然。所以 LTI 系统稳定的充要条件是 ROC 包含单位圆。

对于因果稳定的 LTI 系统,其系统函数 H(z)H(z) 如果存在极点,则全部极点必须位于单位圆内。

# 线性常微分方程

* 线性常系数微分方程

如果由线性常系数微分方程描述的系统满足初始松弛条件,则系统是因果 LTI 的,其 H(z)H(z) 的 ROC 必是最外侧极点的外部。

对于由线性常系数微分方程描述的 LTI 系统:

k=0Naky[nk]=k=0Mbkx[nk]\sum_{k=0}^{N}a_k\cdot y[n-k]=\sum_{k=0}^{M}b_k\cdot x[n-k]

两边进行 z 变换,可得:

k=0NakzkY(z)=k=0MbkzkX(z)Y(z)k=0Nakzk=X(z)k=0Mbkzk\sum_{k=0}^{N}a_k\cdot z^{-k}\cdot Y(z)=\sum_{k=0}^{M}b_k\cdot z^{-k}\cdot X(z)\\ Y(z)\sum_{k=0}^{N}a_k\cdot z^{-k}=X(z)\sum_{k=0}^{M}b_k\cdot z^{-k}

所以:

H(z)=Y(z)X(z)=k=0Mbkzkk=0NakzkH(z)={Y(z)\over X(z)}={\sum_{k=0}^{M}b_{k}z^{-k}\over\sum_{k=0}^{N}a_{k}z^{-k}}

可得到 H(z)H(z) 是一个有理函数。系统的单位冲激响应 h[n]h[n] 可由 H(z)H(z) 反变换获得。

# 因果 LTI 系统的方框图表示

  • 级联
  • 并联
  • 反馈联接

# 直接型表示

# 级联型表示

H(z)H(z) 因式分解,在无重阶极点时可得:

H(z)=k=0Mbkzkk=0Nakzk=b0a0k=1M(1+μkz1)k=1N(1+ηkzk)H(z)={\sum_{k=0}^{M}b_{k}z^{-k}\over\sum_{k=0}^{N}a_{k}z^{-k}} =\frac{b_0}{a_0}{\sum_{k=1}^{M}(1+\mu_k z^{-1})\over\sum_{k=1}^{N}(1+\eta_kz^{-k})}

M=NM=N 为偶数时,可得:

H(z)=b0a0k=1N21+β1kz1+β2kz21+α1kz1+α2kz2=b0a0k=1N2Hk(z)H(z)=\frac{b_0}{a_0}\sum_{k=1}^{\frac{N}{2}}{1+\beta_{1k} z^{-1}+\beta_{2k}z^{-2}\over1+\alpha_{1k}z^{-1}+\alpha_{2k}z^{-2}} =\frac{b_0}{a_0}\sum_{k=1}^{\frac{N}{2}}H_k(z)

其中 Hk(z)H_k(z) 是二阶子系统。系统级联表示为 N2\frac{N}{2} 个二阶子系统的级联如下:

级联表示

# 并联型表示

H(z)H(z) 展开为部分分式,在无重阶极点时可得:

H(z)=b0a0+k=1NAk1+ηkz1H(z)=\frac{b_0}{a_0}+\sum_{k=1}^{N}\frac{A_k}{1+\eta_kz^{-1}}

M=NM=N 为偶数时,可得:

H(z)=b0a0+k=1N2r0k+r1kz11+α1kz1+α2kz2=b0a0+k=1N2Hk(z)H(z)=\frac{b_0}{a_0}+\sum_{k=1}^{\frac{N}{2}}{r_{0k}+r_{1k} z^{-1}\over1+\alpha_{1k}z^{-1}+\alpha_{2k}z^{-2}} =\frac{b_0}{a_0}+\sum_{k=1}^{\frac{N}{2}}H_k'(z)

其中 Hk(z)H_k'(z) 是二阶子系统。系统级联表示为 N2\frac{N}{2} 个二阶子系统的并联如下:

并联表示

# 单边 z 变换

Unilateral z Transform

单边 z 变换是仅考虑大于 1-1 之后部分信号的双边 z 变换,也就是 x[n]u[n]x[n]\cdot u[n] 的双边 z 变换:

χ(z)=n=0+x[n]zn\chi(z)=\sum_{n=0}^{+\infin}x[n]z^{-n}

单边 z 变换的反变换与同 ROC 的双边 z 变换的反变换相同:

x[n]=12πjX(z)zn1dz,n0x[n]=\frac{1}{2\pi j}\oint X(z)z^{n-1}dz,\ \ n\geq0

X(z)X(z)χ(z)\chi(z) 不同,是因为 x[n]x[n]n<0n<0 的部分对 X(z)X(z) 有作用,而对 χ(z)\chi(z) 没有任何作用所致。

由于单边拉普拉斯变换不存在类似双边拉普拉斯变换中与 ROC 相关的多义性,一般不再强调其 ROC ,任何单边 z 变换的 ROC 一定是最外侧极点的外部。

因果信号的双边 z 变换和单边 z 变换完全相同。⭐️从而可以利用双边 LT 的基本变换对。

# 性质

由于单边拉普拉斯变换是特殊的双边拉普拉斯变换,因此其大部分性质与双边拉普拉斯变换相同,主要的不同是时移特性,分为:

  • 时移特性
    • 时延
    • 时间超前

# 时延

x[n]UzTχ(z)x[n1]UzTz1χ(z)+x[1]x[n2]UzTz2χ(z)+x[1]z1+x[2]......x[n]\stackrel{UzT}{\longleftrightarrow}\chi(z)\\ \dArr\\ \begin{aligned} x[n-1]&\stackrel{UzT}{\longleftrightarrow}z^{-1}\chi(z)+x[-1]\\ x[n-2]&\stackrel{UzT}{\longleftrightarrow}z^{-2}\chi(z)+x[-1]z^{-1}+x[-2]\\ &...... \end{aligned}

# 时间超前

x[n]UzTχ(z)x[n+1]UzTz(χ(z)x[0])x[n]\stackrel{UzT}{\longleftrightarrow}\chi(z)\\ \dArr\\ x[n+1]\stackrel{UzT}{\longleftrightarrow}z\big(\chi(z)-x[0]\big)

# 差分方程

利用单边 z 变换和时延性质来解具有非零初始条件的线性常系数差分方程,单边 z 变换在将线性常系数差分方程变换为 z 域代数方程时,可以自动将方程的初始条件引入,因而在解决增量线性系统问题时特别有用。

往往假定系统为因果系统。该条件下得到的结果在进行单边 z 反变换的时候可以确定为右边信号

以二阶为例(最高二阶差分),将初始条件带入后,整理得到如下形式:

Aγ(z)=By[1]+Cy[2]+Dχ(z)γ(z)=BAy[1]+CAy[2]+DAχ(z)\begin{aligned} A\gamma(z)&=By[-1]+Cy[-2]+D\chi(z)\\ \gamma(z)&=\frac{B}{A}y[-1]+\frac{C}{A}y[-2]+\frac{D}{A}\chi(z) \end{aligned}

其中 DAχ(z)\frac{D}{A}\chi(z) 对应的单边 z 反变换为零状态响应BAy[1]+CAy[2]\frac{B}{A}y[-1]+\frac{C}{A}y[-2] 对应的单边 z 反变换为零输入响应

γ(z)=k111z1+\begin{aligned} \gamma(z)=k_1\frac{1}{1-z^{-1}}+\cdots \end{aligned}

其中 k111z1k_1\frac{1}{1-z^{-1}}强迫响应k1k_1 为常数,也就是对应的单边 z 反变换为 k1u[n]k_1u[n] 形式的才是强迫响应;其他都是自然响应

\ No newline at end of file diff --git a/index.html b/index.html index c573a92c..08c8dce1 100644 --- a/index.html +++ b/index.html @@ -1 +1 @@ -Balloon Party = 風船のパーティー = fuusen no party

Categories

Post List

2.4k words 2 mins.

# 更改主机名 更改主机名的操作和 Debian 基本一致,但是 PVE 中会产生新的问题: 配置文件需要手动迁移 如果该节点已加入了集群,集群同步会出问题: 集群配置文件需要手动更新 节点之间 ssh 通信问题 Cepth 我在这次还没有配置 Cepth,所以情况未知 和 Debian 一样的操作: bash#!/bin/bash# 获取旧主机名字old_hostname=$(hostname)# 输入新主机名echo "请输入新的主机名:"read new_hostnamesudo sed -i...
1.1k words 1 mins.

考完期末考这天修了一晚上 PVE 上的虚拟机启动不了的问题。起因是更换了系统盘,将原来的机械硬盘换成了一个 SSD,重装了 PVE,发现虚拟机无法开机。这期间查询了大量论坛,尝试了各种各样的方法,最后终于以非常简单的方式解决,决定写一写记录一下,避免以后再遇到,因为这个问题单纯看 PVE 的报错竟然是完全和问题原因不沾边的! 更换系统盘前,将虚拟机 vm1 迁移到了另一个节点上,更换系统盘重装系统后,将 vm1 迁移回了这台物理机上,启动虚拟机,得到了如下报错: shellTASK ERROR: KVM virtualisation configured, but not...
5.9k words 5 mins.

如果能把图 GGG 画在平面上,使得除顶点外,边与边之间没有交叉,称 GGG 可嵌入平面,或称 GGG 是可平面图。 可平面图 GGG 的边不交叉的一种画法,称为 GGG 的一种平面嵌入, GGG 的平面嵌入表示的图称为平面图。 可平面图概念和平面图概念有时可以等同看待; 图的平面性问题主要涉及如下几个方面: 平面图的性质 平面图的判定 平面嵌入方法 (平面性算法) 涉及图的平面性问题的拓扑不变量 # 平面图的性质 一个平面图 GGG 把平面分成若干连通片,这些连通片称为 GGG 的区域,或 GGG 的一个面。GGG 的面组成的集合用 Φ\PhiΦ...
3.7k words 3 mins.

磁盘的 block 和文件系统的 block 不是一回事: 磁盘的 block :往往是固定的 512 B; 文件系统的 block 是基本单位,可以自定义,不一定和磁盘的 block 大小相等。 文件系统分配空间的基本单位往往是页面大小 4 KB , 文件系统结构:(自上而下分层) application programs,应用程序 logical file system,逻辑文件系统 file-organization module,文件组织模块 basic file system,基本文件系统 I/O control,I/O...
1.6k words 1 mins.

# 逻辑电平规范与抗噪 # 逻辑电平规范 ⭐️保证输出的电平作为下一级输入是有效的 # CMOS # TTL # 噪声容限 ⭐️保证输出的电平作为下一级输入是有效的基础上,输出与输入的界限相差即为噪声容限 电路抗噪度的一个衡量标准叫做噪声容限 (noisemargin),用伏特表示。对于一个给定的逻辑电路,有两个噪声容限值: 噪声容限高电平 (VNHV_{NH}VNH​) (Noisemargin High) 噪声容限低电平 (VNLV_{NL}VNL​) (Noisemargin...
6.1k words 6 mins.

# 边着色问题 图的边着色,本质上是对应实际问题中的 “划分” 问题或 “分类” 问题。 对 GGG 的边进行着色,若相邻边着不同颜色,则称对 GGG 进行正常边着色; 在对 GGG 正常边着色时,着相同颜色的边集称为该正常边着色的一个色组; 如果能用 kkk 种颜色对图 GGG 进行正常边着色,称 GGG 是 kkk 边可着色的; 对 GGG 进行正常边着色需要的最少颜色数称为 GGG...
2.6k words 2 mins.

I/O 的访问、管理分为两种类型:(或者说按照编址类型划分) I/O 指令(独立编址) 通过 I/O 端口号访问设备管理器 涉及模态转换、状态更迭时才采用 内存映射 I/O (统一编址) 设备的寄存器或存储被映射到内存物理地址空间中; 通过内存 load/store 指令完成 I/O 操作; MMU 设置映射,硬件跳线或程序在启动时设置地址; 实际上绝大多数采用的方式 I/O 控制: 轮询,或者程序直接控制 通过忙等待(轮询)检查 I/O 控制器状态 完全交给 CPU 中断 等待中断来得到 I/O 控制器状态信息 中断到来前 CPU 可以干其他事(CPU、I/O...
1.4k words 1 mins.

# 基础元件 # 555 Timer 可能会考哦 mono-stable one-shot (单稳态触发器) 非稳态延续时间: tw=1.1R1C1t_w=1.1R_1C_1 tw​=1.1R1​C1​ astable multi-vibration oscillator...
304 words 1 mins.

# 串行输入 / 串行输出 # 串行输入 / 并行输出 # 并行输入 / 串行输出 # 并行输入 / 并行输出 最简单 # 双向移位寄存器 # 74HC194 通用 4 位双向移位寄存器 # 移位寄存器计数器 # 约翰逊计数器 一般来说,约翰逊计 数器将会产生模 2n2n2n ,其中 nnn 是计数器中级的个数 # 环形计数器 # 移位寄存器应用 # 精确延时控制 串行输入 / 串行输出移位寄存器可以用来提供从输入到输出的时间延迟,此时间延迟是寄存器中数 nnn...
\ No newline at end of file +Balloon Party = 風船のパーティー = fuusen no party

Categories

Post List

2.4k words 2 mins.

# 更改主机名 更改主机名的操作和 Debian 基本一致,但是 PVE 中会产生新的问题: 配置文件需要手动迁移 如果该节点已加入了集群,集群同步会出问题: 集群配置文件需要手动更新 节点之间 ssh 通信问题 Cepth 我在这次还没有配置 Cepth,所以情况未知 和 Debian 一样的操作: bash#!/bin/bash# 获取旧主机名字old_hostname=$(hostname)# 输入新主机名echo "请输入新的主机名:"read new_hostnamesudo sed -i...
1.1k words 1 mins.

考完期末考这天修了一晚上 PVE 上的虚拟机启动不了的问题。起因是更换了系统盘,将原来的机械硬盘换成了一个 SSD,重装了 PVE,发现虚拟机无法开机。这期间查询了大量论坛,尝试了各种各样的方法,最后终于以非常简单的方式解决,决定写一写记录一下,避免以后再遇到,因为这个问题单纯看 PVE 的报错竟然是完全和问题原因不沾边的! 更换系统盘前,将虚拟机 vm1 迁移到了另一个节点上,更换系统盘重装系统后,将 vm1 迁移回了这台物理机上,启动虚拟机,得到了如下报错: shellTASK ERROR: KVM virtualisation configured, but not...
5.9k words 5 mins.

如果能把图 GGG 画在平面上,使得除顶点外,边与边之间没有交叉,称 GGG 可嵌入平面,或称 GGG 是可平面图。 可平面图 GGG 的边不交叉的一种画法,称为 GGG 的一种平面嵌入, GGG 的平面嵌入表示的图称为平面图。 可平面图概念和平面图概念有时可以等同看待; 图的平面性问题主要涉及如下几个方面: 平面图的性质 平面图的判定 平面嵌入方法 (平面性算法) 涉及图的平面性问题的拓扑不变量 # 平面图的性质 一个平面图 GGG 把平面分成若干连通片,这些连通片称为 GGG 的区域,或 GGG 的一个面。GGG 的面组成的集合用 Φ\PhiΦ...
3.7k words 3 mins.

磁盘的 block 和文件系统的 block 不是一回事: 磁盘的 block :往往是固定的 512 B; 文件系统的 block 是基本单位,可以自定义,不一定和磁盘的 block 大小相等。 文件系统分配空间的基本单位往往是页面大小 4 KB , 文件系统结构:(自上而下分层) application programs,应用程序 logical file system,逻辑文件系统 file-organization module,文件组织模块 basic file system,基本文件系统 I/O control,I/O...
1.6k words 1 mins.

# 逻辑电平规范与抗噪 # 逻辑电平规范 ⭐️保证输出的电平作为下一级输入是有效的 # CMOS # TTL # 噪声容限 ⭐️保证输出的电平作为下一级输入是有效的基础上,输出与输入的界限相差即为噪声容限 电路抗噪度的一个衡量标准叫做噪声容限 (noisemargin),用伏特表示。对于一个给定的逻辑电路,有两个噪声容限值: 噪声容限高电平 (VNHV_{NH}VNH​) (Noisemargin High) 噪声容限低电平 (VNLV_{NL}VNL​) (Noisemargin...
6.1k words 6 mins.

# 边着色问题 图的边着色,本质上是对应实际问题中的 “划分” 问题或 “分类” 问题。 对 GGG 的边进行着色,若相邻边着不同颜色,则称对 GGG 进行正常边着色; 在对 GGG 正常边着色时,着相同颜色的边集称为该正常边着色的一个色组; 如果能用 kkk 种颜色对图 GGG 进行正常边着色,称 GGG 是 kkk 边可着色的; 对 GGG 进行正常边着色需要的最少颜色数称为 GGG...
2.6k words 2 mins.

I/O 的访问、管理分为两种类型:(或者说按照编址类型划分) I/O 指令(独立编址) 通过 I/O 端口号访问设备管理器 涉及模态转换、状态更迭时才采用 内存映射 I/O (统一编址) 设备的寄存器或存储被映射到内存物理地址空间中; 通过内存 load/store 指令完成 I/O 操作; MMU 设置映射,硬件跳线或程序在启动时设置地址; 实际上绝大多数采用的方式 I/O 控制: 轮询,或者程序直接控制 通过忙等待(轮询)检查 I/O 控制器状态 完全交给 CPU 中断 等待中断来得到 I/O 控制器状态信息 中断到来前 CPU 可以干其他事(CPU、I/O...
304 words 1 mins.

# 串行输入 / 串行输出 # 串行输入 / 并行输出 # 并行输入 / 串行输出 # 并行输入 / 并行输出 最简单 # 双向移位寄存器 # 74HC194 通用 4 位双向移位寄存器 # 移位寄存器计数器 # 约翰逊计数器 一般来说,约翰逊计 数器将会产生模 2n2n2n ,其中 nnn 是计数器中级的个数 # 环形计数器 # 移位寄存器应用 # 精确延时控制 串行输入 / 串行输出移位寄存器可以用来提供从输入到输出的时间延迟,此时间延迟是寄存器中数 nnn...
1.4k words 1 mins.

# 基础元件 # 555 Timer 可能会考哦 mono-stable one-shot (单稳态触发器) 非稳态延续时间: tw=1.1R1C1t_w=1.1R_1C_1 tw​=1.1R1​C1​ astable multi-vibration oscillator...
\ No newline at end of file diff --git a/js/app.js b/js/app.js index 24c3db5f..d86a7780 100644 --- a/js/app.js +++ b/js/app.js @@ -1,4 +1,4 @@ -// build time:Wed Aug 14 2024 22:47:36 GMT+0800 (中国标准时间) +// build time:Wed Aug 14 2024 23:17:28 GMT+0800 (中国标准时间) var e={version:"0.2.5",hostname:"https://fuuzen.github.io",root:"/",statics:"/",favicon:{normal:"images/favicon.ico",hidden:"images/failure.ico"},darkmode:false,auto_scroll:true,js:{valine:"gh/amehime/MiniValine@4.2.2-beta10/dist/MiniValine.min.js",chart:"npm/frappe-charts@1.5.0/dist/frappe-charts.min.iife.min.js",copy_tex:"npm/katex@0.12.0/dist/contrib/copy-tex.min.js",fancybox:"combine/npm/jquery@3.5.1/dist/jquery.min.js,npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js,npm/justifiedGallery@3.8.1/dist/js/jquery.justifiedGallery.min.js"},css:{valine:"css/comment.css",katex:"npm/katex@0.12.0/dist/katex.min.css",mermaid:"css/mermaid.css",fancybox:"combine/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css,npm/justifiedGallery@3.8.1/dist/css/justifiedGallery.min.css"},loader:{start:true,"switch":false},search:{appID:"Z7A3XW4R2I",apiKey:"12db1ad54372045549ef465881c17e743",indexName:"my-hexo-blog",hits:{per_page:10}},valine:{appId:"ZjtofcGYicZjb65Bkc4DBrMK-MdYXbMMI",appKey:"XdEJOK09W9oW6x0aehYIatY3",placeholder:"ヽ(○´∀`)ノ♪",avatar:"mp",pageSize:10,lang:"en",visitor:true,NoRecordIP:false,serverURLs:null,powerMode:true,tagMeta:{visitor:"新朋友",master:"主人",friend:"小伙伴",investor:"金主粑粑"},tagColor:{master:"var(--color-orange)",friend:"var(--color-aqua)",investor:"var(--color-pink)"},tagMember:{master:null,friend:null,investor:null}},quicklink:{timeout:3e3,priority:true},audio:[{title:"🌈二次元",list:["https://music.163.com/#/playlist?id=9222813860"]}],fireworks:["rgba(255,182,185,.9)","rgba(250,227,217,.9)","rgba(187,222,214,.9)","rgba(138,198,209,.9)"]};const t=function(e,t){return Math.floor(Math.random()*(t-e+1))+e};const a=function(){return u("main > .inner").offsetHeight};const n=function(e,t,a){if(a){t()}else{var n=document.createElement("script");n.onload=n.onreadystatechange=function(e,a){if(a||!n.readyState||/loaded|complete/.test(n.readyState)){n.onload=n.onreadystatechange=null;n=undefined;if(!a&&t)setTimeout(t,0)}};n.src=e;document.head.appendChild(n)}};const i=function(t,a){var n=e[t][a];if(n.indexOf("npm")>-1||n.indexOf("gh")>-1||n.indexOf("combine")>-1)return"//fastly.jsdelivr.net/"+n;if(n.indexOf("http")>-1)return n;return m+n};const r=function(e,t,a){if(LOCAL[e]){n(i("js",e),t||function(){window[e]=true},a||window[e])}};const s=function(e,t){if(window["css"+e])return;if(LOCAL[e]){document.head.createChild("link",{rel:"stylesheet",href:i("css",e)});window["css"+e]=true}};const o=function(e){var t=e.text||e.textContent||e.innerHTML||"";var a=e.parentNode;a.removeChild(e);var n=document.createElement("script");if(e.id){n.id=e.id}if(e.className){n.className=e.className}if(e.type){n.type=e.type}if(e.src){n.src=e.src;n.async=false}if(e.dataset.pjax!==undefined){n.dataset.pjax=""}if(t!==""){n.appendChild(document.createTextNode(t))}a.appendChild(n)};const c=function(e,t,a){var n={targets:typeof t=="number"?e.parentNode:document.scrollingElement,duration:500,easing:"easeInOutQuad",scrollTop:t||(typeof e=="number"?e:e?e.top()+document.documentElement.scrollTop-R:0),complete:function(){a&&a()}};anime(n)};const l=function(e,t,a){var n={};var i="none";switch(t){case 0:n={opacity:[1,0]};break;case 1:n={opacity:[0,1]};i="block";break;case"bounceUpIn":n={begin:function(t){e.display("block")},translateY:[{value:-60,duration:200},{value:10,duration:200},{value:-5,duration:200},{value:0,duration:200}],opacity:[0,1]};i="block";break;case"shrinkIn":n={begin:function(t){e.display("block")},scale:[{value:1.1,duration:300},{value:1,duration:200}],opacity:1};i="block";break;case"slideRightIn":n={begin:function(t){e.display("block")},translateX:[100,0],opacity:[0,1]};i="block";break;case"slideRightOut":n={translateX:[0,100],opacity:[1,0]};break;default:n=t;i=t.display;break}anime(Object.assign({targets:e,duration:200,easing:"linear"},n)).finished.then(function(){e.display(i);a&&a()})};const d={get:function(e){return localStorage.getItem(e)},set:function(e,t){localStorage.setItem(e,t);return t},del:function(e){localStorage.removeItem(e)}};const u=function(e,t){t=t||document;if(e.indexOf("#")===0){return t.getElementById(e.replace("#",""))}return t.querySelector(e)};u.all=function(e,t){t=t||document;return t.querySelectorAll(e)};u.each=function(e,t,a){return u.all(e,a).forEach(t)};Object.assign(HTMLElement.prototype,{createChild:function(e,t,a){var n=document.createElement(e);Object.assign(n,t);switch(a){case"after":this.insertAfter(n);break;case"replace":this.innerHTML="";default:this.appendChild(n)}return n},wrap:function(e){var t=document.createElement("div");Object.assign(t,e);this.parentNode.insertBefore(t,this);this.parentNode.removeChild(this);t.appendChild(this)},height:function(e){if(e){this.style.height=typeof e=="number"?e+"rem":e}return this.getBoundingClientRect().height},width:function(e){if(e){this.style.width=typeof e=="number"?e+"rem":e}return this.getBoundingClientRect().width},top:function(){return this.getBoundingClientRect().top},left:function(){return this.getBoundingClientRect().left},attr:function(e,t){if(t===null){return this.removeAttribute(e)}if(t){this.setAttribute(e,t);return this}else{return this.getAttribute(e)}},insertAfter:function(e){var t=this.parentNode;if(t.lastChild==this){t.appendChild(e)}else{t.insertBefore(e,this.nextSibling)}},display:function(e){if(e==null){return this.style.display}else{this.style.display=e;return this}},child:function(e){return u(e,this)},find:function(e){return u.all(e,this)},_class:function(e,t,a){var n=t.indexOf(" ")?t.split(" "):[t];var i=this;n.forEach(function(t){if(e=="toggle"){i.classList.toggle(t,a)}else{i.classList[e](t)}})},addClass:function(e){this._class("add",e);return this},removeClass:function(e){this._class("remove",e);return this},toggleClass:function(e,t){this._class("toggle",e,t);return this},hasClass:function(e){return this.classList.contains(e)}});var f=null;const h=/mobile/i.test(window.navigator.userAgent);const p=function(e,t){var a={type:"audio",mode:"random",btns:["play-pause","music"],controls:["mode","backward","play-pause","forward","volume"],events:{"play-pause":function(t){if(i.paused){e.player.play()}else{e.player.pause()}},music:function(e){if(r.el.hasClass("show")){r.hide()}else{r.el.addClass("show");s.scroll().title()}}}},n={random:function(e){return Math.floor(Math.random()*e)},parse:function(e){var t=[];[["music.163.com.*song.*id=(\\d+)","netease","song"],["music.163.com.*album.*id=(\\d+)","netease","album"],["music.163.com.*artist.*id=(\\d+)","netease","artist"],["music.163.com.*playlist.*id=(\\d+)","netease","playlist"],["music.163.com.*discover/toplist.*id=(\\d+)","netease","playlist"],["y.qq.com.*song/(\\w+).html","tencent","song"],["y.qq.com.*album/(\\w+).html","tencent","album"],["y.qq.com.*singer/(\\w+).html","tencent","artist"],["y.qq.com.*playsquare/(\\w+).html","tencent","playlist"],["y.qq.com.*playlist/(\\w+).html","tencent","playlist"],["xiami.com.*song/(\\w+)","xiami","song"],["xiami.com.*album/(\\w+)","xiami","album"],["xiami.com.*artist/(\\w+)","xiami","artist"],["xiami.com.*collect/(\\w+)","xiami","playlist"]].forEach(function(a){var n=new RegExp(a[0]);var i=n.exec(e);if(i!==null){t=[a[1],a[2],i[1]]}});return t},fetch:function(e){var t=[];return new Promise(function(a,i){e.forEach(function(e){var i=n.parse(e);if(i[0]){var r=JSON.stringify(i);var s=d.get(r);if(s){t.push.apply(t,JSON.parse(s));a(t)}else{fetch("https://api.i-meto.com/meting/api?server="+i[0]+"&type="+i[1]+"&id="+i[2]+"&r="+Math.random()).then(function(e){return e.json()}).then(function(e){d.set(r,JSON.stringify(e));t.push.apply(t,e);a(t)}).catch(function(e){})}}else{t.push(e);a(t)}})})},secondToTime:function(e){var t=function(e){return isNaN(e)?"00":e<10?"0"+e:""+e};var a=Math.floor(e/3600);var n=Math.floor((e-a*3600)/60);var i=Math.floor(e-a*3600-n*60);return(a>0?[a,n,i]:[n,i]).map(t).join(":")},nameMap:{dragStart:h?"touchstart":"mousedown",dragMove:h?"touchmove":"mousemove",dragEnd:h?"touchend":"mouseup"}},i=null;e.player={_id:n.random(999999),group:true,load:function(e){var t="";var a=this;if(e&&e.length>0){if(this.options.rawList!==e){this.options.rawList=e;s.clear()}}else{t="none";this.pause()}for(var n in g.el){g.el[n].display(t)}return this},fetch:function(){var e=this;return new Promise(function(t,a){if(s.data.length>0){t()}else{if(e.options.rawList){var i=[];e.options.rawList.forEach(function(t,a){i.push(new Promise(function(i,r){var o=a;var c;if(!t.list){o=0;e.group=false;c=[t]}else{e.group=true;c=t.list}n.fetch(c).then(function(e){s.add(o,e);i()})}))});Promise.all(i).then(function(){t(true)})}}}).then(function(t){if(t){s.create();m.create();e.mode()}})},mode:function(){var e=s.data.length;if(!e||s.errnum==e)return;var t=m.step=="next"?1:-1;var a=function(){var a=s.index+t;if(a>e||a<0){a=m.step=="next"?0:e-1}s.index=a};var i=function(){var t=n.random(e);if(s.index!==t){s.index=t}else{a()}};switch(this.options.mode){case"random":i();break;case"order":a();break;case"loop":if(m.step)a();if(s.index==-1)i();break}this.init()},"switch":function(e){if(typeof e=="number"&&e!=s.index&&s.current()&&!s.current().error){s.index=e;this.init()}},init:function(){var e=s.current();if(!e||e["error"]){this.mode();return}var t=false;if(!i.paused){t=true;this.stop()}i.attr("src",e.url);i.attr("title",e.name+" - "+e.artist);this.volume(d.get("_PlayerVolume")||"0.7");this.muted(d.get("_PlayerMuted"));p.create();if(this.options.type=="audio")l.create();if(t==true){this.play()}},play:function(){f&&f.player.pause();if(s.current().error){this.mode();return}var e=this;i.play().then(function(){s.scroll()}).catch(function(e){})},pause:function(){i.pause();document.title=y},stop:function(){i.pause();i.currentTime=0;document.title=y},seek:function(e){e=Math.max(e,0);e=Math.min(e,i.duration);i.currentTime=e;p.update(e/i.duration)},muted:function(e){if(e=="muted"){i.muted=e;d.set("_PlayerMuted",e);m.update(0)}else{d.del("_PlayerMuted");i.muted=false;m.update(i.volume)}},volume:function(e){if(!isNaN(e)){m.update(e);d.set("_PlayerVolume",e);i.volume=e}},mini:function(){r.hide()}};var r={el:null,create:function(){if(this.el)return;this.el=e.createChild("div",{className:"player-info",innerHTML:(e.player.options.type=="audio"?'
':"")+'
'},"after");l.el=this.el.child(".preview");s.el=this.el.child(".playlist");m.el=this.el.child(".controller")},hide:function(){var e=this.el;e.addClass("hide");window.setTimeout(function(){e.removeClass("show hide")},300)}};var s={el:null,data:[],index:-1,errnum:0,add:function(e,t){var a=this;t.forEach(function(t,n){t.group=e;t.name=t.name||t.title||"Meida name";t.artist=t.artist||t.author||"Anonymous";t.cover=t.cover||t.pic;t.type=t.type||"normal";a.data.push(t)})},clear:function(){this.data=[];this.el.innerHTML="";if(this.index!==-1){this.index=-1;e.player.fetch()}},create:function(){var t=this.el;this.data.map(function(a,n){if(a.el)return;var r="list-"+e.player._id+"-"+a.group;var o=u("#"+r);if(!o){o=t.createChild("div",{id:r,className:e.player.group?"tab":"",innerHTML:"
    "});if(e.player.group){o.attr("data-title",e.player.options.rawList[a.group]["title"]).attr("data-id",e.player._id)}}a.el=o.child("ol").createChild("li",{title:a.name+" - "+a.artist,innerHTML:''+a.name+""+a.artist+"",onclick:function(t){var a=t.currentTarget;if(s.index===n&&p.el){if(i.paused){e.player.play()}else{e.player.seek(i.duration*p.percent(t,a))}return}e.player.switch(n);e.player.play()}});return a});he()},current:function(){return this.data[this.index]},scroll:function(){var e=this.current();var t=this.el.child("li.active");t&&t.removeClass("active");var a=this.el.child(".tab.active");a&&a.removeClass("active");t=this.el.find(".nav li")[e.group];t&&t.addClass("active");a=this.el.find(".tab")[e.group];a&&a.addClass("active");c(e.el,e.el.offsetTop);return this},title:function(){if(i.paused)return;var e=this.current();document.title="Now Playing..."+e["name"]+" - "+e["artist"]+" | "+y},error:function(){var e=this.current();e.el.removeClass("current").addClass("error");e.error=true;this.errnum++}};var o={el:null,data:null,index:0,create:function(e){var t=s.index;var a=this;var n=s.current().lrc;var i=function(n){if(t!==s.index)return;a.data=a.parse(n);var i="";a.data.forEach(function(e,t){i+=""+e[1]+"

    "});a.el=e.createChild("div",{className:"inner",innerHTML:i},"replace");a.index=0};if(n.startsWith("http"))this.fetch(n,i);else i(n)},update:function(e){if(!this.data)return;if(this.index>this.data.length-1||e=this.data[this.index+1][0])){for(var t=0;t=this.data[t][0]&&(!this.data[t+1]||e/g,"").replace(/^\s+|\s+$/g,"");if(r){const o=r.length;for(var c=0;c
    '+'

    '+t.name+"

    "+t.artist+""+'
    ';this.el.child(".cover").addEventListener("click",e.player.options.events["play-pause"]);o.create(this.el.child(".lrc"))}};var p={el:null,bar:null,create:function(){var e=s.current().el;if(e){if(this.el){this.el.parentNode.removeClass("current").removeEventListener(n.nameMap.dragStart,this.drag);this.el.remove()}this.el=e.createChild("div",{className:"progress"});this.el.attr("data-dtime",n.secondToTime(0));this.bar=this.el.createChild("div",{className:"bar"});e.addClass("current");e.addEventListener(n.nameMap.dragStart,this.drag);s.scroll()}},update:function(e){this.bar.width(Math.floor(e*100)+"%");this.el.attr("data-ptime",n.secondToTime(e*i.duration))},seeking:function(e){if(e)this.el.addClass("seeking");else this.el.removeClass("seeking")},percent:function(e,t){var a=((e.clientX||e.changedTouches[0].clientX)-t.left())/t.width();a=Math.max(a,0);return Math.min(a,1)},drag:function(t){t.preventDefault();var a=s.current().el;var r=function(e){e.preventDefault();var t=p.percent(e,a);p.update(t);o.update(t*i.duration)};var c=function(t){t.preventDefault();a.removeEventListener(n.nameMap.dragEnd,c);a.removeEventListener(n.nameMap.dragMove,r);var s=p.percent(t,a);p.update(s);e.player.seek(s*i.duration);i.disableTimeupdate=false;p.seeking(false)};i.disableTimeupdate=true;p.seeking(true);a.addEventListener(n.nameMap.dragMove,r);a.addEventListener(n.nameMap.dragEnd,c)}};var m={el:null,btns:{},step:"next",create:function(){if(!e.player.options.controls)return;var t=this;e.player.options.controls.forEach(function(a){if(t.btns[a])return;var r={onclick:function(n){t.events[a]?t.events[a](n):e.player.options.events[a](n)}};switch(a){case"volume":r.className=" "+(i.muted?"off":"on");r.innerHTML='
    ';r["on"+n.nameMap.dragStart]=t.events["volume"];r.onclick=null;break;case"mode":r.className=" "+e.player.options.mode;break;default:r.className="";break}r.className=a+r.className+" btn";t.btns[a]=t.el.createChild("div",r)});t.btns["volume"].bar=t.btns["volume"].child(".bar")},events:{mode:function(t){switch(e.player.options.mode){case"loop":e.player.options.mode="random";break;case"random":e.player.options.mode="order";break;default:e.player.options.mode="loop"}m.btns["mode"].className="mode "+e.player.options.mode+" btn";d.set("_PlayerMode",e.player.options.mode)},volume:function(t){t.preventDefault();var a=t.currentTarget;var r=false;var s=function(t){t.preventDefault();e.player.volume(m.percent(t,a));r=true};var o=function(t){t.preventDefault();a.removeEventListener(n.nameMap.dragEnd,o);a.removeEventListener(n.nameMap.dragMove,s);if(r){e.player.muted();e.player.volume(m.percent(t,a))}else{if(i.muted){e.player.muted();e.player.volume(i.volume)}else{e.player.muted("muted");m.update(0)}}};a.addEventListener(n.nameMap.dragMove,s);a.addEventListener(n.nameMap.dragEnd,o)},backward:function(t){m.step="prev";e.player.mode()},forward:function(t){m.step="next";e.player.mode()}},update:function(e){m.btns["volume"].className="volume "+(!i.muted&&e>0?"on":"off")+" btn";m.btns["volume"].bar.width(Math.floor(e*100)+"%")},percent:function(e,t){var a=((e.clientX||e.changedTouches[0].clientX)-t.left())/t.width();a=Math.max(a,0);return Math.min(a,1)}};var v={onerror:function(){s.error();e.player.mode()},ondurationchange:function(){if(i.duration!==1){p.el.attr("data-dtime",n.secondToTime(i.duration))}},onloadedmetadata:function(){e.player.seek(0);p.el.attr("data-dtime",n.secondToTime(i.duration))},onplay:function(){e.parentNode.addClass("playing");K(this.attr("title"));f=e},onpause:function(){e.parentNode.removeClass("playing");f=null},ontimeupdate:function(){if(!this.disableTimeupdate){p.update(this.currentTime/this.duration);o.update(this.currentTime)}},onended:function(t){e.player.mode();e.player.play()}};var g={el:{},create:function(){if(!e.player.options.btns)return;var t=this;e.player.options.btns.forEach(function(a){if(t.el[a])return;t.el[a]=e.createChild("div",{className:a+" btn",onclick:function(t){e.player.fetch().then(function(){e.player.options.events[a](t)})}})})}};var b=function(t){if(e.player.created)return;e.player.options=Object.assign(a,t);e.player.options.mode=d.get("_PlayerMode")||e.player.options.mode;g.create();i=e.createChild(e.player.options.type,v);r.create();e.parentNode.addClass(e.player.options.type);e.player.created=true};b(t);return e};var m=e.statics.indexOf("//")>0?e.statics:e.root;var v={x:"undefined",y:"undefined"};var g=0;var y,b;const w=document.getElementsByTagName("body")[0];const C=document.documentElement;const x=u("#container");const k=u("#loading");const L=u("#nav");const E=u("#header");const T=L.child(".toggle");const M=u("#quick");const N=u("#sidebar");const O=u("#brand");var j=u("#tool"),I,H,A,q;var S=u("#search");var R,_,P;var D=window.innerHeight;var W=window.innerWidth;var B=0,Y=window.location.href;var z;const X=lozad("img, [data-background-image]",{loaded:function(e){e.addClass("lozaded")}});const F={timer:null,lock:false,show:function(){clearTimeout(this.timer);document.body.removeClass("loaded");k.attr("style","display:block");F.lock=false},hide:function(t){if(!e.loader.start)t=-1;this.timer=setTimeout(this.vanish,t||3e3)},vanish:function(){if(F.lock)return;if(e.loader.start)l(k,0);document.body.addClass("loaded");F.lock=true}};const U=function(e){var t=u(".theme .ic");if(e=="dark"){C.attr("data-theme",e);t.removeClass("i-sun");t.addClass("i-moon")}else{C.attr("data-theme",null);t.removeClass("i-moon");t.addClass("i-sun")}};const G=function(e){if(C.attr("data-theme")=="dark")e="#222";u('meta[name="theme-color"]').attr("content",e)};const V=function(){window.matchMedia("(prefers-color-scheme: dark)").addListener(function(e){if(e.matches){U("dark")}else{U()}});var t=d.get("theme");if(t){U(t)}else{if(e.darkmode){U("dark")}}u(".theme").addEventListener("click",function(e){var t=e.currentTarget.child(".ic");var a=w.createChild("div",{id:"neko",innerHTML:'
    '});var n=function(){l(a,{delay:2500,opacity:0},function(){w.removeChild(a)})};if(t.hasClass("i-sun")){var i=function(){a.addClass("dark");U("dark");d.set("theme","dark");n()}}else{a.addClass("dark");var i=function(){a.removeClass("dark");U();d.set("theme","light");n()}}l(a,1,function(){setTimeout(i,210)})})};const J=function(){document.addEventListener("visibilitychange",function(){switch(document.visibilityState){case"hidden":u('[rel="icon"]').attr("href",m+e.favicon.hidden);document.title=LOCAL.favicon.hide;if(e.loader.switch)F.show();clearTimeout(b);break;case"visible":u('[rel="icon"]').attr("href",m+e.favicon.normal);document.title=LOCAL.favicon.show;if(e.loader.switch)F.hide(1e3);b=setTimeout(function(){document.title=y},2e3);break}})};const K=function(e){if(!e)return;var t=w.createChild("div",{innerHTML:e,className:"tip"});setTimeout(function(){t.addClass("hide");setTimeout(function(){w.removeChild(t)},300)},3e3)};const $=function(e){R=L.height();_=E.height();P=_+u("#waves").height();if(W!=window.innerWidth)ae(null,1);D=window.innerHeight;W=window.innerWidth;N.child(".panels").height(D+"px")};const Q=function(e){var t=window.innerHeight;var n=a();var i=n>t?n-t:document.body.scrollHeight-t;var r=window.pageYOffset>_;var s=window.pageYOffset>0;if(r){G("#FFF")}else{G("#222")}L.toggleClass("show",r);j.toggleClass("affix",s);O.toggleClass("affix",s);N.toggleClass("affix",window.pageYOffset>P&&document.body.offsetWidth>991);if(typeof v.y=="undefined"){v.y=window.pageYOffset}g=v.y-window.pageYOffset;if(g<0){L.removeClass("up");L.toggleClass("down",r)}else if(g>0){L.removeClass("down");L.toggleClass("up",r)}else{}v.y=window.pageYOffset;var o=Math.round(Math.min(100*window.pageYOffset/i,100))+"%";H.child("span").innerText=o;u(".percent").width(o)};const Z=function(){if(e.auto_scroll)d.set(Y,v.y)};const ee=function(t){var a=window.location.hash;var n=null;if(B){d.del(Y);return}if(a)n=u(decodeURI(a));else{n=e.auto_scroll?parseInt(d.get(Y)):0}if(n){c(n);B=1}if(t&&a&&!B){c(n);B=1}};const te=function(e,t){var a=w.createChild("textarea",{style:{top:window.scrollY+"px",position:"absolute",opacity:"0"},readOnly:true,value:e});const n=document.getSelection();const i=n.rangeCount>0?n.getRangeAt(0):false;a.select();a.setSelectionRange(0,e.length);a.readOnly=false;var r=document.execCommand("copy");t&&t(r);a.blur();if(i){n.removeAllRanges();n.addRange(i)}w.removeChild(a)};const ae=function(e,t){if(N.hasClass("on")){N.removeClass("on");T.removeClass("close");if(t){N.style=""}else{l(N,"slideRightOut")}}else{if(t){N.style=""}else{l(N,"slideRightIn",function(){N.addClass("on");T.addClass("close")})}}};const ne=function(){var e=N.child(".inner");var t=N.find(".panel");if(N.child(".tab")){e.removeChild(N.child(".tab"))}var a=document.createElement("ul"),n="active";a.className="tab";["contents","related","overview"].forEach(function(e){var t=N.child(".panel."+e);if(t.innerHTML.replace(/(^\s*)|(\s*$)/g,"").length<1){if(e=="contents"){q.display("none")}return}if(e=="contents"){q.display("")}var i=document.createElement("li");var r=document.createElement("span");var s=document.createTextNode(t.attr("data-title"));r.appendChild(s);i.appendChild(r);i.addClass(e+" item");if(n){t.addClass(n);i.addClass(n)}else{t.removeClass("active")}i.addEventListener("click",function(e){var t=event.currentTarget;if(t.hasClass("active"))return;N.find(".tab .item").forEach(function(e){e.removeClass("active")});N.find(".panel").forEach(function(e){e.removeClass("active")});N.child(".panel."+t.className.replace(" item","")).addClass("active");t.addClass("active")});a.appendChild(i);n=""});if(a.childNodes.length>1){e.insertBefore(a,e.childNodes[0]);N.child(".panels").style.paddingTop=""}else{N.child(".panels").style.paddingTop=".625rem"}};const ie=function(){var t=u.all(".contents li");if(t.length<1){return}var a=Array.prototype.slice.call(t)||[];var n=null;a=a.map(function(t,a){var i=t.child("a.toc-link");var s=u(decodeURI(i.attr("href")));if(!s)return;var o=s.child("a.anchor");var l=function(e){e.preventDefault();var t=u(decodeURI(e.currentTarget.attr("href")));n=a;c(t,null,function(){r(a);n=null})};i.addEventListener("click",l);o&&o.addEventListener("click",function(t){l(t);te(e.hostname+"/"+LOCAL.path+t.currentTarget.attr("href"))});return s});var i=N.child(".contents.panel");var r=function(e,n){var r=t[e];if(!r)return;if(r.hasClass("current")){return}u.each(".toc .active",function(e){e&&e.removeClass("active current")});a.forEach(function(e){e&&e.removeClass("active")});r.addClass("active current");a[e]&&a[e].addClass("active");var s=r.parentNode;while(!s.matches(".contents")){if(s.matches("li")){s.addClass("active");var o=u(s.child("a.toc-link").attr("href"));if(o){o.addClass("active")}}s=s.parentNode}if(getComputedStyle(N).display!="none"&&i.hasClass("active")){c(i,r.offsetTop-i.offsetHeight/4)}};var s=function(e){var t=0;var n=e[t];if(n.boundingClientRect.top>0){t=a.indexOf(n.target);return t===0?0:t-1}for(;t0){t.target.addClass("show");e.unobserve(t.target)}}})},{root:null,threshold:[.3]});u.each(".index.wrap article.item, .index.wrap section.item",function(t){e.observe(t)});u(".index.wrap .item:first-child").addClass("show")}u.each(".cards .item",function(e,t){["mouseenter","touchstart"].forEach(function(t){e.addEventListener(t,function(t){if(u(".cards .item.active")){u(".cards .item.active").removeClass("active")}e.addClass("active")})});["mouseleave"].forEach(function(t){e.addEventListener(t,function(t){e.removeClass("active")})})})};const de=function(){u.each("span.exturl",function(e){var t=document.createElement("a");t.href=decodeURIComponent(atob(e.dataset.url).split("").map(function(e){return"%"+("00"+e.charCodeAt(0).toString(16)).slice(-2)}).join(""));t.rel="noopener external nofollow noreferrer";t.target="_blank";t.className=e.className;t.title=e.title||e.innerText;t.innerHTML=e.innerHTML;if(e.dataset.backgroundImage){t.dataset.backgroundImage=e.dataset.backgroundImage}e.parentNode.replaceChild(t,e)})};const ue=function(e){if(u(e+" .md img")){s("fancybox");r("fancybox",function(){var t=jQuery.noConflict();u.each(e+" p.gallery",function(e){var t=document.createElement("div");t.className="gallery";t.attr("data-height",e.attr("data-height")||220);t.innerHTML=e.innerHTML.replace(/
    /g,"");e.parentNode.insertBefore(t,e);e.remove()});u.each(e+" .md img:not(.emoji):not(.vemoji)",function(e){var a=t(e);var n,i="image-info";if(!a.is("a img")){var r=a.attr("data-src")||a.attr("src");a.data("safe-src",r);var s=a.wrap('').parent("a");if(!a.is(".gallery img")){s.attr("data-fancybox","default").attr("rel","default")}else{i="jg-caption"}}if(n=e.attr("title")){s.attr("data-caption",n);var o=document.createElement("span");var c=document.createTextNode(n);o.appendChild(c);o.addClass(i);e.insertAfter(o)}});u.each(e+" div.gallery",function(e,a){t(e).justifiedGallery({rowHeight:t(e).data("height")||120,rel:"gallery-"+a}).on("jg.complete",function(){t(this).find("a").each(function(e,t){t.attr("data-fancybox","gallery-"+a)})})});t.fancybox.defaults.hash=false;t(e+" .fancybox").fancybox({loop:true,helpers:{overlay:{locked:false}}})},window.jQuery)}};const fe=function(){pe();if(!u(".md"))return;ue(".post.block");u(".post.block").oncopy=function(e){K(LOCAL.copyright);if(LOCAL.nocopy){e.preventDefault();return}var t=u("#copyright");if(window.getSelection().toString().length>30&&t){e.preventDefault();var a="# "+t.child(".author").innerText;var n="# "+t.child(".link").innerText;var i="# "+t.child(".license").innerText;var r=a+"
    "+n+"
    "+i+"

    "+window.getSelection().toString().replace(/\r\n/g,"
    ");var s=a+"\n"+n+"\n"+i+"\n\n"+window.getSelection().toString().replace(/\r\n/g,"\n");if(e.clipboardData){e.clipboardData.setData("text/html",r);e.clipboardData.setData("text/plain",s)}else if(window.clipboardData){return window.clipboardData.setData("text",s)}}};u.each("li ruby",function(e){var t=e.parentNode;if(e.parentNode.tagName!="LI"){t=e.parentNode.parentNode}t.addClass("ruby")});u.each("ol[start]",function(e){e.style.counterReset="counter "+parseInt(e.attr("start")-1)});u.each(".md table",function(e){e.wrap({className:"table-container"})});u.each(".highlight > .table-container",function(e){e.className="code-container"});u.each("figure.highlight",function(e){var t=e.child(".code-container");var a=e.child("figcaption");e.insertAdjacentHTML("beforeend",'
    ');var n=e.child(".copy-btn");if(LOCAL.nocopy){n.remove()}else{n.addEventListener("click",function(e){var a=e.currentTarget;var n="",i="";t.find("pre").forEach(function(e){i+=n+e.innerText;n="\n"});te(i,function(e){a.child(".ic").className=e?"ic i-check":"ic i-times";a.blur();K(LOCAL.copyright)})});n.addEventListener("mouseleave",function(e){setTimeout(function(){e.target.child(".ic").className="ic i-clipboard"},1e3)})}var i=e.child(".breakline-btn");i.addEventListener("click",function(t){var a=t.currentTarget;if(e.hasClass("breakline")){e.removeClass("breakline");a.child(".ic").className="ic i-align-left"}else{e.addClass("breakline");a.child(".ic").className="ic i-align-justify"}});var r=e.child(".fullscreen-btn");var s=function(){e.removeClass("fullscreen");e.scrollTop=0;w.removeClass("fullscreen");r.child(".ic").className="ic i-expand"};var o=function(t){var a=t.currentTarget;if(e.hasClass("fullscreen")){s();u&&u();c(e)}else{e.addClass("fullscreen");w.addClass("fullscreen");r.child(".ic").className="ic i-compress";d&&d()}};r.addEventListener("click",o);a&&a.addEventListener("click",o);if(t&&t.find("tr").length>15){t.style.maxHeight="300px";t.insertAdjacentHTML("beforeend",'
    ');var l=t.child(".show-btn");var d=function(){t.style.maxHeight="";l.addClass("open")};var u=function(){t.style.maxHeight="300px";l.removeClass("open")};l.addEventListener("click",function(e){if(l.hasClass("open")){s();u();c(t)}else{d()}})}});u.each("pre.mermaid > svg",function(e){e.style.maxWidth=""});u.each(".reward button",function(e){e.addEventListener("click",function(e){e.preventDefault();var t=u("#qr");if(t.display()==="inline-flex"){l(t,0)}else{l(t,1,function(){ t.display("inline-flex")})}})});u.each(".quiz > ul.options li",function(e){e.addEventListener("click",function(t){if(e.hasClass("correct")){e.toggleClass("right");e.parentNode.parentNode.addClass("show")}else{e.toggleClass("wrong")}})});u.each(".quiz > p",function(e){e.addEventListener("click",function(t){e.parentNode.toggleClass("show")})});u.each(".quiz > p:first-child",function(e){var t=e.parentNode;var a="choice";if(t.hasClass("true")||t.hasClass("false"))a="true_false";if(t.hasClass("multi"))a="multiple";if(t.hasClass("fill"))a="gap_fill";if(t.hasClass("essay"))a="essay";e.attr("data-type",LOCAL.quiz[a])});u.each(".quiz .mistake",function(e){e.attr("data-type",LOCAL.quiz.mistake)});u.each("div.tags a",function(e){e.className=["primary","success","info","warning","danger"][Math.floor(Math.random()*5)]});u.each(".md div.player",function(e){p(e,{type:e.attr("data-type"),mode:"order",btns:[]}).player.load(JSON.parse(e.attr("data-src"))).fetch()})};const he=function(){var e;u.each("div.tab",function(t,a){if(t.attr("data-ready"))return;var n=t.attr("data-id");var i=t.attr("data-title");var r=u("#"+n);if(!r){r=document.createElement("div");r.className="tabs";r.id=n;r.innerHTML='
    ';var s=r.child(".show-btn");s.addEventListener("click",function(e){c(r)});t.parentNode.insertBefore(r,t);e=true}else{e=false}var o=r.child(".nav ul");if(!o){o=r.createChild("div",{className:"nav",innerHTML:"
      "}).child("ul")}var l=o.createChild("li",{innerHTML:i});if(e){l.addClass("active");t.addClass("active")}l.addEventListener("click",function(e){var a=e.currentTarget;r.find(".active").forEach(function(e){e.removeClass("active")});t.addClass("active");a.addClass("active")});r.appendChild(t);t.attr("data-ready",true)})};const pe=function(){var e=u("#comments");if(!e){A.display("none");return}else{A.display("")}if(!window.IntersectionObserver){s("valine")}else{var t=new IntersectionObserver(function(e,t){var a=e[0];s("valine");if(a.isIntersecting||a.intersectionRatio>0){l(u("#comments"),"bounceUpIn");t.disconnect()}});t.observe(e)}};const me=function(t){if(e.search===null)return;if(!S){S=w.createChild("div",{id:"search",innerHTML:'
      '})}var a=instantsearch({indexName:e.search.indexName,searchClient:algoliasearch(e.search.appID,e.search.apiKey),searchFunction:function(e){var t=u(".search-input");if(t.value){e.search()}}});a.on("render",function(){t.refresh(u("#search-hits"))});a.addWidgets([instantsearch.widgets.configure({hitsPerPage:e.search.hits.per_page||10}),instantsearch.widgets.searchBox({container:".search-input-container",placeholder:LOCAL.search.placeholder,showReset:false,showSubmit:false,showLoadingIndicator:false,cssClasses:{input:"search-input"}}),instantsearch.widgets.stats({container:"#search-stats",templates:{text:function(e){var t=LOCAL.search.stats.replace(/\$\{hits}/,e.nbHits).replace(/\$\{time}/,e.processingTimeMS);return t+'
      '}}}),instantsearch.widgets.hits({container:"#search-hits",templates:{item:function(t){var a=t.categories?""+t.categories.join('')+"":"";return''+a+t._highlightResult.title.value+""},empty:function(e){return'
      '+LOCAL.search.empty.replace(/\$\{query}/,e.query)+"
      "}},cssClasses:{item:"item"}}),instantsearch.widgets.pagination({container:"#search-pagination",scrollTo:false,showFirst:false,showLast:false,templates:{first:'',last:'',previous:'',next:''},cssClasses:{root:"pagination",item:"pagination-item",link:"page-number",selectedItem:"current",disabledItem:"disabled-item"}})]);a.start();u.each(".search",function(e){e.addEventListener("click",function(){document.body.style.overflow="hidden";l(S,"shrinkIn",function(){u(".search-input").focus()})})});const n=function(){document.body.style.overflow="";l(S,0)};S.addEventListener("click",function(e){if(e.target===S){n()}});u(".close-btn").addEventListener("click",n);window.addEventListener("pjax:success",n);window.addEventListener("keyup",function(e){if(e.key==="Escape"){n()}})};const ve=function(){u.each(".overview .menu > .item",function(e){L.child(".menu").appendChild(e.cloneNode(true))});k.addEventListener("click",F.vanish);T.addEventListener("click",ae);u(".dimmer").addEventListener("click",ae);M.child(".down").addEventListener("click",se);M.child(".up").addEventListener("click",re);if(!j){j=E.createChild("div",{id:"tool",innerHTML:'
      0%
      '})}I=j.child(".player");H=j.child(".back-to-top");A=j.child(".chat");q=j.child(".contents");H.addEventListener("click",re);A.addEventListener("click",oe);q.addEventListener("click",ae);p(I);u("main").addEventListener("click",function(){I.player.mini()})};const ge=function(){Z();if(N.hasClass("on")){l(N,function(){N.removeClass("on");T.removeClass("close")})}u("#main").innerHTML="";u("#main").appendChild(k.lastChild.cloneNode(true));c(0)};const ye=function(t){B=0;Y=window.location.href;s("katex");r("copy_tex");s("mermaid");r("chart");r("valine",function(){var t=Object.assign({},e.valine);t=Object.assign(t,LOCAL.valine||{});t.el="#comments";t.pathname=LOCAL.path;t.pjax=z;t.lazyload=X;new MiniValine(t);setTimeout(function(){ee(1);ue(".v")},1e3)},window.MiniValine);if(!t){u.each("script[data-pjax]",o)}y=document.title;$();ce();ne();ie();de();fe();he();I.player.load(LOCAL.audio||e.audio||{});F.hide();setTimeout(function(){ee()},500);le();X.observe()};const be=function(){ve();z=new Pjax({selectors:["head title",".languages",".pjax","script[data-config]"],analytics:false,cacheBust:false});e.quicklink.ignores=LOCAL.ignores;quicklink.listen(e.quicklink);J();V();me(z);window.addEventListener("scroll",Q);window.addEventListener("resize",$);window.addEventListener("pjax:send",ge);window.addEventListener("pjax:success",ye);window.addEventListener("beforeunload",function(){Z()});ye(1)};window.addEventListener("DOMContentLoaded",be);console.log("%c Theme.Shoka v"+e.version+" %c https://shoka.lostyu.me/ ","color: white; background: #e9546b; padding:5px 0;","padding:4px;border:1px solid #e9546b;");var we=document.createElement("canvas");we.style.cssText="position:fixed;top:0;left:0;pointer-events:none;z-index:9999999";document.body.appendChild(we);var Ce=we.getContext("2d");var xe=30;var ke=0;var Le=0;var Ee="click";var Te=e.fireworks;function Me(){we.width=window.innerWidth*2;we.height=window.innerHeight*2;we.style.width=window.innerWidth+"px";we.style.height=window.innerHeight+"px";we.getContext("2d").scale(2,2)}function Ne(e){ke=e.clientX||e.touches&&e.touches[0].clientX;Le=e.clientY||e.touches&&e.touches[0].clientY}function Oe(e){var t=anime.random(0,360)*Math.PI/180;var a=anime.random(50,180);var n=[-1,1][anime.random(0,1)]*a;return{x:e.x+n*Math.cos(t),y:e.y+n*Math.sin(t)}}function je(e,t){var a={};a.x=e;a.y=t;a.color=Te[anime.random(0,Te.length-1)];a.radius=anime.random(16,32);a.endPos=Oe(a);a.draw=function(){Ce.beginPath();Ce.arc(a.x,a.y,a.radius,0,2*Math.PI,true);Ce.fillStyle=a.color;Ce.fill()};return a}function Ie(e,t){var a={};a.x=e;a.y=t;a.color="#FFF";a.radius=.1;a.alpha=.5;a.lineWidth=6;a.draw=function(){Ce.globalAlpha=a.alpha;Ce.beginPath();Ce.arc(a.x,a.y,a.radius,0,2*Math.PI,true);Ce.lineWidth=a.lineWidth;Ce.strokeStyle=a.color;Ce.stroke();Ce.globalAlpha=1};return a}function He(e){for(var t=0;t格攻击 - 密码学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      SageMath 🔧 一个非常好用的工具

      # 扩展维纳攻击

      私钥过小时,能够对 NN 进行分解。维纳证明了:

      d<13N14(q<p<2q)d\lt\frac{1}{3}N^{1\over 4}\\ (q\lt p\lt 2q)

      的时候,一定能够对 NN 进行分解。

      # 格规约

      # LLL

      Lenstra–Lenstra–Lovász

      基于格的约简算法,它将输入矩阵转换为其最简形式

      使用 LLL 或类似的格规约算法找到格中近似最短的非零向量

      # BKZ

      Block Korkine-Zolotarev

      是 LLL 算法的一种改进版本,能够更有效地处理高维格。BKZ 算法的基本思想是通过逐步降低格的基向量长度,将原始格转化为一个更紧密的格。这样做可以使格的基向量更加正交,并且可能使格的基向量更接近标准正交基。BKZ 算法通过多次应用基向量间的 Gram-Schmidt 正交化过程和基向量的坐标变换来实现这一点。

      一般用 BKZ 效果会比 LLL 好,其中的 block_size 设置越大效果越好,但算得越慢,最大取值是格的维度。

      # 格攻击

      格攻击其实是一个启发式算法

      # 基本域

      需要用到它的容积

      设矩阵 B=[b0,b1,,bn1]B=[b_0,b_1,\cdots,b_{n-1}] 为一组格基,则这组格基的基本域为:

      F(b0,,bn1):={t0b0++tn1bn10ti<1}\mathscr{F}(b_0,\cdots,b_{n-1}):=\{t_0b_0+\cdots+t_{n-1}b_{n-1}|0≤t_i<1\}

      基本域的容积等于格基的行列式(的绝对值):

      Vol(F)=det(L(B))\text{Vol}(\mathscr{F})=\det(\mathscr{L}(B))

      # 超球体

      高维空间的球体,也需要用到它的容积

      BR(a)\mathbb{B}_R(a) 为一个以点 aa 为圆心,半径为 RRnn 维球体,那么 BR(a)\mathbb{B}_R(a) 的容积(或者说体积)为:

      Vol(BR(a))=πn2RnΓ(1+n2)\text{Vol}(\mathbb{B}_R(a))={\pi^{\frac{n}{2}}R^n\over\Gamma(1+\frac{n}{2})}

      长度短于 σ(L)\sigma(L) 的格向量(约)只有一个,所以如果我们通过计算得到一个向量长度(约)小于 σ(L)\sigma(L) ,那么大概率可以确定它是一个最短向量,在维度不高的情况下,可以用 LLL 把他求出来:

      σ(L)=n2πe2(detL)1n\sigma(L)=\sqrt[2]{n\over2\pi e}(\det L)^{1\over n}

      SageMath 🔧 一个非常好用的工具

      # 扩展维纳攻击

      私钥过小时,能够对 NN 进行分解。维纳证明了:

      d<13N14(q<p<2q)d\lt\frac{1}{3}N^{1\over 4}\\ (q\lt p\lt 2q)

      的时候,一定能够对 NN 进行分解。

      # 格规约

      # LLL

      Lenstra–Lenstra–Lovász

      基于格的约简算法,它将输入矩阵转换为其最简形式

      使用 LLL 或类似的格规约算法找到格中近似最短的非零向量

      # BKZ

      Block Korkine-Zolotarev

      是 LLL 算法的一种改进版本,能够更有效地处理高维格。BKZ 算法的基本思想是通过逐步降低格的基向量长度,将原始格转化为一个更紧密的格。这样做可以使格的基向量更加正交,并且可能使格的基向量更接近标准正交基。BKZ 算法通过多次应用基向量间的 Gram-Schmidt 正交化过程和基向量的坐标变换来实现这一点。

      一般用 BKZ 效果会比 LLL 好,其中的 block_size 设置越大效果越好,但算得越慢,最大取值是格的维度。

      # 格攻击

      格攻击其实是一个启发式算法

      # 基本域

      需要用到它的容积

      设矩阵 B=[b0,b1,,bn1]B=[b_0,b_1,\cdots,b_{n-1}] 为一组格基,则这组格基的基本域为:

      F(b0,,bn1):={t0b0++tn1bn10ti<1}\mathscr{F}(b_0,\cdots,b_{n-1}):=\{t_0b_0+\cdots+t_{n-1}b_{n-1}|0≤t_i<1\}

      基本域的容积等于格基的行列式(的绝对值):

      Vol(F)=det(L(B))\text{Vol}(\mathscr{F})=\det(\mathscr{L}(B))

      # 超球体

      高维空间的球体,也需要用到它的容积

      BR(a)\mathbb{B}_R(a) 为一个以点 aa 为圆心,半径为 RRnn 维球体,那么 BR(a)\mathbb{B}_R(a) 的容积(或者说体积)为:

      Vol(BR(a))=πn2RnΓ(1+n2)\text{Vol}(\mathbb{B}_R(a))={\pi^{\frac{n}{2}}R^n\over\Gamma(1+\frac{n}{2})}

      长度短于 σ(L)\sigma(L) 的格向量(约)只有一个,所以如果我们通过计算得到一个向量长度(约)小于 σ(L)\sigma(L) ,那么大概率可以确定它是一个最短向量,在维度不高的情况下,可以用 LLL 把他求出来:

      σ(L)=n2πe2(detL)1n\sigma(L)=\sqrt[2]{n\over2\pi e}(\det L)^{1\over n}的参数上

      \ No newline at end of file +c-16-25.333-24-45-24-59z"/>的参数上

      \ No newline at end of file diff --git a/math/discrete-math/algebra/coset-of-subgroup/index.html b/math/discrete-math/algebra/coset-of-subgroup/index.html index 39829c17..f622e743 100644 --- a/math/discrete-math/algebra/coset-of-subgroup/index.html +++ b/math/discrete-math/algebra/coset-of-subgroup/index.html @@ -1 +1 @@ -子群的陪集 - 代数结构 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 群子集的乘积运算

      # 定义

      AABB 是群 GG 的两个非空子集,称集合:

      AB={abaA,bB}AB = \{ab|a\in A, b\in B \}

      为群的子集 AABB乘积 (product)

      如果 gGg\in G 为群 GG 的一个元素,A={g}A=\{g\} ,则:

      • ABAB 简记为 gB={gbbB}gB = \{gb|b\in B\}
      • BABA 简记为 Bg={bgbB}Bg = \{bg|b\in B\}

      注意,即使有 AB=BAAB=BA,也不意味着 aA,bB,ab=ba\forall a\in A, b\in B,\ \ \ ab =ba,正确的结论应该是:aA,bB,aA,bB,ab=ba\forall a\in A, b\in B,\ \ \ \exist a'\in A, b'\in B,\ \ \ ab = b'a'

      # 交换群的交换律

      GG交换群时,对 GG 的任意子集 A,BA,B ,满足交换律,有 AB=BAAB=BA ;但对于非交换群,一般没有 AB=BAAB=BA ,也就是没有交换律成立。

      # 满足结合律

      群的子集运算满足结合律:A(BC)=(AB)CA(BC) = (AB)C

      # 对单元素满足消去律

      gA=gBgA=gBAg=BgAg=Bg,则 A=BA=B

      但对普遍的

      AC=BC⇏A=BAC=BC\not\rArr A=B


      证明(不妨考虑 gA=gBgA=gB

      aA\forall a\in A,有 gagAga\in gA

      因为 gA=gBgA=gB ,所以 gagBga\in gB ,所以:

      bB,ga=gb\exist b\in B,\ \ \ ga=gb

      由群满足消去律可得:b=ab=a

      所以 a=bBa=b\in B ,所以有 ABA\sube B ;同理可证 BAB\sube A,从而可得 A=BA=B

      # 幂运算

      HH 是群 GG 的子群,则 HH=HHH=H

      # 乘积的子群充要条件

      如果 A,BA,B 是群 GG 的两个子群,则 ABAB 也是群 GG 的子群当且仅当 AB=BAAB=BA


      必要性: ABGAB=BAAB\leq G\rArr AB=BA

      对于 a,b,abAB\forall a,b,\ \ ab\in AB,只需证 abBAab\in BA

      由于 ABGAB\leq G ,所以 abAB,(ab)1=ab\exist a'b'\in AB,\ \ \ (ab)^{-1}=a'b'

      ab=((ab)1)1=(ab)1=b1a1BAab=((ab)^{-1})^{-1}=(a'b')^{-1}=b'^{-1}a'^{-1}\in BA

      从而可得 ABBAAB\sube BA ;同理可证 BAABBA\sube AB,从而可得 AB=BAAB=BA


      充分性: AB=BAABGAB=BA\rArr AB\leq G

      对于 a1,b1,a2,b2,a1b1,a2b2AB\forall a_1,b_1,a_2,b_2,\ \ \ a_1b_1,a_2b_2\in AB,有:a1b1(a2b2)1ABa_1b_1(a_2b_2)^{-1}\in AB

      a1b1(a2b2)1=a1b1b21a21=a1(b1b21)a21ABA=A(BA)=A(AB)=(AA)B=ABa_1b_1(a_2b_2)^{-1}=a_1b_1b_2^{-1}a_2^{-1}=a_1(b_1b_2^{-1})a_2^{-1}\\ \in ABA=A(BA)=A(AB)=(AA)B=AB

      从而由子群判定定理二可知 ABABGG 的子群

      # 乘积的子集关系

      A,B,CA,B,C 是群 GG 的非空子集(不一定是群),若 BCB⊆C ,则有 ABACAB⊆ACBABCBA⊆BC


      证明

      对任意 xABx\in AB ,则存在 aA,bBa\in A,b\in B,使得 x=abx=ab 。由 bBb\in B ,且 BCB⊆C,因此 bCb\in C,因此 x=abACx=ab\in AC ,因此 ABBCAB⊆BC

      对任意 xBAx\in BA ,则存在 aA,bBa\in A,b\in B ,使得 x=bax=ba 。由 bBb\in B ,且 BCB⊆C ,因此 bCb\in C ,因此 x=abACx=ab\in AC ,因此 BACABA⊆CA

      # 子群的陪集及其性质

      # 陪集定义

      GG 是群,HHGG 的子群

      对任意 aGa\in G,群 GG子集 aH={ahhH}aH=\{ah|h\in H\}Ha={hahH}Ha=\{ha|h\in H\} ,分别称为 HHGG 中的左陪集 (left coset) 和右陪集 (right coset)

      子群 HH 的所有右陪集构成的集合族 G\HG\backslash HGG 的一个划分

      子群 HH 的所有左陪集构成的集合族 G/HG/H 也是 GG 的一个划分

      注意陪集不一定是群了

      # 陪集举例

      对于群 (U(5),5)(U(5),⊗_5),子群 H={1,4}H=\{1,4\}

      5⊗_51234
      11234
      22413
      33142
      44321

      1H={151,154}={1,4}2H={251,254}=2,33H={351,354}={3,2}4H={451,454}={4,1}1H=\{1⊗_5 1,1⊗_5 4\}=\{1,4\}\\ 2H=\{2⊗_5 1,2⊗_5 4\}={2,3}\\ 3H=\{3⊗_5 1,3⊗_5 4\}=\{3,2\}\\ 4H=\{4⊗_5 1,4⊗_5 4\}=\{4,1\}

      HH 有两个不同的陪集 {1,4}\{1, 4\}{2,3}\{2,3\}


      对于下面的置换群 (G,)(G,\circ) ,子群 H={f1,f2}H=\{f_1, f_2\}

      \circf1f_1f2f_2f3f_3f4f_4f5f_5f6f_6
      f1f_1f1f_1f2f_2f3f_3f4f_4f5f_5f6f_6
      f2f_2f2f_2f1f_1f6f_6f5f_5f4f_4f3f_3
      f3f_3f3f_3f5f_5f1f_1f6f_6f2f_2f4f_4
      f4f_4f4f_4f6f_6f5f_5f1f_1f3f_3f2f_2
      f5f_5f5f_5f3f_3f4f_4f2f_2f6f_6f1f_1
      f6f_6f6f_6f4f_4f2f_2f3f_3f1f_1f5f_5

      f1H={f1f1,f1f2}={f1,f2}f2H={f2f1,f2f2}={f2,f1}f3H={f3f1,f3f2}={f3,f5}f4H={f4f1,f4f2}={f4,f6}f5H={f5f1,f5f2}={f5,f3}f6H={f6f1,f6f2}={f6,f4}Hf3={f1f3,f2f3}={f3,f6}Hf4={f1f4,f2f4}={f4,f5}Hf5={f1f5,f2f5}={f5,f4}Hf6={f1f6,f2f6}={f6,f3}f_1 H=\{f_1\circ f_1, f_1\circ f_2\}=\{f_1, f_2\}\\ f_2 H=\{f_2\circ f_1, f_2\circ f_2\}=\{f_2, f_1\}\\ f_3 H=\{f_3\circ f_1, f_3\circ f_2\}=\{f_3, f_5\}\\ f_4 H=\{f_4\circ f_1, f_4\circ f_2\}=\{f_4, f_6\}\\ f_5 H=\{f_5\circ f_1, f_5\circ f_2\}=\{f_5, f_3\}\\ f_6 H=\{f_6\circ f_1, f_6\circ f_2\}=\{f_6, f_4\}\\ Hf_3=\{f_1\circ f_3, f_2\circ f_3\}=\{f_3, f_6\}\\ Hf_4=\{f_1\circ f_4, f_2\circ f_4\}=\{f_4, f_5\}\\ Hf_5=\{f_1\circ f_5, f_2\circ f_5\}=\{f_5, f_4\}\\ Hf_6=\{f_1\circ f_6, f_2\circ f_6\}=\{f_6, f_3\}

      HH 有三个不同的陪集,且左右陪集不相等,例如 f3HHf3f_3H≠Hf_3

      # 不同元素陪集相同充要条件

      a,bG\forall a,b\in G

      • Ha=HbHa=Hb 当且仅当 aHba\in Hb 当且仅当 ab1Hab^{-1}\in H
      • aH=bHaH=bH 当且仅当 abHa\in bH 当且仅当 b1aHb^{-1}a\in H

      # 陪集不变的充要条件

      HH 是群 GG 的子群,对任意的 aGa\in G

      • HaHHa=H 的充分必要条件是 aHa\in H

      引理

      eHe\in H ,所以 aeaHaa=ea\in Ha


      证明

      必要性:若 HaHHa=H ,则因为 aHaa\in Ha ,从而 aHa\in H

      充分性:反之若 aHa\in H ,则对任意 haHaha\in Ha ,由 HH 对群运算封闭,也有 haHha\in H ,从而有 HaHHa\subseteq H

      而这时对任意 hHh\in H ,由 aHa\in Ha1Ha^{-1}\in H ,从而 ha1Hha^{-1}\in H ,从而有 hha1aHah=ha^{-1}a\in Ha ,即有 HHaH\subseteq Ha

      于是又 HaH,HHaHa\subseteq H,H\subseteq Ha 得到 Ha=HHa=H

      # 陪集的子群充要条件

      HH 是群 GG 的子群,对任意的 aGa\in G

      • 右陪集 HaHaGG 的子群当且仅当 Ha=HHa=H 当且仅当 aHa\in H
      • 左陪集 aHaHGG 的子群当且仅当 aH=HaH=H 当且仅当 aHa\in H

      证明以右陪集为例:

      必要性:若 HaGHa\leq G ,所以 eHae\in Ha ,从而存在 hHh\in H 使得 ehae=ha ,从而 ah1e=h1Ha=h^{-1}e=h^{-1}\in H

      充分性:若 aHa\in H ,则 HaHHa=H 是子群。

      # 子群陪集运算性质

      HH 是群 GG 的子群,则 a,bG\forall a,b\in G 有:

      aHbab1HHa=Hba\in Hb\Longleftrightarrow ab^{-1}\in H\Longleftrightarrow Ha=Hb


      循环论证:


      (1)aHbab1Ha\in Hb\Longrightarrow ab^{-1}\in H

      aHba\in Hb ,即存在 hHh\in H 使得 a=hba=hb 。从而 ab1hHab^{-1}=h\in H


      (2)ab1HHa=Hbab^{-1}\in H\Longrightarrow Ha=Hb

      对于任意的 haHaha\in Ha ,这里 hHh\in H ,因此 hab1Hhab^{-1}\in H,从而:

      ha=hab1bHbha=hab^{-1}b\in Hb

      这表明 HaHbHa\subseteq Hb 。类似地,对任意的 hbHahb\in Ha ,这里 hHh\in H 。由于 ab1Hab^{-1}\in H ,则也有:

      ba1=(b1)1a1=(ab1)1Hba^{-1}=(b^{-1})^{-1}a^{-1}=(ab^{-1})^{-1}\in H

      因此 ha=hba1aHaha=hba^{-1}a\in Ha ,这表明 HbHaHb\subseteq Ha 。综合起来就有 Ha=BbHa=Bb


      (3)Ha=HbaHbHa=Hb\Longrightarrow a\in Hb

      Ha=HbHa=Hb ,则由 aHaa\in HaHH 是子群)可得 aHba\in Hb

      # 子群陪集构成等价关系

      HH 是群 GG 的子群,在 GG 上定义二元关系 RG×GR\in G\times G

      a,bG,aRbab1H\forall a,b\in G,\ \ \ a\text{R}b\Longleftrightarrow ab^{-1}\in H

      RRGG 上的等价关系,且 [a]R=Ha[a]_R=Ha


      证明

      上面已经证明了 ab1HHa=Hbab^{-1}\in H\Longleftrightarrow Ha=Hb,因此 aRbHa=Hba\text{R}b\Longleftrightarrow Ha= Hb

      从而 RR 确实是自反、对称和传递的,即 RR 是等价关系。

      对任意 bGb\in G ,我们有:

      bHaHb=HabRab[a]Rb\in Ha\Longleftrightarrow Hb=Ha\Longleftrightarrow b\text{R}a\Longleftrightarrow b\in[a]_R

      这就表明 Ha=[a]RHa=[a]_R

      # 子群陪集构成划分

      HGH≤G,则:

      • (i)a,bG\forall a,b\in G ,
        • Ha=HbHa=Hb
        • HaHb=Ha\cap Hb=\varnothing
      • (ii)U{HaaG}=G\mathbb U\{Ha|a\in G\}=G

      证明 —— 由等价类的性质立即可得。

      # 正规子群

      若对任意元素 aGa\in G 都有 aH=HaaH=Ha,即左右陪集相等,则称 HHGG 的正规子群,

      # 左右陪集关系

      一个子群的左陪集的所有元素的逆元素组成这个子群的一个右陪集

      符号化描述:

      HGH\leq GaGa\in G

      S={x1xaH}S=\{x^{-1}|x\in{aH}\}

      # 拉格朗日定理

      # 引理

      HHGG 的子群,对任意 aGa\in G ,有 H=aH=Ha|H|=|aH|=|Ha|,即这三个集合等势

      集合等势:若两个集合前存在双函数,即称它们等势。对于有限集,就是这两个集合有相同元素个数


      证明

      定义 φ:HHa\varphi:H\to Ha 为:

      hH,φ(h)=haHa\forall h\in H,\ \ \ \varphi(h)=ha\in Ha

      由群的消去律我们有:h1,h2H\forall h_1,h_2\in H

      φ(h1)=φ(h2)h1a=h2ah1=h2\varphi(h_1)=\varphi(h_2)\Longrightarrow h_1a=h_2a\Longrightarrow h_1=h_2

      从而 φ\varphi 是双函数,即 Ha=H|Ha|=|H|

      类似定义 φ:Ha\varphi':H\to a

      hH,φ(h)=ahaH\forall h\in H,\ \ \ \varphi'(h)=ah\in aH

      不难证明 aH=H|aH|=|H|

      # 指标

      HH 是群 GG 的子群。称子群 HH 在群 GG 中的左陪集或右陪集的个数(有限或无限)为 HHGG 中的指标 (index),记为 [G:H][G:H]

      也称 [G:H][G:H]GG 关于 HH 的陪集个数。

      # 拉格朗日定理

      HH 是有限群 GG 的子群,则:

      G=H[G:H]|G|=|H|\cdot[G:H]


      证明

      [G:H]=r[G:H]=r ,则子群 HH​ 有 rr 个不同的右陪集,设为 Ha1,Ha2,,HarH_{a_1},H_{a_2},\cdots,H_{a_r} 。由于 G=U{HaaG}G=U\{Ha|a\in G\} ,且对任意的 a,bGa,b\in GHa=HbHa=Hb 或者 HaHb=Ha\cap Hb=\varnothing ,因此:

      G=Ha1Ha2HarG=Ha1+Ha2++HarG=H_{a_1}\cup H_{a_2}\cup \cdots\cup H_{a_r}\\ |G|=|H_{a_1}|+|H_{a_2}|+\cdots+|H_{a_r}|

      而对任意的 aGa\in GHa=H|Ha|=|H| ,因此 G=rH=H[G:E]|G|=r|H|=|H|\cdot[G:E]

      # 推论 1 (元素阶与群阶的关系)

      GGnn 阶有限群,单位元是 ee ,则对 GG 的任意元素 aaaa 的阶 a|a|nn 的因子,且 an=ea^{n}=e


      证明

      对任意的 aGa\in G<a><a>GG 的子群,因此由拉格朗日定理 <a>|<a>|nn 的因子;

      但另一方面,若 a=r|a|=r ,则因 <a><a>aa 生成的子群,于是

      <a>={a0=e,a1,,ar1}<a>=\{a^{0}=e,a^{1},\cdots,a^{r-1}\}

      <a>=a=r|<a>|=|a|=r ,从而 a|a| 是群 G 的阶 n 的因子,进而由 == 定理 1.6?== 有 an=ea^{n}=e ,因为对任意的 mZm\in \mathbb{Z} , am=ea^{m}=e 当且仅当 rmr|m

      元素的阶是群的阶的因子;

      但并不是群的阶的每个因子,群都存在元素的阶恰好等于这个因子!

      # 推论 2 (费马小定理)

      pp 是素数,aa 是与 pp 互素的整数,则有:

      ap11(modp)a^{p-1}\equiv1(\bmod p)


      证明

      因为在群 U(p)U(p) ,即群 Zp\mathbb{Z}_p^* 中,由于 aapp 互素,aa(准确地说,aa 整除 pp 的余数)属于 Zp\mathbb{Z}_p^*

      Zp\mathbb{Z}_p^* 的阶是 p1p-1 ,因此 ap1a^{p-1} 等于单位元 1 ,对于 U(p)U(p) 的模 pp 乘运算而言,就是 ap11(modp)a^{p-1}\equiv 1(\bmod p)

      # 推论 3

      H,KH,K 都是 GG 的有限子群,证明:

      • (1) 记 S={hKhH}S=\{hK|h\in H\},则 SSHH划分,从而 HK=SK|HK|=|S|\cdot|K|
      • (2)HK=HKHK|HK|=\frac{|H|\cdot|K|}{|H\cap K|}

      (1)证明

      即证 h1Kh_1Kh2Kh_2K 要么相等,要么不相交

      h1K=h2Kh11h2Kh1Kh2K=h_1K=h_2K\lrArr h_1^{-1}h_2\in K\\ h_1K\cap h_2K=\varnothing


      (2)证明

      为方便起见,记 M=HKM=H\cap K ,由于 HHKK 都是 GG 的子群,因此 MM 也是 GG 的子群且也是 HH 的子群。

      定义函数 φ:H/MS\varphi:H/M\to S,对任意 hHh\in Hφ(hM)=hK\varphi(hM)=hK

      下面证明 φ\varphi 的定义是合适的,且是双函数,从而结合拉格朗日定理有 S=H/M=H/M|S|=|H/M|=|H|/|M| ,从而得到 HK=HKM|HK|=\frac{|H|\cdot|K|}{|M|}

      (a) 证明 φ\varphi 的定义是合适的:

      对任意 h1,h2Hh_1,h_2\in H ,若 h1M=h2Mh_1M=h_2M ,则 h11h2MKh_1^{-1}h_2\in M\subseteq K ,从而 φ(h1M)=φ(h2M)\varphi(h_1M)=\varphi(h_2M),这说明 φ(hM)\varphi(hM) 的值不会因为选取的代表 hh 不同面不同,即 φ\varphi 的定义是合适的。

      (b) 证明 φ\varphi 是单函数:

      对任意 h1,h2Hh_1,h_2\in H,若 φ(h1M)=φ(h2M)\varphi(h_1M)=\varphi(h_2M),即 h1K=h2Kh_1K=h_2K ,从而 h11h2Kh_1^{-1}h_2\in K

      h1,h2Hh_1,h_2\in H ,因此也有 h11h2Hh_1^{-1}h_2\in H

      从而 h11h2HK=Mh_1^{-1}h_2\in H\cap K=M

      从而 h1M=h2Mh_1M=h_2M ,这就表明 φ\varphi 是单函数。

      (c) 显然 φ\varphi 是满函数,对任意 hKShK\in S ,都有 φ(hM)=hk\varphi(hM)=hk

      因此 S=H/M|S|=|H/M| ,由拉格朗日定理有 S=H/M=H/M|S|=|H/M|=|H|/|M| ,最后得到:

      HK=HMK=HKHK|HK|=\frac{|H|}{|M|}|K|=\frac{|H|\cdot|K|}{|H\cap K|}

      # 举例

      不容易找到两个子群的交不等于 {e}\{e\} 的例子,利用计算机程序可找到如下的例子:U(33)={1,2,4,5,7,8,10,13,14,16,17,19,20,23,25,26,28,29,31,32}U(33)=\{1,2,4,5,7,8,10,13,14,16,17,19,20,23,25,26,28,29,31,32\}

      • 子群 {1,2,4,8,16,17,25,29,31,32}\{1,2,4,8,16,17,25,29,31,32\} 是循环子群,生成元为:2,8,17,292,8,17,29
      • 子群 {1,4,5,14,16,20,23,25,26,31}\{1,4,5,14,16,20,23,25,26,31\} 是循环子群,生成元为:5,14,20,265,14,20,26

      上述两个子群交集为 {1,4,16,25,31}\{1,4,16,25,31\}

      # 西罗定理

      可了解,不考

      GGnn 阶循环群,aa 是生成元。对于 nn 的每个正因子 kk , 有且仅有一个 kk 阶循环子群。并且由 anka^{\frac{n}{k}} 生成.

      \ No newline at end of file +子群的陪集 - 代数结构 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 群子集的乘积运算

      # 定义

      AABB 是群 GG 的两个非空子集,称集合:

      AB={abaA,bB}AB = \{ab|a\in A, b\in B \}

      为群的子集 AABB乘积 (product)

      如果 gGg\in G 为群 GG 的一个元素,A={g}A=\{g\} ,则:

      • ABAB 简记为 gB={gbbB}gB = \{gb|b\in B\}
      • BABA 简记为 Bg={bgbB}Bg = \{bg|b\in B\}

      注意,即使有 AB=BAAB=BA,也不意味着 aA,bB,ab=ba\forall a\in A, b\in B,\ \ \ ab =ba,正确的结论应该是:aA,bB,aA,bB,ab=ba\forall a\in A, b\in B,\ \ \ \exist a'\in A, b'\in B,\ \ \ ab = b'a'

      # 交换群的交换律

      GG交换群时,对 GG 的任意子集 A,BA,B ,满足交换律,有 AB=BAAB=BA ;但对于非交换群,一般没有 AB=BAAB=BA ,也就是没有交换律成立。

      # 满足结合律

      群的子集运算满足结合律:A(BC)=(AB)CA(BC) = (AB)C

      # 对单元素满足消去律

      gA=gBgA=gBAg=BgAg=Bg,则 A=BA=B

      但对普遍的

      AC=BC⇏A=BAC=BC\not\rArr A=B


      证明(不妨考虑 gA=gBgA=gB

      aA\forall a\in A,有 gagAga\in gA

      因为 gA=gBgA=gB ,所以 gagBga\in gB ,所以:

      bB,ga=gb\exist b\in B,\ \ \ ga=gb

      由群满足消去律可得:b=ab=a

      所以 a=bBa=b\in B ,所以有 ABA\sube B ;同理可证 BAB\sube A,从而可得 A=BA=B

      # 幂运算

      HH 是群 GG 的子群,则 HH=HHH=H

      # 乘积的子群充要条件

      如果 A,BA,B 是群 GG 的两个子群,则 ABAB 也是群 GG 的子群当且仅当 AB=BAAB=BA


      必要性: ABGAB=BAAB\leq G\rArr AB=BA

      对于 a,b,abAB\forall a,b,\ \ ab\in AB,只需证 abBAab\in BA

      由于 ABGAB\leq G ,所以 abAB,(ab)1=ab\exist a'b'\in AB,\ \ \ (ab)^{-1}=a'b'

      ab=((ab)1)1=(ab)1=b1a1BAab=((ab)^{-1})^{-1}=(a'b')^{-1}=b'^{-1}a'^{-1}\in BA

      从而可得 ABBAAB\sube BA ;同理可证 BAABBA\sube AB,从而可得 AB=BAAB=BA


      充分性: AB=BAABGAB=BA\rArr AB\leq G

      对于 a1,b1,a2,b2,a1b1,a2b2AB\forall a_1,b_1,a_2,b_2,\ \ \ a_1b_1,a_2b_2\in AB,有:a1b1(a2b2)1ABa_1b_1(a_2b_2)^{-1}\in AB

      a1b1(a2b2)1=a1b1b21a21=a1(b1b21)a21ABA=A(BA)=A(AB)=(AA)B=ABa_1b_1(a_2b_2)^{-1}=a_1b_1b_2^{-1}a_2^{-1}=a_1(b_1b_2^{-1})a_2^{-1}\\ \in ABA=A(BA)=A(AB)=(AA)B=AB

      从而由子群判定定理二可知 ABABGG 的子群

      # 乘积的子集关系

      A,B,CA,B,C 是群 GG 的非空子集(不一定是群),若 BCB⊆C ,则有 ABACAB⊆ACBABCBA⊆BC


      证明

      对任意 xABx\in AB ,则存在 aA,bBa\in A,b\in B,使得 x=abx=ab 。由 bBb\in B ,且 BCB⊆C,因此 bCb\in C,因此 x=abACx=ab\in AC ,因此 ABBCAB⊆BC

      对任意 xBAx\in BA ,则存在 aA,bBa\in A,b\in B ,使得 x=bax=ba 。由 bBb\in B ,且 BCB⊆C ,因此 bCb\in C ,因此 x=abACx=ab\in AC ,因此 BACABA⊆CA

      # 子群的陪集及其性质

      # 陪集定义

      GG 是群,HHGG 的子群

      对任意 aGa\in G,群 GG子集 aH={ahhH}aH=\{ah|h\in H\}Ha={hahH}Ha=\{ha|h\in H\} ,分别称为 HHGG 中的左陪集 (left coset) 和右陪集 (right coset)

      子群 HH 的所有右陪集构成的集合族 G\HG\backslash HGG 的一个划分

      子群 HH 的所有左陪集构成的集合族 G/HG/H 也是 GG 的一个划分

      注意陪集不一定是群了

      # 陪集举例

      对于群 (U(5),5)(U(5),⊗_5),子群 H={1,4}H=\{1,4\}

      5⊗_51234
      11234
      22413
      33142
      44321

      1H={151,154}={1,4}2H={251,254}=2,33H={351,354}={3,2}4H={451,454}={4,1}1H=\{1⊗_5 1,1⊗_5 4\}=\{1,4\}\\ 2H=\{2⊗_5 1,2⊗_5 4\}={2,3}\\ 3H=\{3⊗_5 1,3⊗_5 4\}=\{3,2\}\\ 4H=\{4⊗_5 1,4⊗_5 4\}=\{4,1\}

      HH 有两个不同的陪集 {1,4}\{1, 4\}{2,3}\{2,3\}


      对于下面的置换群 (G,)(G,\circ) ,子群 H={f1,f2}H=\{f_1, f_2\}

      \circf1f_1f2f_2f3f_3f4f_4f5f_5f6f_6
      f1f_1f1f_1f2f_2f3f_3f4f_4f5f_5f6f_6
      f2f_2f2f_2f1f_1f6f_6f5f_5f4f_4f3f_3
      f3f_3f3f_3f5f_5f1f_1f6f_6f2f_2f4f_4
      f4f_4f4f_4f6f_6f5f_5f1f_1f3f_3f2f_2
      f5f_5f5f_5f3f_3f4f_4f2f_2f6f_6f1f_1
      f6f_6f6f_6f4f_4f2f_2f3f_3f1f_1f5f_5

      f1H={f1f1,f1f2}={f1,f2}f2H={f2f1,f2f2}={f2,f1}f3H={f3f1,f3f2}={f3,f5}f4H={f4f1,f4f2}={f4,f6}f5H={f5f1,f5f2}={f5,f3}f6H={f6f1,f6f2}={f6,f4}Hf3={f1f3,f2f3}={f3,f6}Hf4={f1f4,f2f4}={f4,f5}Hf5={f1f5,f2f5}={f5,f4}Hf6={f1f6,f2f6}={f6,f3}f_1 H=\{f_1\circ f_1, f_1\circ f_2\}=\{f_1, f_2\}\\ f_2 H=\{f_2\circ f_1, f_2\circ f_2\}=\{f_2, f_1\}\\ f_3 H=\{f_3\circ f_1, f_3\circ f_2\}=\{f_3, f_5\}\\ f_4 H=\{f_4\circ f_1, f_4\circ f_2\}=\{f_4, f_6\}\\ f_5 H=\{f_5\circ f_1, f_5\circ f_2\}=\{f_5, f_3\}\\ f_6 H=\{f_6\circ f_1, f_6\circ f_2\}=\{f_6, f_4\}\\ Hf_3=\{f_1\circ f_3, f_2\circ f_3\}=\{f_3, f_6\}\\ Hf_4=\{f_1\circ f_4, f_2\circ f_4\}=\{f_4, f_5\}\\ Hf_5=\{f_1\circ f_5, f_2\circ f_5\}=\{f_5, f_4\}\\ Hf_6=\{f_1\circ f_6, f_2\circ f_6\}=\{f_6, f_3\}

      HH 有三个不同的陪集,且左右陪集不相等,例如 f3HHf3f_3H≠Hf_3

      # 不同元素陪集相同充要条件

      a,bG\forall a,b\in G

      • Ha=HbHa=Hb 当且仅当 aHba\in Hb 当且仅当 ab1Hab^{-1}\in H
      • aH=bHaH=bH 当且仅当 abHa\in bH 当且仅当 b1aHb^{-1}a\in H

      # 陪集不变的充要条件

      HH 是群 GG 的子群,对任意的 aGa\in G

      • HaHHa=H 的充分必要条件是 aHa\in H

      引理

      eHe\in H ,所以 aeaHaa=ea\in Ha


      证明

      必要性:若 HaHHa=H ,则因为 aHaa\in Ha ,从而 aHa\in H

      充分性:反之若 aHa\in H ,则对任意 haHaha\in Ha ,由 HH 对群运算封闭,也有 haHha\in H ,从而有 HaHHa\subseteq H

      而这时对任意 hHh\in H ,由 aHa\in Ha1Ha^{-1}\in H ,从而 ha1Hha^{-1}\in H ,从而有 hha1aHah=ha^{-1}a\in Ha ,即有 HHaH\subseteq Ha

      于是又 HaH,HHaHa\subseteq H,H\subseteq Ha 得到 Ha=HHa=H

      # 陪集的子群充要条件

      HH 是群 GG 的子群,对任意的 aGa\in G

      • 右陪集 HaHaGG 的子群当且仅当 Ha=HHa=H 当且仅当 aHa\in H
      • 左陪集 aHaHGG 的子群当且仅当 aH=HaH=H 当且仅当 aHa\in H

      证明以右陪集为例:

      必要性:若 HaGHa\leq G ,所以 eHae\in Ha ,从而存在 hHh\in H 使得 ehae=ha ,从而 ah1e=h1Ha=h^{-1}e=h^{-1}\in H

      充分性:若 aHa\in H ,则 HaHHa=H 是子群。

      # 子群陪集运算性质

      HH 是群 GG 的子群,则 a,bG\forall a,b\in G 有:

      aHbab1HHa=Hba\in Hb\Longleftrightarrow ab^{-1}\in H\Longleftrightarrow Ha=Hb


      循环论证:


      (1)aHbab1Ha\in Hb\Longrightarrow ab^{-1}\in H

      aHba\in Hb ,即存在 hHh\in H 使得 a=hba=hb 。从而 ab1hHab^{-1}=h\in H


      (2)ab1HHa=Hbab^{-1}\in H\Longrightarrow Ha=Hb

      对于任意的 haHaha\in Ha ,这里 hHh\in H ,因此 hab1Hhab^{-1}\in H,从而:

      ha=hab1bHbha=hab^{-1}b\in Hb

      这表明 HaHbHa\subseteq Hb 。类似地,对任意的 hbHahb\in Ha ,这里 hHh\in H 。由于 ab1Hab^{-1}\in H ,则也有:

      ba1=(b1)1a1=(ab1)1Hba^{-1}=(b^{-1})^{-1}a^{-1}=(ab^{-1})^{-1}\in H

      因此 ha=hba1aHaha=hba^{-1}a\in Ha ,这表明 HbHaHb\subseteq Ha 。综合起来就有 Ha=BbHa=Bb


      (3)Ha=HbaHbHa=Hb\Longrightarrow a\in Hb

      Ha=HbHa=Hb ,则由 aHaa\in HaHH 是子群)可得 aHba\in Hb

      # 子群陪集构成等价关系

      HH 是群 GG 的子群,在 GG 上定义二元关系 RG×GR\in G\times G

      a,bG,aRbab1H\forall a,b\in G,\ \ \ a\text{R}b\Longleftrightarrow ab^{-1}\in H

      RRGG 上的等价关系,且 [a]R=Ha[a]_R=Ha


      证明

      上面已经证明了 ab1HHa=Hbab^{-1}\in H\Longleftrightarrow Ha=Hb,因此 aRbHa=Hba\text{R}b\Longleftrightarrow Ha= Hb

      从而 RR 确实是自反、对称和传递的,即 RR 是等价关系。

      对任意 bGb\in G ,我们有:

      bHaHb=HabRab[a]Rb\in Ha\Longleftrightarrow Hb=Ha\Longleftrightarrow b\text{R}a\Longleftrightarrow b\in[a]_R

      这就表明 Ha=[a]RHa=[a]_R

      # 子群陪集构成划分

      HGH≤G,则:

      • (i)a,bG\forall a,b\in G ,
        • Ha=HbHa=Hb
        • HaHb=Ha\cap Hb=\varnothing
      • (ii)U{HaaG}=G\mathbb U\{Ha|a\in G\}=G

      证明 —— 由等价类的性质立即可得。

      # 正规子群

      若对任意元素 aGa\in G 都有 aH=HaaH=Ha,即左右陪集相等,则称 HHGG 的正规子群,

      # 左右陪集关系

      一个子群的左陪集的所有元素的逆元素组成这个子群的一个右陪集

      符号化描述:

      HGH\leq GaGa\in G

      S={x1xaH}S=\{x^{-1}|x\in{aH}\}

      # 拉格朗日定理

      # 引理

      HHGG 的子群,对任意 aGa\in G ,有 H=aH=Ha|H|=|aH|=|Ha|,即这三个集合等势

      集合等势:若两个集合前存在双函数,即称它们等势。对于有限集,就是这两个集合有相同元素个数


      证明

      定义 φ:HHa\varphi:H\to Ha 为:

      hH,φ(h)=haHa\forall h\in H,\ \ \ \varphi(h)=ha\in Ha

      由群的消去律我们有:h1,h2H\forall h_1,h_2\in H

      φ(h1)=φ(h2)h1a=h2ah1=h2\varphi(h_1)=\varphi(h_2)\Longrightarrow h_1a=h_2a\Longrightarrow h_1=h_2

      从而 φ\varphi 是双函数,即 Ha=H|Ha|=|H|

      类似定义 φ:Ha\varphi':H\to a

      hH,φ(h)=ahaH\forall h\in H,\ \ \ \varphi'(h)=ah\in aH

      不难证明 aH=H|aH|=|H|

      # 指标

      HH 是群 GG 的子群。称子群 HH 在群 GG 中的左陪集或右陪集的个数(有限或无限)为 HHGG 中的指标 (index),记为 [G:H][G:H]

      也称 [G:H][G:H]GG 关于 HH 的陪集个数。

      # 拉格朗日定理

      HH 是有限群 GG 的子群,则:

      G=H[G:H]|G|=|H|\cdot[G:H]


      证明

      [G:H]=r[G:H]=r ,则子群 HH​ 有 rr 个不同的右陪集,设为 Ha1,Ha2,,HarH_{a_1},H_{a_2},\cdots,H_{a_r} 。由于 G=U{HaaG}G=U\{Ha|a\in G\} ,且对任意的 a,bGa,b\in GHa=HbHa=Hb 或者 HaHb=Ha\cap Hb=\varnothing ,因此:

      G=Ha1Ha2HarG=Ha1+Ha2++HarG=H_{a_1}\cup H_{a_2}\cup \cdots\cup H_{a_r}\\ |G|=|H_{a_1}|+|H_{a_2}|+\cdots+|H_{a_r}|

      而对任意的 aGa\in GHa=H|Ha|=|H| ,因此 G=rH=H[G:E]|G|=r|H|=|H|\cdot[G:E]

      # 推论 1 (元素阶与群阶的关系)

      GGnn 阶有限群,单位元是 ee ,则对 GG 的任意元素 aaaa 的阶 a|a|nn 的因子,且 an=ea^{n}=e


      证明

      对任意的 aGa\in G<a><a>GG 的子群,因此由拉格朗日定理 <a>|<a>|nn 的因子;

      但另一方面,若 a=r|a|=r ,则因 <a><a>aa 生成的子群,于是

      <a>={a0=e,a1,,ar1}<a>=\{a^{0}=e,a^{1},\cdots,a^{r-1}\}

      <a>=a=r|<a>|=|a|=r ,从而 a|a| 是群 G 的阶 n 的因子,进而由 == 定理 1.6?== 有 an=ea^{n}=e ,因为对任意的 mZm\in \mathbb{Z} , am=ea^{m}=e 当且仅当 rmr|m

      元素的阶是群的阶的因子;

      但并不是群的阶的每个因子,群都存在元素的阶恰好等于这个因子!

      # 推论 2 (费马小定理)

      pp 是素数,aa 是与 pp 互素的整数,则有:

      ap11(modp)a^{p-1}\equiv1(\bmod p)


      证明

      因为在群 U(p)U(p) ,即群 Zp\mathbb{Z}_p^* 中,由于 aapp 互素,aa(准确地说,aa 整除 pp 的余数)属于 Zp\mathbb{Z}_p^*

      Zp\mathbb{Z}_p^* 的阶是 p1p-1 ,因此 ap1a^{p-1} 等于单位元 1 ,对于 U(p)U(p) 的模 pp 乘运算而言,就是 ap11(modp)a^{p-1}\equiv 1(\bmod p)

      # 推论 3

      H,KH,K 都是 GG 的有限子群,证明:

      • (1) 记 S={hKhH}S=\{hK|h\in H\},则 SSHH划分,从而 HK=SK|HK|=|S|\cdot|K|
      • (2)HK=HKHK|HK|=\frac{|H|\cdot|K|}{|H\cap K|}

      (1)证明

      即证 h1Kh_1Kh2Kh_2K 要么相等,要么不相交

      h1K=h2Kh11h2Kh1Kh2K=h_1K=h_2K\lrArr h_1^{-1}h_2\in K\\ h_1K\cap h_2K=\varnothing


      (2)证明

      为方便起见,记 M=HKM=H\cap K ,由于 HHKK 都是 GG 的子群,因此 MM 也是 GG 的子群且也是 HH 的子群。

      定义函数 φ:H/MS\varphi:H/M\to S,对任意 hHh\in Hφ(hM)=hK\varphi(hM)=hK

      下面证明 φ\varphi 的定义是合适的,且是双函数,从而结合拉格朗日定理有 S=H/M=H/M|S|=|H/M|=|H|/|M| ,从而得到 HK=HKM|HK|=\frac{|H|\cdot|K|}{|M|}

      (a) 证明 φ\varphi 的定义是合适的:

      对任意 h1,h2Hh_1,h_2\in H ,若 h1M=h2Mh_1M=h_2M ,则 h11h2MKh_1^{-1}h_2\in M\subseteq K ,从而 φ(h1M)=φ(h2M)\varphi(h_1M)=\varphi(h_2M),这说明 φ(hM)\varphi(hM) 的值不会因为选取的代表 hh 不同面不同,即 φ\varphi 的定义是合适的。

      (b) 证明 φ\varphi 是单函数:

      对任意 h1,h2Hh_1,h_2\in H,若 φ(h1M)=φ(h2M)\varphi(h_1M)=\varphi(h_2M),即 h1K=h2Kh_1K=h_2K ,从而 h11h2Kh_1^{-1}h_2\in K

      h1,h2Hh_1,h_2\in H ,因此也有 h11h2Hh_1^{-1}h_2\in H

      从而 h11h2HK=Mh_1^{-1}h_2\in H\cap K=M

      从而 h1M=h2Mh_1M=h_2M ,这就表明 φ\varphi 是单函数。

      (c) 显然 φ\varphi 是满函数,对任意 hKShK\in S ,都有 φ(hM)=hk\varphi(hM)=hk

      因此 S=H/M|S|=|H/M| ,由拉格朗日定理有 S=H/M=H/M|S|=|H/M|=|H|/|M| ,最后得到:

      HK=HMK=HKHK|HK|=\frac{|H|}{|M|}|K|=\frac{|H|\cdot|K|}{|H\cap K|}

      # 举例

      不容易找到两个子群的交不等于 {e}\{e\} 的例子,利用计算机程序可找到如下的例子:U(33)={1,2,4,5,7,8,10,13,14,16,17,19,20,23,25,26,28,29,31,32}U(33)=\{1,2,4,5,7,8,10,13,14,16,17,19,20,23,25,26,28,29,31,32\}

      • 子群 {1,2,4,8,16,17,25,29,31,32}\{1,2,4,8,16,17,25,29,31,32\} 是循环子群,生成元为:2,8,17,292,8,17,29
      • 子群 {1,4,5,14,16,20,23,25,26,31}\{1,4,5,14,16,20,23,25,26,31\} 是循环子群,生成元为:5,14,20,265,14,20,26

      上述两个子群交集为 {1,4,16,25,31}\{1,4,16,25,31\}

      # 西罗定理

      可了解,不考

      GGnn 阶循环群,aa 是生成元。对于 nn 的每个正因子 kk , 有且仅有一个 kk 阶循环子群。并且由 anka^{\frac{n}{k}} 生成.

      \ No newline at end of file diff --git a/math/discrete-math/algebra/group-basics/index.html b/math/discrete-math/algebra/group-basics/index.html index 2fd252d9..a944f8fb 100644 --- a/math/discrete-math/algebra/group-basics/index.html +++ b/math/discrete-math/algebra/group-basics/index.html @@ -1 +1 @@ -群论基础 - 代数结构 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 群 (Group) 的定义

      如果集合 G 及其二元运算 \cdot 满足下面的性质,则称 (G,)(G,\cdot ) 是群:

      • 二元运算 \cdot 满足结合律:即 a,b,cG∀a,b,c\in G(ab)c=a(bc)(a\cdot b)\cdot c=a\cdot(b\cdot c)
      • 单位元 ee,即存在 eGe\in G,使得 aG∀a\in Gea=ae=ae\cdot a=a\cdot e=a
      • aG∀a\in G 关于 \cdot逆元 a1a^{-1},即 aG∀a\in G,存在 bGb\in G,使得 ab=ba=ea\cdot b=b\cdot a=e,记 bba1a^{-1}

      从代数系统角度说,群有三个运算:

      • 二元运算 \cdot
      • 一元运算 ()1(-)^{-1}
      • 零元运算 ee

      其中二元运算占主导地位,在谈到群时经常只明确给出它的二元运算。进一步,在上下文能明确其运算时,人们通常直接称集合 GG 是群

      如果集合 SS 有满足结合律的二元运算 \cdot ,则称 (S,)(S,\cdot)半群 (semi-group)

      如果 \cdot 还有单位元 ee,则称 (S,,e)(S,\cdot,e)独异点 (monoid)

      # 常用群举例

      # 整数加群

      整数集 Z 及整数加法运算构成群,称为整数加群

      • 单位元是 00
      • 每个整数 zz 的逆元是 z-z

      # 模 m 剩余类加群 Zm\mathbb{Z}_m

      对整数 m2m≥2,记 Zm={0,1,,m1}\mathbb{Z}_m=\{0,1,\cdots,m-1\}Zm\mathbb{Z}_m 及 模 mmm\oplus_m 构成群,称为mm 剩余类加群

      00 是单位元,对每个整数 zZmz\in \mathbb Z_m,它的逆元是 ((z)+m)modm((-z)+m)\bmod m

      模m剩余类加法群

      # Q\mathbb{Q^*} R\mathbb{R^*} C\mathbb{C^*} 乘法群

      整数集 Z\mathbb Z 关于整数乘法不构成群,但非零有理数集Q\mathbb Q^*、非零实数集 R\mathbb R^*、非零复数集 C\mathbb C^* 关于数的乘法运算构成群

      # 实矩阵乘法群

      实数域上的 n 阶方阵构成的集合为 Mn(R)M_n (\mathbb R),则它关于矩阵加法构成群;记实数域上的 n 阶可逆方阵构成的集合为 GLn(R)GL_n (\mathbb R),则它关于矩阵乘法构成群

      # 双函数复合群

      集合 S 上的所有双函数 f:SSf:S→S 及复合构成群

      • 恒等函数是单位元
      • 逆函数给出逆元

      # 模 m 单位群 U (m)

      Zm\mathbb Z_m 及 模 m 乘 m⊗_m 不构成群,但令U(m)={aaZm且a与m互质}U(m)=\{a∣a\in Z_m \text{且a与m互质}\},则 U (m) 与m⊗_m 构成群,称为模 m 单位群

      • 1 是单位元
      • 对每个整数 zU(m)z\in U(m),它的逆元是同余方程 xz1(modm)xz≡1(\text{mod} m) 的解
        • 利用贝祖定理(即 a,bZ+s,tZ,gcd(a,b)=as+bt∀a,b\in \mathbb Z^+,\exist s, t\in \mathbb Z,gcd⁡(a,b)=as+bt)可证明 U (m) 对 m⊗_m 封闭,以及上述同余方程解的存在性,也即逆元的存在性

      当 p 是素数,则 U (p) 群也记为 Zp\mathbb Z_p^*

      模 m 单位群的阶:U(m)=ϕ(m)|U(m)|=ϕ(m),这里 ϕ(m)ϕ(m) 是欧拉函数,即:

      U(m)=ϕ(m)=mi=1s(11pi)|U(m)|=ϕ(m)=m\prod_{i=1}^{s}(1-\frac{1}{p_i} )

      这里 p1,,psp_1,⋯, p_s 是 m 的 s 个不同的素因子

      # 具体群举例

      1

      2

      3克莱因4元群

      4

      # 群的一些术语

      # 交换群

      群的运算不一定满足交换律,满足交换律的群称为交换群,也称为阿贝尔群

      # 群的阶

      群 G 的元素个数(准确地说 G 的基数)|G | 称为群 G 的阶 (order),如果 G 是有穷集,则称为有穷群(有限群),否则称为无穷群(无限群)

      # 加群

      当群称为加群时通常将它:

      • 单位元记为 0
      • 元素 a 的逆元记为 - a
      • 运算称为加法
      • 运算的结果称为和
      • 运算用加号 + 表示

      通常只有当群是交换群的时候,才使用加号 '+' 表示这个群的运算

      # 乘群

      将不是加群的群称为乘群,并将:

      • 乘群的单位元通常用 1 或 e 表示
      • 元素 a 的逆元用a1a^{-1} 表示
      • 运算称为乘法
      • 运算结果称为积
      • 运算用 \circ\cdot 或 * 表示,但通常省略不写!

      # 群的一些基本性质

      群有单位元,因此群不可能是空集

      群要求每个元素都有逆元,而运算的零元不可能有逆,因此群没有零元(除平凡群 ({e},)(\{e\},\circ) 外)!

      # 逆运算基本性质

      GG 是群,有:

      aG(a1)1=a∀a\in G,(a^{-1})^{-1}= a

      a,bG,(ab)1=b1a1∀a, b\in G, (ab)^{-1}= b^{-1} a^{-1}


      证明

      根据逆元的定义有 aaa1a^{-1} 互为逆元。

      (b^{-1} a^{-1})(ab)=b^{-1}(a^{-1}a)b=b^{-1}eb=b^{-1} b=e$

      类似地:

      ab(b1a1)=eab(b^{-1}a^{-1})=e

      因此 ababb1a1b^{-1}a^{-1} 互为逆元。

      # 群满足消去律

      群的二元运算满足消去律

      GG 是群,对任意 a,b,cGa,b,c\in G, ab=acab=ac 蕴涵 b=cb=c ,同样 ba=caba=ca 蕴涵 b=cb=c


      证明

      ab=acab=ac,则有 a1(ab)=a1(ac)a^{-1}(ab)=a^{-1} (ac)

      而群运算满足结合律,因此 (a1a)b=(a1a)c(a^{-1} a)b=(a^{-1} a)c

      a1a=ea^{-1} a=eee 是单位元,从而有 b=cb=c

      同理可证 ba=caba=ca 蕴涵 b=cb=c

      # 群的充要条件 1

      给定非空集 GG 及其上的二元运算(假定是乘法运算而省略其运算符号)。GG 关于该二元运算构成群的充分必要条件是:

      • GG 的二元运算满足结合律
      • GG 的二元运算有左单位元:即存在 eGe\in G 使得对任意的 aGa\in Gea=aea=a
      • GG 的每个元素相对左单位元有左逆元:即 aG\forall a\in G,存在 aGa'\in G 使得 aa=ea'a=e

      “左” 换成 “右” 也一样

      证明:

      aG,aG,aa=eaaa=aa(aa)=aae=a\forall a\in G,\ \ \exist a'\in G,\ \ a'a=e\\ aa'a=a\\ a(a'a)=a\\ ae=a

      所以 e 也是右单位元;

      aG,aG,aa=eaG,aa=eaa=eaa=aaaa=a(aa)a=aea=aa=e\forall a\in G,\ \ \exist a'\in G,\ \ a'a=e\\ \exist a''\in G,\ \ a''a'=e \\ aa'=eaa'=a''a'aa'=a''(a'a)a'=a''ea'=a''a'=e

      所以 每个元素的左逆元也是右逆元。

      # 群的充要条件 2

      给定非空集 GG 及其二元运算,且该二元运算满足结合律GG 构成群的充分必要条件是:

      对任意的 a,bGa,b\in G,方程 ax=bax=bya=bya=bGG 中都有解。

      # 问题 5

      给定非空集 GG 及其上的二元运算(假定是乘法运算而省略其运算符号)满足:

      • 该运算有左单位元 ee ,即 aG∀a\in Gea=aea=a
      • 对关于该左单位元,每个元素有右逆,即任意 aGa\in G ,存在 bb 使得 ab=eab=e

      请问 GG 关于该运算是否一定构成群?

      # 群的充要条件 3

      给定非空有限集 GG 及其二元运算,该二元运算满足结合律满足消去律,即对任意 a,b,cGa, b, c\in Gab=acab = ac 蕴含 b=cb = c 以及 ba=caba = ca 蕴含 b=cb = c

      证明 GG 关于该运算构成群。

      # 群的幂运算

      # 定义

      (G,)(G,\circ) 是群,定义群的幂运算:aG,nZ∀a\in G, ∀n\in Z ,定义 aann 次幂,记为 ana^n

      群元素的阶

      # 加群的幂运算

      对于加群,元素的幂运算实际上是倍数运算

      • 例如对于整数加群 (Z,+)(Z, +) ,整数 zznn 次幂实际上是 nznz 。这时有:
        • 0z=00z=0
        • (nz)=n(z)(-nz)= n(-z)
        • nz+mz=(n+m)znz + mz = (n+m)z
        • m(nz)=(mn)zm(nz)= (mn)z

      # 基本性质

      (G,)(G, \circ) 是群,对任意 aG,m,nZa\in G,\ \ m, n\in Z ,有:

      anam=an+m(an)m=anma^n\circ a^m= a^{n+m}\\(a^n )^m=a^{nm}


      证明

      • 先对于 m0m≥0,对 mm 实施数学归纳法;
      • 再对于 m<0m<0 ,利用 am=(a1)ma^m=(a^{-1})^{-m}

      # 常用性质

      a,ba,b 是群 GG 的元素,容易得到:

      nZ,(aba1)n=abna1\forall n\in \mathbb Z\ ,\ (aba^{-1} )^n=ab^n a^{-1}

      # 群元素的阶

      # 定义

      (G,)(G,∘) 元素 aa阶 (order),记为 a|a| ,是指最小的正整数 kk 使得 ak=ea^k=e ,若这样的正整数不存在,则称元素 aa 的阶无穷

      # 任意幂的阶

      GG 是群,ee 是其单位元,aaGG 的任意元素,且 a=n|a|=n

      • 对任意整数 mmam=ea^m=e 当且仅当 nmn|m
      • 特别的,m=1m=-1 时,a1=n|a^{-1}|=n
      • 对任意整数 mm : am=ngcd(n,m)|a^m| = \frac{n}{gcd(n, m)}

      定理9证明

      # 阶内运算可轮换

      a,b,ca,b,c 是群 GG 的元素,证明:

      • a=a1=cac1|a|=|a^{-1}|=|cac^{-1}|
      • ab=ba|ab|=|ba|
      • abc=bca=cab|abc|=|bca|=|cab|

      (2) 因为 ab=a(ba)a1ab = a(ba)a^{-1} ,所以由 (1) 可知:

      ab=a(ba)a1=ba|ab|=|a(ba)a^{-1}|=|ba|


      (3) 因为:

      • abc=a(bc)abc=a(bc)
      • bca=(bc)abca=(bc)a
      • cab=(ca)bcab=(ca)b

      因此由 (1) 可知:

      abc=a(bc)=(bc)a=bca=b(ca)=(ca)b=cab|abc|=|a(bc)|=|(bc)a|=|bca|=|b(ca)|=|(ca)b|=|cab|

      虽然 abc=bca|abc|=|bca| ,但是 abcbac|abc|\neq|bac| !这与置换群有关

      # 子群

      # 定义

      GG 是群,HHGG 的子集,如果 HH 关于 GG 的运算也构成群,则称 HHGG 的子群,记为:

      HGH\leq G

      HHGG 的子群,且 HGH≠G ,则称 HHGG真子群,记为:

      H<GH\lt G

      显然 H={e}H=\{e\}GG 的子群,这里 eeGG 的单位元,将 {e}\{e\}GG 自己称为群 GG平凡子群,其他子群称为非平凡子群

      从代数系统角度说,子群就是子代数,下面定理说明子群对群的三个运算都封闭!

      # 子群判定定理 1

      给定 GG 是群,HGH⊆G 关于 GG 的运算构成群,也就是 HHGG 的子群当且仅当:

      • HHGG 的 (二元) 运算封闭
      • HH 对零元运算封闭,即 GG 的单位元应属于 HH
      • HH 对一元运算封闭,即 aH,a1H\forall a\in H,\ \ a^{-1}\in H

      # 子群判定定理 2

      群 G 的非空子集 H 是 G 的子群当且仅当:

      • eHe\in H
      • a,bH,abH∀a, b\in H,\ \ \ ab\in H

      子群判定定理一证明1子群判定定理一证明2

      实际上是构造 aa=ajia^{|a|} = a^{j-i} ,其中 a>0|a|>0aa 的阶

      # 子群判定定理 3

      群 G 的非空子集 H 是 G 的子群当且仅当:

      • a,bH,ab1H∀a, b\in H,\ \ \ ab^{-1}\in H
      • a,bH,b1aH∀a, b\in H,\ \ \ b^{-1}a\in H

      # 群的中心

      定义群 G 的中心

      C={aGxG,xa=ax}C=\{a\in G∣∀x\in G, xa=ax\}

      即 C 是 G 中那些与 G 的任何元素都可交换的元素构成的集合.

      证明:C 是 G 的子群 ( CGC\leq G )

      • 首先 C 是否是非空集?哪个元素一定属于 C?
      • 其次,如何运用子群的判定定理证明 C 是 G 的子群?
        • 例如利用子群判定定理二,如何证明对任意 a, b\in C,都有 ab-1\in C ?
        • 或者利用子群判定定理一,证明对任意 a\in C 有 a-1\in C,以及对任意 a,b\in C 有 ab\in C ?

      首先,由群的性质:xG,xe=ex=e\forall x\in G,\ \ \ xe=ex=e ,所以 eCe\in C ,因此 C 非空

      a,bC\forall a,b\in C ,为证明 ab1Cab^{-1}\in C 只需证明它与 G 中所有元素都可交换即可。

      xG\forall x\in G ,有:

      (ab1)x=ab1(x1)1=a(x1b)1=bCa(bx1)1=a(xb1)=结合律(ax)b1=aC(xa)b1=结合律x(ab1)\begin{aligned} (ab^{-1})x &=ab^{-1}(x^{-1})^{-1}\\ &=a(x^{-1}b)^{-1}\\ &\overset{b\in C}{=}a(bx^{-1})^{-1}\\ &=a(xb^{-1})\\ &\overset{\text{结合律}}{=}(ax)b^{-1}\\ &\overset{a\in C}{=}(xa)b^{-1}\\ &\overset{\text{结合律}}{=}x(ab^{-1}) \end{aligned}

      # 交并与子群的关系

      GG 是群,且 HGH≤G , KGK≤G ,证明:

      • $ H\cap K≤G$(交保持子群,可推广)
      • $ H∪K≤G$ 当且仅当 HKH⊆KKHK⊆H并保持子群的充要条件

      问题15证明1问题15证明2

      # 生成子群

      简单地说,群 GG 的一个子集的生成子群就是包含这个子集的最小的子群。群 GG 的子集 SS 的生成子群记为:

      S⟨S⟩

      两个子群的交总是子群这个命题可推广到任意多个子群的交也总是子群,从而对于群 GG 的某个子集 SS ,可给出包含 SS 的最小子群,这个子群就是 SS生成子群 S⟨S⟩ ,可由所有包含 SS 的子群的交给出,即:

      <S>={HSHHG}\text{<}S\text{>}=\cap\{H|S\subseteq H \land H\leq G\}

      • 如果 SS 为有限集 S={a1,a2,,an}S=\{a_1, a_2,\cdots,a_n\} ,将 S⟨S⟩ 直接记为 a1,a2,,an⟨a_1, a_2,\cdots,a_n ⟩
      • 对于群 GG ,若存在 aGa\in G ,使得 G=aG=⟨a⟩ ,即 GG 是由元素 aa 生成的群,这时称 G 为循环群

      空集生成的子群是什么?

      # 生成子群元素的表示

      GG 是群,SSGG 的非空子集,则:

      S={a1l1a2l2...aklkaiS,li=±1,kN}⟨S⟩=\cap\{a_{1}^{l_{1}}a_{2}^{l_{2}}...a_{k}^{l_{k}}| a_{i}\in S,\ \ \ l_{i}=\pm 1,\ \ \ k\in\mathbb{N} \}

      S⟨S⟩ 的任意元素可表示成有限个 S 的元素或其逆的乘积

      问题16证明

      S={a}S=\{a\} 时,即有 ⟨a⟩=\

      # 循环群

      GG 是群,如果存在 aGa\in G 使得

      G=a={akkZ}G=⟨a⟩=\{a^k | k\in Z\}

      则称 GG循环群 (cyclic group),并称 aaGG 的一个生成元

      • GG 是无限集时称为无限循环群
      • GGnn 个元素时,称为 n 阶循环群

      # 性质 (不考证明)

      GG 是群,ee 是它的单位元

      1. a1=a⟨a^{-1}⟩= ⟨a⟩
      2. GG 是有限群,则 G=aG=aG=⟨a⟩⟺|G|= |a|
      3. GG 是无限循环群,则
        • G={e,a,a1,a2,a2,,an,an,}G = \{e, a, a^{-1}, a^2, a^{-2}, ⋯, a^n, a^{-n}, ⋯\}
        • k,lZ,ak=alk=l\forall k, l\in Z,\ \ \ a^k= a^l⟺k= l
      4. GGnn 阶循环群,则
        • G={e,a,a2,a3,,an1}G = \{e, a, a^2, a^{3}, ⋯, a^{n-1}\}
        • k,lZ,ak=alnkl\forall k, l\in Z,\ \ \ a^k = a^l ⟺n | k-l

      # 循环群举例

      整数加群 Z\mathbb Z 是无限循环群

      显然 Z=1=1\mathbb Z= ⟨1⟩= ⟨-1⟩ , 即 1 和 -1 是它的生成元

      对任意 dZd\in \mathbb Z ,若 d±1d≠±1 ,显然有 1∉d1\not\in⟨d⟩ ,因此 1 和 -1 是 Z\mathbb Z 的仅有的两个生成元。


      mm 加群 Zm\mathbb Z_mmm 阶循环群,显然 Zm=1\mathbb Z_m=⟨1⟩


      U(5)U(5) 是 4 阶循环群,U(5)=2=3U(5)=⟨2⟩=⟨3⟩

      mm 是素数时,U(m)U(m)m1m-1 阶循环群(证明这个需要不少数论知识)

      mm 不是素数时:

      • U(m)U(m) 可能是循环群(例如 U(9)={1,2,4,5,7,8}=2U(9)=\{1,2,4,5,7,8\}=⟨2⟩
      • 也可能不是循环群(例如U(15)={1,2,4,7,8,11,13,14}U(15)=\{1,2,4,7,8,11,13,14\}

      # 生成元的数量与结构

      定理17


      定理17证明

      # 子群保持循环群

      循环群的任意子群都是循环群


      定理18证明

      # 问题

      如果一个群的所有非平凡子群都是循环群,那么这个群一定是循环群吗?

      不一定

      U(12)={1,5,7,11}U(12)=\{1,5,7,11\} 不是循环群,但它的每个非平凡子群都是循环群!

      1=1,5=2,7=2,11=2|1|=1 , |5| = 2 , |7| = 2 , |11| = 2 ,可见 U(12)U(12) 的所有非平凡子群都是二阶群,不难证明所有二阶群都是循环群

      # 生成元任意幂的生成子群

      推论19

      # 循环群的子群⭐️

      推论20

      推论20证明1推论20证明2

      例题:

      Z14\mathbb{Z}_{14} 加群的所有子群是:

      • 1=Z14⟨1⟩=\mathbb{Z}_{14}
      • 2={0,2,4,6,8,10,12,14}⟨2⟩=\{0,2,4,6,8,10,12,14\}
      • 7={0,7}⟨7⟩=\{0,7\}
      • 0=0⟨0⟩={0}

      U(14)U(14) 的所有子群是:

      • 3⟨3⟩
      • 32=9⟨3^2=9⟩
      • 33=13⟨3^3=13⟩
      • 36=1⟨3^6=1⟩
      \ No newline at end of file +群论基础 - 代数结构 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 群 (Group) 的定义

      如果集合 G 及其二元运算 \cdot 满足下面的性质,则称 (G,)(G,\cdot ) 是群:

      • 二元运算 \cdot 满足结合律:即 a,b,cG∀a,b,c\in G(ab)c=a(bc)(a\cdot b)\cdot c=a\cdot(b\cdot c)
      • 单位元 ee,即存在 eGe\in G,使得 aG∀a\in Gea=ae=ae\cdot a=a\cdot e=a
      • aG∀a\in G 关于 \cdot逆元 a1a^{-1},即 aG∀a\in G,存在 bGb\in G,使得 ab=ba=ea\cdot b=b\cdot a=e,记 bba1a^{-1}

      从代数系统角度说,群有三个运算:

      • 二元运算 \cdot
      • 一元运算 ()1(-)^{-1}
      • 零元运算 ee

      其中二元运算占主导地位,在谈到群时经常只明确给出它的二元运算。进一步,在上下文能明确其运算时,人们通常直接称集合 GG 是群

      如果集合 SS 有满足结合律的二元运算 \cdot ,则称 (S,)(S,\cdot)半群 (semi-group)

      如果 \cdot 还有单位元 ee,则称 (S,,e)(S,\cdot,e)独异点 (monoid)

      # 常用群举例

      # 整数加群

      整数集 Z 及整数加法运算构成群,称为整数加群

      • 单位元是 00
      • 每个整数 zz 的逆元是 z-z

      # 模 m 剩余类加群 Zm\mathbb{Z}_m

      对整数 m2m≥2,记 Zm={0,1,,m1}\mathbb{Z}_m=\{0,1,\cdots,m-1\}Zm\mathbb{Z}_m 及 模 mmm\oplus_m 构成群,称为mm 剩余类加群

      00 是单位元,对每个整数 zZmz\in \mathbb Z_m,它的逆元是 ((z)+m)modm((-z)+m)\bmod m

      模m剩余类加法群

      # Q\mathbb{Q^*} R\mathbb{R^*} C\mathbb{C^*} 乘法群

      整数集 Z\mathbb Z 关于整数乘法不构成群,但非零有理数集Q\mathbb Q^*、非零实数集 R\mathbb R^*、非零复数集 C\mathbb C^* 关于数的乘法运算构成群

      # 实矩阵乘法群

      实数域上的 n 阶方阵构成的集合为 Mn(R)M_n (\mathbb R),则它关于矩阵加法构成群;记实数域上的 n 阶可逆方阵构成的集合为 GLn(R)GL_n (\mathbb R),则它关于矩阵乘法构成群

      # 双函数复合群

      集合 S 上的所有双函数 f:SSf:S→S 及复合构成群

      • 恒等函数是单位元
      • 逆函数给出逆元

      # 模 m 单位群 U (m)

      Zm\mathbb Z_m 及 模 m 乘 m⊗_m 不构成群,但令U(m)={aaZm且a与m互质}U(m)=\{a∣a\in Z_m \text{且a与m互质}\},则 U (m) 与m⊗_m 构成群,称为模 m 单位群

      • 1 是单位元
      • 对每个整数 zU(m)z\in U(m),它的逆元是同余方程 xz1(modm)xz≡1(\text{mod} m) 的解
        • 利用贝祖定理(即 a,bZ+s,tZ,gcd(a,b)=as+bt∀a,b\in \mathbb Z^+,\exist s, t\in \mathbb Z,gcd⁡(a,b)=as+bt)可证明 U (m) 对 m⊗_m 封闭,以及上述同余方程解的存在性,也即逆元的存在性

      当 p 是素数,则 U (p) 群也记为 Zp\mathbb Z_p^*

      模 m 单位群的阶:U(m)=ϕ(m)|U(m)|=ϕ(m),这里 ϕ(m)ϕ(m) 是欧拉函数,即:

      U(m)=ϕ(m)=mi=1s(11pi)|U(m)|=ϕ(m)=m\prod_{i=1}^{s}(1-\frac{1}{p_i} )

      这里 p1,,psp_1,⋯, p_s 是 m 的 s 个不同的素因子

      # 具体群举例

      1

      2

      3克莱因4元群

      4

      # 群的一些术语

      # 交换群

      群的运算不一定满足交换律,满足交换律的群称为交换群,也称为阿贝尔群

      # 群的阶

      群 G 的元素个数(准确地说 G 的基数)|G | 称为群 G 的阶 (order),如果 G 是有穷集,则称为有穷群(有限群),否则称为无穷群(无限群)

      # 加群

      当群称为加群时通常将它:

      • 单位元记为 0
      • 元素 a 的逆元记为 - a
      • 运算称为加法
      • 运算的结果称为和
      • 运算用加号 + 表示

      通常只有当群是交换群的时候,才使用加号 '+' 表示这个群的运算

      # 乘群

      将不是加群的群称为乘群,并将:

      • 乘群的单位元通常用 1 或 e 表示
      • 元素 a 的逆元用a1a^{-1} 表示
      • 运算称为乘法
      • 运算结果称为积
      • 运算用 \circ\cdot 或 * 表示,但通常省略不写!

      # 群的一些基本性质

      群有单位元,因此群不可能是空集

      群要求每个元素都有逆元,而运算的零元不可能有逆,因此群没有零元(除平凡群 ({e},)(\{e\},\circ) 外)!

      # 逆运算基本性质

      GG 是群,有:

      aG(a1)1=a∀a\in G,(a^{-1})^{-1}= a

      a,bG,(ab)1=b1a1∀a, b\in G, (ab)^{-1}= b^{-1} a^{-1}


      证明

      根据逆元的定义有 aaa1a^{-1} 互为逆元。

      (b^{-1} a^{-1})(ab)=b^{-1}(a^{-1}a)b=b^{-1}eb=b^{-1} b=e$

      类似地:

      ab(b1a1)=eab(b^{-1}a^{-1})=e

      因此 ababb1a1b^{-1}a^{-1} 互为逆元。

      # 群满足消去律

      群的二元运算满足消去律

      GG 是群,对任意 a,b,cGa,b,c\in G, ab=acab=ac 蕴涵 b=cb=c ,同样 ba=caba=ca 蕴涵 b=cb=c


      证明

      ab=acab=ac,则有 a1(ab)=a1(ac)a^{-1}(ab)=a^{-1} (ac)

      而群运算满足结合律,因此 (a1a)b=(a1a)c(a^{-1} a)b=(a^{-1} a)c

      a1a=ea^{-1} a=eee 是单位元,从而有 b=cb=c

      同理可证 ba=caba=ca 蕴涵 b=cb=c

      # 群的充要条件 1

      给定非空集 GG 及其上的二元运算(假定是乘法运算而省略其运算符号)。GG 关于该二元运算构成群的充分必要条件是:

      • GG 的二元运算满足结合律
      • GG 的二元运算有左单位元:即存在 eGe\in G 使得对任意的 aGa\in Gea=aea=a
      • GG 的每个元素相对左单位元有左逆元:即 aG\forall a\in G,存在 aGa'\in G 使得 aa=ea'a=e

      “左” 换成 “右” 也一样

      证明:

      aG,aG,aa=eaaa=aa(aa)=aae=a\forall a\in G,\ \ \exist a'\in G,\ \ a'a=e\\ aa'a=a\\ a(a'a)=a\\ ae=a

      所以 e 也是右单位元;

      aG,aG,aa=eaG,aa=eaa=eaa=aaaa=a(aa)a=aea=aa=e\forall a\in G,\ \ \exist a'\in G,\ \ a'a=e\\ \exist a''\in G,\ \ a''a'=e \\ aa'=eaa'=a''a'aa'=a''(a'a)a'=a''ea'=a''a'=e

      所以 每个元素的左逆元也是右逆元。

      # 群的充要条件 2

      给定非空集 GG 及其二元运算,且该二元运算满足结合律GG 构成群的充分必要条件是:

      对任意的 a,bGa,b\in G,方程 ax=bax=bya=bya=bGG 中都有解。

      # 问题 5

      给定非空集 GG 及其上的二元运算(假定是乘法运算而省略其运算符号)满足:

      • 该运算有左单位元 ee ,即 aG∀a\in Gea=aea=a
      • 对关于该左单位元,每个元素有右逆,即任意 aGa\in G ,存在 bb 使得 ab=eab=e

      请问 GG 关于该运算是否一定构成群?

      # 群的充要条件 3

      给定非空有限集 GG 及其二元运算,该二元运算满足结合律满足消去律,即对任意 a,b,cGa, b, c\in Gab=acab = ac 蕴含 b=cb = c 以及 ba=caba = ca 蕴含 b=cb = c

      证明 GG 关于该运算构成群。

      # 群的幂运算

      # 定义

      (G,)(G,\circ) 是群,定义群的幂运算:aG,nZ∀a\in G, ∀n\in Z ,定义 aann 次幂,记为 ana^n

      群元素的阶

      # 加群的幂运算

      对于加群,元素的幂运算实际上是倍数运算

      • 例如对于整数加群 (Z,+)(Z, +) ,整数 zznn 次幂实际上是 nznz 。这时有:
        • 0z=00z=0
        • (nz)=n(z)(-nz)= n(-z)
        • nz+mz=(n+m)znz + mz = (n+m)z
        • m(nz)=(mn)zm(nz)= (mn)z

      # 基本性质

      (G,)(G, \circ) 是群,对任意 aG,m,nZa\in G,\ \ m, n\in Z ,有:

      anam=an+m(an)m=anma^n\circ a^m= a^{n+m}\\(a^n )^m=a^{nm}


      证明

      • 先对于 m0m≥0,对 mm 实施数学归纳法;
      • 再对于 m<0m<0 ,利用 am=(a1)ma^m=(a^{-1})^{-m}

      # 常用性质

      a,ba,b 是群 GG 的元素,容易得到:

      nZ,(aba1)n=abna1\forall n\in \mathbb Z\ ,\ (aba^{-1} )^n=ab^n a^{-1}

      # 群元素的阶

      # 定义

      (G,)(G,∘) 元素 aa阶 (order),记为 a|a| ,是指最小的正整数 kk 使得 ak=ea^k=e ,若这样的正整数不存在,则称元素 aa 的阶无穷

      # 任意幂的阶

      GG 是群,ee 是其单位元,aaGG 的任意元素,且 a=n|a|=n

      • 对任意整数 mmam=ea^m=e 当且仅当 nmn|m
      • 特别的,m=1m=-1 时,a1=n|a^{-1}|=n
      • 对任意整数 mm : am=ngcd(n,m)|a^m| = \frac{n}{gcd(n, m)}

      定理9证明

      # 阶内运算可轮换

      a,b,ca,b,c 是群 GG 的元素,证明:

      • a=a1=cac1|a|=|a^{-1}|=|cac^{-1}|
      • ab=ba|ab|=|ba|
      • abc=bca=cab|abc|=|bca|=|cab|

      (2) 因为 ab=a(ba)a1ab = a(ba)a^{-1} ,所以由 (1) 可知:

      ab=a(ba)a1=ba|ab|=|a(ba)a^{-1}|=|ba|


      (3) 因为:

      • abc=a(bc)abc=a(bc)
      • bca=(bc)abca=(bc)a
      • cab=(ca)bcab=(ca)b

      因此由 (1) 可知:

      abc=a(bc)=(bc)a=bca=b(ca)=(ca)b=cab|abc|=|a(bc)|=|(bc)a|=|bca|=|b(ca)|=|(ca)b|=|cab|

      虽然 abc=bca|abc|=|bca| ,但是 abcbac|abc|\neq|bac| !这与置换群有关

      # 子群

      # 定义

      GG 是群,HHGG 的子集,如果 HH 关于 GG 的运算也构成群,则称 HHGG 的子群,记为:

      HGH\leq G

      HHGG 的子群,且 HGH≠G ,则称 HHGG真子群,记为:

      H<GH\lt G

      显然 H={e}H=\{e\}GG 的子群,这里 eeGG 的单位元,将 {e}\{e\}GG 自己称为群 GG平凡子群,其他子群称为非平凡子群

      从代数系统角度说,子群就是子代数,下面定理说明子群对群的三个运算都封闭!

      # 子群判定定理 1

      给定 GG 是群,HGH⊆G 关于 GG 的运算构成群,也就是 HHGG 的子群当且仅当:

      • HHGG 的 (二元) 运算封闭
      • HH 对零元运算封闭,即 GG 的单位元应属于 HH
      • HH 对一元运算封闭,即 aH,a1H\forall a\in H,\ \ a^{-1}\in H

      # 子群判定定理 2

      群 G 的非空子集 H 是 G 的子群当且仅当:

      • eHe\in H
      • a,bH,abH∀a, b\in H,\ \ \ ab\in H

      子群判定定理一证明1子群判定定理一证明2

      实际上是构造 aa=ajia^{|a|} = a^{j-i} ,其中 a>0|a|>0aa 的阶

      # 子群判定定理 3

      群 G 的非空子集 H 是 G 的子群当且仅当:

      • a,bH,ab1H∀a, b\in H,\ \ \ ab^{-1}\in H
      • a,bH,b1aH∀a, b\in H,\ \ \ b^{-1}a\in H

      # 群的中心

      定义群 G 的中心

      C={aGxG,xa=ax}C=\{a\in G∣∀x\in G, xa=ax\}

      即 C 是 G 中那些与 G 的任何元素都可交换的元素构成的集合.

      证明:C 是 G 的子群 ( CGC\leq G )

      • 首先 C 是否是非空集?哪个元素一定属于 C?
      • 其次,如何运用子群的判定定理证明 C 是 G 的子群?
        • 例如利用子群判定定理二,如何证明对任意 a, b\in C,都有 ab-1\in C ?
        • 或者利用子群判定定理一,证明对任意 a\in C 有 a-1\in C,以及对任意 a,b\in C 有 ab\in C ?

      首先,由群的性质:xG,xe=ex=e\forall x\in G,\ \ \ xe=ex=e ,所以 eCe\in C ,因此 C 非空

      a,bC\forall a,b\in C ,为证明 ab1Cab^{-1}\in C 只需证明它与 G 中所有元素都可交换即可。

      xG\forall x\in G ,有:

      (ab1)x=ab1(x1)1=a(x1b)1=bCa(bx1)1=a(xb1)=结合律(ax)b1=aC(xa)b1=结合律x(ab1)\begin{aligned} (ab^{-1})x &=ab^{-1}(x^{-1})^{-1}\\ &=a(x^{-1}b)^{-1}\\ &\overset{b\in C}{=}a(bx^{-1})^{-1}\\ &=a(xb^{-1})\\ &\overset{\text{结合律}}{=}(ax)b^{-1}\\ &\overset{a\in C}{=}(xa)b^{-1}\\ &\overset{\text{结合律}}{=}x(ab^{-1}) \end{aligned}

      # 交并与子群的关系

      GG 是群,且 HGH≤G , KGK≤G ,证明:

      • $ H\cap K≤G$(交保持子群,可推广)
      • $ H∪K≤G$ 当且仅当 HKH⊆KKHK⊆H并保持子群的充要条件

      问题15证明1问题15证明2

      # 生成子群

      简单地说,群 GG 的一个子集的生成子群就是包含这个子集的最小的子群。群 GG 的子集 SS 的生成子群记为:

      S⟨S⟩

      两个子群的交总是子群这个命题可推广到任意多个子群的交也总是子群,从而对于群 GG 的某个子集 SS ,可给出包含 SS 的最小子群,这个子群就是 SS生成子群 S⟨S⟩ ,可由所有包含 SS 的子群的交给出,即:

      <S>={HSHHG}\text{<}S\text{>}=\cap\{H|S\subseteq H \land H\leq G\}

      • 如果 SS 为有限集 S={a1,a2,,an}S=\{a_1, a_2,\cdots,a_n\} ,将 S⟨S⟩ 直接记为 a1,a2,,an⟨a_1, a_2,\cdots,a_n ⟩
      • 对于群 GG ,若存在 aGa\in G ,使得 G=aG=⟨a⟩ ,即 GG 是由元素 aa 生成的群,这时称 G 为循环群

      空集生成的子群是什么?

      # 生成子群元素的表示

      GG 是群,SSGG 的非空子集,则:

      S={a1l1a2l2...aklkaiS,li=±1,kN}⟨S⟩=\cap\{a_{1}^{l_{1}}a_{2}^{l_{2}}...a_{k}^{l_{k}}| a_{i}\in S,\ \ \ l_{i}=\pm 1,\ \ \ k\in\mathbb{N} \}

      S⟨S⟩ 的任意元素可表示成有限个 S 的元素或其逆的乘积

      问题16证明

      S={a}S=\{a\} 时,即有 ⟨a⟩=\

      # 循环群

      GG 是群,如果存在 aGa\in G 使得

      G=a={akkZ}G=⟨a⟩=\{a^k | k\in Z\}

      则称 GG循环群 (cyclic group),并称 aaGG 的一个生成元

      • GG 是无限集时称为无限循环群
      • GGnn 个元素时,称为 n 阶循环群

      # 性质 (不考证明)

      GG 是群,ee 是它的单位元

      1. a1=a⟨a^{-1}⟩= ⟨a⟩
      2. GG 是有限群,则 G=aG=aG=⟨a⟩⟺|G|= |a|
      3. GG 是无限循环群,则
        • G={e,a,a1,a2,a2,,an,an,}G = \{e, a, a^{-1}, a^2, a^{-2}, ⋯, a^n, a^{-n}, ⋯\}
        • k,lZ,ak=alk=l\forall k, l\in Z,\ \ \ a^k= a^l⟺k= l
      4. GGnn 阶循环群,则
        • G={e,a,a2,a3,,an1}G = \{e, a, a^2, a^{3}, ⋯, a^{n-1}\}
        • k,lZ,ak=alnkl\forall k, l\in Z,\ \ \ a^k = a^l ⟺n | k-l

      # 循环群举例

      整数加群 Z\mathbb Z 是无限循环群

      显然 Z=1=1\mathbb Z= ⟨1⟩= ⟨-1⟩ , 即 1 和 -1 是它的生成元

      对任意 dZd\in \mathbb Z ,若 d±1d≠±1 ,显然有 1∉d1\not\in⟨d⟩ ,因此 1 和 -1 是 Z\mathbb Z 的仅有的两个生成元。


      mm 加群 Zm\mathbb Z_mmm 阶循环群,显然 Zm=1\mathbb Z_m=⟨1⟩


      U(5)U(5) 是 4 阶循环群,U(5)=2=3U(5)=⟨2⟩=⟨3⟩

      mm 是素数时,U(m)U(m)m1m-1 阶循环群(证明这个需要不少数论知识)

      mm 不是素数时:

      • U(m)U(m) 可能是循环群(例如 U(9)={1,2,4,5,7,8}=2U(9)=\{1,2,4,5,7,8\}=⟨2⟩
      • 也可能不是循环群(例如U(15)={1,2,4,7,8,11,13,14}U(15)=\{1,2,4,7,8,11,13,14\}

      # 生成元的数量与结构

      定理17


      定理17证明

      # 子群保持循环群

      循环群的任意子群都是循环群


      定理18证明

      # 问题

      如果一个群的所有非平凡子群都是循环群,那么这个群一定是循环群吗?

      不一定

      U(12)={1,5,7,11}U(12)=\{1,5,7,11\} 不是循环群,但它的每个非平凡子群都是循环群!

      1=1,5=2,7=2,11=2|1|=1 , |5| = 2 , |7| = 2 , |11| = 2 ,可见 U(12)U(12) 的所有非平凡子群都是二阶群,不难证明所有二阶群都是循环群

      # 生成元任意幂的生成子群

      推论19

      # 循环群的子群⭐️

      推论20

      推论20证明1推论20证明2

      例题:

      Z14\mathbb{Z}_{14} 加群的所有子群是:

      • 1=Z14⟨1⟩=\mathbb{Z}_{14}
      • 2={0,2,4,6,8,10,12,14}⟨2⟩=\{0,2,4,6,8,10,12,14\}
      • 7={0,7}⟨7⟩=\{0,7\}
      • 0=0⟨0⟩={0}

      U(14)U(14) 的所有子群是:

      • 3⟨3⟩
      • 32=9⟨3^2=9⟩
      • 33=13⟨3^3=13⟩
      • 36=1⟨3^6=1⟩
      \ No newline at end of file diff --git a/math/discrete-math/algebra/homomorphism/index.html b/math/discrete-math/algebra/homomorphism/index.html index b5d45a1a..0b582d0b 100644 --- a/math/discrete-math/algebra/homomorphism/index.html +++ b/math/discrete-math/algebra/homomorphism/index.html @@ -1 +1 @@ -群的同态与同构 - 代数结构 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 群的同态

      # 定义

      GGGG' 是两个群,函数 φ:GGφ:G→G' 如果满足:

      a,bG,φ(ab)=φ(a)φ(b)∀a,b\in G,\ \ φ(ab)= φ(a)φ(b)

      φφ 是群 GGGG'同态 (homomorphism)(一个函数)

      φ(a)φ(b)φ(a)φ(b)GG' 中的运算,而 ababGG 中的运算

      考察同态 φ\varphi 作为函数的性质,可以将同态分为:

      • 如果 G=GG=G' ,则称 φφ 为自同态 (automorphism);
      • 如果同态 φ:GGφ:G→G' 是满函数,则称为满同态 (epimorphism),并称 GGGG' 同态,记为φ:GGφ:G∼G'
      • 如果同态 φ:GGφ:G→G' 是单函数,则称为单同态 (monomorphism);
      • 如果同态 φ:GGφ:G→G' 是双函数,则称为同构 (isomorphism),并称群 GGGG' 同构,记为 φ:GGφ:G≅G'

      # 群同态的单位元

      eeGG 的单位元,则 φ(e)\varphi(e)GG' 的单位元;

      GG' 的单位元 ee' ,则:

      φ(e)φ(e)=φ(ee)=φ(e)=φ(e)e\varphi(e)\varphi(e)=\varphi(ee)=\varphi(e)=\varphi(e)e'

      从而由群的运算满足消去律得 φ(e)=e\varphi(e)=e'

      # 群同态的逆元

      群同态与求逆元操作可交换:

      aG,(φ(a))1=φ(a1)\forall a\in G,\ \ (\varphi(a))^{-1}=\varphi(a^{-1})


      证明, 对任意的 aGa\in G :

      φ(a1)φ(a)=φ(a1a)=φ(e)=eφ(a)φ(a1)=φ(aa1)=φ(e)=e\varphi(a^{-1})\varphi(a)=\varphi(a^{-1}a)=\varphi(e)=e'\\ \varphi(a)\varphi(a^{-1})=\varphi(aa^{-1})=\varphi(e)=e'

      这就表明在群 GG' 中,φ(a)\varphi(a) 的逆元是 φ(a1)\varphi(a^{-1}) ,即 φ(a))1=φ(a1)\varphi(a))^{-1}=\varphi(a^{-1})

      # 群同态例子

      G,GG,G' 是群,ee'GG' 的单位元,函数 φ:GGφ:G→G'aG,φ(a)=e∀a\in G,\ \ φ(a)=e'φ\varphi 是同态,称为 GGGG'零同态


      对于整数加群 (Z,+)(Z,+) 和模 n 加群 (Zn,n)(Z_n,⊕_n) ,函数 φ:ZZnφ:Z→Z_nzZ,φ(z)=zmodn∀z\in Z, φ(z)= z \bmod nφ\varphi满同态

      z1,z2Z,φ(z1+z2)=(z1+z2)modn=(z1modn)n(z2modn)=φ(z1)nφ(z2)\begin{aligned} &∀z_1, z_2\in Z,\\ φ(z_1+z_2 )&=(z_1+z_2 )\bmod n\\ &= (z_1 \bmod n) ⊕_n (z_2 \bmod n)\\ &= φ(z_1 ) ⊕_n φ(z_2 ) \end{aligned}


      对于实数加群 (R,+)(\mathbb R,+) 和非零实数集关于乘法构成的群 (R,)(\mathbb R^*, \cdot ) ,固定某实数 aR(a0,1)a\in \mathbb R(a≠0,1) ,定义 φ:RR,rR,φ(r)=arφ:\mathbb R→\mathbb R^*,\ \ ∀r\in \mathbb R, φ(r)= a^rφ\varphi单同态

      r,rR,φ(r+r)=ar+r=arar=φ(r)φ(r)\begin{aligned} &∀r,r'\in \mathbb R,\\ φ(r+r')&=a^{r+r'}\\ &=a^r\cdot a^{r'}\\ &=φ(r)\cdot φ(r') \end{aligned}

      # 群的同构

      # 内自同构

      内自同构

      # 平移与正则表示

      左平移、左正则表示的定义如下:

      置换群 GlG_l 称为群 GG左正则表示 (left regular representation),左乘置换 φaφ_a 称为由元素 aa 确定的左平移 (left translation)。

      左平移和左正则表示

      当然,类似的可以定义右平移、右正则表示

      # 凯莱定理

      每个群都同构与一个置换群(变换群)

      凯莱定理证明

      # 循环群的结构定理

      1. G=<a>G=<a> 是无限循环群,则 G(Z,+)G\cong(\mathbb Z,+)
      2. G=<a>G=<a>nn 阶循环群,则 G(Zn,n)G\cong(\mathbb Z_n,\oplus_n)

      循环群结构定理证明

      无限循环群中 ak=ala^k=a^l 蕴涵 k=lk=l

      nn 阶循环群中 ak=ala^k=a^l 蕴涵 nkln|k-l

      # 群同态的基本性质

      # 群同态与元素的阶

      群同态与元素的阶

      群同态与子群-证明

      # 群同态与子群

      群同态与子群

      ⭐️特别地, H=GH=G 的时候这里就有:

      φ(G)G\varphi(G)\leq G'


      群同态与子群-证明

      # 群同态与正规子群

      群同态与正规子群

      φ(N)\varphi(N) 不一定是 GG' 的正规子群!φ1(M)\varphi^{-1}(M) 不一定是 GG 的正规子群!

      群同态与正规子群-证明

      # 群的同态基本定理

      # 群同态的核

      # 定义

      群同态的核

      :: primary

      所有同态映射结果为单位元的原像的集合

      :::

      # 核是正规子群

      群同态的核基本性质1


      由上述引理可证:

      φ:GG\varphi:G\to G' 是群 GG 到群 GG' 的同态,则 Ker(φ)\text{Ker}(\varphi)GG正规子群,也就是 Ker(φ)G\text{Ker}(\varphi)\leq G

      # 群的同态基本定理

      群的同态基本定理

      群的同态基本定理-证明

      ::: primaty

      结合群同态与子群的关系,就有:商群 G/Ker(φ)φ(G)=G的某个子群GG/\text{Ker}(\varphi)\cong\varphi(G)=G'\text{的某个子群}\leq G'

      :::

      # 正规子群与商群

      由正规子群导出的商群的自然映射满同态,且它的核是该正规子群,由群的同态基本定理有该正规子群与其导出的商群同构。

      商群与自然映射

      # 应用举例

      正规子群与商群应用举例

      # 第二同构定理

      第二同构定理


      证明

      (1) 利用子群判定定理证明:h1,h2H,k1,k2K,(h1k1)(h2k2)1HK∀h_1,h_2\in H,k_1,k_2\in K,\ \ (h_1k_1)(h_2k_2)^{-1}\in HK

      (2) 利用正规子群判断定理证明:对任意 hH,nHK,hnh1HKh\in H, n\in H\cap K, hnh^{-1}\in H\cap K;以及对 h1H,k1K,nK\forall h_1\in H,\forall k_1\in K,\forall n\in K ,有:(h1k1)n(h1k1)1HK(h_1k_1)n(h_1k_1)^{-1}\in HK

      (3) 构造同态 φ:HHK/Kφ:H→ HK/K ,使得 Ker(φ)=HK\text{Ker}(φ)=H\cap K

      # 第三同构定理

      第三同构定理

      # Zm\mathbb Z_mZn\mathbb Z_n 的同态数

      结论 —— 所有 Zm\mathbb Z_mZn\mathbb Z_n 的同态映射如下:

      {φa:xaxa=0,lcm(m,n)m,2lcm(m,n)m,3lcm(m,n)m,,[gcd(m,n)1]lcm(m,n)m=nlcm(m,n)m}\{\varphi_a:\overline{x}\to a\overline{x}|a=0,\frac{\text{lcm}(m,n)}{m},2\frac{\text{lcm}(m,n)}{m},3\frac{\text{lcm}(m,n)}{m},\cdots,[\gcd(m,n)-1]\frac{\text{lcm}(m,n)}{m}=n-\frac{\text{lcm}(m,n)}{m}\}

      总共有 gcd(m,n)\gcd(m,n) 个同态映射。

      上面的两个 x\overline{x} (xax\overline{x}\to a\overline{x}) ,我们虽然使用了同一个记号,但它们代表的意义是不同的:

      • 前一个表示的是 Zm\mathbb Z_m 中的剩余类 {x+mzzZ}\{x+mz|z\in\mathbb Z\}
      • 后一个表示的是 Zn\mathbb Z_n 中的剩余类 {x+nzzZ}\{x+nz|z\in\mathbb Z\}

      今后,在遇到此类情况时,我们都采用这样的记号,不再一一说明。读者应根据上下文,了解两个 x\overline{x} 的不同含义,以免混淆。

      摘抄自《近世代数》(第二版,韩士安,林磊) 的参考答案。

      \ No newline at end of file +群的同态与同构 - 代数结构 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 群的同态

      # 定义

      GGGG' 是两个群,函数 φ:GGφ:G→G' 如果满足:

      a,bG,φ(ab)=φ(a)φ(b)∀a,b\in G,\ \ φ(ab)= φ(a)φ(b)

      φφ 是群 GGGG'同态 (homomorphism)(一个函数)

      φ(a)φ(b)φ(a)φ(b)GG' 中的运算,而 ababGG 中的运算

      考察同态 φ\varphi 作为函数的性质,可以将同态分为:

      • 如果 G=GG=G' ,则称 φφ 为自同态 (automorphism);
      • 如果同态 φ:GGφ:G→G' 是满函数,则称为满同态 (epimorphism),并称 GGGG' 同态,记为φ:GGφ:G∼G'
      • 如果同态 φ:GGφ:G→G' 是单函数,则称为单同态 (monomorphism);
      • 如果同态 φ:GGφ:G→G' 是双函数,则称为同构 (isomorphism),并称群 GGGG' 同构,记为 φ:GGφ:G≅G'

      # 群同态的单位元

      eeGG 的单位元,则 φ(e)\varphi(e)GG' 的单位元;

      GG' 的单位元 ee' ,则:

      φ(e)φ(e)=φ(ee)=φ(e)=φ(e)e\varphi(e)\varphi(e)=\varphi(ee)=\varphi(e)=\varphi(e)e'

      从而由群的运算满足消去律得 φ(e)=e\varphi(e)=e'

      # 群同态的逆元

      群同态与求逆元操作可交换:

      aG,(φ(a))1=φ(a1)\forall a\in G,\ \ (\varphi(a))^{-1}=\varphi(a^{-1})


      证明, 对任意的 aGa\in G :

      φ(a1)φ(a)=φ(a1a)=φ(e)=eφ(a)φ(a1)=φ(aa1)=φ(e)=e\varphi(a^{-1})\varphi(a)=\varphi(a^{-1}a)=\varphi(e)=e'\\ \varphi(a)\varphi(a^{-1})=\varphi(aa^{-1})=\varphi(e)=e'

      这就表明在群 GG' 中,φ(a)\varphi(a) 的逆元是 φ(a1)\varphi(a^{-1}) ,即 φ(a))1=φ(a1)\varphi(a))^{-1}=\varphi(a^{-1})

      # 群同态例子

      G,GG,G' 是群,ee'GG' 的单位元,函数 φ:GGφ:G→G'aG,φ(a)=e∀a\in G,\ \ φ(a)=e'φ\varphi 是同态,称为 GGGG'零同态


      对于整数加群 (Z,+)(Z,+) 和模 n 加群 (Zn,n)(Z_n,⊕_n) ,函数 φ:ZZnφ:Z→Z_nzZ,φ(z)=zmodn∀z\in Z, φ(z)= z \bmod nφ\varphi满同态

      z1,z2Z,φ(z1+z2)=(z1+z2)modn=(z1modn)n(z2modn)=φ(z1)nφ(z2)\begin{aligned} &∀z_1, z_2\in Z,\\ φ(z_1+z_2 )&=(z_1+z_2 )\bmod n\\ &= (z_1 \bmod n) ⊕_n (z_2 \bmod n)\\ &= φ(z_1 ) ⊕_n φ(z_2 ) \end{aligned}


      对于实数加群 (R,+)(\mathbb R,+) 和非零实数集关于乘法构成的群 (R,)(\mathbb R^*, \cdot ) ,固定某实数 aR(a0,1)a\in \mathbb R(a≠0,1) ,定义 φ:RR,rR,φ(r)=arφ:\mathbb R→\mathbb R^*,\ \ ∀r\in \mathbb R, φ(r)= a^rφ\varphi单同态

      r,rR,φ(r+r)=ar+r=arar=φ(r)φ(r)\begin{aligned} &∀r,r'\in \mathbb R,\\ φ(r+r')&=a^{r+r'}\\ &=a^r\cdot a^{r'}\\ &=φ(r)\cdot φ(r') \end{aligned}

      # 群的同构

      # 内自同构

      内自同构

      # 平移与正则表示

      左平移、左正则表示的定义如下:

      置换群 GlG_l 称为群 GG左正则表示 (left regular representation),左乘置换 φaφ_a 称为由元素 aa 确定的左平移 (left translation)。

      左平移和左正则表示

      当然,类似的可以定义右平移、右正则表示

      # 凯莱定理

      每个群都同构与一个置换群(变换群)

      凯莱定理证明

      # 循环群的结构定理

      1. G=<a>G=<a> 是无限循环群,则 G(Z,+)G\cong(\mathbb Z,+)
      2. G=<a>G=<a>nn 阶循环群,则 G(Zn,n)G\cong(\mathbb Z_n,\oplus_n)

      循环群结构定理证明

      无限循环群中 ak=ala^k=a^l 蕴涵 k=lk=l

      nn 阶循环群中 ak=ala^k=a^l 蕴涵 nkln|k-l

      # 群同态的基本性质

      # 群同态与元素的阶

      群同态与元素的阶

      群同态与子群-证明

      # 群同态与子群

      群同态与子群

      ⭐️特别地, H=GH=G 的时候这里就有:

      φ(G)G\varphi(G)\leq G'


      群同态与子群-证明

      # 群同态与正规子群

      群同态与正规子群

      φ(N)\varphi(N) 不一定是 GG' 的正规子群!φ1(M)\varphi^{-1}(M) 不一定是 GG 的正规子群!

      群同态与正规子群-证明

      # 群的同态基本定理

      # 群同态的核

      # 定义

      群同态的核

      :: primary

      所有同态映射结果为单位元的原像的集合

      :::

      # 核是正规子群

      群同态的核基本性质1


      由上述引理可证:

      φ:GG\varphi:G\to G' 是群 GG 到群 GG' 的同态,则 Ker(φ)\text{Ker}(\varphi)GG正规子群,也就是 Ker(φ)G\text{Ker}(\varphi)\leq G

      # 群的同态基本定理

      群的同态基本定理

      群的同态基本定理-证明

      ::: primaty

      结合群同态与子群的关系,就有:商群 G/Ker(φ)φ(G)=G的某个子群GG/\text{Ker}(\varphi)\cong\varphi(G)=G'\text{的某个子群}\leq G'

      :::

      # 正规子群与商群

      由正规子群导出的商群的自然映射满同态,且它的核是该正规子群,由群的同态基本定理有该正规子群与其导出的商群同构。

      商群与自然映射

      # 应用举例

      正规子群与商群应用举例

      # 第二同构定理

      第二同构定理


      证明

      (1) 利用子群判定定理证明:h1,h2H,k1,k2K,(h1k1)(h2k2)1HK∀h_1,h_2\in H,k_1,k_2\in K,\ \ (h_1k_1)(h_2k_2)^{-1}\in HK

      (2) 利用正规子群判断定理证明:对任意 hH,nHK,hnh1HKh\in H, n\in H\cap K, hnh^{-1}\in H\cap K;以及对 h1H,k1K,nK\forall h_1\in H,\forall k_1\in K,\forall n\in K ,有:(h1k1)n(h1k1)1HK(h_1k_1)n(h_1k_1)^{-1}\in HK

      (3) 构造同态 φ:HHK/Kφ:H→ HK/K ,使得 Ker(φ)=HK\text{Ker}(φ)=H\cap K

      # 第三同构定理

      第三同构定理

      # Zm\mathbb Z_mZn\mathbb Z_n 的同态数

      结论 —— 所有 Zm\mathbb Z_mZn\mathbb Z_n 的同态映射如下:

      {φa:xaxa=0,lcm(m,n)m,2lcm(m,n)m,3lcm(m,n)m,,[gcd(m,n)1]lcm(m,n)m=nlcm(m,n)m}\{\varphi_a:\overline{x}\to a\overline{x}|a=0,\frac{\text{lcm}(m,n)}{m},2\frac{\text{lcm}(m,n)}{m},3\frac{\text{lcm}(m,n)}{m},\cdots,[\gcd(m,n)-1]\frac{\text{lcm}(m,n)}{m}=n-\frac{\text{lcm}(m,n)}{m}\}

      总共有 gcd(m,n)\gcd(m,n) 个同态映射。

      上面的两个 x\overline{x} (xax\overline{x}\to a\overline{x}) ,我们虽然使用了同一个记号,但它们代表的意义是不同的:

      • 前一个表示的是 Zm\mathbb Z_m 中的剩余类 {x+mzzZ}\{x+mz|z\in\mathbb Z\}
      • 后一个表示的是 Zn\mathbb Z_n 中的剩余类 {x+nzzZ}\{x+nz|z\in\mathbb Z\}

      今后,在遇到此类情况时,我们都采用这样的记号,不再一一说明。读者应根据上下文,了解两个 x\overline{x} 的不同含义,以免混淆。

      摘抄自《近世代数》(第二版,韩士安,林磊) 的参考答案。

      \ No newline at end of file diff --git a/math/discrete-math/algebra/normal-subgroup/index.html b/math/discrete-math/algebra/normal-subgroup/index.html index 4f15c81c..9d86cd1b 100644 --- a/math/discrete-math/algebra/normal-subgroup/index.html +++ b/math/discrete-math/algebra/normal-subgroup/index.html @@ -1 +1 @@ -正规子群与商群 - 代数结构 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 正规子群

      # 定义

      HH 是群 GG子群 (⚠️得先是子群),如果 aG∀a\in G 都有 Ha=aHHa=aH ,则称 HHGG正规子群 (normal subgroup) 或不变子群 (invariant subgroup),记作:

      HGH\unlhd G

      条件 Ha=aHHa=aH 仅表示两个集合 HaHaaHaH 相等。不能错误地认为,由 Ha=aHHa=aH 可推出对 HH 的任意元素 hhha=ahha=ah

      正确的理解是:对任意 hHh\in H ,存在 hHh^′\in H 使得 ha=ahha = ah'

      GG 的单位元子群 {e}\{e\} 和群 GG 本身都是 GG 的正规子群。这两个正规子群称为 GG平凡正规子群。如果 GG 只有平凡正规子群,且 G{e}G≠\{e\} ,则称 GG单群 (simple group)

      # 交换群的子群

      显然交换群 GG 的任意子群都是 GG 的正规子群

      # 等价定义

      HH 是群 GG 的子群,如果 HH任意一个左陪集也是它的一个右陪集,则 HHGG 的正规子群


      证明:

      对任意 aGa\in GHH 的左陪集 aHaH 也是 HH 的右陪集,即存在 bGb\in G ,使得 aH=HbaH=Hb ;

      同时 aaHa\in aH ,因此 aHba\in Hb

      而又有 aHaa\in Ha ,所以 aHaHba\in Ha\cap Hb

      根据陪集的性质有 Ha=HbHa=Hb ,因此 Ha=Hb=aHHa=Hb=aH ,因此 HHGG 的正规子群。

      # 判定定理

      GG 是群,NNGG 的子群,则下列四个条件等价:

      1. NNGG 的正规子群,即 aG,aN=Na\forall a\in G,\ \ \ aN=Na
      2. NGN\leq GaG,aNa1=N\forall a\in G,\ \ \ aNa^{-1}=N
      3. NGN\leq GaG,aNa1N\forall a\in G,\ \ \ aNa^{-1}\subseteq N
      4. NGN\leq GaG,nN,ana1N\forall a\in G,\forall n\in N,\ \ \ ana^{-1}\in N;⭐️

      这些命题都用集合语言表达,要证明的无非是集合相等或子集关系


      121\rArr 2

      因为 NGN\unlhd G ,所以对任意的 aGa\in G ,有 Na=aNNa=aN ,从而 aNa1=(Na)a1=N(aa1)=NaNa^{-1}=(Na)a^{-1}=N(aa^{-1})=N


      232\rArr 3

      显然 aNa1=NaNa^{-1}=N 蕴含 aNa1NaNa^{-1}\subseteq N


      343\rArr 4

      显然 aNa1=NaNa^{-1}=N 蕴含 aG,nN,ana1N\forall a\in G,\forall n\in N,\ \ \ ana^{-1}\in N


      414\rArr 1

      若对任意 aG,nNa\in G,n\in Nana1Nana^{-1}\in N 从而可得:

      an=(ana1)aNaan=(ana^{-1})a\in Na

      也就是得到 aNNaaN\subseteq Na

      类似的,仍然由对任意 aG,nNa\in G,n\in Nana1Nana^{-1}\in N 可得:

      a1na=(a1)n(a1)1Na^{-1}na=(a^{-1})n(a^{-1})^{-1}\in N

      从而有:

      na=aa1na=a(a1na)aNna=aa^{-1}na=a(a^{-1}na)\in aN

      也就是得到 NaaNNa\subseteq aN

      综合起来就有 Na=aNNa=aN ,即 NNGG 的正规子群。

      # 子集与正规子群

      对于:

      HKGH\subseteq K\subseteq G

      • HHGG 的正规子群,则 HH 也是 KK 的正规子群
      • HHKK 的正规子群,且 KKGG 的正规子群,则推不出 HHGG 的正规子群!也就是正规子群关系 /\unlhd/\unrhd 对子集关系不具有传递性⚠️

      # 子群交保持正规子群

      GG 是群,H,KH,KGG 的正规子群,则 HKH\cap K 也是 GG 的正规子群


      证明

      对于子群的交,首先由子群判定定理,不难得到当 HHKK 是子群时,HKH\cap K 也是子群。

      对任意 aG,hHKa\in G,h\in H\cap K ,由 HHKK 是正规子群有 aha1Haha^{-1}\in Haha1Kaha^{-1}\in K ,从而 aha1HKaha^{-1}\in H\cap K ,因此 HKH\cap K 也是正规子群。

      # 子群乘保持正规子群

      GG 是群,H,KH,KGG 的正规子群,则 HKHK 也是 GG 的正规子群


      对于 HKHK ,首先对任意 h1k1,h2k2HKh_1k_1,h_2k_2\in HK ,有 h1k1(h2k2)1=h1k1k21h21h_1k_1(h_2k_2)^{-1}=h_1k_1k_2^{-1}h_2^{-1}

      由于 KK 是子群,有 k1k21Kk_1k_2^{-1}\in K ,即存在 k1k21=kKk_1k_2^{-1}=k\in K ;

      KK 是正规子群,满足 h1K=Kh1h_1K=Kh_1 ,所以存在 kKk'\in K 使得 h1k=kh1h_1k=k'h_1

      因此:

      h1k1(h2k2)1=h1k1k21h21=h1kh21=kh1h21h_1k_1(h_2k_2)^{-1}=h_1k_1k_2^{-1}h_2^{-1}=h_1kh_2^{-1}=k'h_1h_2^{-1}

      由于 HH 是子群,有 h1h21Hh_1h_2^{-1}\in H ,即存在 h1h21=hHh_1h_2^{-1}=h\in H ;

      KK 是正规子群,满足 hK=KhhK=Kh ,所以存在 kKk''\in K 使得 kh=hkk'h=hk''

      因此:

      h1k1(h2k2)1=kh1h21=kh=hkHKh_1k_1(h_2k_2)^{-1}=k'h_1h_2^{-1}=k'h=hk''\in HK

      所以 HKHKGG 的子群。

      进一步,对任意 aG,hkHKa\in G,\ \ \ hk \in HK ,由 HH 是正规子群,存在 hHh'\in H ,使得 ah=haah= h'a ,从而有 ahka1=haka1ahka^{-1}=h'aka^{-1}

      KK 是正规子群,所以 aka1Kaka^{-1}\in K ,所以 ahka1=haka1HKahka^{-1} =h'aka^{-1}\in HK ,从而 HKHK 也是正规子群。

      # 双陪集正规子群

      名字乱起的,只为了好记

      一个子群只有 2 个陪集,则它一定是正规子群


      证明

      显然这 2 个陪集就是 HHGHG-H

      aG\forall a\in G ,若 aHa\in H ,则显然因为 eHe\in H ,所以 ae=ea=aHae=ea=a\in H ,且 aeaH,eaHaae\in aH,ea\in Ha ,所以此时 aH=H=HaaH=H=Ha

      aHa\notin H ,则因为 eHe\in H ,所以 ae=ea=aHae=ea=a\notin H ,且 aeaH,eaHaae\in aH,ea\in Ha ,所以此时 aHH,HaHaH\neq H,Ha\neq H ,所以 aH=GH=HaaH=G-H=Ha

      # 唯一阶正规子群

      名字乱起的,只为了好记

      HHGG 的子群,则 aG\forall a\in G ,有 aHa1aHa^{-1} 也是 GG 的子群,且 H=aHa1|H|=|aHa^{-1}|

      如果群 GG 的子群 HH 不与 GG 的任意其他子群等势,则 HHGG 的正规子群.


      证明

      h1,h2H,ah1a1,ah2a1aHa1ah1a1(ah2a1)1=a(h1h21)a1HGh1h21Hah1a1(ah2a1)1=a(h1h21)a1aHa1\forall h_1,h_2\in H,\ \ \ ah_1a^{-1},ah_2a^{-1}\in aHa^{-1}\\ ah_1a^{-1}(ah_2a^{-1})^{-1}=a(h_1h_2^{-1})a^{-1}\\ H\leq G\rArr h_1h_2^{-1}\in H\\ \rArr ah_1a^{-1}(ah_2a^{-1})^{-1}=a(h_1h_2^{-1})a^{-1}\in aHa^{-1}

      可知 aHa1aHa^{-1} 也是 GG 的子群。定义映射:

      φ:HaHa1,φ(h)=aha1\varphi:H\to aHa^{-1},\varphi(h)=aha^{-1}

      显然容易证明 φ\varphi 是双函数,所以 H=aHa1|H|=|aHa^{-1}|

      # 正规子群的指标

      GG 是群,HHGG 的正规子群,且 [G:H]=m[G:H]=m ,对任意 gGg\in G ,有 gmHg^m\in H


      证明:

      gG,gmHgG,hH,gm=h\forall g\in G,\ \ g^{m}\in H\lrArr \forall g\in G,\exist h\in H,\ \ g^{m}=h

      gm=hgGH=hgG=hHe=e\begin{aligned} g^{m}&=h\\ g^{\frac{|G|}{|H|}}&=h\\ g^{|G|}&=h^{|H|}\\ e&=e \end{aligned}

      # 商群

      # 定义

      对群 GG 的正规子群 NN ,不必区分左陪集 aNaN 和右陪集 NaNa ,直接称 aNaNNaNa 为陪集。

      G/NG/N 表示它的所有陪集组成的集合,即 G/N={NaaG}G/N=\{Na|a\in G\} ,可在 G/NG/N 上定义运算 使得 G/NG/N 也构成群:

      Na,Nb,NaNb=Nab∀Na,Nb,\ \ Na∘Nb=Nab


      由于运算 是根据陪集的代表(例如陪集 NaNa 的代表是 aa )定义的,因此也要验证运算∘的定义是合适的,即:

      Na=Na,Nb=NbNa=Na', Nb=Nb' 时,需要有 Nab=NabNab = Na'b'

      Nab=(Na)b=(Na)b=(aN)b=a(Nb)=a(Nb)=(aN)b=NabNa'b'=(Na')b'=(Na)b'=(aN)b'=a(Nb')=a(Nb)=(aN)b=Nab


      证明运算 使得 G/NG/N 也构成群:

      满足结合律;对任意的 a,b,cGa,b,c\in G ,有:

      (HaHb)Hc=(Hab)Hc=H(ab)c=Ha(bc)=HaHbc=Ha(HbHc)\begin{aligned} (Ha\circ Hb)\circ Hc &=(Hab)\circ Hc\\ &=H(ab)c\\ &=Ha(bc)\\ &=Ha\circ Hbc\\ &=Ha\circ(Hb\circ Hc) \end{aligned}

      单位元是 He=HHe=H ;对 aG\forall a\in G ,有:

      HHa=HeHa=HHa=HaHe=H(ae)=HaH\circ Ha=He\circ Ha=H\circ Ha=Ha\circ He=H(ae)=Ha

      G/HG/H 的每个元素 HaHa 都有逆元 Ha1GHa^{-1}\in G ;对任意的 HaG/HHa\in G/H ,有 Ha1G/HHa^{-1}\in G/H ,且:

      Ha1Ha=H(a1a)=He=H(aa1)=HaHa1Ha^{-1}\circ Ha=H(a^{-1}a)=He=H(aa^{-1})=Ha\circ Ha^{-1}


      GG 为群,HHGG 的正规子群。HH 的所有陪集 G/HG/H 关于上述运算 构成的群称为群 GG 关于(正规 / 不变)子群 HH商群 (quotient group),仍记作 G/HG/H

      商群就是群依据某个正规子群得到的划分

      # 商群元素的阶

      GG交换群HHGG 的所有阶数有限的元素构成的集合,则 HHGG 的正规子群,且商群 G/HG/H 只有单位元的阶数是有限的


      证明

      由于 GG 是交换群,因此只要证明:

      所有阶数有限的元素构成的集合 H={akZ+,ak=e}H=\{a|\exist k\in \mathbb{Z}^+,\ a^k = e\} ,这里 eeGG 的单位元,只要证明 HHGG 的子群即可。

      对任意 a,bHa,b\in H ,存在 i,jZ+i,j\in \mathbb{Z}^+ ,使得 ai=e,bj=ea^i=e,\ b^j=e ,从而

      (ab1)ij=aij(b1)ij=(ai)j(bj)i=ejei=e(ab^{-1})^{ij}=a^{ij}(b^{-1})^{ij}=(a^{i})^{j}(b^{j})^{-i}=e^{j}e^{-i}=e

      因此 ab1ab^{-1} 也是有限阶元,即 ab1Hab^{-1}\in H ,根据子群判定定理有 HHGG 的子群。

      而对 hH,gG\forall h\in H,\forall g\in G ,易知 ghg1=h|ghg^{-1}|=|h| ,所以 ghg1Hghg^{-1}\in H ,所以 HHGG 的正规子群。

      要证明 G/HG/H 只有单位元的阶数有限,只要证明它的任意元素,如果阶数有限,则这个元素就是单位元。

      对于任意陪集 xHG/HxH\in G/H ,如果它是有限阶的,即存在正整数 kk 使得 (xH)k=xkH=H(xH)^{k}=x^{k}H=H ,从而 xkHx^{k}\in H ,即 xkx^{k} 是有限阶的,从而存在正整数 jj 使得 (xk)j=xkj=e(x^{k})^{j}=x^{kj}=e ,这意味着 xx 也是有限阶的,即 xHx\in H ,从而 xH=HxH=H 是单位元,因此在商群 G/HG/H 中,只有单位元 HH 是有限阶的。

      # 商群保持循环群

      HH 是循环群 GG 的正规子群,则其商群 G/HG/H 也是循环群。


      显然若 aaHH 的生成元,则 aHaH 也是 G/HG/H 的生成元

      # 有限交换群性质

      GGnn有限交换群,则对 nn 的任意因子 ppGG 必有 pp 阶元。


      证明:对 nn 使用数学归纳法。

      (归纳基)显然当 n=2n=2 时,任意 2 阶群都有 2 阶元。

      显然 2 阶群 {e,a}\{e,a\} 一定满足 a2=aa1=ea^2=aa^{-1}=e,因为唯一的非单位元的逆一定是它自己。

      (归纳步)对于 n=k+1n=k+1 ,假设对于任意 2,3,,k2,3,\cdots,k 阶有限交换群,对于群的阶的任意素因子 pp 都有 pp 阶元,考虑 k+1k+1 阶有限交换群 GG ,考虑 ppk+1k+1 的任意素因子。

      为应用归纳假设,需要考虑阶数比 k+1k+1 阶小的有限交换群 GG',而且 GG'GG 有许多相似的性质,这样就需要利用商群的构造:即找到正规子群 HH

      由于 GG 是交换群,所以子群 HH 就是正规子群,使得 G=G/HG'=G/HG/HG/H 的阶是 GG 的阶除以 HH 的阶,只要 HH 不是只有单位元,那么 G/HG/H 的阶比 GG 的阶小。

      对于 GG 的阶 k+1k+1 的素因子 pp

      (1)如果 ppa|a| 的因子,则:

      sZ+,a=spas=agcd(a,s)=as=p\exist s\in\mathbb{Z}^+,\ \ |a|=sp\\ |a^s|=\frac{|a|}{\gcd(|a|,s)}=\frac{|a|}{s}=p

      所以 asa^s 就是 pp 阶元。


      (2)如果 pp 不是 a|a| 的因子,则:

      H=<a>H=<a>aa 的输出子群,H=a|H|=|a|,则因为 GG 是交换群,所以 HH 是正规子群。

      商群 G/HG/H 仍是交换群,且:G/H=k+1a<k+1|G/H|=\frac{k+1}{|a|}\lt k+1

      ppk+1=k+1aak+1=\frac{k+1}{|a|}|a| 的素因子,且 pp 不是 a|a| 的因子,由数论知识得到 pp 就是 k+1a\frac{k+1}{|a|} 的因子;

      所以由归纳假设, bHG/H,bH=p\exist bH\in G/H,\ \ |bH|=p ;所以 (bH)p=bpH=H(bH)^p=b^pH=H ,所以 bpHb^p\in H ;且 H=a|H|=|a| ,所以 (bp)a=(ba)p=e(b^{p})^{|a|}=(b^{|a|})^p=e

      另一方面,由于 pp 不是 a|a| 的因子,所以由 bH=p|bH|=p 可得 baH=(bH)aHb^{|a|}H=(bH)^{|a|}\neq H;所以 baHb^{|a|}\notin H ,所以 baeb^{|a|}\neq e

      所以 bab^{|a|} 就是 pp 阶元

      \ No newline at end of file +正规子群与商群 - 代数结构 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 正规子群

      # 定义

      HH 是群 GG子群 (⚠️得先是子群),如果 aG∀a\in G 都有 Ha=aHHa=aH ,则称 HHGG正规子群 (normal subgroup) 或不变子群 (invariant subgroup),记作:

      HGH\unlhd G

      条件 Ha=aHHa=aH 仅表示两个集合 HaHaaHaH 相等。不能错误地认为,由 Ha=aHHa=aH 可推出对 HH 的任意元素 hhha=ahha=ah

      正确的理解是:对任意 hHh\in H ,存在 hHh^′\in H 使得 ha=ahha = ah'

      GG 的单位元子群 {e}\{e\} 和群 GG 本身都是 GG 的正规子群。这两个正规子群称为 GG平凡正规子群。如果 GG 只有平凡正规子群,且 G{e}G≠\{e\} ,则称 GG单群 (simple group)

      # 交换群的子群

      显然交换群 GG 的任意子群都是 GG 的正规子群

      # 等价定义

      HH 是群 GG 的子群,如果 HH任意一个左陪集也是它的一个右陪集,则 HHGG 的正规子群


      证明:

      对任意 aGa\in GHH 的左陪集 aHaH 也是 HH 的右陪集,即存在 bGb\in G ,使得 aH=HbaH=Hb ;

      同时 aaHa\in aH ,因此 aHba\in Hb

      而又有 aHaa\in Ha ,所以 aHaHba\in Ha\cap Hb

      根据陪集的性质有 Ha=HbHa=Hb ,因此 Ha=Hb=aHHa=Hb=aH ,因此 HHGG 的正规子群。

      # 判定定理

      GG 是群,NNGG 的子群,则下列四个条件等价:

      1. NNGG 的正规子群,即 aG,aN=Na\forall a\in G,\ \ \ aN=Na
      2. NGN\leq GaG,aNa1=N\forall a\in G,\ \ \ aNa^{-1}=N
      3. NGN\leq GaG,aNa1N\forall a\in G,\ \ \ aNa^{-1}\subseteq N
      4. NGN\leq GaG,nN,ana1N\forall a\in G,\forall n\in N,\ \ \ ana^{-1}\in N;⭐️

      这些命题都用集合语言表达,要证明的无非是集合相等或子集关系


      121\rArr 2

      因为 NGN\unlhd G ,所以对任意的 aGa\in G ,有 Na=aNNa=aN ,从而 aNa1=(Na)a1=N(aa1)=NaNa^{-1}=(Na)a^{-1}=N(aa^{-1})=N


      232\rArr 3

      显然 aNa1=NaNa^{-1}=N 蕴含 aNa1NaNa^{-1}\subseteq N


      343\rArr 4

      显然 aNa1=NaNa^{-1}=N 蕴含 aG,nN,ana1N\forall a\in G,\forall n\in N,\ \ \ ana^{-1}\in N


      414\rArr 1

      若对任意 aG,nNa\in G,n\in Nana1Nana^{-1}\in N 从而可得:

      an=(ana1)aNaan=(ana^{-1})a\in Na

      也就是得到 aNNaaN\subseteq Na

      类似的,仍然由对任意 aG,nNa\in G,n\in Nana1Nana^{-1}\in N 可得:

      a1na=(a1)n(a1)1Na^{-1}na=(a^{-1})n(a^{-1})^{-1}\in N

      从而有:

      na=aa1na=a(a1na)aNna=aa^{-1}na=a(a^{-1}na)\in aN

      也就是得到 NaaNNa\subseteq aN

      综合起来就有 Na=aNNa=aN ,即 NNGG 的正规子群。

      # 子集与正规子群

      对于:

      HKGH\subseteq K\subseteq G

      • HHGG 的正规子群,则 HH 也是 KK 的正规子群
      • HHKK 的正规子群,且 KKGG 的正规子群,则推不出 HHGG 的正规子群!也就是正规子群关系 /\unlhd/\unrhd 对子集关系不具有传递性⚠️

      # 子群交保持正规子群

      GG 是群,H,KH,KGG 的正规子群,则 HKH\cap K 也是 GG 的正规子群


      证明

      对于子群的交,首先由子群判定定理,不难得到当 HHKK 是子群时,HKH\cap K 也是子群。

      对任意 aG,hHKa\in G,h\in H\cap K ,由 HHKK 是正规子群有 aha1Haha^{-1}\in Haha1Kaha^{-1}\in K ,从而 aha1HKaha^{-1}\in H\cap K ,因此 HKH\cap K 也是正规子群。

      # 子群乘保持正规子群

      GG 是群,H,KH,KGG 的正规子群,则 HKHK 也是 GG 的正规子群


      对于 HKHK ,首先对任意 h1k1,h2k2HKh_1k_1,h_2k_2\in HK ,有 h1k1(h2k2)1=h1k1k21h21h_1k_1(h_2k_2)^{-1}=h_1k_1k_2^{-1}h_2^{-1}

      由于 KK 是子群,有 k1k21Kk_1k_2^{-1}\in K ,即存在 k1k21=kKk_1k_2^{-1}=k\in K ;

      KK 是正规子群,满足 h1K=Kh1h_1K=Kh_1 ,所以存在 kKk'\in K 使得 h1k=kh1h_1k=k'h_1

      因此:

      h1k1(h2k2)1=h1k1k21h21=h1kh21=kh1h21h_1k_1(h_2k_2)^{-1}=h_1k_1k_2^{-1}h_2^{-1}=h_1kh_2^{-1}=k'h_1h_2^{-1}

      由于 HH 是子群,有 h1h21Hh_1h_2^{-1}\in H ,即存在 h1h21=hHh_1h_2^{-1}=h\in H ;

      KK 是正规子群,满足 hK=KhhK=Kh ,所以存在 kKk''\in K 使得 kh=hkk'h=hk''

      因此:

      h1k1(h2k2)1=kh1h21=kh=hkHKh_1k_1(h_2k_2)^{-1}=k'h_1h_2^{-1}=k'h=hk''\in HK

      所以 HKHKGG 的子群。

      进一步,对任意 aG,hkHKa\in G,\ \ \ hk \in HK ,由 HH 是正规子群,存在 hHh'\in H ,使得 ah=haah= h'a ,从而有 ahka1=haka1ahka^{-1}=h'aka^{-1}

      KK 是正规子群,所以 aka1Kaka^{-1}\in K ,所以 ahka1=haka1HKahka^{-1} =h'aka^{-1}\in HK ,从而 HKHK 也是正规子群。

      # 双陪集正规子群

      名字乱起的,只为了好记

      一个子群只有 2 个陪集,则它一定是正规子群


      证明

      显然这 2 个陪集就是 HHGHG-H

      aG\forall a\in G ,若 aHa\in H ,则显然因为 eHe\in H ,所以 ae=ea=aHae=ea=a\in H ,且 aeaH,eaHaae\in aH,ea\in Ha ,所以此时 aH=H=HaaH=H=Ha

      aHa\notin H ,则因为 eHe\in H ,所以 ae=ea=aHae=ea=a\notin H ,且 aeaH,eaHaae\in aH,ea\in Ha ,所以此时 aHH,HaHaH\neq H,Ha\neq H ,所以 aH=GH=HaaH=G-H=Ha

      # 唯一阶正规子群

      名字乱起的,只为了好记

      HHGG 的子群,则 aG\forall a\in G ,有 aHa1aHa^{-1} 也是 GG 的子群,且 H=aHa1|H|=|aHa^{-1}|

      如果群 GG 的子群 HH 不与 GG 的任意其他子群等势,则 HHGG 的正规子群.


      证明

      h1,h2H,ah1a1,ah2a1aHa1ah1a1(ah2a1)1=a(h1h21)a1HGh1h21Hah1a1(ah2a1)1=a(h1h21)a1aHa1\forall h_1,h_2\in H,\ \ \ ah_1a^{-1},ah_2a^{-1}\in aHa^{-1}\\ ah_1a^{-1}(ah_2a^{-1})^{-1}=a(h_1h_2^{-1})a^{-1}\\ H\leq G\rArr h_1h_2^{-1}\in H\\ \rArr ah_1a^{-1}(ah_2a^{-1})^{-1}=a(h_1h_2^{-1})a^{-1}\in aHa^{-1}

      可知 aHa1aHa^{-1} 也是 GG 的子群。定义映射:

      φ:HaHa1,φ(h)=aha1\varphi:H\to aHa^{-1},\varphi(h)=aha^{-1}

      显然容易证明 φ\varphi 是双函数,所以 H=aHa1|H|=|aHa^{-1}|

      # 正规子群的指标

      GG 是群,HHGG 的正规子群,且 [G:H]=m[G:H]=m ,对任意 gGg\in G ,有 gmHg^m\in H


      证明:

      gG,gmHgG,hH,gm=h\forall g\in G,\ \ g^{m}\in H\lrArr \forall g\in G,\exist h\in H,\ \ g^{m}=h

      gm=hgGH=hgG=hHe=e\begin{aligned} g^{m}&=h\\ g^{\frac{|G|}{|H|}}&=h\\ g^{|G|}&=h^{|H|}\\ e&=e \end{aligned}

      # 商群

      # 定义

      对群 GG 的正规子群 NN ,不必区分左陪集 aNaN 和右陪集 NaNa ,直接称 aNaNNaNa 为陪集。

      G/NG/N 表示它的所有陪集组成的集合,即 G/N={NaaG}G/N=\{Na|a\in G\} ,可在 G/NG/N 上定义运算 使得 G/NG/N 也构成群:

      Na,Nb,NaNb=Nab∀Na,Nb,\ \ Na∘Nb=Nab


      由于运算 是根据陪集的代表(例如陪集 NaNa 的代表是 aa )定义的,因此也要验证运算∘的定义是合适的,即:

      Na=Na,Nb=NbNa=Na', Nb=Nb' 时,需要有 Nab=NabNab = Na'b'

      Nab=(Na)b=(Na)b=(aN)b=a(Nb)=a(Nb)=(aN)b=NabNa'b'=(Na')b'=(Na)b'=(aN)b'=a(Nb')=a(Nb)=(aN)b=Nab


      证明运算 使得 G/NG/N 也构成群:

      满足结合律;对任意的 a,b,cGa,b,c\in G ,有:

      (HaHb)Hc=(Hab)Hc=H(ab)c=Ha(bc)=HaHbc=Ha(HbHc)\begin{aligned} (Ha\circ Hb)\circ Hc &=(Hab)\circ Hc\\ &=H(ab)c\\ &=Ha(bc)\\ &=Ha\circ Hbc\\ &=Ha\circ(Hb\circ Hc) \end{aligned}

      单位元是 He=HHe=H ;对 aG\forall a\in G ,有:

      HHa=HeHa=HHa=HaHe=H(ae)=HaH\circ Ha=He\circ Ha=H\circ Ha=Ha\circ He=H(ae)=Ha

      G/HG/H 的每个元素 HaHa 都有逆元 Ha1GHa^{-1}\in G ;对任意的 HaG/HHa\in G/H ,有 Ha1G/HHa^{-1}\in G/H ,且:

      Ha1Ha=H(a1a)=He=H(aa1)=HaHa1Ha^{-1}\circ Ha=H(a^{-1}a)=He=H(aa^{-1})=Ha\circ Ha^{-1}


      GG 为群,HHGG 的正规子群。HH 的所有陪集 G/HG/H 关于上述运算 构成的群称为群 GG 关于(正规 / 不变)子群 HH商群 (quotient group),仍记作 G/HG/H

      商群就是群依据某个正规子群得到的划分

      # 商群元素的阶

      GG交换群HHGG 的所有阶数有限的元素构成的集合,则 HHGG 的正规子群,且商群 G/HG/H 只有单位元的阶数是有限的


      证明

      由于 GG 是交换群,因此只要证明:

      所有阶数有限的元素构成的集合 H={akZ+,ak=e}H=\{a|\exist k\in \mathbb{Z}^+,\ a^k = e\} ,这里 eeGG 的单位元,只要证明 HHGG 的子群即可。

      对任意 a,bHa,b\in H ,存在 i,jZ+i,j\in \mathbb{Z}^+ ,使得 ai=e,bj=ea^i=e,\ b^j=e ,从而

      (ab1)ij=aij(b1)ij=(ai)j(bj)i=ejei=e(ab^{-1})^{ij}=a^{ij}(b^{-1})^{ij}=(a^{i})^{j}(b^{j})^{-i}=e^{j}e^{-i}=e

      因此 ab1ab^{-1} 也是有限阶元,即 ab1Hab^{-1}\in H ,根据子群判定定理有 HHGG 的子群。

      而对 hH,gG\forall h\in H,\forall g\in G ,易知 ghg1=h|ghg^{-1}|=|h| ,所以 ghg1Hghg^{-1}\in H ,所以 HHGG 的正规子群。

      要证明 G/HG/H 只有单位元的阶数有限,只要证明它的任意元素,如果阶数有限,则这个元素就是单位元。

      对于任意陪集 xHG/HxH\in G/H ,如果它是有限阶的,即存在正整数 kk 使得 (xH)k=xkH=H(xH)^{k}=x^{k}H=H ,从而 xkHx^{k}\in H ,即 xkx^{k} 是有限阶的,从而存在正整数 jj 使得 (xk)j=xkj=e(x^{k})^{j}=x^{kj}=e ,这意味着 xx 也是有限阶的,即 xHx\in H ,从而 xH=HxH=H 是单位元,因此在商群 G/HG/H 中,只有单位元 HH 是有限阶的。

      # 商群保持循环群

      HH 是循环群 GG 的正规子群,则其商群 G/HG/H 也是循环群。


      显然若 aaHH 的生成元,则 aHaH 也是 G/HG/H 的生成元

      # 有限交换群性质

      GGnn有限交换群,则对 nn 的任意因子 ppGG 必有 pp 阶元。


      证明:对 nn 使用数学归纳法。

      (归纳基)显然当 n=2n=2 时,任意 2 阶群都有 2 阶元。

      显然 2 阶群 {e,a}\{e,a\} 一定满足 a2=aa1=ea^2=aa^{-1}=e,因为唯一的非单位元的逆一定是它自己。

      (归纳步)对于 n=k+1n=k+1 ,假设对于任意 2,3,,k2,3,\cdots,k 阶有限交换群,对于群的阶的任意素因子 pp 都有 pp 阶元,考虑 k+1k+1 阶有限交换群 GG ,考虑 ppk+1k+1 的任意素因子。

      为应用归纳假设,需要考虑阶数比 k+1k+1 阶小的有限交换群 GG',而且 GG'GG 有许多相似的性质,这样就需要利用商群的构造:即找到正规子群 HH

      由于 GG 是交换群,所以子群 HH 就是正规子群,使得 G=G/HG'=G/HG/HG/H 的阶是 GG 的阶除以 HH 的阶,只要 HH 不是只有单位元,那么 G/HG/H 的阶比 GG 的阶小。

      对于 GG 的阶 k+1k+1 的素因子 pp

      (1)如果 ppa|a| 的因子,则:

      sZ+,a=spas=agcd(a,s)=as=p\exist s\in\mathbb{Z}^+,\ \ |a|=sp\\ |a^s|=\frac{|a|}{\gcd(|a|,s)}=\frac{|a|}{s}=p

      所以 asa^s 就是 pp 阶元。


      (2)如果 pp 不是 a|a| 的因子,则:

      H=<a>H=<a>aa 的输出子群,H=a|H|=|a|,则因为 GG 是交换群,所以 HH 是正规子群。

      商群 G/HG/H 仍是交换群,且:G/H=k+1a<k+1|G/H|=\frac{k+1}{|a|}\lt k+1

      ppk+1=k+1aak+1=\frac{k+1}{|a|}|a| 的素因子,且 pp 不是 a|a| 的因子,由数论知识得到 pp 就是 k+1a\frac{k+1}{|a|} 的因子;

      所以由归纳假设, bHG/H,bH=p\exist bH\in G/H,\ \ |bH|=p ;所以 (bH)p=bpH=H(bH)^p=b^pH=H ,所以 bpHb^p\in H ;且 H=a|H|=|a| ,所以 (bp)a=(ba)p=e(b^{p})^{|a|}=(b^{|a|})^p=e

      另一方面,由于 pp 不是 a|a| 的因子,所以由 bH=p|bH|=p 可得 baH=(bH)aHb^{|a|}H=(bH)^{|a|}\neq H;所以 baHb^{|a|}\notin H ,所以 baeb^{|a|}\neq e

      所以 bab^{|a|} 就是 pp 阶元

      \ No newline at end of file diff --git a/math/discrete-math/algebra/permutation-group/index.html b/math/discrete-math/algebra/permutation-group/index.html index c680192f..e929a29c 100644 --- a/math/discrete-math/algebra/permutation-group/index.html +++ b/math/discrete-math/algebra/permutation-group/index.html @@ -1 +1 @@ -置换群 - 代数结构 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 置换群的定义

      S={1,2,,n}S=\{1,2,\cdots,n\} ; S 上的任意双函数 σ:SS\sigma:S\to S 称为 S 上的一个 n 元置换 (permutation),记为:

      σ=(12nσ(1)σ(2)σ(n))\sigma= \begin{pmatrix} 1 & 2 & \cdots & n \\ \sigma(1) & \sigma(2) & \cdots & \sigma(n) \end{pmatrix} \quad

      # 置换群的构成

      # 置换乘法

      σ,τ\sigma,\tau 都是 S 上的 n 元置换,则 σ,τ\sigma,\tau 作为函数的复合 στ\sigma\circ\tauτσ\tau\circ\sigma 也是 n 元置换,称为 σ,τ\sigma,\tau乘积,记为 στ\sigma\tauτσ\tau\sigma

      • στ(i)=σ(τ(i))στ(i)=σ(τ(i))
      • τσ(i)=τ(σ(i))τσ(i)=τ(σ(i))

      # 恒等置换

      记为 e ,为 S 上的恒等函数。显然它是置换乘法的单位元

      # 逆置换

      对于某个置换 σ\sigma

      σ=(12nσ(1)σ(2)σ(n))\sigma= \begin{pmatrix} 1 & 2 & \cdots & n \\ \sigma(1) & \sigma(2) & \cdots & \sigma(n) \end{pmatrix} \quad

      σ\sigma​ 关于 (置换) 乘法的逆置换是:

      σ=(σ(1)σ(2)σ(n)12n)\sigma= \begin{pmatrix} \sigma(1) & \sigma(2) & \cdots & \sigma(n)\\ 1 & 2 & \cdots & n \end{pmatrix} \quad

      # 对称群

      SS 上的所有 n 元置换关于置换乘法构成群,这个群称 n 元对称群(symmetric group),并记为 SnS_n , SnS_n 的任意子群都称作 n 元置换群(permutation group)。

      # 轮换

      若 S 上的 n 元置换 σ\sigma 满足:

      σ(i1)=i2,σ(i2)=i3,,σ(ik1)=ik,σ(ik)=i1\sigma(i_1)=i_2,\ \ \ \sigma(i_2)=i_3,\ \cdots\ ,\ \sigma(i_{k-1})=i_k,\ \ \ \sigma(i_k)=i_1

      其中 ijS,j=1,,ki_j\in S,\ \ \ j=1,\cdots,k ;且满足其他元素不变,则称 σ\sigma 为 S 上的 k 阶轮换(cycle),记为:

      σ=(i1i2ik)\sigma=(i_1\ i_2\ \cdots\ i_k)

      特别地有:

      • 2 阶轮换也叫做对换
      • 1 阶轮换 (1)(1) 就是恒等置换

      σ=(i1i2ir)\sigma=(i_1\ i_2\ \cdots\ i_r)τ=(j1j2js)\tau=(j_1\ j_2\ \cdots\ j_s) 是两个轮换,如果对任意的 k=1,2,,rk=1,2,\cdots,r 及任意的 l=1,2,,sl=1,2,\cdots,s 都有 ikjli_k\neq j_l ,称 σ\sigmaτ\tau两个不相交的轮换σ\sigmaτ\tau 不相交

      # 轮换性质 1

      σSnσ\in S_n 是 n 阶置换,证明:σ(i1i2ik)σ1=(σ(i1)σ(i2)σ(ik))σ(i_1\ i_2\ \cdots\ i_k)σ^{-1}= (σ(i_1)\ σ(i_2 )\ \cdots\ σ(i_k ))

      轮换性质1证明

      # 轮换性质 2

      不相交轮换的可交换性

      任意两个不相交轮换的乘积可交换,即若 σ 和 τ 是两个不相交的轮换,则 στ=τσστ=τσ

      轮换性质2eg

      # 轮换性质 3

      置换的轮换表示

      每个置换都可表示为一些不相交轮换的乘积

      轮换性质3eg

      通常省略轮换表示中的一阶轮换,例如这里可以直接记为:σ=(15236)(78)σ=(1\ 5\ 2\ 3\ 6)(7\ 8)

      # 置换的对换表示

      任意置换都可表示成对换的乘积,因为任意轮换都可表示成对换的乘积

      σ=(i1i2ik)\sigma=(i_1\ i_2\ \cdots\ i_k)S={1,2,,n}S=\{1,2,\cdots,n\} 上的 k 阶轮换,则:

      σ=(i1i2)(i2i3)(ik1ik)\sigma=(i_1\ i_2)(i_2\ i_3)\cdots(i_{k-1}\ i_k)

      轮换性质4证明

      • 置换的轮换表示中的轮换是不交的,而对换表示式中的对换是允许有交
      • 轮换表示式在某种意义下(不考虑因子次序和 1 轮换个数)是惟一的,但对换表示式不惟一

      轮换性质4eg1

      轮换性质4eg2

      ⭐️一般地,k 阶轮换 (i1i2i3ik)(i_1\ i_2\ i_3\ \cdots i_k) 也等于 (i1ik)(i1ik1)(i1i2)(i_1\ i_k)(i_1\ i_{k-1} )\cdots(i_1\ i_2)

      # 奇偶性

      一个置换表为对换的乘积,所用的对换个数的奇偶性是惟一的。

      • 可表示成偶数个对换的乘积的置换称为偶置换 (even permutation)

      • 可表示成奇数个对换的乘积的置换称为奇置换 (odd permutation)

      • 任何两个偶置换的积是偶置换;

      • 两个奇置换的积是偶置换;

      • 一个偶置换与一个奇置换的积是奇置换;

      • 一个偶置换的逆置换仍然是偶置换;

      • 一个奇置换的逆仍然是奇置换;

      n>1n>1 时,在全体 n 元置换中,奇置换与偶置换各有 n!2\frac{n!}{2}

      # 交错群

      在 n 元对称群 S_n 中,全体偶置换构成 S_n 的子群称这个子群称为 n 元交错群 (alternative group)。

      交错群eg

      123
      f1f_1123
      f2f_2213
      f3f_3321
      f4f_4132
      f5f_5231
      f6f_6312

      S3S_3 中的偶置换包括 (1)(1)(表示成 0 个对换的乘积)、(123)=(12)(23)(1\ 2\ 3)=(1\ 2)(2\ 3)(132)=(13)(32)(1\ 3\ 2)=(1\ 3)(3\ 2) ,这些偶置换构成了 3 元交错群 A3={(1),(123),(132)}={f1,f5,f6}A_3 = \{(1), (1\ 2\ 3), (1\ 3\ 2)\} = \{f_1, f_5, f_6 \}

      \ No newline at end of file +置换群 - 代数结构 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 置换群的定义

      S={1,2,,n}S=\{1,2,\cdots,n\} ; S 上的任意双函数 σ:SS\sigma:S\to S 称为 S 上的一个 n 元置换 (permutation),记为:

      σ=(12nσ(1)σ(2)σ(n))\sigma= \begin{pmatrix} 1 & 2 & \cdots & n \\ \sigma(1) & \sigma(2) & \cdots & \sigma(n) \end{pmatrix} \quad

      # 置换群的构成

      # 置换乘法

      σ,τ\sigma,\tau 都是 S 上的 n 元置换,则 σ,τ\sigma,\tau 作为函数的复合 στ\sigma\circ\tauτσ\tau\circ\sigma 也是 n 元置换,称为 σ,τ\sigma,\tau乘积,记为 στ\sigma\tauτσ\tau\sigma

      • στ(i)=σ(τ(i))στ(i)=σ(τ(i))
      • τσ(i)=τ(σ(i))τσ(i)=τ(σ(i))

      # 恒等置换

      记为 e ,为 S 上的恒等函数。显然它是置换乘法的单位元

      # 逆置换

      对于某个置换 σ\sigma

      σ=(12nσ(1)σ(2)σ(n))\sigma= \begin{pmatrix} 1 & 2 & \cdots & n \\ \sigma(1) & \sigma(2) & \cdots & \sigma(n) \end{pmatrix} \quad

      σ\sigma​ 关于 (置换) 乘法的逆置换是:

      σ=(σ(1)σ(2)σ(n)12n)\sigma= \begin{pmatrix} \sigma(1) & \sigma(2) & \cdots & \sigma(n)\\ 1 & 2 & \cdots & n \end{pmatrix} \quad

      # 对称群

      SS 上的所有 n 元置换关于置换乘法构成群,这个群称 n 元对称群(symmetric group),并记为 SnS_n , SnS_n 的任意子群都称作 n 元置换群(permutation group)。

      # 轮换

      若 S 上的 n 元置换 σ\sigma 满足:

      σ(i1)=i2,σ(i2)=i3,,σ(ik1)=ik,σ(ik)=i1\sigma(i_1)=i_2,\ \ \ \sigma(i_2)=i_3,\ \cdots\ ,\ \sigma(i_{k-1})=i_k,\ \ \ \sigma(i_k)=i_1

      其中 ijS,j=1,,ki_j\in S,\ \ \ j=1,\cdots,k ;且满足其他元素不变,则称 σ\sigma 为 S 上的 k 阶轮换(cycle),记为:

      σ=(i1i2ik)\sigma=(i_1\ i_2\ \cdots\ i_k)

      特别地有:

      • 2 阶轮换也叫做对换
      • 1 阶轮换 (1)(1) 就是恒等置换

      σ=(i1i2ir)\sigma=(i_1\ i_2\ \cdots\ i_r)τ=(j1j2js)\tau=(j_1\ j_2\ \cdots\ j_s) 是两个轮换,如果对任意的 k=1,2,,rk=1,2,\cdots,r 及任意的 l=1,2,,sl=1,2,\cdots,s 都有 ikjli_k\neq j_l ,称 σ\sigmaτ\tau两个不相交的轮换σ\sigmaτ\tau 不相交

      # 轮换性质 1

      σSnσ\in S_n 是 n 阶置换,证明:σ(i1i2ik)σ1=(σ(i1)σ(i2)σ(ik))σ(i_1\ i_2\ \cdots\ i_k)σ^{-1}= (σ(i_1)\ σ(i_2 )\ \cdots\ σ(i_k ))

      轮换性质1证明

      # 轮换性质 2

      不相交轮换的可交换性

      任意两个不相交轮换的乘积可交换,即若 σ 和 τ 是两个不相交的轮换,则 στ=τσστ=τσ

      轮换性质2eg

      # 轮换性质 3

      置换的轮换表示

      每个置换都可表示为一些不相交轮换的乘积

      轮换性质3eg

      通常省略轮换表示中的一阶轮换,例如这里可以直接记为:σ=(15236)(78)σ=(1\ 5\ 2\ 3\ 6)(7\ 8)

      # 置换的对换表示

      任意置换都可表示成对换的乘积,因为任意轮换都可表示成对换的乘积

      σ=(i1i2ik)\sigma=(i_1\ i_2\ \cdots\ i_k)S={1,2,,n}S=\{1,2,\cdots,n\} 上的 k 阶轮换,则:

      σ=(i1i2)(i2i3)(ik1ik)\sigma=(i_1\ i_2)(i_2\ i_3)\cdots(i_{k-1}\ i_k)

      轮换性质4证明

      • 置换的轮换表示中的轮换是不交的,而对换表示式中的对换是允许有交
      • 轮换表示式在某种意义下(不考虑因子次序和 1 轮换个数)是惟一的,但对换表示式不惟一

      轮换性质4eg1

      轮换性质4eg2

      ⭐️一般地,k 阶轮换 (i1i2i3ik)(i_1\ i_2\ i_3\ \cdots i_k) 也等于 (i1ik)(i1ik1)(i1i2)(i_1\ i_k)(i_1\ i_{k-1} )\cdots(i_1\ i_2)

      # 奇偶性

      一个置换表为对换的乘积,所用的对换个数的奇偶性是惟一的。

      • 可表示成偶数个对换的乘积的置换称为偶置换 (even permutation)

      • 可表示成奇数个对换的乘积的置换称为奇置换 (odd permutation)

      • 任何两个偶置换的积是偶置换;

      • 两个奇置换的积是偶置换;

      • 一个偶置换与一个奇置换的积是奇置换;

      • 一个偶置换的逆置换仍然是偶置换;

      • 一个奇置换的逆仍然是奇置换;

      n>1n>1 时,在全体 n 元置换中,奇置换与偶置换各有 n!2\frac{n!}{2}

      # 交错群

      在 n 元对称群 S_n 中,全体偶置换构成 S_n 的子群称这个子群称为 n 元交错群 (alternative group)。

      交错群eg

      123
      f1f_1123
      f2f_2213
      f3f_3321
      f4f_4132
      f5f_5231
      f6f_6312

      S3S_3 中的偶置换包括 (1)(1)(表示成 0 个对换的乘积)、(123)=(12)(23)(1\ 2\ 3)=(1\ 2)(2\ 3)(132)=(13)(32)(1\ 3\ 2)=(1\ 3)(3\ 2) ,这些偶置换构成了 3 元交错群 A3={(1),(123),(132)}={f1,f5,f6}A_3 = \{(1), (1\ 2\ 3), (1\ 3\ 2)\} = \{f_1, f_5, f_6 \}

      \ No newline at end of file diff --git a/math/discrete-math/algebra/prime-max-ideal/index.html b/math/discrete-math/algebra/prime-max-ideal/index.html index 42b6e75d..9f0588c4 100644 --- a/math/discrete-math/algebra/prime-max-ideal/index.html +++ b/math/discrete-math/algebra/prime-max-ideal/index.html @@ -1 +1 @@ -素理想与极大理想 - 代数结构 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 素理想

      非交换环上也可以定义素理想、极大理想,但这里只考虑交换环上的素理想和极大理想!

      # 定义

      RR 是交换环,PPRR 的真理想。若对任意 a,bRa,b\in RabPab\in P 蕴涵 aPa\in PbPb\in P ,则称 PPRR素理想 (prime ideal)。

      素理想的概念 b 本质上来自数论中的基本结论:若 pp 为素数,则 p|ab\Rightarrow p|a\or p|b。

      # 整数环的素理想

      nn 是正整数,n\langle n\rangle 是整数环 Z\mathbb Z 的素理想当且仅当 nn 是素数。

      零理想 I={0}I=\{0\} 是整数环 Z\mathbb Z 的素理想,但是 Z\mathbb Z 不是素理想,因为素理想要求是真理想!

      # 素理想的充要条件

      RR 是有单位元 e0e≠0 的交换环,IIRR 的理想,则 IIRR 的素理想当且仅当 R/IR/I整环

      # 极大理想

      # 定义

      RR 是交换环,MMRR 的真理想。若对 RR 的任意包含 MM 的理想 NN ,必有 N=MN=MN=RN=R,则称 MMRR极大理想 (maximal ideal)。

      极大理想就是没有真包含它的非平凡理想

      # 极大理想的证明

      证明 IIRR 的极大理想的思路:(RR 是有单位元 ee 的交换环)

      假设 JJ 是理想且 IJI\sub J,...... 得到 eJe\in J,所以 J=RJ=R,所以 IIRR 的极大理想。

      # 整数环的极大理想

      pp 是正整数,p\langle p\rangle 是整数环 Z\mathbb Z 的极大理想当且仅当 pp 是素数,和素理想一致!

      # 极大理想的充要条件

      RR 是有单位元 ee 的交换环,IIRR 的理想,则:IIRR 的极大理想当且仅当 R/IR/I


      • 在交换环 RR 中,IIRR 的素理想当且仅当在 R/IR/Iaˉbˉ=0ˉ\bar{a}\bar{b}=\bar0 蕴涵 aˉ=0ˉ\bar a=\bar 0bˉ=0ˉ\bar b=\bar 0,当且仅当 R/IR/I 的每个元素不是零因子
      • 在有单位元交换环 RR 中,IIRR 的极大理想当且仅当每个真包含 II 的理想都包含 RR 的单位元(从而就包含 RR 的所有元素)

      # 推论

      RR 是有单位元的交换环,由于域都是整环,因此 RR 的每个极大理想都是 RR 的素理想。

      • 如果没有单位元,则极大理想不一定是素理想
        • 例如对于 R=2ZR=2\mathbb ZI=4ZI=4\mathbb ZIIRR 的极大理想,但 II 不是 RR 的素理想
      • 一个素理想(即使是非零素理想)也不一定是极大理想

      # 多项式环的极大理想

      证明 Zm[x]\mathbb Z_m[x] 的理想 ax2+bx+c\langle ax^2+bx+c\rangle (这里以二阶多项式为例)是极大理想思路:

      考察商环 Zm[x]/ax2+bx+c\mathbb Z_m[x]/\langle ax^2+bx+c\rangle 是否是,可以看其所有非零元素是否构成循环群,若构成循环群,则每个非零元素都可逆,则商环是域。

      # 高斯整环的极大理想

      以下结论包括了高斯整环中的所有极大理想:

      • 高斯整环 Z[i]\mathbb Z[i] 的主理想 a+bi\langle a+bi\rangle 是极大理想当且仅当 a2+b2a^2+b^2 是素数,且高斯整环 Z[i]\mathbb Z[i] 关于极大理想 a+bi\langle a+bi\rangle 的商环 Z[i]/a+bi\mathbb Z[i]/\langle a+bi\rangle 和模 a2+b2a^2+b^2 剩余类环 Za2+b2\mathbb Z_{a^2+b^2} 同构。

      a2+b2a^2+b^2 是素数,则一定有 a2+b23mod4a^2+b^2\equiv3\bmod4

      • 高斯整环 Z[i]\mathbb Z[i] 的主理想 p\langle p\rangle 是极大理想当且仅当 pp 是素数并且 p3mod4p\equiv3\bmod4,和整数环中一致。且高斯整环 Z[i]\mathbb Z[i] 关于极大理想 p\langle p\rangle 的商环 Z[i]/p\mathbb Z[i]/\langle p\rangle 和模 p2p^2 剩余类环 Zp2\mathbb Z_{p^2} 同构。

      • 高斯整环中,1+i\langle1+i\rangle1i\langle1-i\rangle 是极大理想。

      \ No newline at end of file +素理想与极大理想 - 代数结构 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 素理想

      非交换环上也可以定义素理想、极大理想,但这里只考虑交换环上的素理想和极大理想!

      # 定义

      RR 是交换环,PPRR 的真理想。若对任意 a,bRa,b\in RabPab\in P 蕴涵 aPa\in PbPb\in P ,则称 PPRR素理想 (prime ideal)。

      素理想的概念 b 本质上来自数论中的基本结论:若 pp 为素数,则 p|ab\Rightarrow p|a\or p|b。

      # 整数环的素理想

      nn 是正整数,n\langle n\rangle 是整数环 Z\mathbb Z 的素理想当且仅当 nn 是素数。

      零理想 I={0}I=\{0\} 是整数环 Z\mathbb Z 的素理想,但是 Z\mathbb Z 不是素理想,因为素理想要求是真理想!

      # 素理想的充要条件

      RR 是有单位元 e0e≠0 的交换环,IIRR 的理想,则 IIRR 的素理想当且仅当 R/IR/I整环

      # 极大理想

      # 定义

      RR 是交换环,MMRR 的真理想。若对 RR 的任意包含 MM 的理想 NN ,必有 N=MN=MN=RN=R,则称 MMRR极大理想 (maximal ideal)。

      极大理想就是没有真包含它的非平凡理想

      # 极大理想的证明

      证明 IIRR 的极大理想的思路:(RR 是有单位元 ee 的交换环)

      假设 JJ 是理想且 IJI\sub J,...... 得到 eJe\in J,所以 J=RJ=R,所以 IIRR 的极大理想。

      # 整数环的极大理想

      pp 是正整数,p\langle p\rangle 是整数环 Z\mathbb Z 的极大理想当且仅当 pp 是素数,和素理想一致!

      # 极大理想的充要条件

      RR 是有单位元 ee 的交换环,IIRR 的理想,则:IIRR 的极大理想当且仅当 R/IR/I


      • 在交换环 RR 中,IIRR 的素理想当且仅当在 R/IR/Iaˉbˉ=0ˉ\bar{a}\bar{b}=\bar0 蕴涵 aˉ=0ˉ\bar a=\bar 0bˉ=0ˉ\bar b=\bar 0,当且仅当 R/IR/I 的每个元素不是零因子
      • 在有单位元交换环 RR 中,IIRR 的极大理想当且仅当每个真包含 II 的理想都包含 RR 的单位元(从而就包含 RR 的所有元素)

      # 推论

      RR 是有单位元的交换环,由于域都是整环,因此 RR 的每个极大理想都是 RR 的素理想。

      • 如果没有单位元,则极大理想不一定是素理想
        • 例如对于 R=2ZR=2\mathbb ZI=4ZI=4\mathbb ZIIRR 的极大理想,但 II 不是 RR 的素理想
      • 一个素理想(即使是非零素理想)也不一定是极大理想

      # 多项式环的极大理想

      证明 Zm[x]\mathbb Z_m[x] 的理想 ax2+bx+c\langle ax^2+bx+c\rangle (这里以二阶多项式为例)是极大理想思路:

      考察商环 Zm[x]/ax2+bx+c\mathbb Z_m[x]/\langle ax^2+bx+c\rangle 是否是,可以看其所有非零元素是否构成循环群,若构成循环群,则每个非零元素都可逆,则商环是域。

      # 高斯整环的极大理想

      以下结论包括了高斯整环中的所有极大理想:

      • 高斯整环 Z[i]\mathbb Z[i] 的主理想 a+bi\langle a+bi\rangle 是极大理想当且仅当 a2+b2a^2+b^2 是素数,且高斯整环 Z[i]\mathbb Z[i] 关于极大理想 a+bi\langle a+bi\rangle 的商环 Z[i]/a+bi\mathbb Z[i]/\langle a+bi\rangle 和模 a2+b2a^2+b^2 剩余类环 Za2+b2\mathbb Z_{a^2+b^2} 同构。

      a2+b2a^2+b^2 是素数,则一定有 a2+b23mod4a^2+b^2\equiv3\bmod4

      • 高斯整环 Z[i]\mathbb Z[i] 的主理想 p\langle p\rangle 是极大理想当且仅当 pp 是素数并且 p3mod4p\equiv3\bmod4,和整数环中一致。且高斯整环 Z[i]\mathbb Z[i] 关于极大理想 p\langle p\rangle 的商环 Z[i]/p\mathbb Z[i]/\langle p\rangle 和模 p2p^2 剩余类环 Zp2\mathbb Z_{p^2} 同构。

      • 高斯整环中,1+i\langle1+i\rangle1i\langle1-i\rangle 是极大理想。

      \ No newline at end of file diff --git a/math/discrete-math/algebra/ring/index.html b/math/discrete-math/algebra/ring/index.html index e5103d01..5ebb728b 100644 --- a/math/discrete-math/algebra/ring/index.html +++ b/math/discrete-math/algebra/ring/index.html @@ -1 +1 @@ -环 - 代数结构 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 环的相关定义

      RR 是非空集合,如果在 RR 上定义了两个二元运算 “++”(称为加法)和 “ \cdot ”(称为乘法),且满足:

      • (1) RR 关于加法 ++ 构成交换群(即加群)
      • (2) RR 关于乘法 \cdot 构成半群,即乘法满足结合律:a,b,cR,a(bc)=(ab)c\forall a,b,c\in R,\ \ a\cdot(b\cdot c)=(a\cdot b)\cdot c
      • (3) 乘法 \cdot 对加法有左右分配律

      a,b,cRa(b+c)=ab+ac(b+c)a=ba+ca\forall a,b,c\in R\\ a\cdot(b+c)=a\cdot b+a\cdot c\\ (b+c)\cdot a=b\cdot a+c\cdot a

      则称代数 (R,+,)(R,+,\ \cdot\ ) 是环(ring)。在通过上下文能明确运算时,通常直接称 RR 为环。

      有教材要求环乘法必须有单位元,也有教材要求环乘法必须满足交换律等

      对环 (R,+,)(R,+,\ \cdot\ )(R,+)(R\ ,+) 是交换群,称为环 RR 的加法群,其单位元通常用 0 表示,称为环 RR 的零元,元素 aa 的加法逆元记为 a-a ,称为 aa 的负元。

      通过负元引入环的减法,即 aba-b 定义为 a+(b)a+(-b)

      • 环乘法是否满足交换律
        • 若环 RR 的乘法也满足交换律,则称为交换环 (commutative ring)
      • 是否有单位元
        • 若环 RR 的乘法有单位元,则称为有单位元环,环乘法的单位元通常记为 ee11 ,并称为环 RR 的单位元
      • 环乘法当环 RR 有单位元 ee 时,考虑环的元素是否有逆元
        • 若对 aRa\in R ,存在 bRb\in R ,使得 ab=ba=eab=ba=e ,则称 aa 是可逆元,或称为环 RR单位 (unit),并称 bbaa 的逆元。当然这时 bb 也是可逆元,且 aabb 的逆元
        • 所有可逆元关于环乘法构成群,称为 RR单位群 (group of units),记为 U(R)U(R)
      • 环乘法是否有零因子
        • 对环 RR 的两个非零元素 a,ba,b ,若 ab=0a\cdot b=0 ,则称 aa左零因子 (left zero-divisor),b 是右零因子 (right zero-divisor)。左零因子和右零因子统称为零因子
        • 若环 RR 的所有非零元素都不是左零因子或右零因子,则称 RR 为无零因子环。

      当集合 RR 只有一个元素 00 ,定义 RR 的加法运算和乘法运算:0+0=0,00=00+0=0,\ 0\cdot 0=0,则 ({0},+,)(\{0\},+,\ \cdot\ ) 构成环,这个环称为零环。在这个环中,零元也是单位元,而零元也是可逆元

      零环过于简单,通常在对环进行讨论时都将零环排除在外。因此在提到环时,总是默认环至少有两个元素,这时零元不可能是单位元,也不可能是可逆元。

      # 整环

      • 有单位元
      • 无零因子
      • (乘法) 可交换

      的环称为整环 (integral domain)


      证明一个环是整环:

      \forall a,b\in R,\ \ ab=0\Rightarrow a=0\or b=0

      # 除环

      • 有单位元
      • 至少有两个元素
      • 每个非零元都可逆 (乘法)
      • (无零因子,可逆元都不是零因子)

      的环称为除环 (division ring)

      #

      交换除环称为 (field) (比较常用),也即需满足:

      • 有单位元
      • 至少有两个元素
      • 每个非零元都可逆 (乘法)
      • (乘法) 可交换
      • (无零因子,可逆元都不是零因子)

      可逆元都不是零因子(为什么?),因此域都是整环!

      非交换除环也称 (skew field) (比较少用)

      # 常用环

      # 整数环及其子环

      • 整数集 Z\mathbb Z 关于普通加法 ++ 和普通乘法 \cdot 构成环,称为整数环

        • 整数环 Z\mathbb Z交换环,(乘法) 零元是 0,单位元是 1

        • 只有 1 和 -1 是可逆元,因此整数环的单位群是 ({1,1},)(\{1, -1\},\ \cdot\ )

        • 整数环的每个非零整数都不是零因子,因此整数环是整环

      • 固定整数 dd ,集合 dZ={kdkZ}d\mathbb Z=\{kd|k\in \mathbb Z\} 关于普通加法 ++ 和普通乘法 \cdot 也构成交换环

        • d1d≠1 时,环 dZd\mathbb Z 没有单位元。显然环 dZd\mathbb Z 也是无零因子环

        • 具体来说,所有偶数构成的集合 2Z2\mathbb Z 关于普通加法和普通乘法构成无单位元、无零因子的交换环。

      # 模 m 剩余类环及其子环

      固定整数 m2m≥2 ,模 mm 剩余类 Zm={0,1,,m1}\mathbb Z_m=\{\overline{0},\overline{1},\cdots,\overline{m-1}\} 关于模 mmm⊕_m 和模 mmm⊗_m 构成环,称为模 mm 剩余类环 (residue class ring)

      • 0\overline 0 表示整除 mm 余 0 的所有整数构成的集合,Zm\mathbb Z_m 的元素是集合

      • mm 剩余类环 Z\mathbb Z 是有单位元交换环,零元是 0,有单位元 1

      • 对于 aZma\in \mathbb Z_m ,如果 aamm 互质,则 aa 关于模 mm 乘有逆元,因此单位群是 U(m)U(m)

      • mm 是质数 pp 时,Zp={0}U(p)\mathbb Z_p=\{0\}\cup U(p) ,关于 p⊕_pp⊗_p 构成有单位元、每个非零元都可逆的交换环,也即这时 Zp\mathbb Z_p 是域

      • mm 不是质数时,若 m=kd(2km,2km)m=kd(2≤k≤m,2≤k≤m) ,则 kkdd 都是模 mm 剩余类环的零因子,这时就不是无零因子环,当然也不是整环

      # 有理数域

      有理数集 QQ 关于普通加法 ++ 和普通乘法 \cdot 构成环

      • 有单位元 1,是交换环,而且每个非零有理数 rr 都有逆 1/r1/r

      • 单位群是所有非零有理数集 Q\mathbb Q^* 关于普通乘法构成的群 (Q,)(\mathbb Q^*,\ \cdot\ )

      • 因此通常直接称有理数集 Q\mathbb Q 为有理数域

      实数集 R\mathbb R 和复数集 C\mathbb C 关于普通加法 ++ 和普通乘法 \cdot 也都构成域,分别称为实数域 R\mathbb R 和复数域 C\mathbb C

      • 单位群分别是所有非零实数集 R\mathbb R^* 和非零复数集 C\mathbb C^* 关于普通乘法构成的群

      • 复数域 C\mathbb C 的零元是实数 0,单位元是实数 1,而复数乘法的逆为:(a+bi)1=abia2+b2(a+bi)^{-1}=\frac{a-bi}{a^2+b^2}

      # 高斯整环

      高斯整环

      # 类高斯整环

      看起来和高斯整环很像,我乱起的名字,不是很重要

      类高斯整环1

      类高斯整环2

      # 全矩阵环

      全矩阵环

      # 多项式环

      多项式环1多项式环2

      例子

      多项式环举例

      # 理想

      # 定义

      RR 是环,IIRR 的非空子集。若 I 满足:

      1. r1,r2I\forall r_1,r_2\in I,有 r1r2Ir_1-r_2\in I
      2. rI,sR,rs,srI\forall r\in I,\ \forall s\in R,\ \ rs,sr\in I

      则称 II 为环 RR理想 (ideal),记为 IRI⊲R,若 IIRR 的真子集,则称 IIRR真理想 (proper ideal)。

      理想是子环:显然如果 IIRR 的理想,则 II 必定是 RR 的子环;

      ⚠️ 当然子环不一定是理想 ⚠️

      RR 的单个零元构成的集合 {0}\{0\}(称为零理想)和 RR 本身都是 RR 的理想,这两个理想称为 RR平凡理想。因此 RR 的非平凡理想就是非零真理想

      # 常用理想

      整数环 ZZ 的所有理想是 dZ={dzzZ},d=0,1,dZ=\{dz|z\in Z\},\ d=0,1,\cdots

      mm 剩余类环 ZmZ_m 的所有理想是 dZm={dzzZm},d=0,1,,m1dZ_m=\{dz|z\in Z_m\},\ d=0, 1, \cdots, m-1


      证明

      理想是子环,而 ZZ 的每个子环都具有形式 dZdZ ,而且对任意子环 dZdZ ,对任意 dzdZdz\in dZ ,以及 sZs\in Z ,显然有 dzs,sdzdZdzs, sdz\in dZ ,因此每个子环 dZdZ 都是 ZZ 的理想

      类似可得到模 mm 剩余类环 ZmZ_m 的所有理想是 dZm,d=0,1,,m1dZ_m, d=0, 1, \cdots, m-1

      # 运算

      #

      RR 是环,I,JI,J 都是 RR 的理想,I+JI+J 称为理想 IIJJ

      I+J={a+bRaI,bJ}I+J=\{a+b\in R|a\in I, b\in J\}

      #

      IJI\cap J 称为 IIJJ

      IJ={xRxI,xJ}I\cap J=\{x\in R|x\in I,x\in J\}

      #

      IJIJ 称为理想 IIJJ

      IJ={a1b1+a2b2++anbnnN,akI,bkJ}IJ=\{a_1b_1+a_2b_2+\cdots+a_nb_n|n\in\mathbb N^*,a_k\in I,b_k\in J\}

      # 和交积保持理想

      IIJJ 都是环 RR 的理想,则 I+JI+JIJI\cap JIJIJ 也是环 RR 的理想

      环的任意有限多个理想的和仍是理想,而任意有限或无限多个理想的交仍是理想

      # 主理想

      # 定义

      RR 是环,aaRR 的元素,记所有包含 aa 的理想构成的集合为:

      ={IRaI}\sum=\{I\lhd R|a\in I\}

      至少有 RR\in\sum ,所以 \sum 非空。令:

      a=II\langle a\rangle=\bigcap_{I\in\sum}I

      a\langle a\rangle 是理想,而且是包含 aa 的最小理想。这个理想称由 aa 生成的主理想(principal ideal),aa 为其生成元

      # 定理结论

      RR 的由 aa 生成的主理想满足:

      a={(i=1nxiayi)+xa+ay+maxi,yi,x,yR,nZ+,mZ}\langle a\rangle=\big\{ \big(\sum_{i=1}^{n}x_iay_i\big) +xa+ay+ma\big|x_i,y_i,x,y\in R,n\in\mathbb Z^+,m\in\mathbb Z \big\}

      RR 有单位元,则:

      \langle a\rangle=\big\{ \big(\sum_{i=1}^{n}x_iay_i\big) \big|x_i,y_i\in R \big\}\

      RR交换环,则:

      a={xa+maxR,mZ}\langle a\rangle=\big\{ xa+ma\big|x\in R,m\in\mathbb Z \big\}

      ⭐️若 RR有单位元的交换环,则:

      a=aR={arrR}\langle a\rangle=aR=\big\{ ar\big|r\in R \big\}

      # 常用理想的主理想

      • 整数环 Z\mathbb Z 的每个理想 dZd\mathbb Z 都是主理想,即是 d\langle d\rangle
      • mm 剩余类环 Zm\mathbb Z_m 的每个理想 dZmd\mathbb Z_m 也都是主理想,即也是 d\langle d\rangle

      RR 是环,a1,a2,,anRa_1,a_2,\cdots,a_n\in R,则:

      a1,a2,,an=a1+a2++an\langle a_1,a_2,\cdots,a_n\rangle=\langle a_1\rangle+\langle a_2\rangle+\cdots+\langle a_n\rangle

      也是 RR 的理想,并且是包含 a1,a2,,ana_1,a_2,\cdots,a_n 的最小理想!称为由 a1,a2,,ana_1,a_2,\cdots,a_n 生成的理想。

      整数环 Z\mathbb Za1,a2a_1,a_2 生成的理想是gcd(a1,a2)\langle\gcd(a_1,a_2)\rangle

      # 商环

      环关于理想的商环

      # 定义

      RR 是环,II(R,+,)(R,+,\ \cdot\ ) 的一个理想,则 (I,+)(I,+)(R,+)(R,+) 的正规子群,它所有(关于加群)的陪集构成集合 R/I{x+IxR}R/I=\{x+I|x\in R\} 、记陪集 x+Ix+Ix\overline x

      # 运算的定义

      # 加法

      在集合 R/IR/I 上可定义加法 ++

      x,yR/I,x+y=x+y(x+I)+(y+I)=(x+y)+I\forall \overline x,\overline y\in R/I,\\ \overline{x}+\overline{y}=\overline{x+y}\Longleftrightarrow (x+I)+(y+I)=(x+y)+I

      这里 x+y\overline{x}+\overline{y} 中的 ++ 是要定义的加法,即后面所说商环中的加法,而 x+y\overline{x+y} 中的 ++ 是环 RR 中的加法。

      根据正规子群的性质,该定义是合适的。

      # 乘法

      在集合 R/IR/I 上可定义乘法 ×\times

      x,yR/I,xy=xy(x+I)(y+I)=(xy)+I\forall \overline x,\overline y\in R/I,\\ \overline{x}\cdot\overline{y}=\overline{x\cdot y}\Longleftrightarrow (x+I)\cdot(y+I)=(x\cdot y)+I

      这里 xy\overline{x}\cdot\overline{y} 中的 $\cdot $ 是要定义的乘法,即后面所说商环中的乘法,而 xy\overline{x\cdot y} 中的 $\cdot $ 是环 RR 中的乘法。


      由于这定义在等价类(陪集)上,因此需要证明该定义是合适的,即与选择的代表无关,即:

      x1=x2y1=y2x1y1=x2y2\overline{x_1}=\overline{x_2}\ \land\overline{y_1}=\overline{y_2}\\ \Downarrow\\ \overline{x_1\cdot y_1}=\overline{x_2\cdot y_2}

      商环乘法合适定义证明

      # 构成环

      商环构成环证明1

      商环构成环证明2

      # 商环定义

      RR 是环,II 是理想,则环的加群关于理想的商群 R/IR/I构成环(基于上面定义的加法和乘法),称为环 RR 关于理想 II 的商环(quotient ring),仍记为 R/IR/I

      R/I={x+IxR}R/I=\{x+I|x\in R\}

      基本性质:

      • a=a+I\overline{a}=a+I
      • 商环的(加法)零元:0=0+I\overline{0}=0+I
      • 商环的(加法)单位元:e=e+I\overline{e}=e+I

      # 环同态

      环的同态就是与环的加法与乘法都可交换的函数

      (R,+,)(R,+,\cdot)(R,,)(R',\oplus,\otimes) 是环,φ:RR\varphi:R\to R'RRRR' 的函数,若对 a,bR\forall a,b\in R 有:

      φ(a+b)=φ(a)φ(b)φ(ab)=φ(a)φ(b)\varphi(a+b)=\varphi(a)\oplus\varphi(b)\\ \varphi(a\cdot b)=\varphi(a)\otimes\varphi(b)

      则称 φ\varphiRRRR'同态

      • φ\varphi 是单函数,则称为单同态
      • φ\varphi 是满函数,则称为满同态
      • φ\varphi 是双函数,则称为同构,记为:RRR\cong R'

      RRRR' 是两个环,定义函数 φ:RRφ:R→R^′aR,φ(a)=0∀a\in R,φ(a)= 0,这里 0 是 RR' 的零元,则容易验证 φφ 是同态,这个同态称为零同态 (zero homomorphism)

      RR 是环,IIRR 的理想,则很自然地有同态 ρ:RR/Iρ:R→R/IaR,ρ(a)=a∀a\in R,ρ(a)=\overline a,这里 a\overline aaa 所在的等价类,即 a+Ia+I 。这个同态称为商环 R/IR/I自然同态 (natural morphism)

      零同态、自然同态都是满同态。

      自然同态一个例子:

      • 整数环 Z\mathbb Z 到模 mm 剩余类环 Zm\mathbb Z_m 有很自然的满同态 φ:ZZmφ:\mathbb Z→\mathbb Z_mzZ,φ(z)=zmodm∀z\in \mathbb Z, φ(z)=z\bmod m

      零同态全部映射到零元,单同态给出子代数,满同态给出商代数

      环同态保持:

      • 加法单位元
      • 子环

      不保持:

      • 理想

      # Zm\mathbb{Z}_mZn\mathbb{Z}_n 的同态

      zm到zn的同态符号约定

      φ:ZmZn\varphi:\mathbb{Z}_m\to\mathbb{Z}_nZm\mathbb{Z}_mZn\mathbb{Z}_n 的同态,当且仅当:

      • φ(1)=[a]\varphi(\overline1)=[a];(环同态由该值决定)
      • φ(x)=x[a]\varphi(\overline{x})=x[a];(乘法陪集)
      • m[a]=[0]m[a]=[0]
      • [a]2=[a][a]^2=[a];([a][a]Zm\mathbb{Z}_m 的幂等元)

      # 环扩张

      环的扩张定理,也称为挖补定理

      环扩张定理

      如图,RRSS' 是 2 个没有公共元素的环,存在 RRSS' 的单同态:

      ψ:RS\psi:R\to S'

      并且:ψ(R)=S\psi(R)=S

      那么 RR 可以扩张为 RR' ,满足:

      • RR=SSR'-R=S'-S
      • SRS'\cong R'

      RR 是一个没有单位元的环,则存在一个有单位元的环 RR' ,使得 RRRR' 的子环。

      # 特征

      RR 是环。若存在最小正整数 nn 使得对所有 aRa\in Rna=0na=0 ,则称 nn 为环 RR特征。如果不存在这样的正整数,则称 RR 的特征为 0。环 R 的特征记为 Char RR

      数域 Z,Q,R,C\mathbb Z, \mathbb Q, \mathbb R, \mathbb C 的特征都是 0,而模 mm 剩余类环 Zm\mathbb Z_m 的特征是 mm

      【定理】设 RR 是有单位元 ee 的环。若 ee 关于加法的阶为无穷大,则 Char R=0R=0,否则 Char R=eR=|e|,这里 e|e| 在环的加群中的阶。

      证明 若 ee 的加法的阶为无穷大,则不存在正整数 nn 使得 ne=0ne=0 ,从而 Char R=0R= 0,否则,若 e=n|e|=n ,则 ne=0ne=0 ,从而对任意 aRa\in Rna=n(ea)=(ne)a=0na=n(ea)=(ne)a=0

      整环的特征是 0 或是一个素数,进而域的特征也只能是 0 或是素数。

      根据 RR 的特征构造 Z\mathbb ZRR 的同态

      【定理】设 RR 是有单位元 ee 的环,定义函数 φ:ZRφ:\mathbb Z→RnZ,φ(n)=ne∀n\in \mathbb Z, φ(n)=ne,则 φφ 是环 Z\mathbb ZRR 的同态。

      【推论】设 RR 是有单位元 ee 的环。

      1. 如果 RR 的特征为 n>0n>0,则 RR 包含一个与 Zn\mathbb Z_n 同构的子环;

      2. 如果 RR 的特征为 0 ,则 RR 包含一个与 Z\mathbb Z 同构的子环。

        • 所以特征为 0 的环一定是无穷环

      ⭐️每个有限域的阶必为素数的幂,即有限域的阶可表示为 pnp^n ( pp 是素数、nn 是正整数),该有限域通常称为 Galois 域 (Galois Fields),记为 GF(pn)GF(p^n)

      【推论】设 FF 是域。

      1. 如果 FF 的特征为 0 ,则 FF 包含一个与有理数域同构的子域;

      2. 如果 RR 的特征是素数 pp ,则 FF 包含一个与模 pp 剩余类环 Zp\mathbb Z_p 同构的子域。

      # 素域

      若域 FF 不包含任何真子域,则称 F 是素域 (prime field)。

      特征为素数 pp交换环中:

      (a±b)pn=apn+bpn(a\pm b)^{p^n}=a^{p^n}+b^{p^n}


      证明思路

      交换环中也有二项式定理,以此证明 (a±b)p=ap+bp(a\pm b)^{p}=a^{p}+b^{p} ,然后数学归纳法即可。

      \ No newline at end of file +环 - 代数结构 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 环的相关定义

      RR 是非空集合,如果在 RR 上定义了两个二元运算 “++”(称为加法)和 “ \cdot ”(称为乘法),且满足:

      • (1) RR 关于加法 ++ 构成交换群(即加群)
      • (2) RR 关于乘法 \cdot 构成半群,即乘法满足结合律:a,b,cR,a(bc)=(ab)c\forall a,b,c\in R,\ \ a\cdot(b\cdot c)=(a\cdot b)\cdot c
      • (3) 乘法 \cdot 对加法有左右分配律

      a,b,cRa(b+c)=ab+ac(b+c)a=ba+ca\forall a,b,c\in R\\ a\cdot(b+c)=a\cdot b+a\cdot c\\ (b+c)\cdot a=b\cdot a+c\cdot a

      则称代数 (R,+,)(R,+,\ \cdot\ ) 是环(ring)。在通过上下文能明确运算时,通常直接称 RR 为环。

      有教材要求环乘法必须有单位元,也有教材要求环乘法必须满足交换律等

      对环 (R,+,)(R,+,\ \cdot\ )(R,+)(R\ ,+) 是交换群,称为环 RR 的加法群,其单位元通常用 0 表示,称为环 RR 的零元,元素 aa 的加法逆元记为 a-a ,称为 aa 的负元。

      通过负元引入环的减法,即 aba-b 定义为 a+(b)a+(-b)

      • 环乘法是否满足交换律
        • 若环 RR 的乘法也满足交换律,则称为交换环 (commutative ring)
      • 是否有单位元
        • 若环 RR 的乘法有单位元,则称为有单位元环,环乘法的单位元通常记为 ee11 ,并称为环 RR 的单位元
      • 环乘法当环 RR 有单位元 ee 时,考虑环的元素是否有逆元
        • 若对 aRa\in R ,存在 bRb\in R ,使得 ab=ba=eab=ba=e ,则称 aa 是可逆元,或称为环 RR单位 (unit),并称 bbaa 的逆元。当然这时 bb 也是可逆元,且 aabb 的逆元
        • 所有可逆元关于环乘法构成群,称为 RR单位群 (group of units),记为 U(R)U(R)
      • 环乘法是否有零因子
        • 对环 RR 的两个非零元素 a,ba,b ,若 ab=0a\cdot b=0 ,则称 aa左零因子 (left zero-divisor),b 是右零因子 (right zero-divisor)。左零因子和右零因子统称为零因子
        • 若环 RR 的所有非零元素都不是左零因子或右零因子,则称 RR 为无零因子环。

      当集合 RR 只有一个元素 00 ,定义 RR 的加法运算和乘法运算:0+0=0,00=00+0=0,\ 0\cdot 0=0,则 ({0},+,)(\{0\},+,\ \cdot\ ) 构成环,这个环称为零环。在这个环中,零元也是单位元,而零元也是可逆元

      零环过于简单,通常在对环进行讨论时都将零环排除在外。因此在提到环时,总是默认环至少有两个元素,这时零元不可能是单位元,也不可能是可逆元。

      # 整环

      • 有单位元
      • 无零因子
      • (乘法) 可交换

      的环称为整环 (integral domain)


      证明一个环是整环:

      \forall a,b\in R,\ \ ab=0\Rightarrow a=0\or b=0

      # 除环

      • 有单位元
      • 至少有两个元素
      • 每个非零元都可逆 (乘法)
      • (无零因子,可逆元都不是零因子)

      的环称为除环 (division ring)

      #

      交换除环称为 (field) (比较常用),也即需满足:

      • 有单位元
      • 至少有两个元素
      • 每个非零元都可逆 (乘法)
      • (乘法) 可交换
      • (无零因子,可逆元都不是零因子)

      可逆元都不是零因子(为什么?),因此域都是整环!

      非交换除环也称 (skew field) (比较少用)

      # 常用环

      # 整数环及其子环

      • 整数集 Z\mathbb Z 关于普通加法 ++ 和普通乘法 \cdot 构成环,称为整数环

        • 整数环 Z\mathbb Z交换环,(乘法) 零元是 0,单位元是 1

        • 只有 1 和 -1 是可逆元,因此整数环的单位群是 ({1,1},)(\{1, -1\},\ \cdot\ )

        • 整数环的每个非零整数都不是零因子,因此整数环是整环

      • 固定整数 dd ,集合 dZ={kdkZ}d\mathbb Z=\{kd|k\in \mathbb Z\} 关于普通加法 ++ 和普通乘法 \cdot 也构成交换环

        • d1d≠1 时,环 dZd\mathbb Z 没有单位元。显然环 dZd\mathbb Z 也是无零因子环

        • 具体来说,所有偶数构成的集合 2Z2\mathbb Z 关于普通加法和普通乘法构成无单位元、无零因子的交换环。

      # 模 m 剩余类环及其子环

      固定整数 m2m≥2 ,模 mm 剩余类 Zm={0,1,,m1}\mathbb Z_m=\{\overline{0},\overline{1},\cdots,\overline{m-1}\} 关于模 mmm⊕_m 和模 mmm⊗_m 构成环,称为模 mm 剩余类环 (residue class ring)

      • 0\overline 0 表示整除 mm 余 0 的所有整数构成的集合,Zm\mathbb Z_m 的元素是集合

      • mm 剩余类环 Z\mathbb Z 是有单位元交换环,零元是 0,有单位元 1

      • 对于 aZma\in \mathbb Z_m ,如果 aamm 互质,则 aa 关于模 mm 乘有逆元,因此单位群是 U(m)U(m)

      • mm 是质数 pp 时,Zp={0}U(p)\mathbb Z_p=\{0\}\cup U(p) ,关于 p⊕_pp⊗_p 构成有单位元、每个非零元都可逆的交换环,也即这时 Zp\mathbb Z_p 是域

      • mm 不是质数时,若 m=kd(2km,2km)m=kd(2≤k≤m,2≤k≤m) ,则 kkdd 都是模 mm 剩余类环的零因子,这时就不是无零因子环,当然也不是整环

      # 有理数域

      有理数集 QQ 关于普通加法 ++ 和普通乘法 \cdot 构成环

      • 有单位元 1,是交换环,而且每个非零有理数 rr 都有逆 1/r1/r

      • 单位群是所有非零有理数集 Q\mathbb Q^* 关于普通乘法构成的群 (Q,)(\mathbb Q^*,\ \cdot\ )

      • 因此通常直接称有理数集 Q\mathbb Q 为有理数域

      实数集 R\mathbb R 和复数集 C\mathbb C 关于普通加法 ++ 和普通乘法 \cdot 也都构成域,分别称为实数域 R\mathbb R 和复数域 C\mathbb C

      • 单位群分别是所有非零实数集 R\mathbb R^* 和非零复数集 C\mathbb C^* 关于普通乘法构成的群

      • 复数域 C\mathbb C 的零元是实数 0,单位元是实数 1,而复数乘法的逆为:(a+bi)1=abia2+b2(a+bi)^{-1}=\frac{a-bi}{a^2+b^2}

      # 高斯整环

      高斯整环

      # 类高斯整环

      看起来和高斯整环很像,我乱起的名字,不是很重要

      类高斯整环1

      类高斯整环2

      # 全矩阵环

      全矩阵环

      # 多项式环

      多项式环1多项式环2

      例子

      多项式环举例

      # 理想

      # 定义

      RR 是环,IIRR 的非空子集。若 I 满足:

      1. r1,r2I\forall r_1,r_2\in I,有 r1r2Ir_1-r_2\in I
      2. rI,sR,rs,srI\forall r\in I,\ \forall s\in R,\ \ rs,sr\in I

      则称 II 为环 RR理想 (ideal),记为 IRI⊲R,若 IIRR 的真子集,则称 IIRR真理想 (proper ideal)。

      理想是子环:显然如果 IIRR 的理想,则 II 必定是 RR 的子环;

      ⚠️ 当然子环不一定是理想 ⚠️

      RR 的单个零元构成的集合 {0}\{0\}(称为零理想)和 RR 本身都是 RR 的理想,这两个理想称为 RR平凡理想。因此 RR 的非平凡理想就是非零真理想

      # 常用理想

      整数环 ZZ 的所有理想是 dZ={dzzZ},d=0,1,dZ=\{dz|z\in Z\},\ d=0,1,\cdots

      mm 剩余类环 ZmZ_m 的所有理想是 dZm={dzzZm},d=0,1,,m1dZ_m=\{dz|z\in Z_m\},\ d=0, 1, \cdots, m-1


      证明

      理想是子环,而 ZZ 的每个子环都具有形式 dZdZ ,而且对任意子环 dZdZ ,对任意 dzdZdz\in dZ ,以及 sZs\in Z ,显然有 dzs,sdzdZdzs, sdz\in dZ ,因此每个子环 dZdZ 都是 ZZ 的理想

      类似可得到模 mm 剩余类环 ZmZ_m 的所有理想是 dZm,d=0,1,,m1dZ_m, d=0, 1, \cdots, m-1

      # 运算

      #

      RR 是环,I,JI,J 都是 RR 的理想,I+JI+J 称为理想 IIJJ

      I+J={a+bRaI,bJ}I+J=\{a+b\in R|a\in I, b\in J\}

      #

      IJI\cap J 称为 IIJJ

      IJ={xRxI,xJ}I\cap J=\{x\in R|x\in I,x\in J\}

      #

      IJIJ 称为理想 IIJJ

      IJ={a1b1+a2b2++anbnnN,akI,bkJ}IJ=\{a_1b_1+a_2b_2+\cdots+a_nb_n|n\in\mathbb N^*,a_k\in I,b_k\in J\}

      # 和交积保持理想

      IIJJ 都是环 RR 的理想,则 I+JI+JIJI\cap JIJIJ 也是环 RR 的理想

      环的任意有限多个理想的和仍是理想,而任意有限或无限多个理想的交仍是理想

      # 主理想

      # 定义

      RR 是环,aaRR 的元素,记所有包含 aa 的理想构成的集合为:

      ={IRaI}\sum=\{I\lhd R|a\in I\}

      至少有 RR\in\sum ,所以 \sum 非空。令:

      a=II\langle a\rangle=\bigcap_{I\in\sum}I

      a\langle a\rangle 是理想,而且是包含 aa 的最小理想。这个理想称由 aa 生成的主理想(principal ideal),aa 为其生成元

      # 定理结论

      RR 的由 aa 生成的主理想满足:

      a={(i=1nxiayi)+xa+ay+maxi,yi,x,yR,nZ+,mZ}\langle a\rangle=\big\{ \big(\sum_{i=1}^{n}x_iay_i\big) +xa+ay+ma\big|x_i,y_i,x,y\in R,n\in\mathbb Z^+,m\in\mathbb Z \big\}

      RR 有单位元,则:

      \langle a\rangle=\big\{ \big(\sum_{i=1}^{n}x_iay_i\big) \big|x_i,y_i\in R \big\}\

      RR交换环,则:

      a={xa+maxR,mZ}\langle a\rangle=\big\{ xa+ma\big|x\in R,m\in\mathbb Z \big\}

      ⭐️若 RR有单位元的交换环,则:

      a=aR={arrR}\langle a\rangle=aR=\big\{ ar\big|r\in R \big\}

      # 常用理想的主理想

      • 整数环 Z\mathbb Z 的每个理想 dZd\mathbb Z 都是主理想,即是 d\langle d\rangle
      • mm 剩余类环 Zm\mathbb Z_m 的每个理想 dZmd\mathbb Z_m 也都是主理想,即也是 d\langle d\rangle

      RR 是环,a1,a2,,anRa_1,a_2,\cdots,a_n\in R,则:

      a1,a2,,an=a1+a2++an\langle a_1,a_2,\cdots,a_n\rangle=\langle a_1\rangle+\langle a_2\rangle+\cdots+\langle a_n\rangle

      也是 RR 的理想,并且是包含 a1,a2,,ana_1,a_2,\cdots,a_n 的最小理想!称为由 a1,a2,,ana_1,a_2,\cdots,a_n 生成的理想。

      整数环 Z\mathbb Za1,a2a_1,a_2 生成的理想是gcd(a1,a2)\langle\gcd(a_1,a_2)\rangle

      # 商环

      环关于理想的商环

      # 定义

      RR 是环,II(R,+,)(R,+,\ \cdot\ ) 的一个理想,则 (I,+)(I,+)(R,+)(R,+) 的正规子群,它所有(关于加群)的陪集构成集合 R/I{x+IxR}R/I=\{x+I|x\in R\} 、记陪集 x+Ix+Ix\overline x

      # 运算的定义

      # 加法

      在集合 R/IR/I 上可定义加法 ++

      x,yR/I,x+y=x+y(x+I)+(y+I)=(x+y)+I\forall \overline x,\overline y\in R/I,\\ \overline{x}+\overline{y}=\overline{x+y}\Longleftrightarrow (x+I)+(y+I)=(x+y)+I

      这里 x+y\overline{x}+\overline{y} 中的 ++ 是要定义的加法,即后面所说商环中的加法,而 x+y\overline{x+y} 中的 ++ 是环 RR 中的加法。

      根据正规子群的性质,该定义是合适的。

      # 乘法

      在集合 R/IR/I 上可定义乘法 ×\times

      x,yR/I,xy=xy(x+I)(y+I)=(xy)+I\forall \overline x,\overline y\in R/I,\\ \overline{x}\cdot\overline{y}=\overline{x\cdot y}\Longleftrightarrow (x+I)\cdot(y+I)=(x\cdot y)+I

      这里 xy\overline{x}\cdot\overline{y} 中的 $\cdot $ 是要定义的乘法,即后面所说商环中的乘法,而 xy\overline{x\cdot y} 中的 $\cdot $ 是环 RR 中的乘法。


      由于这定义在等价类(陪集)上,因此需要证明该定义是合适的,即与选择的代表无关,即:

      x1=x2y1=y2x1y1=x2y2\overline{x_1}=\overline{x_2}\ \land\overline{y_1}=\overline{y_2}\\ \Downarrow\\ \overline{x_1\cdot y_1}=\overline{x_2\cdot y_2}

      商环乘法合适定义证明

      # 构成环

      商环构成环证明1

      商环构成环证明2

      # 商环定义

      RR 是环,II 是理想,则环的加群关于理想的商群 R/IR/I构成环(基于上面定义的加法和乘法),称为环 RR 关于理想 II 的商环(quotient ring),仍记为 R/IR/I

      R/I={x+IxR}R/I=\{x+I|x\in R\}

      基本性质:

      • a=a+I\overline{a}=a+I
      • 商环的(加法)零元:0=0+I\overline{0}=0+I
      • 商环的(加法)单位元:e=e+I\overline{e}=e+I

      # 环同态

      环的同态就是与环的加法与乘法都可交换的函数

      (R,+,)(R,+,\cdot)(R,,)(R',\oplus,\otimes) 是环,φ:RR\varphi:R\to R'RRRR' 的函数,若对 a,bR\forall a,b\in R 有:

      φ(a+b)=φ(a)φ(b)φ(ab)=φ(a)φ(b)\varphi(a+b)=\varphi(a)\oplus\varphi(b)\\ \varphi(a\cdot b)=\varphi(a)\otimes\varphi(b)

      则称 φ\varphiRRRR'同态

      • φ\varphi 是单函数,则称为单同态
      • φ\varphi 是满函数,则称为满同态
      • φ\varphi 是双函数,则称为同构,记为:RRR\cong R'

      RRRR' 是两个环,定义函数 φ:RRφ:R→R^′aR,φ(a)=0∀a\in R,φ(a)= 0,这里 0 是 RR' 的零元,则容易验证 φφ 是同态,这个同态称为零同态 (zero homomorphism)

      RR 是环,IIRR 的理想,则很自然地有同态 ρ:RR/Iρ:R→R/IaR,ρ(a)=a∀a\in R,ρ(a)=\overline a,这里 a\overline aaa 所在的等价类,即 a+Ia+I 。这个同态称为商环 R/IR/I自然同态 (natural morphism)

      零同态、自然同态都是满同态。

      自然同态一个例子:

      • 整数环 Z\mathbb Z 到模 mm 剩余类环 Zm\mathbb Z_m 有很自然的满同态 φ:ZZmφ:\mathbb Z→\mathbb Z_mzZ,φ(z)=zmodm∀z\in \mathbb Z, φ(z)=z\bmod m

      零同态全部映射到零元,单同态给出子代数,满同态给出商代数

      环同态保持:

      • 加法单位元
      • 子环

      不保持:

      • 理想

      # Zm\mathbb{Z}_mZn\mathbb{Z}_n 的同态

      zm到zn的同态符号约定

      φ:ZmZn\varphi:\mathbb{Z}_m\to\mathbb{Z}_nZm\mathbb{Z}_mZn\mathbb{Z}_n 的同态,当且仅当:

      • φ(1)=[a]\varphi(\overline1)=[a];(环同态由该值决定)
      • φ(x)=x[a]\varphi(\overline{x})=x[a];(乘法陪集)
      • m[a]=[0]m[a]=[0]
      • [a]2=[a][a]^2=[a];([a][a]Zm\mathbb{Z}_m 的幂等元)

      # 环扩张

      环的扩张定理,也称为挖补定理

      环扩张定理

      如图,RRSS' 是 2 个没有公共元素的环,存在 RRSS' 的单同态:

      ψ:RS\psi:R\to S'

      并且:ψ(R)=S\psi(R)=S

      那么 RR 可以扩张为 RR' ,满足:

      • RR=SSR'-R=S'-S
      • SRS'\cong R'

      RR 是一个没有单位元的环,则存在一个有单位元的环 RR' ,使得 RRRR' 的子环。

      # 特征

      RR 是环。若存在最小正整数 nn 使得对所有 aRa\in Rna=0na=0 ,则称 nn 为环 RR特征。如果不存在这样的正整数,则称 RR 的特征为 0。环 R 的特征记为 Char RR

      数域 Z,Q,R,C\mathbb Z, \mathbb Q, \mathbb R, \mathbb C 的特征都是 0,而模 mm 剩余类环 Zm\mathbb Z_m 的特征是 mm

      【定理】设 RR 是有单位元 ee 的环。若 ee 关于加法的阶为无穷大,则 Char R=0R=0,否则 Char R=eR=|e|,这里 e|e| 在环的加群中的阶。

      证明 若 ee 的加法的阶为无穷大,则不存在正整数 nn 使得 ne=0ne=0 ,从而 Char R=0R= 0,否则,若 e=n|e|=n ,则 ne=0ne=0 ,从而对任意 aRa\in Rna=n(ea)=(ne)a=0na=n(ea)=(ne)a=0

      整环的特征是 0 或是一个素数,进而域的特征也只能是 0 或是素数。

      根据 RR 的特征构造 Z\mathbb ZRR 的同态

      【定理】设 RR 是有单位元 ee 的环,定义函数 φ:ZRφ:\mathbb Z→RnZ,φ(n)=ne∀n\in \mathbb Z, φ(n)=ne,则 φφ 是环 Z\mathbb ZRR 的同态。

      【推论】设 RR 是有单位元 ee 的环。

      1. 如果 RR 的特征为 n>0n>0,则 RR 包含一个与 Zn\mathbb Z_n 同构的子环;

      2. 如果 RR 的特征为 0 ,则 RR 包含一个与 Z\mathbb Z 同构的子环。

        • 所以特征为 0 的环一定是无穷环

      ⭐️每个有限域的阶必为素数的幂,即有限域的阶可表示为 pnp^n ( pp 是素数、nn 是正整数),该有限域通常称为 Galois 域 (Galois Fields),记为 GF(pn)GF(p^n)

      【推论】设 FF 是域。

      1. 如果 FF 的特征为 0 ,则 FF 包含一个与有理数域同构的子域;

      2. 如果 RR 的特征是素数 pp ,则 FF 包含一个与模 pp 剩余类环 Zp\mathbb Z_p 同构的子域。

      # 素域

      若域 FF 不包含任何真子域,则称 F 是素域 (prime field)。

      特征为素数 pp交换环中:

      (a±b)pn=apn+bpn(a\pm b)^{p^n}=a^{p^n}+b^{p^n}


      证明思路

      交换环中也有二项式定理,以此证明 (a±b)p=ap+bp(a\pm b)^{p}=a^{p}+b^{p} ,然后数学归纳法即可。

      \ No newline at end of file diff --git a/math/discrete-math/discrete-math-basics/dmb/index.html b/math/discrete-math/discrete-math-basics/dmb/index.html index f82afc25..a61c8d1b 100644 --- a/math/discrete-math/discrete-math-basics/dmb/index.html +++ b/math/discrete-math/discrete-math-basics/dmb/index.html @@ -1 +1 @@ -离散数学基础 - 整理 - 离散数学基础 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +离散数学基础 - 整理 - 离散数学基础 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/math/discrete-math/discrete-math-basics/dmbs/algebra-system/index.html b/math/discrete-math/discrete-math-basics/dmbs/algebra-system/index.html index c9abfa4f..1ca542e1 100644 --- a/math/discrete-math/discrete-math-basics/dmbs/algebra-system/index.html +++ b/math/discrete-math/discrete-math-basics/dmbs/algebra-system/index.html @@ -1 +1 @@ -离散数学基础:代数系统 - 离散数学基础 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 思维导图

      代数系统

      # 二元运算

      封闭性

      # 定义

      f:S×SS是集合S的运算,则称集合S对运算f封闭\begin{aligned}& f:S\times S\to S 是集合S的运算,\\& 则称集合S对运算f封闭 \end{aligned}

      TSS的子集,若t1,t2T(f(t1,t2)T)则称集合TS的运算f封闭\begin{aligned}& T\subseteq S是S的子集,若\forall t_1,t_2\in T(f(t_1,t_2)\in T),\\& 则称集合T对S的运算f封闭 \end{aligned}

      # 经典例子

      自然数集、整数集和实数集对加法、乘法运算封闭\begin{aligned}& 自然数集、整数集和实数集对加法、乘法运算封闭 \end{aligned}

      自然数集和整数集对实数集的加法、乘法运算封闭\begin{aligned}& 自然数集和整数集对实数集的加法、乘法运算封闭 \end{aligned}

      自然数集对整数集的加法、乘法运算封闭\begin{aligned}& 自然数集对整数集的加法、乘法运算封闭 \end{aligned}

      自然数集对实数集和整数集的减法运算不封闭\begin{aligned}& 自然数集对实数集和整数集的减法运算不封闭 \end{aligned}

      自然数集、整数集和实数集对除法运算不封闭\begin{aligned}& 自然数集、整数集和实数集对除法运算不封闭 \end{aligned}

      关系复合P(A×B)×P(C×D)P(A×D)的函数一般情况下不是某个集合的运算关系复合是运算A=B=C=D关系复合P(A×A)×P(A×A)P(A×A)的函数\begin{aligned}& 关系复合\circ 是P(A\times B)\times P(C\times D)\to P(A\times D)的函数\\& 一般情况下\circ 不是某个集合的运算\\& 关系复合\circ 是运算\\ \Leftrightarrow & A=B=C=D\\ \Leftrightarrow & 关系复合\circ 是P(A\times A)\times P(A\times A)\to P(A\times A)的函数 \end{aligned}

      函数族AA关于关系复合运算封闭,AAP(A×A)\begin{aligned}& 函数族A^A关于关系复合运算\circ 封闭,A^A\subseteq P(A\times A) \end{aligned}

      # 特殊元

      # 左单位元

      el是运算的左单位元xS,elx=x\begin{aligned}& e_l是运算\circ的左单位元\Leftrightarrow\forall x\in S, e_l\circ x=x \end{aligned}

      # 右单位元

      er是运算的右单位元xS,xer=x\begin{aligned}& e_r是运算\circ的右单位元\Leftrightarrow\forall x\in S, x\circ e_r=x \end{aligned}

      # 单位元

      (幺元)

      e是运算的单位元xS,xe=ex=x\begin{aligned}& e是运算\circ的单位元\Leftrightarrow\forall x\in S, x\circ e=e\circ x=x \end{aligned}

      • 左逆元
        (左逆)

      ylx(关于运算)的左逆元ylx=ex左可逆\begin{aligned}& y_l 是x(关于运算\circ)的左逆元\\\Leftrightarrow& y_l\circ x=e\\\Leftrightarrow& x左可逆 \end{aligned}

      • 右逆元
        (右逆)

      yrx(关于运算)的右逆元xyr=ex右可逆\begin{aligned}& y_r 是x(关于运算\circ)的右逆元\\\Leftrightarrow& x\circ y_r=e\\\Leftrightarrow&x右可逆 \end{aligned}

      • 逆元
        (逆)

      yx(关于运算)的逆元y既是x的左逆又是x的右逆x可逆\begin{aligned}& y是x(关于运算\circ)的逆元\\\Leftrightarrow& y既是x的左逆又是x的右逆\\\Leftrightarrow& x可逆 \end{aligned}

      • 性质

        • 单位元若存在一定是唯一的
        • 若满足结合律,且单位元存在,则可逆元素有唯一逆元

      # 左零元

      θl是运算的左单位元xS,θlx=θl\begin{aligned}& \theta_l 是运算\circ的左单位元\Leftrightarrow\forall x\in S, \theta_l \circ x=\theta_l \end{aligned}

      # 左零元

      θr是运算的左单位元xS,xθr=θr\begin{aligned}& \theta_r 是运算\circ的左单位元\Leftrightarrow\forall x\in S, x\circ\theta_r =\theta_r \end{aligned}

      # 零元

      θ是运算的左单位元xS,xθ=θx=θ\begin{aligned}& \theta 是运算\circ的左单位元\Leftrightarrow\forall x\in S, x\circ\theta=\theta\circ x =\theta \end{aligned}

      # 幂等元

      xx=x\begin{aligned}& x\circ x=x \end{aligned}

      # 二元运算性质

      # 交换律

      • 描述

      运算S上是可交换的,或满足交换律的\begin{aligned}& 运算\circ 在S上是可交换的,或满足交换律的 \end{aligned}

      • 定义

      x,yS,xy=yx\begin{aligned}& \forall x,y\in S,\ \ \ x\circ y=y\circ x \end{aligned}

      # 结合律

      • 描述

      运算S上是可结合的,或满足结合律的\begin{aligned}& 运算\circ 在S上是可结合的,或满足结合律的 \end{aligned}

      • 定义

      x,y,zS,(xy)z=x(yx)\begin{aligned}& \forall x,y,z\in S,\ \ \ (x\circ y)\circ z=x\circ (y\circ x) \end{aligned}

      • 满足结合律的运算的指数运算 (幂运算)

        • 定义

      xn=xx...x\begin{aligned}& x^n=x\circ x\circ...\circ x \end{aligned}

      xn={xxn1xn=1n>1\begin{aligned} x^n=\left\{\begin{aligned} &x\\ &x^{n-1}\circ x \end{aligned}\right. && \begin{aligned} &n=1\\ &n\gt 1 \end{aligned} \end{aligned}

      • 性质

      xnxm=xn+m\begin{aligned}& x^nx^m=x^{n+m} \end{aligned}

      (xn)xm=xnm\begin{aligned}& (x^n)x^m=x^{nm} \end{aligned}

      # 幂等律

      • 定义

      S的运算满足幂等律xS,xx=xS的所有元素都是幂等元\begin{aligned}& S的运算\circ 满足幂等律\\\Leftrightarrow& \forall x\in S, x\circ x=x\\\Leftrightarrow& S的所有元素都是幂等元 \end{aligned}

      # 分配律

      • 描述

      运算对运算是可分配的,或满足分配律的\begin{aligned}& 运算*对运算\circ 是可分配的,或满足分配律的 \end{aligned}

      • 定义

      x,y,zS,x(yz)=(xy)(xz)(yz)x=(yx)(zx)\begin{aligned} \forall x,y,z\in S\ ,\ & x*(y\circ z)=(x*y)\circ(x*z)\\& (y\circ z)*x=(y*x)\circ(z*x) \end{aligned}

      # 吸收律

      • 描述

      运算对运算是可分配的,或满足分配律的\begin{aligned}& 运算*对运算\circ 是可分配的,或满足分配律的 \end{aligned}

      • 定义

      x,yS,x(xy)=xx(xy)=x\begin{aligned} \forall x,y\in S\ ,\ &x*(x\circ y)=x\\&x\circ(x*y)=x \end{aligned}

      • 典例

      逻辑与、或满足吸收律\begin{aligned}& 逻辑与、或满足吸收律 \end{aligned}

      集合交、并满足吸收律\begin{aligned}& 集合交、并满足吸收律 \end{aligned}

      # 消去律

      • 定义

      x,y,zS,x不是零元xy=xzy=zyx=zxy=z\begin{aligned}& \forall x,y,z\in S\ ,\ x不是零元\\& x\circ y=x\circ z\to y=z\\& y\circ x=z\circ x\to y=z \end{aligned}

      • 典例

      数集加法、乘法满足消去律\begin{aligned}& 数集加法、乘法满足消去律 \end{aligned}

      集合交、并不满足消去律\begin{aligned}& 集合交、并不满足消去律 \end{aligned}

      #

      # 定义

      • 一个群包含

      一个二元运算\begin{aligned}& 一个二元运算\circ \end{aligned}

      满足结合律\begin{aligned}& \circ 满足结合律 \end{aligned}

      一个零元运算即单位元e\begin{aligned}& 一个零元运算即单位元e \end{aligned}

      e的单位元\begin{aligned}& e是\circ 的单位元 \end{aligned}

      一个一元运算()1\begin{aligned}& 一个一元运算(-)^{-1} \end{aligned}

      ()1给出每个元素关于的逆元\begin{aligned}& (-)^{-1}给出每个元素关于\circ 的逆元 \end{aligned}

      • 一个独异点包含

      一个二元运算\begin{aligned}& 一个二元运算\circ \end{aligned}

      满足结合律\begin{aligned}& \circ 满足结合律 \end{aligned}

      一个零元运算即单位元e\begin{aligned}& 一个零元运算即单位元e \end{aligned}

      e的单位元\begin{aligned}& e是\circ 的单位元 \end{aligned}

      • 一个半
        群包含

      一个二元运算\begin{aligned}& 一个二元运算\circ \end{aligned}

      满足结合律\begin{aligned}& \circ 满足结合律 \end{aligned}

      # 性质

      • 群有唯一单位元,没有零元,且所有元素有唯一逆元
      • 群的二元运算满足消去律

      # 阿贝尔群

      (可交换群)

      运算满足交换律的群运算满足交换律的群

      # 群的阶

      • 群的元素个数

      # 群元素的阶

      定义群元素an次幂:an={ean1a(a1)nn=0n>0n<0a的阶a是使ak=e成立的最小正整数k,当k不存在时a是无限阶元\begin{aligned}& 定义群元素a的n次幂:\\& \begin{aligned} a^n=\left\{\begin{aligned} &e\\ &a^{n-1}a\\ &(a^{-1})^{|n|} \end{aligned}\right. &&&& \begin{aligned} &n=0\\ &n\gt 0\\ &n\lt 0 \end{aligned} \end{aligned}\\& a的阶|a|是使a^k=e成立的最小正整数k,当k不存在时a是无限阶元 \end{aligned}

      • 性质

      am=enm,mZ\begin{aligned}& a^m=e\iff n|m,\ \ m\in \mathbb Z \end{aligned}

      (a1)k=(ak)1,kN\begin{aligned}& (a^{-1})^k=(a^k)^{-1},\ k\in\mathbb N \end{aligned}

      a1=a\begin{aligned}& |a^{-1}|=|a| \end{aligned}

      a=amgcd(a,m),mZ\begin{aligned}& |a|=|a^m|gcd(|a|,m),\ \ m\in \mathbb Z \end{aligned}

      # 模 m 单位群

      # 定义

      Zm={0,1,2,...,m1}U(m)Zm中所有与m互质的数构成的集合:Um={aZmgcd(a,m)=1}m乘运算Um构成群\begin{aligned}& \mathbb{Z}_m=\{0,1,2,...,m-1\}\\& U(m)是\mathbb{Z}_m中所有与m互质的数构成的集合:\\& U_m=\{a\in\mathbb{Z}_m|gcd(a,m)=1\}\\& 模m乘运算\otimes与U_m构成群 \end{aligned}

      # 正规子群

      or
      不变子群

      # 定义

      HG的子群,aG,Ha=aH\begin{aligned}& H是G的子群, \forall a\in G,\ Ha=aH \end{aligned}

      # 平凡正规子群

      G的单位元子群{e}G的单位元子群\{e\}

      G本身G本身

      # 单群

      G的正规子群只有平凡正规子群,且G{e}\begin{aligned}& G的正规子群只有平凡正规子群,且G\neq \{e\} \end{aligned}

      # 正规子群

      经典例子

      • 交换群

      A交换群每个元素左陪集等于右陪集故交换群每个子群都是正规子群\begin{aligned}& A交换群每个元素左陪集等于右陪集\\& 故交换群每个子群都是正规子群 \end{aligned}

      • 只有 2 个
        相异陪集

      待补待补

      # 商群

      # 描述

      G关于正规子群H的商群G关于正规子群H的商群

      # 定义

      NG的正规子群,N的全体陪集构成集合G/N定义G/N上的运算a,bG,NaNb=Nab从而G/N关于运算构成群,单位元为N\begin{aligned}& N是G的正规子群,N的全体陪集构成集合G/N\\& 定义G/N上的运算\circ 为\forall a,b\in G,\ \ Na\circ Nb=Nab\\& 从而G/N关于运算\circ构成群,单位元为N \end{aligned}

      # 群同态

      # 描述

      GG的一个同态f是一个函数f:GG群G到G'的一个同态f是一个函数f:G\to G'

      # 定义

      a,bG,f(ab)=f(a)f(b)\begin{aligned}& \forall a,b\in G,\ \ \ f(ab)=f(a)f(b) \end{aligned}

      # 自同态

      G到自己的同态f:GG群G到自己的同态f:G\to G

      # 满同态

      f是满函数f是满函数

      # 单同态

      f是单函数f是单函数

      # 同构

      f是双函数f是双函数

      GGG\cong G'

      \ No newline at end of file +离散数学基础:代数系统 - 离散数学基础 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 思维导图

      代数系统

      # 二元运算

      封闭性

      # 定义

      f:S×SS是集合S的运算,则称集合S对运算f封闭\begin{aligned}& f:S\times S\to S 是集合S的运算,\\& 则称集合S对运算f封闭 \end{aligned}

      TSS的子集,若t1,t2T(f(t1,t2)T)则称集合TS的运算f封闭\begin{aligned}& T\subseteq S是S的子集,若\forall t_1,t_2\in T(f(t_1,t_2)\in T),\\& 则称集合T对S的运算f封闭 \end{aligned}

      # 经典例子

      自然数集、整数集和实数集对加法、乘法运算封闭\begin{aligned}& 自然数集、整数集和实数集对加法、乘法运算封闭 \end{aligned}

      自然数集和整数集对实数集的加法、乘法运算封闭\begin{aligned}& 自然数集和整数集对实数集的加法、乘法运算封闭 \end{aligned}

      自然数集对整数集的加法、乘法运算封闭\begin{aligned}& 自然数集对整数集的加法、乘法运算封闭 \end{aligned}

      自然数集对实数集和整数集的减法运算不封闭\begin{aligned}& 自然数集对实数集和整数集的减法运算不封闭 \end{aligned}

      自然数集、整数集和实数集对除法运算不封闭\begin{aligned}& 自然数集、整数集和实数集对除法运算不封闭 \end{aligned}

      关系复合P(A×B)×P(C×D)P(A×D)的函数一般情况下不是某个集合的运算关系复合是运算A=B=C=D关系复合P(A×A)×P(A×A)P(A×A)的函数\begin{aligned}& 关系复合\circ 是P(A\times B)\times P(C\times D)\to P(A\times D)的函数\\& 一般情况下\circ 不是某个集合的运算\\& 关系复合\circ 是运算\\ \Leftrightarrow & A=B=C=D\\ \Leftrightarrow & 关系复合\circ 是P(A\times A)\times P(A\times A)\to P(A\times A)的函数 \end{aligned}

      函数族AA关于关系复合运算封闭,AAP(A×A)\begin{aligned}& 函数族A^A关于关系复合运算\circ 封闭,A^A\subseteq P(A\times A) \end{aligned}

      # 特殊元

      # 左单位元

      el是运算的左单位元xS,elx=x\begin{aligned}& e_l是运算\circ的左单位元\Leftrightarrow\forall x\in S, e_l\circ x=x \end{aligned}

      # 右单位元

      er是运算的右单位元xS,xer=x\begin{aligned}& e_r是运算\circ的右单位元\Leftrightarrow\forall x\in S, x\circ e_r=x \end{aligned}

      # 单位元

      (幺元)

      e是运算的单位元xS,xe=ex=x\begin{aligned}& e是运算\circ的单位元\Leftrightarrow\forall x\in S, x\circ e=e\circ x=x \end{aligned}

      • 左逆元
        (左逆)

      ylx(关于运算)的左逆元ylx=ex左可逆\begin{aligned}& y_l 是x(关于运算\circ)的左逆元\\\Leftrightarrow& y_l\circ x=e\\\Leftrightarrow& x左可逆 \end{aligned}

      • 右逆元
        (右逆)

      yrx(关于运算)的右逆元xyr=ex右可逆\begin{aligned}& y_r 是x(关于运算\circ)的右逆元\\\Leftrightarrow& x\circ y_r=e\\\Leftrightarrow&x右可逆 \end{aligned}

      • 逆元
        (逆)

      yx(关于运算)的逆元y既是x的左逆又是x的右逆x可逆\begin{aligned}& y是x(关于运算\circ)的逆元\\\Leftrightarrow& y既是x的左逆又是x的右逆\\\Leftrightarrow& x可逆 \end{aligned}

      • 性质

        • 单位元若存在一定是唯一的
        • 若满足结合律,且单位元存在,则可逆元素有唯一逆元

      # 左零元

      θl是运算的左单位元xS,θlx=θl\begin{aligned}& \theta_l 是运算\circ的左单位元\Leftrightarrow\forall x\in S, \theta_l \circ x=\theta_l \end{aligned}

      # 左零元

      θr是运算的左单位元xS,xθr=θr\begin{aligned}& \theta_r 是运算\circ的左单位元\Leftrightarrow\forall x\in S, x\circ\theta_r =\theta_r \end{aligned}

      # 零元

      θ是运算的左单位元xS,xθ=θx=θ\begin{aligned}& \theta 是运算\circ的左单位元\Leftrightarrow\forall x\in S, x\circ\theta=\theta\circ x =\theta \end{aligned}

      # 幂等元

      xx=x\begin{aligned}& x\circ x=x \end{aligned}

      # 二元运算性质

      # 交换律

      • 描述

      运算S上是可交换的,或满足交换律的\begin{aligned}& 运算\circ 在S上是可交换的,或满足交换律的 \end{aligned}

      • 定义

      x,yS,xy=yx\begin{aligned}& \forall x,y\in S,\ \ \ x\circ y=y\circ x \end{aligned}

      # 结合律

      • 描述

      运算S上是可结合的,或满足结合律的\begin{aligned}& 运算\circ 在S上是可结合的,或满足结合律的 \end{aligned}

      • 定义

      x,y,zS,(xy)z=x(yx)\begin{aligned}& \forall x,y,z\in S,\ \ \ (x\circ y)\circ z=x\circ (y\circ x) \end{aligned}

      • 满足结合律的运算的指数运算 (幂运算)

        • 定义

      xn=xx...x\begin{aligned}& x^n=x\circ x\circ...\circ x \end{aligned}

      xn={xxn1xn=1n>1\begin{aligned} x^n=\left\{\begin{aligned} &x\\ &x^{n-1}\circ x \end{aligned}\right. && \begin{aligned} &n=1\\ &n\gt 1 \end{aligned} \end{aligned}

      • 性质

      xnxm=xn+m\begin{aligned}& x^nx^m=x^{n+m} \end{aligned}

      (xn)xm=xnm\begin{aligned}& (x^n)x^m=x^{nm} \end{aligned}

      # 幂等律

      • 定义

      S的运算满足幂等律xS,xx=xS的所有元素都是幂等元\begin{aligned}& S的运算\circ 满足幂等律\\\Leftrightarrow& \forall x\in S, x\circ x=x\\\Leftrightarrow& S的所有元素都是幂等元 \end{aligned}

      # 分配律

      • 描述

      运算对运算是可分配的,或满足分配律的\begin{aligned}& 运算*对运算\circ 是可分配的,或满足分配律的 \end{aligned}

      • 定义

      x,y,zS,x(yz)=(xy)(xz)(yz)x=(yx)(zx)\begin{aligned} \forall x,y,z\in S\ ,\ & x*(y\circ z)=(x*y)\circ(x*z)\\& (y\circ z)*x=(y*x)\circ(z*x) \end{aligned}

      # 吸收律

      • 描述

      运算对运算是可分配的,或满足分配律的\begin{aligned}& 运算*对运算\circ 是可分配的,或满足分配律的 \end{aligned}

      • 定义

      x,yS,x(xy)=xx(xy)=x\begin{aligned} \forall x,y\in S\ ,\ &x*(x\circ y)=x\\&x\circ(x*y)=x \end{aligned}

      • 典例

      逻辑与、或满足吸收律\begin{aligned}& 逻辑与、或满足吸收律 \end{aligned}

      集合交、并满足吸收律\begin{aligned}& 集合交、并满足吸收律 \end{aligned}

      # 消去律

      • 定义

      x,y,zS,x不是零元xy=xzy=zyx=zxy=z\begin{aligned}& \forall x,y,z\in S\ ,\ x不是零元\\& x\circ y=x\circ z\to y=z\\& y\circ x=z\circ x\to y=z \end{aligned}

      • 典例

      数集加法、乘法满足消去律\begin{aligned}& 数集加法、乘法满足消去律 \end{aligned}

      集合交、并不满足消去律\begin{aligned}& 集合交、并不满足消去律 \end{aligned}

      #

      # 定义

      • 一个群包含

      一个二元运算\begin{aligned}& 一个二元运算\circ \end{aligned}

      满足结合律\begin{aligned}& \circ 满足结合律 \end{aligned}

      一个零元运算即单位元e\begin{aligned}& 一个零元运算即单位元e \end{aligned}

      e的单位元\begin{aligned}& e是\circ 的单位元 \end{aligned}

      一个一元运算()1\begin{aligned}& 一个一元运算(-)^{-1} \end{aligned}

      ()1给出每个元素关于的逆元\begin{aligned}& (-)^{-1}给出每个元素关于\circ 的逆元 \end{aligned}

      • 一个独异点包含

      一个二元运算\begin{aligned}& 一个二元运算\circ \end{aligned}

      满足结合律\begin{aligned}& \circ 满足结合律 \end{aligned}

      一个零元运算即单位元e\begin{aligned}& 一个零元运算即单位元e \end{aligned}

      e的单位元\begin{aligned}& e是\circ 的单位元 \end{aligned}

      • 一个半
        群包含

      一个二元运算\begin{aligned}& 一个二元运算\circ \end{aligned}

      满足结合律\begin{aligned}& \circ 满足结合律 \end{aligned}

      # 性质

      • 群有唯一单位元,没有零元,且所有元素有唯一逆元
      • 群的二元运算满足消去律

      # 阿贝尔群

      (可交换群)

      运算满足交换律的群运算满足交换律的群

      # 群的阶

      • 群的元素个数

      # 群元素的阶

      定义群元素an次幂:an={ean1a(a1)nn=0n>0n<0a的阶a是使ak=e成立的最小正整数k,当k不存在时a是无限阶元\begin{aligned}& 定义群元素a的n次幂:\\& \begin{aligned} a^n=\left\{\begin{aligned} &e\\ &a^{n-1}a\\ &(a^{-1})^{|n|} \end{aligned}\right. &&&& \begin{aligned} &n=0\\ &n\gt 0\\ &n\lt 0 \end{aligned} \end{aligned}\\& a的阶|a|是使a^k=e成立的最小正整数k,当k不存在时a是无限阶元 \end{aligned}

      • 性质

      am=enm,mZ\begin{aligned}& a^m=e\iff n|m,\ \ m\in \mathbb Z \end{aligned}

      (a1)k=(ak)1,kN\begin{aligned}& (a^{-1})^k=(a^k)^{-1},\ k\in\mathbb N \end{aligned}

      a1=a\begin{aligned}& |a^{-1}|=|a| \end{aligned}

      a=amgcd(a,m),mZ\begin{aligned}& |a|=|a^m|gcd(|a|,m),\ \ m\in \mathbb Z \end{aligned}

      # 模 m 单位群

      # 定义

      Zm={0,1,2,...,m1}U(m)Zm中所有与m互质的数构成的集合:Um={aZmgcd(a,m)=1}m乘运算Um构成群\begin{aligned}& \mathbb{Z}_m=\{0,1,2,...,m-1\}\\& U(m)是\mathbb{Z}_m中所有与m互质的数构成的集合:\\& U_m=\{a\in\mathbb{Z}_m|gcd(a,m)=1\}\\& 模m乘运算\otimes与U_m构成群 \end{aligned}

      # 正规子群

      or
      不变子群

      # 定义

      HG的子群,aG,Ha=aH\begin{aligned}& H是G的子群, \forall a\in G,\ Ha=aH \end{aligned}

      # 平凡正规子群

      G的单位元子群{e}G的单位元子群\{e\}

      G本身G本身

      # 单群

      G的正规子群只有平凡正规子群,且G{e}\begin{aligned}& G的正规子群只有平凡正规子群,且G\neq \{e\} \end{aligned}

      # 正规子群

      经典例子

      • 交换群

      A交换群每个元素左陪集等于右陪集故交换群每个子群都是正规子群\begin{aligned}& A交换群每个元素左陪集等于右陪集\\& 故交换群每个子群都是正规子群 \end{aligned}

      • 只有 2 个
        相异陪集

      待补待补

      # 商群

      # 描述

      G关于正规子群H的商群G关于正规子群H的商群

      # 定义

      NG的正规子群,N的全体陪集构成集合G/N定义G/N上的运算a,bG,NaNb=Nab从而G/N关于运算构成群,单位元为N\begin{aligned}& N是G的正规子群,N的全体陪集构成集合G/N\\& 定义G/N上的运算\circ 为\forall a,b\in G,\ \ Na\circ Nb=Nab\\& 从而G/N关于运算\circ构成群,单位元为N \end{aligned}

      # 群同态

      # 描述

      GG的一个同态f是一个函数f:GG群G到G'的一个同态f是一个函数f:G\to G'

      # 定义

      a,bG,f(ab)=f(a)f(b)\begin{aligned}& \forall a,b\in G,\ \ \ f(ab)=f(a)f(b) \end{aligned}

      # 自同态

      G到自己的同态f:GG群G到自己的同态f:G\to G

      # 满同态

      f是满函数f是满函数

      # 单同态

      f是单函数f是单函数

      # 同构

      f是双函数f是双函数

      GGG\cong G'

      \ No newline at end of file diff --git a/math/discrete-math/discrete-math-basics/dmbs/counting/index.html b/math/discrete-math/discrete-math-basics/dmbs/counting/index.html index 006cabbe..553e340a 100644 --- a/math/discrete-math/discrete-math-basics/dmbs/counting/index.html +++ b/math/discrete-math/discrete-math-basics/dmbs/counting/index.html @@ -1 +1 @@ -离散数学基础:排列组合计数问题 - 离散数学基础 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 思维导图

      排列组合计数问题

      #

      P(n,r)=n!(nr)!P(n,r)=\frac{n!}{(n-r)!}

      n个不同物体不允许重复地选r个物体的排列数n个不同物体不允许重复地选r个物体的排列数

      n元素的字符集上长度为r且不含重复字符的字符串数n元素的字符集上长度为r且不含重复字符的字符串数

      #

      nrn^r

      n类不同物体不允许重复地选r个物体的排列数n类不同物体不允许重复地选r个物体的排列数

      n元素的字符集上长度为r且可含重复字符的字符串数n元素的字符集上长度为r且可含重复字符的字符串数

      #

      C(n,r)=n!r!(nr)!C(n,r)=\frac{n!}{r!(n-r)!}

      n个不同物体不允许重复地选r个物体的组合数n个不同物体不允许重复地选r个物体的组合数

      r个无区别的物体放到n个无区别的容器里将r个无区别的物体放到n个无区别的容器里

      长度为n且有r1(0)的二进制串数长度为n且有r个1(或0)的二进制串数

      n元素集合的r元素子集的个数n元素集合的r元素子集的个数

      #

      C(n1+r,r)=(n1+r)!r!(n1)!C(n-1+r,r)=\frac{(n-1+r)!}{r!(n-1)!}

      n类不同物体允许重复地选r个物体的组合数n类不同物体允许重复地选r个物体的组合数

      r个无区别的物体放到n个可区别的容器里将r个无区别的物体放到n个可区别的容器里

      不定方程x1+x2+...+xn=r的非负整数解的个数\begin{aligned} &不定方程x_1 +x_2 +...+x_n =r\\ &的非负整数解的个数 \end{aligned}

      #

      i=1n(rj=1i1mjmi)=(rm1)(rm1m2)...(rm1m2...mn1mn)=r!m1!m2!...m3!\begin{aligned} &\prod_{i=1}^{n} \begin{pmatrix}r-\sum_{j=1}^{i-1}m_j\\m_i\end{pmatrix}\\ =& \begin{pmatrix}r\\m_1\end{pmatrix} \begin{pmatrix}r-m_1\\m_2\end{pmatrix} ... \begin{pmatrix}r-m_1-m_2-...-m_{n-1}\\m_n\end{pmatrix} \\ =&\frac{r!}{m_1!m_2!...m_3!} \end{aligned}

      分别有m1,m2,...,mn个的n类不同物体的m1+m2+...+mn=r排列数\begin{aligned} &分别有m_1,m_2,...,m_n个的n类不同物体的\\ &m_1+m_2+...+m_n=r排列数 \end{aligned}

      r个无区别的物体放到n个可区别的容器里将r个无区别的物体放到n个可区别的容器里

      m1+m2+...+mn=r个可区别的物体放到n个可区别的容器使第i个容器恰有mi个物体的方法数\begin{aligned} &m_1+m_2+...+m_n=r个可区别的物体\\ &放到n个可区别的容器使第i个容器\\ &恰有m_i个物体的方法数 \end{aligned}

      #

      不定方程x1+x2+...+xn=r的满足ximini的非负整数解个数等于不定方程(x1min1)+(x2min2)+...+(xnminn)=ri=1nminix1+x2+...+xn=ri=1nmini的非负整数解的个数\begin{aligned} &不定方程x_1 +x_2 +...+x_n =r的满足x_i\geq min_i的非负整数解个数等于\\ &不定方程(x_1-min_1)+(x_2-min_2)+...+(x_n-min_n)=r- \sum_{i=1}^{n}min_i \\ &即x_1 +x_2 +...+x_n =r- \sum_{i=1}^{n}min_i \\ &的非负整数解的个数 \end{aligned}

      #

      不定方程x1+x2+...+xn=r的满足maxiximini的非负整数解个数:U是不定方程x1+x2+...+xn=ri=1nmini的非负整数解构成的集合N=U,性质Pi表示ximaxi,N(Pi)等于U中满足性质Pi的元素个数所求解的个数=NN(P1P2...Pn)=N(P1P2...Pn)利用容斥原理求解\begin{aligned} &不定方程x_1 +x_2 +...+x_n =r的满足max_i\geq x_i\geq min_i的非负整数解个数:\\ &令U是不定方程x_1 +x_2 +...+x_n =r- \sum_{i=1}^{n}min_i 的非负整数解构成的集合\\ &N=|U|,性质P_i表示x_i\geq max_i,N(P_i)等于U中满足性质P_i的元素个数\\ &所求解的个数= N-N(\overline{P_1\cup P_2\cup...\cup P_n}) =N(\overline{P_1}\cap\overline{P_2}\cap...\cap\overline{P_n})\\ &利用容斥原理求解 \end{aligned}

      \ No newline at end of file +离散数学基础:排列组合计数问题 - 离散数学基础 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 思维导图

      排列组合计数问题

      #

      P(n,r)=n!(nr)!P(n,r)=\frac{n!}{(n-r)!}

      n个不同物体不允许重复地选r个物体的排列数n个不同物体不允许重复地选r个物体的排列数

      n元素的字符集上长度为r且不含重复字符的字符串数n元素的字符集上长度为r且不含重复字符的字符串数

      #

      nrn^r

      n类不同物体不允许重复地选r个物体的排列数n类不同物体不允许重复地选r个物体的排列数

      n元素的字符集上长度为r且可含重复字符的字符串数n元素的字符集上长度为r且可含重复字符的字符串数

      #

      C(n,r)=n!r!(nr)!C(n,r)=\frac{n!}{r!(n-r)!}

      n个不同物体不允许重复地选r个物体的组合数n个不同物体不允许重复地选r个物体的组合数

      r个无区别的物体放到n个无区别的容器里将r个无区别的物体放到n个无区别的容器里

      长度为n且有r1(0)的二进制串数长度为n且有r个1(或0)的二进制串数

      n元素集合的r元素子集的个数n元素集合的r元素子集的个数

      #

      C(n1+r,r)=(n1+r)!r!(n1)!C(n-1+r,r)=\frac{(n-1+r)!}{r!(n-1)!}

      n类不同物体允许重复地选r个物体的组合数n类不同物体允许重复地选r个物体的组合数

      r个无区别的物体放到n个可区别的容器里将r个无区别的物体放到n个可区别的容器里

      不定方程x1+x2+...+xn=r的非负整数解的个数\begin{aligned} &不定方程x_1 +x_2 +...+x_n =r\\ &的非负整数解的个数 \end{aligned}

      #

      i=1n(rj=1i1mjmi)=(rm1)(rm1m2)...(rm1m2...mn1mn)=r!m1!m2!...m3!\begin{aligned} &\prod_{i=1}^{n} \begin{pmatrix}r-\sum_{j=1}^{i-1}m_j\\m_i\end{pmatrix}\\ =& \begin{pmatrix}r\\m_1\end{pmatrix} \begin{pmatrix}r-m_1\\m_2\end{pmatrix} ... \begin{pmatrix}r-m_1-m_2-...-m_{n-1}\\m_n\end{pmatrix} \\ =&\frac{r!}{m_1!m_2!...m_3!} \end{aligned}

      分别有m1,m2,...,mn个的n类不同物体的m1+m2+...+mn=r排列数\begin{aligned} &分别有m_1,m_2,...,m_n个的n类不同物体的\\ &m_1+m_2+...+m_n=r排列数 \end{aligned}

      r个无区别的物体放到n个可区别的容器里将r个无区别的物体放到n个可区别的容器里

      m1+m2+...+mn=r个可区别的物体放到n个可区别的容器使第i个容器恰有mi个物体的方法数\begin{aligned} &m_1+m_2+...+m_n=r个可区别的物体\\ &放到n个可区别的容器使第i个容器\\ &恰有m_i个物体的方法数 \end{aligned}

      #

      不定方程x1+x2+...+xn=r的满足ximini的非负整数解个数等于不定方程(x1min1)+(x2min2)+...+(xnminn)=ri=1nminix1+x2+...+xn=ri=1nmini的非负整数解的个数\begin{aligned} &不定方程x_1 +x_2 +...+x_n =r的满足x_i\geq min_i的非负整数解个数等于\\ &不定方程(x_1-min_1)+(x_2-min_2)+...+(x_n-min_n)=r- \sum_{i=1}^{n}min_i \\ &即x_1 +x_2 +...+x_n =r- \sum_{i=1}^{n}min_i \\ &的非负整数解的个数 \end{aligned}

      #

      不定方程x1+x2+...+xn=r的满足maxiximini的非负整数解个数:U是不定方程x1+x2+...+xn=ri=1nmini的非负整数解构成的集合N=U,性质Pi表示ximaxi,N(Pi)等于U中满足性质Pi的元素个数所求解的个数=NN(P1P2...Pn)=N(P1P2...Pn)利用容斥原理求解\begin{aligned} &不定方程x_1 +x_2 +...+x_n =r的满足max_i\geq x_i\geq min_i的非负整数解个数:\\ &令U是不定方程x_1 +x_2 +...+x_n =r- \sum_{i=1}^{n}min_i 的非负整数解构成的集合\\ &N=|U|,性质P_i表示x_i\geq max_i,N(P_i)等于U中满足性质P_i的元素个数\\ &所求解的个数= N-N(\overline{P_1\cup P_2\cup...\cup P_n}) =N(\overline{P_1}\cap\overline{P_2}\cap...\cap\overline{P_n})\\ &利用容斥原理求解 \end{aligned}

      \ No newline at end of file diff --git a/math/discrete-math/discrete-math-basics/dmbs/difference-equations/index.html b/math/discrete-math/discrete-math-basics/dmbs/difference-equations/index.html index 0e9fa27e..eda3a06f 100644 --- a/math/discrete-math/discrete-math-basics/dmbs/difference-equations/index.html +++ b/math/discrete-math/discrete-math-basics/dmbs/difference-equations/index.html @@ -1 +1 @@ -离散数学基础:递推关系式 - 离散数学基础 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 思维导图

      递推关系式

      # 递推关系式相关概念

      # 定义

      用序列中某些前面的项ai,0i<n表示第nan的等式\text{用序列中某些前面的项}a_i,0\leq i\lt n\text{表示第}n\text{项}a_n\text{的等式}

      #

      序列{an}满足一个递推关系式,则{an}即为该递推关系式的一个解\text{序列}\{a_n\}\text{满足一个递推关系式,则}\{a_n\}\text{即为该递推关系式的一个解}

      # 封闭公式解

      序列{an}的第n项可以用不含序列中任何项的通项公式表达,则该通项公式称为该递推关系式的封闭公式解\begin{aligned} &\text{序列}\{a_n\}\text{的第n项可以用不含序列中任何项的通项公式表达,}\\ &\text{则该通项公式称为该递推关系式的封闭公式解} \end{aligned}

      # 常系数线性递推关系式的一般形式

      an=c1an1+c2an2+...+ckank+F(n)\begin{aligned} &a_n = c_1a_{n-1}+c_2a_{n-2}+...+c_ka_{n-k}+F(n) \end{aligned}

      F(n)=0则为齐次\text{若}F(n)=0\text{则为齐次}

      F(n)0则为非齐次\text{若}F(n)\neq 0\text{则为非齐次}

      # 线性齐次递推关系式的解

      # 特征方程

      xn=c1xn1+c2xn2+...+ckxnk+F(n)\begin{aligned} &x^n = c_1x^{n-1}+c_2x^{n-2}+...+c_kx^{n-k}+F(n) \end{aligned}

      # 特征方程的根

      r1,r2,...rt,重数分别为m1,m2,...m3,这门课没管复根情况咱就不背了捏\begin{aligned} r_1,r_2,...r_t,\text{重数分别为}m_1,m_2,...m_3,\text{这门课没管复根情况咱就不背了捏} \end{aligned}

      # 解的形式

      an=(β1,0+β1,1n+...+β1,m11nm11)r1n+(β2,0+β2,1n+...+β2,m21nm21)r2n+...+(βt,0+βt,1n+...+βt,mt1nmt1)rtn代入至少t个初始条件解出待定系数β1,β2,...βt即可得到解\begin{aligned} a_n &= (\beta_{1,0}+\beta_{1,1}n+...+\beta_{1,m_1-1}n^{m_1-1})r_1^{n} \\& +(\beta_{2,0}+\beta_{2,1}n+...+\beta_{2,m_2-1}n^{m_2-1})r_2^{n} \\& +...\\& +(\beta_{t,0}+\beta_{t,1}n+...+\beta_{t,m_t-1}n^{m_t-1})r_t^{n}\\& \text{代入至少t个初始条件解出待定系数}\beta_1,\beta_2,...\beta_t\text{即可得到解} \end{aligned}

      # 线性非齐次递推关系式的解

      # 伴随齐次递推关系式

      F(n)=0得到:\text{令}F(n)=0\text{得到:}

      an=c1an1+c2an2+...+ckank\begin{aligned} &a_n = c_1a_{n-1}+c_2a_{n-2}+...+c_ka_{n-k} \end{aligned}

      • 按照线性齐次递推关系式求解得到:

        • 通解,即伴随齐次递推关系式的解

      # F (n) 形式

      F(n)=(btnt+bt1nt1+...+b1n+b0)sn\begin{aligned} F(n)=(b_tn^t+b_{t-1}n^{t-1}+...+b_1n+b_0)s^n \end{aligned}

      这门课没管的别的情况咱就不背了捏

      # 特解的形式

      • s 不是伴随线性齐次递推关系式的特征方程的根

      an(p)=(ptnt+pt1nt1+...+p1n+p0)sn\begin{aligned} a_n^{(p)} = (p_tn^t+p_{t-1}n^{t-1}+...+p_1n+p_0)s^n \end{aligned}

      • s 是伴随线性齐次递推关系式的特征方程的 m 重根

      an(p)=nm(ptnt+pt1nt1+...+p1n+p0)sn\begin{aligned} a_n^{(p)} = n^m(p_tn^t+p_{t-1}n^{t-1}+...+p_1n+p_0)s^n \end{aligned}

      将特解代入递推关系式,对得到的关于n的多项式的等式两边比较系数,可以确定待定系数p0,p1,...pt\text{将特解代入递推关系式,对得到的关于n的多项式的等式两边比较系数,可以确定待定系数}p_0,p_1,...p_t

      # 解的形式

      an=通解+特解=通解+an(p)\begin{aligned} a_n = \text{通解}+\text{特解}=\text{通解}+a_n^{(p)} \end{aligned}

      # 算法效率

      分析主定理
      (Master Therorem)

      #

      f(n)是实递增函数,且满足递推关系式f(n)=af(nb)+Cnd,则:f(n){O(nd)a<bdO(ndlogn)a=bdO(nlogba)a>bda,bZ,a1,b>1,C,dR,C>0,d0\begin{aligned} &f(n)\text{是实递增函数,且满足递推关系式}f(n)=af(\frac{n}{b})+Cn^d\text{,则:}\\& \begin{aligned} f(n)是\left\{\begin{aligned} &O(n^d) & a\lt b^d\\ &O(n^dlogn) & a= b^d\\ &O(n^{log_ba})& a\gt b^d \end{aligned}\right. &&&&&& \begin{aligned} &a,b\in\mathbb{Z},a\geq1,b\gt1,\\ &C,d\in\mathbb{R},C\gt0,d\geq0 \end{aligned} \end{aligned} \end{aligned}

      \ No newline at end of file +离散数学基础:递推关系式 - 离散数学基础 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 思维导图

      递推关系式

      # 递推关系式相关概念

      # 定义

      用序列中某些前面的项ai,0i<n表示第nan的等式\text{用序列中某些前面的项}a_i,0\leq i\lt n\text{表示第}n\text{项}a_n\text{的等式}

      #

      序列{an}满足一个递推关系式,则{an}即为该递推关系式的一个解\text{序列}\{a_n\}\text{满足一个递推关系式,则}\{a_n\}\text{即为该递推关系式的一个解}

      # 封闭公式解

      序列{an}的第n项可以用不含序列中任何项的通项公式表达,则该通项公式称为该递推关系式的封闭公式解\begin{aligned} &\text{序列}\{a_n\}\text{的第n项可以用不含序列中任何项的通项公式表达,}\\ &\text{则该通项公式称为该递推关系式的封闭公式解} \end{aligned}

      # 常系数线性递推关系式的一般形式

      an=c1an1+c2an2+...+ckank+F(n)\begin{aligned} &a_n = c_1a_{n-1}+c_2a_{n-2}+...+c_ka_{n-k}+F(n) \end{aligned}

      F(n)=0则为齐次\text{若}F(n)=0\text{则为齐次}

      F(n)0则为非齐次\text{若}F(n)\neq 0\text{则为非齐次}

      # 线性齐次递推关系式的解

      # 特征方程

      xn=c1xn1+c2xn2+...+ckxnk+F(n)\begin{aligned} &x^n = c_1x^{n-1}+c_2x^{n-2}+...+c_kx^{n-k}+F(n) \end{aligned}

      # 特征方程的根

      r1,r2,...rt,重数分别为m1,m2,...m3,这门课没管复根情况咱就不背了捏\begin{aligned} r_1,r_2,...r_t,\text{重数分别为}m_1,m_2,...m_3,\text{这门课没管复根情况咱就不背了捏} \end{aligned}

      # 解的形式

      an=(β1,0+β1,1n+...+β1,m11nm11)r1n+(β2,0+β2,1n+...+β2,m21nm21)r2n+...+(βt,0+βt,1n+...+βt,mt1nmt1)rtn代入至少t个初始条件解出待定系数β1,β2,...βt即可得到解\begin{aligned} a_n &= (\beta_{1,0}+\beta_{1,1}n+...+\beta_{1,m_1-1}n^{m_1-1})r_1^{n} \\& +(\beta_{2,0}+\beta_{2,1}n+...+\beta_{2,m_2-1}n^{m_2-1})r_2^{n} \\& +...\\& +(\beta_{t,0}+\beta_{t,1}n+...+\beta_{t,m_t-1}n^{m_t-1})r_t^{n}\\& \text{代入至少t个初始条件解出待定系数}\beta_1,\beta_2,...\beta_t\text{即可得到解} \end{aligned}

      # 线性非齐次递推关系式的解

      # 伴随齐次递推关系式

      F(n)=0得到:\text{令}F(n)=0\text{得到:}

      an=c1an1+c2an2+...+ckank\begin{aligned} &a_n = c_1a_{n-1}+c_2a_{n-2}+...+c_ka_{n-k} \end{aligned}

      • 按照线性齐次递推关系式求解得到:

        • 通解,即伴随齐次递推关系式的解

      # F (n) 形式

      F(n)=(btnt+bt1nt1+...+b1n+b0)sn\begin{aligned} F(n)=(b_tn^t+b_{t-1}n^{t-1}+...+b_1n+b_0)s^n \end{aligned}

      这门课没管的别的情况咱就不背了捏

      # 特解的形式

      • s 不是伴随线性齐次递推关系式的特征方程的根

      an(p)=(ptnt+pt1nt1+...+p1n+p0)sn\begin{aligned} a_n^{(p)} = (p_tn^t+p_{t-1}n^{t-1}+...+p_1n+p_0)s^n \end{aligned}

      • s 是伴随线性齐次递推关系式的特征方程的 m 重根

      an(p)=nm(ptnt+pt1nt1+...+p1n+p0)sn\begin{aligned} a_n^{(p)} = n^m(p_tn^t+p_{t-1}n^{t-1}+...+p_1n+p_0)s^n \end{aligned}

      将特解代入递推关系式,对得到的关于n的多项式的等式两边比较系数,可以确定待定系数p0,p1,...pt\text{将特解代入递推关系式,对得到的关于n的多项式的等式两边比较系数,可以确定待定系数}p_0,p_1,...p_t

      # 解的形式

      an=通解+特解=通解+an(p)\begin{aligned} a_n = \text{通解}+\text{特解}=\text{通解}+a_n^{(p)} \end{aligned}

      # 算法效率

      分析主定理
      (Master Therorem)

      #

      f(n)是实递增函数,且满足递推关系式f(n)=af(nb)+Cnd,则:f(n){O(nd)a<bdO(ndlogn)a=bdO(nlogba)a>bda,bZ,a1,b>1,C,dR,C>0,d0\begin{aligned} &f(n)\text{是实递增函数,且满足递推关系式}f(n)=af(\frac{n}{b})+Cn^d\text{,则:}\\& \begin{aligned} f(n)是\left\{\begin{aligned} &O(n^d) & a\lt b^d\\ &O(n^dlogn) & a= b^d\\ &O(n^{log_ba})& a\gt b^d \end{aligned}\right. &&&&&& \begin{aligned} &a,b\in\mathbb{Z},a\geq1,b\gt1,\\ &C,d\in\mathbb{R},C\gt0,d\geq0 \end{aligned} \end{aligned} \end{aligned}

      \ No newline at end of file diff --git a/math/discrete-math/discrete-math-basics/dmbs/functions/index.html b/math/discrete-math/discrete-math-basics/dmbs/functions/index.html index c5e6e2ca..44945e39 100644 --- a/math/discrete-math/discrete-math-basics/dmbs/functions/index.html +++ b/math/discrete-math/discrete-math-basics/dmbs/functions/index.html @@ -1 +1 @@ -离散数学基础:函数 - 离散数学基础 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      函数

      # 函数

      (全函数)

      # 描述

      集合A到B的函数,是A×笛卡尔积的一类子集集合A到A的函数也称为A上的函数定义域的每个元素都存在陪域的唯一元素与之对应\begin{aligned} &\text{集合A到B的函数,是}A\times \text{笛卡尔积的一类子集}\\ &\text{集合A到A的函数也称为A上的函数}\\ &\text{定义域的每个元素都存在陪域的唯一元素与之对应} \end{aligned}

      # 记号

      f:AB\begin{aligned} f:A\to B \end{aligned}

      # 定义

      fP(A×B)orfA×B,aA,!bB,<a,b>f\begin{aligned} &f\in P(A\times B) \ or\ f \subseteq A\times B ,\\ &\forall a\in A,\ \exists!b\in B,\ <a,b>\in f \end{aligned}

      #

      b是a在函数f下的像\text{b是a在函数f下的像}

      # 原像

      a是b在函数f下的原像\text{a是b在函数f下的原像}

      # 定义域 or 域

      AA

      # 陪域

      BB

      # 像集

      # 描述

      A的子集S在f下的像集,是f的陪域B的子集\text{A的子集S在f下的像集,是f的陪域B的子集}

      # 记号

      f(S)\begin{aligned} f(S) \end{aligned}

      # 定义

      f(S)={f(x)BxS}={yBxS,y=f(x)}B\begin{aligned} f(S)&=\{f(x)\in B|x\in S\}\\ &=\{y\in B|\exists x\in S,y=f(x)\}\\ &\subseteq B \end{aligned}

      # 值域

      f(A)=ran(f)\begin{aligned} f(A)=\boldsymbol{ran}(f) \end{aligned}

      # 逆像集

      # 描述

      B的子集T在f下的逆像集,是f的域A的子集\text{B的子集T在f下的逆像集,是f的域A的子集}

      # 记号

      f1(T)\begin{aligned} f^{-1}(T) \end{aligned}

      # 定义

      f1(T)={xAf(x)T}A\begin{aligned} f^{-1}(T)=\{x\in A|f(x)\in T\}\subseteq A \end{aligned}

      # 恒等函数

      # 描述

      任意非空集A上的恒等关系ΔA是A的恒等函数来自恒等关系\begin{aligned}&\text{任意非空集A上的恒等关系}\Delta_A\text{是A的恒等函数}\\& \text{来自恒等关系} \end{aligned}

      # 记号

      idA=ΔA\begin{aligned} \boldsymbol{id}_A=\Delta_A \end{aligned}

      # 定义

      f1(T)={xAf(x)T}A\begin{aligned} f^{-1}(T)=\{x\in A|f(x)\in T\}\subseteq A \end{aligned}

      # 空函数

      # 描述

      以空集为定义域的函数都是空函数,当函数陪域为空集时定义域也只能是空集,从而函数也是空函数,否则不满足函数定义来自空关系\begin{aligned}& \text{以空集为定义域的函数都是空函数,}\\& \text{当函数陪域为空集时定义域也只能是空集,}\\& \text{从而函数也是空函数,否则不满足函数定义}\\& \text{来自空关系} \end{aligned}

      # 定义

      f:AB,A=f是空函数B=A=f是空函数\begin{aligned} &f:A\to B,\\ &A=\varnothing\to f\text{是空函数}\\ &B=\varnothing\to A=\varnothing\to f\text{是空函数} \end{aligned}

      # 特征函数

      # 描述

      子集S的特征函数是全集U的任意子集S到2={0,1}的函数\begin{aligned} &\text{子集S的特征函数是}\\ &\text{全集U的任意子集S到}\boldsymbol{2}=\{\boldsymbol{0},\boldsymbol{1}\}\text{的函数} \end{aligned}

      # 记号

      χs:U2\begin{aligned} \chi_s :U\to \boldsymbol{2} \end{aligned}

      # 定义

      χs(x)={10xSx∉S\begin{aligned} \chi_s (x)=\left\{\begin{aligned} \boldsymbol{1}\\ \boldsymbol{0} \end{aligned}\right. &&&& \begin{aligned} x\in S\\ x\not\in S \end{aligned} \end{aligned}

      # 自然映射

      # 描述

      R是非空集A上的等价关系,商集A/R的自然映射是A到A/R的函数,将A的任意元素a映射到它所在的等价类[a]R\begin{aligned} &R\text{是非空集A上的等价关系,}\\ &\text{商集A/R的自然映射是A到A/R的函数},\\ &\text{将A的任意元素a映射到它所在的等价类}[a]_R \end{aligned}

      # 记号

      ρ:AA/R\begin{aligned} \rho :A\to A/R \end{aligned}

      # 定义

      ρ(a)=[a]R\begin{aligned} \rho(a)=[a]_R \end{aligned}

      # 函数集

      (函数族)

      # 描述

      所有从集合A到集合B的函数的集合\text{所有从集合A到集合B的函数的集合}

      # 记号

      BA\begin{aligned} B^A \end{aligned}

      # 偏函数

      # 描述

      与全函数的区别在于:定义域的每个元素至多存在陪域的一个元素与之对应\begin{aligned} &与全函数的区别在于:\\ &定义域的每个元素至多存在陪域的一个元素与之对应 \end{aligned}

      # 记号

      f:AB\begin{aligned} f:A\rightharpoonup B \end{aligned}

      # 定义

      fP(A×B)orfA×B,aA,(!bB,<a,b>f)(!bB,<a,b>f)\begin{aligned} &f\in P(A\times B) \ or\ f \subseteq A\times B ,\ \ \forall a\in A,\\& (\exists!b\in B,\ <a,b>\in f)\lor(!\exists b\in B,\ <a,b>\in f) \end{aligned}

      # 备注

      本门课程里的函数默认是全函数\text{本门课程里的函数默认是全函数}

      # 单函数

      (一对一函数)

      # 描述

      陪域的每个元素至多存在定义域的一个元素与之对应\begin{aligned}\text{陪域的每个元素至多存在定义域的一个元素与之对应} \end{aligned}

      # 定义

      x,yA,xyf(x)f(y)\begin{aligned} &\forall x,y\in A,\ \ x\neq y\to f(x)\neq f(y) \end{aligned}

      x,yA,f(x)=f(y)x=y\begin{aligned} &\forall x,y\in A,\ \ f(x)=f(y)\to x=y \end{aligned}

      f存在左逆\begin{aligned} f\text{存在左逆} \end{aligned}

      # 满函数

      (映上函数)

      # 描述

      陪域的每个元素至少存在定义域的一个元素与之对应\begin{aligned}\text{陪域的每个元素至少存在定义域的一个元素与之对应} \end{aligned}

      # 定义

      ran(f)=B\begin{aligned} \boldsymbol{ran}(f)=B \end{aligned}

      yB,xA,f(x)=y\begin{aligned} &\forall y\in B,\ \ \exists x\in A,\ \ f(x)=y \end{aligned}

      f存在右逆\begin{aligned} f\text{存在右逆} \end{aligned}

      # 双函数

      (一一对应)

      # 描述

      陪域的每个元素都有定义域唯一一个元素与之对应\begin{aligned} \text{陪域的每个元素都有定义域唯一一个元素与之对应} \end{aligned}

      # 定义

      f既是单函数又是满函数\begin{aligned} f\text{既是单函数又是满函数} \end{aligned}

      f:AB是双函数g:BA,gf=idA,fg=idBf1,f1f=idA,ff1=idB\begin{aligned}& f:A\to B\text{是双函数}\\\Leftrightarrow& \exists g:B\to A\ ,\ g\circ f=\boldsymbol{id}_A\ ,\ f\circ g=\boldsymbol{id}_B\\\Leftrightarrow& \exists f^{-1},f^{-1}\circ f=\boldsymbol{id}_A\ ,\ f\circ f^{-1}=\boldsymbol{id}_B \end{aligned}

      # 函数的复合

      # 描述

      函数f:ABg:BC的复合与关系的复合是一致的,是二元运算\begin{aligned} &\text{函数}f:A\to B\text{和}g:B\to C\text{的复合}\\& \text{与关系的复合是一致的,是二元运算} \end{aligned}

      # 记号

      (gf)(x)=g(f(x))\begin{aligned} (g\circ f)(x)=g(f(x)) \end{aligned}

      # 定义

      (gf)(x)=g(f(x))\begin{aligned} (g\circ f)(x)=g(f(x)) \end{aligned}

      gf={<x,y>z(<x,z>f<z,y>g)}={<x,y>z(f(x)=zg(z)=y)}={<x,y>g(f(x))=y}\begin{aligned} g\circ f&=\{<x,y>|\exists z(<x,z>\in f\land<z,y>\in g)\}\\ &=\{<x,y>|\exists z(f(x)=z\land g(z)=y)\}\\ &=\{<x,y>|g(f(x))=y\} \end{aligned}

      # 性质

      关系复合不满足交换律\begin{aligned}& 关系复合不满足交换律 \end{aligned}

      关系复合满足结合律\begin{aligned}&\text{关系复合满足结合律} \end{aligned}

      fg是单函数gf是单函数f是单函数\begin{aligned}& f\text{和}g\text{是单函数}\to g\circ f\text{是单函数}\to f\text{是单函数} \end{aligned}

      fg是满函数gf是满函数g是满函数\begin{aligned}& f\text{和}g\text{是满函数}\to g\circ f\text{是满函数}\to g\text{是满函数} \end{aligned}

      fg是双函数gf是双函数f是单函数且g是满函数\begin{aligned}& f\text{和}g\text{是双函数}\to g\circ f\text{是双函数}\to f\text{是单函数且}g\text{是满函数} \end{aligned}

      # 逆函数

      # 描述

      双函数f作为关系的逆关系f1f的逆函数\begin{aligned}\text{双函数}f\text{作为关系的逆关系}f^{-1}\text{是}f\text{的逆函数} \end{aligned}

      # 定义

      f1={<y,x>B×A<x,y>f}={<y,x>f(x)=y}\begin{aligned} f^{-1}& =\{<y,x>\in B\times A|<x,y>\in f\}\\& =\{<y,x>|f(x)=y\} \end{aligned}

      f1:BA是双函数f的逆函数f1f=idA,ff1=idB\begin{aligned}& f^{-1}:B\to A\text{是双函数}f\text{的逆函数}\\\Leftrightarrow& f^{-1}\circ f=\boldsymbol{id}_A\ ,\ f\circ f^{-1}=\boldsymbol{id}_B \end{aligned}

      # 左逆

      # 描述

      g:BA是函数f的左逆,满足:\begin{aligned} g:B\to A\text{是函数}f\text{的左逆,满足:} \end{aligned}

      # 定义

      gf=idA\begin{aligned} &g\circ f=\boldsymbol{id}_A \end{aligned}

      # 左逆

      # 描述

      g:BA是函数f的右逆,满足:\begin{aligned} g:B\to A\text{是函数}f\text{的右逆,满足:} \end{aligned}

      # 定义

      fg=idB\begin{aligned} &f\circ g=\boldsymbol{id}_B \end{aligned}

      \ No newline at end of file +离散数学基础:函数 - 离散数学基础 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      函数

      # 函数

      (全函数)

      # 描述

      集合A到B的函数,是A×笛卡尔积的一类子集集合A到A的函数也称为A上的函数定义域的每个元素都存在陪域的唯一元素与之对应\begin{aligned} &\text{集合A到B的函数,是}A\times \text{笛卡尔积的一类子集}\\ &\text{集合A到A的函数也称为A上的函数}\\ &\text{定义域的每个元素都存在陪域的唯一元素与之对应} \end{aligned}

      # 记号

      f:AB\begin{aligned} f:A\to B \end{aligned}

      # 定义

      fP(A×B)orfA×B,aA,!bB,<a,b>f\begin{aligned} &f\in P(A\times B) \ or\ f \subseteq A\times B ,\\ &\forall a\in A,\ \exists!b\in B,\ <a,b>\in f \end{aligned}

      #

      b是a在函数f下的像\text{b是a在函数f下的像}

      # 原像

      a是b在函数f下的原像\text{a是b在函数f下的原像}

      # 定义域 or 域

      AA

      # 陪域

      BB

      # 像集

      # 描述

      A的子集S在f下的像集,是f的陪域B的子集\text{A的子集S在f下的像集,是f的陪域B的子集}

      # 记号

      f(S)\begin{aligned} f(S) \end{aligned}

      # 定义

      f(S)={f(x)BxS}={yBxS,y=f(x)}B\begin{aligned} f(S)&=\{f(x)\in B|x\in S\}\\ &=\{y\in B|\exists x\in S,y=f(x)\}\\ &\subseteq B \end{aligned}

      # 值域

      f(A)=ran(f)\begin{aligned} f(A)=\boldsymbol{ran}(f) \end{aligned}

      # 逆像集

      # 描述

      B的子集T在f下的逆像集,是f的域A的子集\text{B的子集T在f下的逆像集,是f的域A的子集}

      # 记号

      f1(T)\begin{aligned} f^{-1}(T) \end{aligned}

      # 定义

      f1(T)={xAf(x)T}A\begin{aligned} f^{-1}(T)=\{x\in A|f(x)\in T\}\subseteq A \end{aligned}

      # 恒等函数

      # 描述

      任意非空集A上的恒等关系ΔA是A的恒等函数来自恒等关系\begin{aligned}&\text{任意非空集A上的恒等关系}\Delta_A\text{是A的恒等函数}\\& \text{来自恒等关系} \end{aligned}

      # 记号

      idA=ΔA\begin{aligned} \boldsymbol{id}_A=\Delta_A \end{aligned}

      # 定义

      f1(T)={xAf(x)T}A\begin{aligned} f^{-1}(T)=\{x\in A|f(x)\in T\}\subseteq A \end{aligned}

      # 空函数

      # 描述

      以空集为定义域的函数都是空函数,当函数陪域为空集时定义域也只能是空集,从而函数也是空函数,否则不满足函数定义来自空关系\begin{aligned}& \text{以空集为定义域的函数都是空函数,}\\& \text{当函数陪域为空集时定义域也只能是空集,}\\& \text{从而函数也是空函数,否则不满足函数定义}\\& \text{来自空关系} \end{aligned}

      # 定义

      f:AB,A=f是空函数B=A=f是空函数\begin{aligned} &f:A\to B,\\ &A=\varnothing\to f\text{是空函数}\\ &B=\varnothing\to A=\varnothing\to f\text{是空函数} \end{aligned}

      # 特征函数

      # 描述

      子集S的特征函数是全集U的任意子集S到2={0,1}的函数\begin{aligned} &\text{子集S的特征函数是}\\ &\text{全集U的任意子集S到}\boldsymbol{2}=\{\boldsymbol{0},\boldsymbol{1}\}\text{的函数} \end{aligned}

      # 记号

      χs:U2\begin{aligned} \chi_s :U\to \boldsymbol{2} \end{aligned}

      # 定义

      χs(x)={10xSx∉S\begin{aligned} \chi_s (x)=\left\{\begin{aligned} \boldsymbol{1}\\ \boldsymbol{0} \end{aligned}\right. &&&& \begin{aligned} x\in S\\ x\not\in S \end{aligned} \end{aligned}

      # 自然映射

      # 描述

      R是非空集A上的等价关系,商集A/R的自然映射是A到A/R的函数,将A的任意元素a映射到它所在的等价类[a]R\begin{aligned} &R\text{是非空集A上的等价关系,}\\ &\text{商集A/R的自然映射是A到A/R的函数},\\ &\text{将A的任意元素a映射到它所在的等价类}[a]_R \end{aligned}

      # 记号

      ρ:AA/R\begin{aligned} \rho :A\to A/R \end{aligned}

      # 定义

      ρ(a)=[a]R\begin{aligned} \rho(a)=[a]_R \end{aligned}

      # 函数集

      (函数族)

      # 描述

      所有从集合A到集合B的函数的集合\text{所有从集合A到集合B的函数的集合}

      # 记号

      BA\begin{aligned} B^A \end{aligned}

      # 偏函数

      # 描述

      与全函数的区别在于:定义域的每个元素至多存在陪域的一个元素与之对应\begin{aligned} &与全函数的区别在于:\\ &定义域的每个元素至多存在陪域的一个元素与之对应 \end{aligned}

      # 记号

      f:AB\begin{aligned} f:A\rightharpoonup B \end{aligned}

      # 定义

      fP(A×B)orfA×B,aA,(!bB,<a,b>f)(!bB,<a,b>f)\begin{aligned} &f\in P(A\times B) \ or\ f \subseteq A\times B ,\ \ \forall a\in A,\\& (\exists!b\in B,\ <a,b>\in f)\lor(!\exists b\in B,\ <a,b>\in f) \end{aligned}

      # 备注

      本门课程里的函数默认是全函数\text{本门课程里的函数默认是全函数}

      # 单函数

      (一对一函数)

      # 描述

      陪域的每个元素至多存在定义域的一个元素与之对应\begin{aligned}\text{陪域的每个元素至多存在定义域的一个元素与之对应} \end{aligned}

      # 定义

      x,yA,xyf(x)f(y)\begin{aligned} &\forall x,y\in A,\ \ x\neq y\to f(x)\neq f(y) \end{aligned}

      x,yA,f(x)=f(y)x=y\begin{aligned} &\forall x,y\in A,\ \ f(x)=f(y)\to x=y \end{aligned}

      f存在左逆\begin{aligned} f\text{存在左逆} \end{aligned}

      # 满函数

      (映上函数)

      # 描述

      陪域的每个元素至少存在定义域的一个元素与之对应\begin{aligned}\text{陪域的每个元素至少存在定义域的一个元素与之对应} \end{aligned}

      # 定义

      ran(f)=B\begin{aligned} \boldsymbol{ran}(f)=B \end{aligned}

      yB,xA,f(x)=y\begin{aligned} &\forall y\in B,\ \ \exists x\in A,\ \ f(x)=y \end{aligned}

      f存在右逆\begin{aligned} f\text{存在右逆} \end{aligned}

      # 双函数

      (一一对应)

      # 描述

      陪域的每个元素都有定义域唯一一个元素与之对应\begin{aligned} \text{陪域的每个元素都有定义域唯一一个元素与之对应} \end{aligned}

      # 定义

      f既是单函数又是满函数\begin{aligned} f\text{既是单函数又是满函数} \end{aligned}

      f:AB是双函数g:BA,gf=idA,fg=idBf1,f1f=idA,ff1=idB\begin{aligned}& f:A\to B\text{是双函数}\\\Leftrightarrow& \exists g:B\to A\ ,\ g\circ f=\boldsymbol{id}_A\ ,\ f\circ g=\boldsymbol{id}_B\\\Leftrightarrow& \exists f^{-1},f^{-1}\circ f=\boldsymbol{id}_A\ ,\ f\circ f^{-1}=\boldsymbol{id}_B \end{aligned}

      # 函数的复合

      # 描述

      函数f:ABg:BC的复合与关系的复合是一致的,是二元运算\begin{aligned} &\text{函数}f:A\to B\text{和}g:B\to C\text{的复合}\\& \text{与关系的复合是一致的,是二元运算} \end{aligned}

      # 记号

      (gf)(x)=g(f(x))\begin{aligned} (g\circ f)(x)=g(f(x)) \end{aligned}

      # 定义

      (gf)(x)=g(f(x))\begin{aligned} (g\circ f)(x)=g(f(x)) \end{aligned}

      gf={<x,y>z(<x,z>f<z,y>g)}={<x,y>z(f(x)=zg(z)=y)}={<x,y>g(f(x))=y}\begin{aligned} g\circ f&=\{<x,y>|\exists z(<x,z>\in f\land<z,y>\in g)\}\\ &=\{<x,y>|\exists z(f(x)=z\land g(z)=y)\}\\ &=\{<x,y>|g(f(x))=y\} \end{aligned}

      # 性质

      关系复合不满足交换律\begin{aligned}& 关系复合不满足交换律 \end{aligned}

      关系复合满足结合律\begin{aligned}&\text{关系复合满足结合律} \end{aligned}

      fg是单函数gf是单函数f是单函数\begin{aligned}& f\text{和}g\text{是单函数}\to g\circ f\text{是单函数}\to f\text{是单函数} \end{aligned}

      fg是满函数gf是满函数g是满函数\begin{aligned}& f\text{和}g\text{是满函数}\to g\circ f\text{是满函数}\to g\text{是满函数} \end{aligned}

      fg是双函数gf是双函数f是单函数且g是满函数\begin{aligned}& f\text{和}g\text{是双函数}\to g\circ f\text{是双函数}\to f\text{是单函数且}g\text{是满函数} \end{aligned}

      # 逆函数

      # 描述

      双函数f作为关系的逆关系f1f的逆函数\begin{aligned}\text{双函数}f\text{作为关系的逆关系}f^{-1}\text{是}f\text{的逆函数} \end{aligned}

      # 定义

      f1={<y,x>B×A<x,y>f}={<y,x>f(x)=y}\begin{aligned} f^{-1}& =\{<y,x>\in B\times A|<x,y>\in f\}\\& =\{<y,x>|f(x)=y\} \end{aligned}

      f1:BA是双函数f的逆函数f1f=idA,ff1=idB\begin{aligned}& f^{-1}:B\to A\text{是双函数}f\text{的逆函数}\\\Leftrightarrow& f^{-1}\circ f=\boldsymbol{id}_A\ ,\ f\circ f^{-1}=\boldsymbol{id}_B \end{aligned}

      # 左逆

      # 描述

      g:BA是函数f的左逆,满足:\begin{aligned} g:B\to A\text{是函数}f\text{的左逆,满足:} \end{aligned}

      # 定义

      gf=idA\begin{aligned} &g\circ f=\boldsymbol{id}_A \end{aligned}

      # 左逆

      # 描述

      g:BA是函数f的右逆,满足:\begin{aligned} g:B\to A\text{是函数}f\text{的右逆,满足:} \end{aligned}

      # 定义

      fg=idB\begin{aligned} &f\circ g=\boldsymbol{id}_B \end{aligned}

      \ No newline at end of file diff --git a/math/discrete-math/discrete-math-basics/dmbs/operations-of-sets-and-relations/index.html b/math/discrete-math/discrete-math-basics/dmbs/operations-of-sets-and-relations/index.html index a57469e6..d6a67ddd 100644 --- a/math/discrete-math/discrete-math-basics/dmbs/operations-of-sets-and-relations/index.html +++ b/math/discrete-math/discrete-math-basics/dmbs/operations-of-sets-and-relations/index.html @@ -1 +1 @@ -离散数学基础:集合与关系的运算 - 离散数学基础 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 思维导图

      集合与关系的运算

      #

      # 定义

      RS={<a,b><a,b>R<a,b>S}\begin{aligned}& R\cup S =\{<a,b>|<a,b>\in R\ \ \lor <a,b>\in S\}\end{aligned}

      # 关系矩阵

      MRS=MRMS=[rijsij]\begin{aligned}& M_{R\cup S} = M_R \lor M_S = [r_{ij}\lor s_{ij}]\end{aligned}

      # 性质

      单位元: 空关系\begin{aligned}&\text{单位元: 空关系}\end{aligned}

      零元:全关系\begin{aligned}&\text{零元:全关系}\end{aligned}

      关系并满足交换律\begin{aligned}&\text{关系并满足交换律}\end{aligned}

      关系并满足结合律\begin{aligned}&\text{关系并满足结合律}\end{aligned}

      关系并的单调性:关系并保持子集关系AB,CDABCDAC,BCABC\begin{aligned}\text{关系并的单调性:关系并保持子集关系}\\ A\subseteq B,C\subseteq D \Rightarrow A\cup B\subseteq C\cup D\\ A\subseteq C,B\subseteq C \Leftrightarrow A\cup B\subseteq C\end{aligned}

      关系并对关系交有分配律\begin{aligned}&\text{关系并对关系交有分配律}\end{aligned}

      关系并对关系差不满足分配律ABACA(BC)\begin{aligned}\text{关系并对关系差不满足分配律}\\ A\cup B-A\cup C\subseteq A\cup(B-C)\end{aligned}

      #

      # 定义

      RS={<a,b><a,b>R<a,b>S}\begin{aligned}& R\cap S =\{<a,b>|<a,b>\in R\ \ \land <a,b>\in S\}\end{aligned}

      # 关系矩阵

      MRS=MRMS=[rijsij]\begin{aligned}& M_{R\cap S} = M_R \land M_S = [r_{ij}\land s_{ij}]\end{aligned}

      # 性质

      单位元:全关系\begin{aligned}& 单位元:全关系 \end{aligned}

      零元: 空关系\begin{aligned}&\text{零元: 空关系}\end{aligned}

      关系交满足交换律\begin{aligned}&\text{关系交满足交换律}\end{aligned}

      关系交满足结合律\begin{aligned}&\text{关系交满足结合律}\end{aligned}

      关系交的单调性:关系交保持子集关系AB,CDABCDCA,CBCAB\begin{aligned}\text{关系交的单调性:关系交保持子集关系}\\ A\subseteq B,C\subseteq D \Rightarrow A\cap B\subseteq C\cap D\\ C\subseteq A,C\subseteq B \Leftrightarrow C\subseteq A\cup B\end{aligned}

      关系交对关系并有分配律\begin{aligned}&\text{关系交对关系并有分配律}\end{aligned}

      关系交对关系差有分配律\begin{aligned}\text{关系交对关系差有分配律}\end{aligned}

      #

      # 定义

      RS={<a,b><a,b>R<a,b>S}\begin{aligned}& R- S =\{<a,b>|<a,b>\in R\ \ \land <a,b>\notin S\}\end{aligned}

      # 关系矩阵

      MRS=MRMS=[rijsij]\begin{aligned}& M_{R- S} = M_R \ominus M_S = [r_{ij}\ominus s_{ij}]\end{aligned}

      运算00=01=11=010=1\begin{aligned}&\text{运算}\ominus:0\ominus0=0\ominus1=1\ominus1=0,1\ominus0=1\end{aligned}

      # 性质

      左零单位: 全关系\begin{aligned}&\text{左零单位: 全关系}\end{aligned}

      右单位元: 空关系\begin{aligned}&\text{右单位元: 空关系}\end{aligned}

      左零元: 空关系\begin{aligned}&\text{左零元: 空关系}\end{aligned}

      右零元: 全关系\begin{aligned}&\text{右零元: 全关系}\end{aligned}

      关系差不满足交换律\begin{aligned}&\text{关系差不满足交换律}\end{aligned}

      关系差不满足结合律\begin{aligned}&\text{关系差不满足结合律}\end{aligned}

      关系差无单调性:关系差不保持子集关系\begin{aligned}&\text{关系差无单调性:关系差不保持子集关系}\end{aligned}

      关系差对关系并没有分配律:A(BC)(AB)(AC)\begin{aligned}\text{关系差对关系并没有分配律}:\\ A-(B\cup C) \subseteq (A-B)\cup(A-C)\end{aligned}

      关系差对关系交没有分配律:(AB)(AC)A(BC)\begin{aligned}\text{关系差对关系交没有分配律}:\\ (A-B)\cap(A-C) \subseteq A-(B\cap C)\end{aligned}

      关系差对关系交、关系并有反分配律:A(BC)=(AB)(AC)A(BC)=(AB)(AC)\begin{aligned}\text{关系差对关系交、关系并有反分配律}:\\ A-(B\cup C) = (A-B)\cap(A-C)\\ A-(B\cap C) = (A-B)\cup(A-C)\end{aligned}

      # 复合

      # 定义

      SR={<a,c>bB(<a,b>R<b,c>S)}\begin{aligned}& S\circ R=\{<a,c>|\exists b\in B(<a,b>\in R\land <b,c>\in S)\}\end{aligned}

      # 关系矩阵

      MRS=MRMS\begin{aligned}& M_{R\circ S} = M_R \odot M_S\end{aligned}

      逻辑积运算:与矩阵乘法本质相同,只是将其中的加法、乘法分别用逻辑或(逻辑加法) 、逻辑与(逻辑减法)替代\begin{aligned}&\text{逻辑积运算}\odot\text{:与矩阵乘法本质相同,}\\& \text{只是将其中的加法、乘法分别用}\\& \text{逻辑或}\lor\text{(逻辑加法) 、逻辑与}\land\text{(逻辑减法)替代}\end{aligned}

      # 备注

      本课程采用逆序复合\begin{aligned}&\text{本课程采用逆序复合}\end{aligned}

      # 性质

      单位元:恒等关系\begin{aligned}&\text{单位元:恒等关系}\end{aligned}

      零元: 空关系\begin{aligned}&\text{零元: 空关系}\end{aligned}

      关系复合不满足交换律\begin{aligned}&\text{关系复合不满足交换律}\end{aligned}

      关系复合满足结合律\begin{aligned}&\text{关系复合满足结合律}\end{aligned}

      关系复合的单调性:关系复合保持子集关系RS,UWURWS\begin{aligned}&\text{关系复合的单调性:关系复合保持子集关系}\\& R\subseteq S, U\subseteq W \to U\circ R\subseteq W\circ S\end{aligned}

      关系复合对关系并有分配律\begin{aligned}&\text{关系复合对关系并有分配律}\end{aligned}

      关系复合对关系交没有分配律:(RS)T(RT)(ST)\begin{aligned}\text{关系复合对关系交没有分配律}:\\ (R\cap S)\circ T \subseteq (R\circ T)\cap(S\circ T)\end{aligned}

      #

      # 定义

      R={<a,b>A×B<a,b>R}=A×BR\begin{aligned} \overline R &=\{<a,b>\in A\times B|<a,b>\notin R\}\\& =A\times B-R\end{aligned}

      # 关系矩阵

      MR=MR=[rij]\begin{aligned}& M_{\overline R}=\overline{M_R}=[\overline{r_{ij}}]\end{aligned}

      # 性质

      关系补的单调性:关系补运算保持相反的子集关系\begin{aligned}&\text{关系补的单调性:关系补运算保持相反的子集关系}\end{aligned}

      关系补对关系并没有分配律:ABAB\begin{aligned}&\text{关系补对关系并没有分配律}: \overline{A\cup B} \subseteq \overline{A}\cup\overline{B}\end{aligned}

      关系补对关系交有分配律\begin{aligned}&\text{关系补对关系交有分配律}\end{aligned}

      关系补对关系差没有分配律:ABAB\begin{aligned}&\text{关系补对关系差没有分配律}: \overline{A}-\overline{B}\subseteq\overline{A-B}\end{aligned}

      关系补对关系复合有分配律\begin{aligned}&\text{关系补对关系复合有分配律}\end{aligned}

      关系逆与关系补有交换律(两个一元运算)\begin{aligned}&\text{关系逆与关系补有交换律(两个一元运算)}\end{aligned}

      #

      # 定义

      R1={<b,a><a,b>R}\begin{aligned}& R^{-1}=\{<b,a>|<a,b>\in R\}\end{aligned}

      # 关系矩阵

      MR1=(MR)T\begin{aligned}& M_{R^{-1}}=(M_R)^T\end{aligned}

      # 性质

      关系逆的单调性:关系逆运算保持子集关系\begin{aligned}&\text{关系逆的单调性:关系逆运算保持子集关系}\end{aligned}

      关系逆对关系并有分配律\begin{aligned}&\text{关系逆对关系并有分配律}\end{aligned}

      关系逆对关系交有分配律\begin{aligned}&\text{关系逆对关系交有分配律}\end{aligned}

      关系逆对关系差有分配律\begin{aligned}&\text{关系逆对关系差有分配律}\end{aligned}

      关系逆对关系复合有分配律\begin{aligned}&\text{关系逆对关系复合有分配律}\end{aligned}

      关系逆与关系补有交换律(两个一元运算)\begin{aligned}&\text{关系逆与关系补有交换律(两个一元运算)}\end{aligned}

      \ No newline at end of file +离散数学基础:集合与关系的运算 - 离散数学基础 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 思维导图

      集合与关系的运算

      #

      # 定义

      RS={<a,b><a,b>R<a,b>S}\begin{aligned}& R\cup S =\{<a,b>|<a,b>\in R\ \ \lor <a,b>\in S\}\end{aligned}

      # 关系矩阵

      MRS=MRMS=[rijsij]\begin{aligned}& M_{R\cup S} = M_R \lor M_S = [r_{ij}\lor s_{ij}]\end{aligned}

      # 性质

      单位元: 空关系\begin{aligned}&\text{单位元: 空关系}\end{aligned}

      零元:全关系\begin{aligned}&\text{零元:全关系}\end{aligned}

      关系并满足交换律\begin{aligned}&\text{关系并满足交换律}\end{aligned}

      关系并满足结合律\begin{aligned}&\text{关系并满足结合律}\end{aligned}

      关系并的单调性:关系并保持子集关系AB,CDABCDAC,BCABC\begin{aligned}\text{关系并的单调性:关系并保持子集关系}\\ A\subseteq B,C\subseteq D \Rightarrow A\cup B\subseteq C\cup D\\ A\subseteq C,B\subseteq C \Leftrightarrow A\cup B\subseteq C\end{aligned}

      关系并对关系交有分配律\begin{aligned}&\text{关系并对关系交有分配律}\end{aligned}

      关系并对关系差不满足分配律ABACA(BC)\begin{aligned}\text{关系并对关系差不满足分配律}\\ A\cup B-A\cup C\subseteq A\cup(B-C)\end{aligned}

      #

      # 定义

      RS={<a,b><a,b>R<a,b>S}\begin{aligned}& R\cap S =\{<a,b>|<a,b>\in R\ \ \land <a,b>\in S\}\end{aligned}

      # 关系矩阵

      MRS=MRMS=[rijsij]\begin{aligned}& M_{R\cap S} = M_R \land M_S = [r_{ij}\land s_{ij}]\end{aligned}

      # 性质

      单位元:全关系\begin{aligned}& 单位元:全关系 \end{aligned}

      零元: 空关系\begin{aligned}&\text{零元: 空关系}\end{aligned}

      关系交满足交换律\begin{aligned}&\text{关系交满足交换律}\end{aligned}

      关系交满足结合律\begin{aligned}&\text{关系交满足结合律}\end{aligned}

      关系交的单调性:关系交保持子集关系AB,CDABCDCA,CBCAB\begin{aligned}\text{关系交的单调性:关系交保持子集关系}\\ A\subseteq B,C\subseteq D \Rightarrow A\cap B\subseteq C\cap D\\ C\subseteq A,C\subseteq B \Leftrightarrow C\subseteq A\cup B\end{aligned}

      关系交对关系并有分配律\begin{aligned}&\text{关系交对关系并有分配律}\end{aligned}

      关系交对关系差有分配律\begin{aligned}\text{关系交对关系差有分配律}\end{aligned}

      #

      # 定义

      RS={<a,b><a,b>R<a,b>S}\begin{aligned}& R- S =\{<a,b>|<a,b>\in R\ \ \land <a,b>\notin S\}\end{aligned}

      # 关系矩阵

      MRS=MRMS=[rijsij]\begin{aligned}& M_{R- S} = M_R \ominus M_S = [r_{ij}\ominus s_{ij}]\end{aligned}

      运算00=01=11=010=1\begin{aligned}&\text{运算}\ominus:0\ominus0=0\ominus1=1\ominus1=0,1\ominus0=1\end{aligned}

      # 性质

      左零单位: 全关系\begin{aligned}&\text{左零单位: 全关系}\end{aligned}

      右单位元: 空关系\begin{aligned}&\text{右单位元: 空关系}\end{aligned}

      左零元: 空关系\begin{aligned}&\text{左零元: 空关系}\end{aligned}

      右零元: 全关系\begin{aligned}&\text{右零元: 全关系}\end{aligned}

      关系差不满足交换律\begin{aligned}&\text{关系差不满足交换律}\end{aligned}

      关系差不满足结合律\begin{aligned}&\text{关系差不满足结合律}\end{aligned}

      关系差无单调性:关系差不保持子集关系\begin{aligned}&\text{关系差无单调性:关系差不保持子集关系}\end{aligned}

      关系差对关系并没有分配律:A(BC)(AB)(AC)\begin{aligned}\text{关系差对关系并没有分配律}:\\ A-(B\cup C) \subseteq (A-B)\cup(A-C)\end{aligned}

      关系差对关系交没有分配律:(AB)(AC)A(BC)\begin{aligned}\text{关系差对关系交没有分配律}:\\ (A-B)\cap(A-C) \subseteq A-(B\cap C)\end{aligned}

      关系差对关系交、关系并有反分配律:A(BC)=(AB)(AC)A(BC)=(AB)(AC)\begin{aligned}\text{关系差对关系交、关系并有反分配律}:\\ A-(B\cup C) = (A-B)\cap(A-C)\\ A-(B\cap C) = (A-B)\cup(A-C)\end{aligned}

      # 复合

      # 定义

      SR={<a,c>bB(<a,b>R<b,c>S)}\begin{aligned}& S\circ R=\{<a,c>|\exists b\in B(<a,b>\in R\land <b,c>\in S)\}\end{aligned}

      # 关系矩阵

      MRS=MRMS\begin{aligned}& M_{R\circ S} = M_R \odot M_S\end{aligned}

      逻辑积运算:与矩阵乘法本质相同,只是将其中的加法、乘法分别用逻辑或(逻辑加法) 、逻辑与(逻辑减法)替代\begin{aligned}&\text{逻辑积运算}\odot\text{:与矩阵乘法本质相同,}\\& \text{只是将其中的加法、乘法分别用}\\& \text{逻辑或}\lor\text{(逻辑加法) 、逻辑与}\land\text{(逻辑减法)替代}\end{aligned}

      # 备注

      本课程采用逆序复合\begin{aligned}&\text{本课程采用逆序复合}\end{aligned}

      # 性质

      单位元:恒等关系\begin{aligned}&\text{单位元:恒等关系}\end{aligned}

      零元: 空关系\begin{aligned}&\text{零元: 空关系}\end{aligned}

      关系复合不满足交换律\begin{aligned}&\text{关系复合不满足交换律}\end{aligned}

      关系复合满足结合律\begin{aligned}&\text{关系复合满足结合律}\end{aligned}

      关系复合的单调性:关系复合保持子集关系RS,UWURWS\begin{aligned}&\text{关系复合的单调性:关系复合保持子集关系}\\& R\subseteq S, U\subseteq W \to U\circ R\subseteq W\circ S\end{aligned}

      关系复合对关系并有分配律\begin{aligned}&\text{关系复合对关系并有分配律}\end{aligned}

      关系复合对关系交没有分配律:(RS)T(RT)(ST)\begin{aligned}\text{关系复合对关系交没有分配律}:\\ (R\cap S)\circ T \subseteq (R\circ T)\cap(S\circ T)\end{aligned}

      #

      # 定义

      R={<a,b>A×B<a,b>R}=A×BR\begin{aligned} \overline R &=\{<a,b>\in A\times B|<a,b>\notin R\}\\& =A\times B-R\end{aligned}

      # 关系矩阵

      MR=MR=[rij]\begin{aligned}& M_{\overline R}=\overline{M_R}=[\overline{r_{ij}}]\end{aligned}

      # 性质

      关系补的单调性:关系补运算保持相反的子集关系\begin{aligned}&\text{关系补的单调性:关系补运算保持相反的子集关系}\end{aligned}

      关系补对关系并没有分配律:ABAB\begin{aligned}&\text{关系补对关系并没有分配律}: \overline{A\cup B} \subseteq \overline{A}\cup\overline{B}\end{aligned}

      关系补对关系交有分配律\begin{aligned}&\text{关系补对关系交有分配律}\end{aligned}

      关系补对关系差没有分配律:ABAB\begin{aligned}&\text{关系补对关系差没有分配律}: \overline{A}-\overline{B}\subseteq\overline{A-B}\end{aligned}

      关系补对关系复合有分配律\begin{aligned}&\text{关系补对关系复合有分配律}\end{aligned}

      关系逆与关系补有交换律(两个一元运算)\begin{aligned}&\text{关系逆与关系补有交换律(两个一元运算)}\end{aligned}

      #

      # 定义

      R1={<b,a><a,b>R}\begin{aligned}& R^{-1}=\{<b,a>|<a,b>\in R\}\end{aligned}

      # 关系矩阵

      MR1=(MR)T\begin{aligned}& M_{R^{-1}}=(M_R)^T\end{aligned}

      # 性质

      关系逆的单调性:关系逆运算保持子集关系\begin{aligned}&\text{关系逆的单调性:关系逆运算保持子集关系}\end{aligned}

      关系逆对关系并有分配律\begin{aligned}&\text{关系逆对关系并有分配律}\end{aligned}

      关系逆对关系交有分配律\begin{aligned}&\text{关系逆对关系交有分配律}\end{aligned}

      关系逆对关系差有分配律\begin{aligned}&\text{关系逆对关系差有分配律}\end{aligned}

      关系逆对关系复合有分配律\begin{aligned}&\text{关系逆对关系复合有分配律}\end{aligned}

      关系逆与关系补有交换律(两个一元运算)\begin{aligned}&\text{关系逆与关系补有交换律(两个一元运算)}\end{aligned}

      \ No newline at end of file diff --git a/math/discrete-math/discrete-math-basics/dmbs/permutaion-and-combination/index.html b/math/discrete-math/discrete-math-basics/dmbs/permutaion-and-combination/index.html index 136ac702..a2638b90 100644 --- a/math/discrete-math/discrete-math-basics/dmbs/permutaion-and-combination/index.html +++ b/math/discrete-math/discrete-math-basics/dmbs/permutaion-and-combination/index.html @@ -1 +1 @@ -离散数学基础:排列与组合 - 离散数学基础 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 思维导图

      排列组合计数问题

      # 排列

      # 记号

      P(n,r)=Pnr=AnrP(n,r)=P_n^r=A_n^r

      # 描述

      • n 个 (可区别的) 物体

        • n 个物体的 r - 排列

          • n 个物体的 n - 排列,或 n 个物体的全排列
      • 集合 S,|S|=n

        • S 的 r - 排列

          • S 的 n - 排列,或 S 的全排列

      # 公式

      P(n,r)=n!(nr)!P(n,r)=\frac{n!}{(n-r)!}

      P(n,n)=n!P(n,n)=n!

      P(n,r)={n!(nr)!,0r<nn!,r=n0,r>nP(n,r)=\left \{ \begin{aligned} & \frac{n!}{(n-r)!} &&,& 0\leq r\lt n \\ &n! &&,&r=n\\ & 0 &&,& r\gt n \end{aligned} \right.

      # 组合

      # 记号

      • 通常将第三个称为二项式系数

      C(n,r)=Cnr=(nr)C(n,r)=C_n^r=\begin{pmatrix}n\\r \end{pmatrix}

      # 描述

      • n 个 (可区别的) 物体

        • n 个物体的 r - 组合
      • 集合 S,|S|=n

        • S 的 r - 组合
      • 长度为 n 的二进制串

        • 长度为 n 且含 r 个 1 (或 0) 的二进制串数

      # 公式

      C(n,r)=C(r,n)=P(n,r)P(r,r)={n!r!(nr)!,0rn0,r>nC(n,r)=C(r,n)=\frac{P(n,r)}{P(r,r)}=\left \{ \begin{aligned} & \frac{n!}{r!(n-r)!} &,& 0\leq r\leq n \\ & 0 &,& r\gt n \end{aligned} \right.

      # 组合证明

      (不严谨)

      # 双计数证明

      • 论证等式两边是针对同一集合元素的不同计数方法

      # 双函数证明

      • 论证等式两边虽然是针对两个不同的集合的元素进行计数,但这两个集合之间存在双函数

      # 代数证明

      (严谨)

      # 利用数学归纳法、组合数、排列数等计算公式的证明

      # 二项式定理

      #

      (x+y)n=k=0n(nk)xkynk(x+y)^n=\sum_{k=0}^{n} \begin{pmatrix}n\\k\end{pmatrix}x^k y^{n-k}

      # 二项式定理的组合数推论

      #

      k=0n(nk)=2n\sum_{k=0}^{n}\begin{pmatrix}n\\k\end{pmatrix} =2^n

      # 帕斯卡等式

      #

      (nk)=(n1k)+(n1k1)\begin{pmatrix}n\\k \end{pmatrix} =\begin{pmatrix}n-1\\k \end{pmatrix} +\begin{pmatrix}n-1\\k-1 \end{pmatrix}

      # 递推式

      #

      r(nr)=(nr+1)(nr1)1r<nr\begin{pmatrix}n\\r\end{pmatrix} =(n-r+1)\begin{pmatrix}n\\r-1 \end{pmatrix} ,1\leq r\lt n

      #

      r(nr)=n(n1r1)1r<nr\begin{pmatrix}n\\r\end{pmatrix} =n\begin{pmatrix}n-1\\r-1 \end{pmatrix} ,1\leq r\lt n

      # 乘积化简式

      #

      (nm)(mk)=(nk)(nkmk)kmn\begin{pmatrix}n\\m\end{pmatrix} \begin{pmatrix}m\\k\end{pmatrix} =\begin{pmatrix}n\\k\end{pmatrix} \begin{pmatrix}n-k\\m-k\end{pmatrix} ,k\leq m\leq n

      # 上下标求和式

      朱世杰恒等式

      # Hockeystick 等式

      (m+r+1r)=k=0r(m+km)=(mm)+(m+1m)+...+(m+rm)=k=0r(m+kk)=(m0)+(m+11)+...+(m+rr)\begin{aligned} &\begin{pmatrix}m+r+1\\r\end{pmatrix}\\ =&\sum_{k=0}^{r} \begin{pmatrix}m+k\\m\end{pmatrix} =\begin{pmatrix}m\\m\end{pmatrix} +\begin{pmatrix}m+1\\m\end{pmatrix} +... +\begin{pmatrix}m+r\\m\end{pmatrix}\\ =&\sum_{k=0}^{r} \begin{pmatrix}m+k\\k\end{pmatrix} =\begin{pmatrix}m\\0\end{pmatrix} +\begin{pmatrix}m+1\\1\end{pmatrix} +... +\begin{pmatrix}m+r\\r\end{pmatrix} \end{aligned}

      # 令 n=r+1 可得到上面 Hockeystick 等式

      k=0n(km)=(0m)+(1m)+...+(nm)=(n+1m+1)\sum_{k=0}^{n} \begin{pmatrix}k\\m\end{pmatrix} =\begin{pmatrix}0\\m\end{pmatrix} +\begin{pmatrix}1\\m\end{pmatrix} +... +\begin{pmatrix}n\\m\end{pmatrix} =\begin{pmatrix}n+1\\m+1\end{pmatrix}

      # 朱世杰 - 范德蒙等式

      #

      k=0r(mrk)(nk)=(m+nr)=(mr)(n0)+(mr1)(n1)+...+(m1)(nr1)+(m0)(nr)\begin{aligned} & \sum_{k=0}^{r} \begin{pmatrix}m\\r-k\end{pmatrix} \begin{pmatrix}n\\k\end{pmatrix} =\begin{pmatrix}m+n\\r\end{pmatrix} \\& =\begin{pmatrix}m\\r\end{pmatrix} \begin{pmatrix}n\\0\end{pmatrix} +\begin{pmatrix}m\\r-1\end{pmatrix} \begin{pmatrix}n\\1\end{pmatrix} +... +\begin{pmatrix}m\\1\end{pmatrix} \begin{pmatrix}n\\r-1\end{pmatrix} +\begin{pmatrix}m\\0\end{pmatrix} \begin{pmatrix}n\\r\end{pmatrix} \end{aligned}

      \ No newline at end of file +离散数学基础:排列与组合 - 离散数学基础 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 思维导图

      排列组合计数问题

      # 排列

      # 记号

      P(n,r)=Pnr=AnrP(n,r)=P_n^r=A_n^r

      # 描述

      • n 个 (可区别的) 物体

        • n 个物体的 r - 排列

          • n 个物体的 n - 排列,或 n 个物体的全排列
      • 集合 S,|S|=n

        • S 的 r - 排列

          • S 的 n - 排列,或 S 的全排列

      # 公式

      P(n,r)=n!(nr)!P(n,r)=\frac{n!}{(n-r)!}

      P(n,n)=n!P(n,n)=n!

      P(n,r)={n!(nr)!,0r<nn!,r=n0,r>nP(n,r)=\left \{ \begin{aligned} & \frac{n!}{(n-r)!} &&,& 0\leq r\lt n \\ &n! &&,&r=n\\ & 0 &&,& r\gt n \end{aligned} \right.

      # 组合

      # 记号

      • 通常将第三个称为二项式系数

      C(n,r)=Cnr=(nr)C(n,r)=C_n^r=\begin{pmatrix}n\\r \end{pmatrix}

      # 描述

      • n 个 (可区别的) 物体

        • n 个物体的 r - 组合
      • 集合 S,|S|=n

        • S 的 r - 组合
      • 长度为 n 的二进制串

        • 长度为 n 且含 r 个 1 (或 0) 的二进制串数

      # 公式

      C(n,r)=C(r,n)=P(n,r)P(r,r)={n!r!(nr)!,0rn0,r>nC(n,r)=C(r,n)=\frac{P(n,r)}{P(r,r)}=\left \{ \begin{aligned} & \frac{n!}{r!(n-r)!} &,& 0\leq r\leq n \\ & 0 &,& r\gt n \end{aligned} \right.

      # 组合证明

      (不严谨)

      # 双计数证明

      • 论证等式两边是针对同一集合元素的不同计数方法

      # 双函数证明

      • 论证等式两边虽然是针对两个不同的集合的元素进行计数,但这两个集合之间存在双函数

      # 代数证明

      (严谨)

      # 利用数学归纳法、组合数、排列数等计算公式的证明

      # 二项式定理

      #

      (x+y)n=k=0n(nk)xkynk(x+y)^n=\sum_{k=0}^{n} \begin{pmatrix}n\\k\end{pmatrix}x^k y^{n-k}

      # 二项式定理的组合数推论

      #

      k=0n(nk)=2n\sum_{k=0}^{n}\begin{pmatrix}n\\k\end{pmatrix} =2^n

      # 帕斯卡等式

      #

      (nk)=(n1k)+(n1k1)\begin{pmatrix}n\\k \end{pmatrix} =\begin{pmatrix}n-1\\k \end{pmatrix} +\begin{pmatrix}n-1\\k-1 \end{pmatrix}

      # 递推式

      #

      r(nr)=(nr+1)(nr1)1r<nr\begin{pmatrix}n\\r\end{pmatrix} =(n-r+1)\begin{pmatrix}n\\r-1 \end{pmatrix} ,1\leq r\lt n

      #

      r(nr)=n(n1r1)1r<nr\begin{pmatrix}n\\r\end{pmatrix} =n\begin{pmatrix}n-1\\r-1 \end{pmatrix} ,1\leq r\lt n

      # 乘积化简式

      #

      (nm)(mk)=(nk)(nkmk)kmn\begin{pmatrix}n\\m\end{pmatrix} \begin{pmatrix}m\\k\end{pmatrix} =\begin{pmatrix}n\\k\end{pmatrix} \begin{pmatrix}n-k\\m-k\end{pmatrix} ,k\leq m\leq n

      # 上下标求和式

      朱世杰恒等式

      # Hockeystick 等式

      (m+r+1r)=k=0r(m+km)=(mm)+(m+1m)+...+(m+rm)=k=0r(m+kk)=(m0)+(m+11)+...+(m+rr)\begin{aligned} &\begin{pmatrix}m+r+1\\r\end{pmatrix}\\ =&\sum_{k=0}^{r} \begin{pmatrix}m+k\\m\end{pmatrix} =\begin{pmatrix}m\\m\end{pmatrix} +\begin{pmatrix}m+1\\m\end{pmatrix} +... +\begin{pmatrix}m+r\\m\end{pmatrix}\\ =&\sum_{k=0}^{r} \begin{pmatrix}m+k\\k\end{pmatrix} =\begin{pmatrix}m\\0\end{pmatrix} +\begin{pmatrix}m+1\\1\end{pmatrix} +... +\begin{pmatrix}m+r\\r\end{pmatrix} \end{aligned}

      # 令 n=r+1 可得到上面 Hockeystick 等式

      k=0n(km)=(0m)+(1m)+...+(nm)=(n+1m+1)\sum_{k=0}^{n} \begin{pmatrix}k\\m\end{pmatrix} =\begin{pmatrix}0\\m\end{pmatrix} +\begin{pmatrix}1\\m\end{pmatrix} +... +\begin{pmatrix}n\\m\end{pmatrix} =\begin{pmatrix}n+1\\m+1\end{pmatrix}

      # 朱世杰 - 范德蒙等式

      #

      k=0r(mrk)(nk)=(m+nr)=(mr)(n0)+(mr1)(n1)+...+(m1)(nr1)+(m0)(nr)\begin{aligned} & \sum_{k=0}^{r} \begin{pmatrix}m\\r-k\end{pmatrix} \begin{pmatrix}n\\k\end{pmatrix} =\begin{pmatrix}m+n\\r\end{pmatrix} \\& =\begin{pmatrix}m\\r\end{pmatrix} \begin{pmatrix}n\\0\end{pmatrix} +\begin{pmatrix}m\\r-1\end{pmatrix} \begin{pmatrix}n\\1\end{pmatrix} +... +\begin{pmatrix}m\\1\end{pmatrix} \begin{pmatrix}n\\r-1\end{pmatrix} +\begin{pmatrix}m\\0\end{pmatrix} \begin{pmatrix}n\\r\end{pmatrix} \end{aligned}

      \ No newline at end of file diff --git a/math/discrete-math/discrete-math-basics/dmbs/principles-of-counting/index.html b/math/discrete-math/discrete-math-basics/dmbs/principles-of-counting/index.html index 212224a3..db1d99b8 100644 --- a/math/discrete-math/discrete-math-basics/dmbs/principles-of-counting/index.html +++ b/math/discrete-math/discrete-math-basics/dmbs/principles-of-counting/index.html @@ -1 +1 @@ -离散数学基础:组合计数基本原理 - 离散数学基础 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 思维导图

      组合计数基本原理

      # 常用引理

      # 引理 1

      # 公式

      AB=AB=AAB| A\overline{B} |=| A-B | = |A| -| A B|

      AB=AB=AABA\overline{B} = A - B = A - A B

      # 证明

      # 容斥原理

      # 2 维

      • 公式

      AB=A+BAB| A \cup B | = |A|+|B|- |A \cap B|

      • 变形

      AB=UAB=UAB+AB| \overline{A} \cap \overline{B} | = |U|-|A\cup B| = |U|- |A| - |B| + |A \cap B|

      • 证明

        • 利用 加法原理 和 常用引理
      \begin{align} |A \cup B| &= |A-B|+|B-A|+|A \cup B|\\ &= |A|-|A \cap B|+|B|-|A \cap B|+|A \cap B|\\ &= |A|+|B|- |A \cap B|\end{align}

      # n 维

      • 公式

        • 奇加偶减
      • 证明

        • 数学归纳法

      # 鸽笼原理

      # 鸽笼原理 / 抽屉原理

      # 公式

      • k+1 或更多只鸽子放在 k 个鸽笼里,则至少有 1 个鸽笼里有两只或更多只鸽子

      # 证明

      • 反证法

      # 推论

      若集合AB都是有穷集合,fAB有:若集合A、B都是有穷集合,\forall f\in A^B有:

      A>B,则f不是单函数|A|\gt|B|,则f不是单函数

      A<B,则f不是满函数|A|\lt|B|\text{,则}f\text{不是满函数}

      A=B,则f是双函数|A|=|B|\text{,则}f\text{是双函数}

      # 广义鸽笼原理

      # 公式

      N个物体放到k个盒子里,至少有1个盒子至少有Nk个物体N\text{个物体放到}k\text{个盒子里,至少有}1\text{个盒子至少有}\left\lceil \frac{N}{k} \right\rceil\text{个物体}

      # 证明

      用反证法,设每个盒子的物体都少于Nk个,令N=kq+r0r<k,分情况考虑:1r>0,则Nk=q+1则每个盒子的物体都少于q+1个,即每个盒子的物体少于等于q个,从而Nkq<kq+1,这与N=kq+1矛盾2r=0,则Nk=q则每个盒子的物体都少于q个,即每个盒子的物体少于等于q1个,从而Nk(q1)=kqk<kq+1,这与N=kq+1矛盾\begin{aligned}&\text{用反证法,设每个盒子的物体都少于}\left\lceil \frac{N}{k} \right\rceil\text{个,令}N=kq+r,0 \le r\lt k\text{,分情况考虑:}\\& \begin{aligned} (1)&r\gt0\text{,则}\left\lceil \frac{N}{k} \right\rceil = q+1\\& \text{则每个盒子的物体都少于}q+1\text{个,即每个盒子的物体少于等于}q\text{个,} \text{从而}N\le kq\lt kq+1\text{,这与}N=kq+1\text{矛盾} \end{aligned}\\& \begin{aligned} (2)&r=0,则 \left\lceil \frac{N}{k} \right\rceil = q\\& \text{则每个盒子的物体都少于}q\text{个,即每个盒子的物体少于等于}q-1\text{个,从而}N\le k(q-1)=kq-k\lt kq+1\text{,这与}N=kq+1\text{矛盾} \end{aligned} \end{aligned}

      # 推论

      # N 个物体放到 k 个盒子,至少有一个盒子有至少几个物体

      最小容量=物体总数盒子数\text{最小容量}=\left\lceil \frac{\text{物体总数}}{\text{盒子数}} \right\rceil

      n=Nkn=\left\lceil \frac{N}{k} \right\rceil

      # 至少需要几个物体放到 k 个盒子里能保证至少有一个盒子有至少 n 个物体

      物体总数(最小容量1)×盒子数+1\text{物体总数}\ge (\text{最小容量}-1)\times\text{盒子数}+1

      N(n1)×k+1N\ge (n-1)\times k+1

      # N 个物体放到至多几个盒子能保证至少有一个盒子有至少 n 个物体

      盒子数物体总数1最小容量1盒子数\le \left\lfloor \frac{\text{物体总数}-1}{\text{最小容量}-1} \right\rfloor

      kN1n1k\le\left\lfloor \frac{N-1}{n-1} \right\rfloor

      # 题型

      证明有连续若干个容器恰好技巧:构造sk=i=1kai作为容器\text{证明有连续若干个容器恰好…… 技巧:构造}s_k=\sum^k_{i=1}{a_i}\text{作为容器}

      # 拉姆齐 (Ramsey) 定理

      # 最简单、最经典形式

      R(3,3)

      # 公式

      # 解释

      任意6个人中,必定有\text{任意}6\text{个人中,必定有}

      要么3个人互相认识\text{要么}3\text{个人互相认识}

      要么3个人互相不认识\text{要么}3\text{个人互相不认识}

      # 图论解释

      对一个6阶完全图,用红、黑两种颜色任意对它的边上色,必定存在\text{对一个}6\text{阶完全图,用红、黑两种颜色任意对它的边上色,必定存在}

      要么一个红色三角形(3阶完全图)\text{要么一个红色三角形(}3\text{阶完全图)}

      要么一个黑色三角形(3阶完全图)\text{要么一个黑色三角形(}3\text{阶完全图)}

      # 证明

      在6个人中任选1人,设为a,将剩下5人分为两个集合:a不认识的人、a认识的人,并分别记为E和F根据鸽笼原理,E和F至少有一个集合至少有52=3分情况考虑:(1)若F中有至少3人(i)若F里的人互相都不认识,则可从F中选3个人得到3个人互相不认识,命题成立(ii)否则,F中至少有2个人是相互认识的,则这这两个人与a构成了3人互相认识,命题成立(2)若E中有至少3人(i)若E里的人互相都认识,则可从E中选3个人得到3个人互相认识,命题成立(ii)否则,F中至少有2个人是相互不认识的,则这这两个人与a构成了3人互相不认识,命题成立综上总是有命题成立\begin{aligned}& \text{在6个人中任选1人,设为a,将剩下5人分为两个集合:a不认识的人、a认识的人,并分别记为E和F} \text{根据鸽笼原理,E和F至少有一个集合至少有}\lceil \frac{5}{2}\rceil=3 \text{人}\\& \text{分情况考虑:}\\& \begin{aligned} \text{(1)}&\text{若F中有至少3人}\\& \begin{aligned} \text{(i)}&\text{若F里的人互相都不认识,则可从F中选3个人得到3个人互相不认识,命题成立} \end{aligned}\\& \begin{aligned} \text{(ii)}&\text{否则,F中至少有2个人是相互认识的,则这这两个人与a构成了3人互相认识,命题成立} \end{aligned} \end{aligned}\\& \begin{aligned} \text{(2)}&\text{若E中有至少3人}\\& \begin{aligned} \text{(i)}&\text{若E里的人互相都认识,则可从E中选3个人得到3个人互相认识,命题成立} \end{aligned}\\& \begin{aligned} \text{(ii)}&\text{否则,F中至少有2个人是相互不认识的,则这这两个人与a构成了3人互相不认识,命题成立} \end{aligned} \end{aligned}\\& \text{综上总是有命题成立} \end{aligned}

      # 一般形式

      R(m,n)

      # 公式

      m,nZ+,m>2,n>2,R(m,n)Z+,使\forall m,n\in\mathbb{Z^+},m\gt 2,n\gt 2,\exists R(m,n)\in \mathbb{Z^+},使

      # 解释

      R(m,n)个人中,必定有R(m,n)\text{个人中,必定有}

      要么m个人互相认识或n个人互相不认识\text{要么m个人互相认识或n个人互相不认识}

      要么n个人互相认识或m个人互相不认识\text{要么n个人互相认识或m个人互相不认识}

      # 图论解释

      对一个R(m,n)阶完全图,用两种颜色任意对它的边上色,必定存在\text{对一个}R(m,n)\text{阶完全图,用两种颜色任意对它的边上色,必定存在}

      要么一个同色m阶完全子图\text{要么一个同色m阶完全子图}

      要么一个同色n阶完全子图\text{要么一个同色n阶完全子图}

      \ No newline at end of file +离散数学基础:组合计数基本原理 - 离散数学基础 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 思维导图

      组合计数基本原理

      # 常用引理

      # 引理 1

      # 公式

      AB=AB=AAB| A\overline{B} |=| A-B | = |A| -| A B|

      AB=AB=AABA\overline{B} = A - B = A - A B

      # 证明

      # 容斥原理

      # 2 维

      • 公式

      AB=A+BAB| A \cup B | = |A|+|B|- |A \cap B|

      • 变形

      AB=UAB=UAB+AB| \overline{A} \cap \overline{B} | = |U|-|A\cup B| = |U|- |A| - |B| + |A \cap B|

      • 证明

        • 利用 加法原理 和 常用引理
      \begin{align} |A \cup B| &= |A-B|+|B-A|+|A \cup B|\\ &= |A|-|A \cap B|+|B|-|A \cap B|+|A \cap B|\\ &= |A|+|B|- |A \cap B|\end{align}

      # n 维

      • 公式

        • 奇加偶减
      • 证明

        • 数学归纳法

      # 鸽笼原理

      # 鸽笼原理 / 抽屉原理

      # 公式

      • k+1 或更多只鸽子放在 k 个鸽笼里,则至少有 1 个鸽笼里有两只或更多只鸽子

      # 证明

      • 反证法

      # 推论

      若集合AB都是有穷集合,fAB有:若集合A、B都是有穷集合,\forall f\in A^B有:

      A>B,则f不是单函数|A|\gt|B|,则f不是单函数

      A<B,则f不是满函数|A|\lt|B|\text{,则}f\text{不是满函数}

      A=B,则f是双函数|A|=|B|\text{,则}f\text{是双函数}

      # 广义鸽笼原理

      # 公式

      N个物体放到k个盒子里,至少有1个盒子至少有Nk个物体N\text{个物体放到}k\text{个盒子里,至少有}1\text{个盒子至少有}\left\lceil \frac{N}{k} \right\rceil\text{个物体}

      # 证明

      用反证法,设每个盒子的物体都少于Nk个,令N=kq+r0r<k,分情况考虑:1r>0,则Nk=q+1则每个盒子的物体都少于q+1个,即每个盒子的物体少于等于q个,从而Nkq<kq+1,这与N=kq+1矛盾2r=0,则Nk=q则每个盒子的物体都少于q个,即每个盒子的物体少于等于q1个,从而Nk(q1)=kqk<kq+1,这与N=kq+1矛盾\begin{aligned}&\text{用反证法,设每个盒子的物体都少于}\left\lceil \frac{N}{k} \right\rceil\text{个,令}N=kq+r,0 \le r\lt k\text{,分情况考虑:}\\& \begin{aligned} (1)&r\gt0\text{,则}\left\lceil \frac{N}{k} \right\rceil = q+1\\& \text{则每个盒子的物体都少于}q+1\text{个,即每个盒子的物体少于等于}q\text{个,} \text{从而}N\le kq\lt kq+1\text{,这与}N=kq+1\text{矛盾} \end{aligned}\\& \begin{aligned} (2)&r=0,则 \left\lceil \frac{N}{k} \right\rceil = q\\& \text{则每个盒子的物体都少于}q\text{个,即每个盒子的物体少于等于}q-1\text{个,从而}N\le k(q-1)=kq-k\lt kq+1\text{,这与}N=kq+1\text{矛盾} \end{aligned} \end{aligned}

      # 推论

      # N 个物体放到 k 个盒子,至少有一个盒子有至少几个物体

      最小容量=物体总数盒子数\text{最小容量}=\left\lceil \frac{\text{物体总数}}{\text{盒子数}} \right\rceil

      n=Nkn=\left\lceil \frac{N}{k} \right\rceil

      # 至少需要几个物体放到 k 个盒子里能保证至少有一个盒子有至少 n 个物体

      物体总数(最小容量1)×盒子数+1\text{物体总数}\ge (\text{最小容量}-1)\times\text{盒子数}+1

      N(n1)×k+1N\ge (n-1)\times k+1

      # N 个物体放到至多几个盒子能保证至少有一个盒子有至少 n 个物体

      盒子数物体总数1最小容量1盒子数\le \left\lfloor \frac{\text{物体总数}-1}{\text{最小容量}-1} \right\rfloor

      kN1n1k\le\left\lfloor \frac{N-1}{n-1} \right\rfloor

      # 题型

      证明有连续若干个容器恰好技巧:构造sk=i=1kai作为容器\text{证明有连续若干个容器恰好…… 技巧:构造}s_k=\sum^k_{i=1}{a_i}\text{作为容器}

      # 拉姆齐 (Ramsey) 定理

      # 最简单、最经典形式

      R(3,3)

      # 公式

      # 解释

      任意6个人中,必定有\text{任意}6\text{个人中,必定有}

      要么3个人互相认识\text{要么}3\text{个人互相认识}

      要么3个人互相不认识\text{要么}3\text{个人互相不认识}

      # 图论解释

      对一个6阶完全图,用红、黑两种颜色任意对它的边上色,必定存在\text{对一个}6\text{阶完全图,用红、黑两种颜色任意对它的边上色,必定存在}

      要么一个红色三角形(3阶完全图)\text{要么一个红色三角形(}3\text{阶完全图)}

      要么一个黑色三角形(3阶完全图)\text{要么一个黑色三角形(}3\text{阶完全图)}

      # 证明

      在6个人中任选1人,设为a,将剩下5人分为两个集合:a不认识的人、a认识的人,并分别记为E和F根据鸽笼原理,E和F至少有一个集合至少有52=3分情况考虑:(1)若F中有至少3人(i)若F里的人互相都不认识,则可从F中选3个人得到3个人互相不认识,命题成立(ii)否则,F中至少有2个人是相互认识的,则这这两个人与a构成了3人互相认识,命题成立(2)若E中有至少3人(i)若E里的人互相都认识,则可从E中选3个人得到3个人互相认识,命题成立(ii)否则,F中至少有2个人是相互不认识的,则这这两个人与a构成了3人互相不认识,命题成立综上总是有命题成立\begin{aligned}& \text{在6个人中任选1人,设为a,将剩下5人分为两个集合:a不认识的人、a认识的人,并分别记为E和F} \text{根据鸽笼原理,E和F至少有一个集合至少有}\lceil \frac{5}{2}\rceil=3 \text{人}\\& \text{分情况考虑:}\\& \begin{aligned} \text{(1)}&\text{若F中有至少3人}\\& \begin{aligned} \text{(i)}&\text{若F里的人互相都不认识,则可从F中选3个人得到3个人互相不认识,命题成立} \end{aligned}\\& \begin{aligned} \text{(ii)}&\text{否则,F中至少有2个人是相互认识的,则这这两个人与a构成了3人互相认识,命题成立} \end{aligned} \end{aligned}\\& \begin{aligned} \text{(2)}&\text{若E中有至少3人}\\& \begin{aligned} \text{(i)}&\text{若E里的人互相都认识,则可从E中选3个人得到3个人互相认识,命题成立} \end{aligned}\\& \begin{aligned} \text{(ii)}&\text{否则,F中至少有2个人是相互不认识的,则这这两个人与a构成了3人互相不认识,命题成立} \end{aligned} \end{aligned}\\& \text{综上总是有命题成立} \end{aligned}

      # 一般形式

      R(m,n)

      # 公式

      m,nZ+,m>2,n>2,R(m,n)Z+,使\forall m,n\in\mathbb{Z^+},m\gt 2,n\gt 2,\exists R(m,n)\in \mathbb{Z^+},使

      # 解释

      R(m,n)个人中,必定有R(m,n)\text{个人中,必定有}

      要么m个人互相认识或n个人互相不认识\text{要么m个人互相认识或n个人互相不认识}

      要么n个人互相认识或m个人互相不认识\text{要么n个人互相认识或m个人互相不认识}

      # 图论解释

      对一个R(m,n)阶完全图,用两种颜色任意对它的边上色,必定存在\text{对一个}R(m,n)\text{阶完全图,用两种颜色任意对它的边上色,必定存在}

      要么一个同色m阶完全子图\text{要么一个同色m阶完全子图}

      要么一个同色n阶完全子图\text{要么一个同色n阶完全子图}

      \ No newline at end of file diff --git a/math/discrete-math/discrete-math-basics/dmbs/relations/index.html b/math/discrete-math/discrete-math-basics/dmbs/relations/index.html index 8b9d0a67..052c4540 100644 --- a/math/discrete-math/discrete-math-basics/dmbs/relations/index.html +++ b/math/discrete-math/discrete-math-basics/dmbs/relations/index.html @@ -1 +1 @@ -离散数学基础:关系 - 离散数学基础 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 思维导图

      关系

      # 笛卡尔积

      # 定义

      A×B={a,baAbB}\begin{aligned}& A\times B=\{\langle a,b\rangle|a\in A\land b\in B\} \end{aligned}

      # 性质

      笛卡尔积运算不满足交换律\begin{aligned}& \text{笛卡尔积运算不满足交换律} \end{aligned}

      笛卡尔积运算不满足结合律\begin{aligned}& \text{笛卡尔积运算不满足结合律} \end{aligned}

      笛卡尔积运算对集合交有分配律\begin{aligned}& \text{笛卡尔积运算对集合交有分配律} \end{aligned}

      笛卡尔积运算对集合并有分配律\begin{aligned}& \text{笛卡尔积运算对集合并有分配律} \end{aligned}

      # 二元关系

      # 描述

      集合AB的二元关系是笛卡尔积A×B的子集\begin{aligned}& \text{集合}A\text{到}B\text{的二元关系是}\\& \text{笛卡尔积}A\times B\text{的子集} \end{aligned}

      集合A上的二元关系是集合A到自己的二元关系\begin{aligned}& \text{集合}A\text{上的二元关系是}\\& \text{集合A到自己的二元关系} \end{aligned}

      # 定义

      RA×B\begin{aligned}& R\subseteq A\times B \end{aligned}

      RA×A\begin{aligned}& R\subseteq A\times A \end{aligned}

      # 描述

      ab有关系R\begin{aligned}& a\text{和}b\text{有关系}R \end{aligned}

      aRb\begin{aligned}& a\ R\ b \end{aligned}

      a,bR\begin{aligned}& \langle a,b\rangle\in R \end{aligned}

      ab没有关系R\begin{aligned}& a\text{和}b\text{没有关系}R \end{aligned}

      ab\begin{aligned}& a\ \not R\ b \end{aligned}

      a,b∉R\begin{aligned}& \langle a,b\rangle\not\in R \end{aligned}

      备注:本课程的关系只考察二元关系

      # 空关系

      # 定义

      \begin{aligned}& \varnothing \end{aligned}

      # 全关系

      # 定义

      A×B\begin{aligned}& A\times B \end{aligned}

      # 恒等关系

      or
      对角关系

      # 定义

      ΔA={<a,a>aA},A\begin{aligned}& \Delta_A=\{<a,a>|a\in A\},\ \ A\neq \varnothing \end{aligned}

      # 关系矩阵

      单位矩阵\begin{aligned}& 单位矩阵 \end{aligned}

      # 自反关系

      # 定义

      aA,<a,a>R\begin{aligned}& \forall a\in A,\ <a,a>\in R \end{aligned}

      # 关系矩阵

      ΔAR\begin{aligned}& \Delta_A\subseteq R \end{aligned}

      # 反自反关系

      # 定义

      aA,<a,a>∉R\begin{aligned}& \forall a\in A,\ <a,a>\not\in R \end{aligned}

      # 关系矩阵

      ΔAR=\begin{aligned}& \Delta_A \cap R=\varnothing \end{aligned}

      # 对称关系

      # 定义

      a,bA,a,bR<b,a>R\begin{aligned}& \forall a,b\in A,\ \langle a,b\rangle\in R\to<b,a>\in R \end{aligned}

      # 关系矩阵

      R=R1\begin{aligned}& R=R^{-1} \end{aligned}

      # 反对称关系

      # 定义

      a,bA,(a,bR)(<b,a>R)a=b\begin{aligned}& \forall a,b\in A,\ (\langle a,b\rangle\in R)\land(<b,a>\in R)\to a=b \end{aligned}

      # 关系矩阵

      RR1ΔA\begin{aligned}& R\cap R^{-1}\subseteq\Delta_A \end{aligned}

      # 备注

      反对称关系一定是对称关系\begin{aligned}& 反对称关系一定是对称关系 \end{aligned}

      # 传递关系

      # 定义

      a,b,cA,(a,bR)(<b,c>R)<a,c>R\begin{aligned}& \forall a,b,c\in A,\ (\langle a,b\rangle\in R)\land(<b,c>\in R)\to <a,c>\in R \end{aligned}

      # 关系矩阵

      RR1R\begin{aligned}& R\circ R^{-1}\subseteq R \end{aligned}

      # 等价关系

      # 定义

      R是自反的、对称的、传递的\begin{aligned}& R\text{是自反的、对称的、传递的} \end{aligned}

      # 等价类

      • 描述

      a所在的等价关系R的等价类,简称a的等价类\begin{aligned}& a\text{所在的等价关系}R\text{的等价类,简称}a\text{的等价类} \end{aligned}

      • 定义

      [a]R={xA<a,x>R}\begin{aligned}& [a]_R=\{x\in A|<a,x>\in R\} \end{aligned}

      # 代表

      b[a]R,则称b为等价类[a]R的一个代表\begin{aligned}& b\in [a]_R\text{,则称}b\text{为等价类}[a]_R\text{的一个代表} \end{aligned}

      # 商集

      • 描述

      集合A关于等价关系R的商集是集合A的所有等价类构成的集合\begin{aligned}& \text{集合}A\text{关于等价关系R的商集是}\\& \text{集合A的所有等价类构成的集合} \end{aligned}

      • 定义

      A/R={[a]RaA}\begin{aligned}& A/R=\{[a]_R|a\in A\} \end{aligned}

      • 基本性质

      商集是一个集合族且是A的划分其中每一个元素都是等价类每个等价类都是这个划分的一个划分块\begin{aligned}& \text{商集是一个集合族且是}A\text{的划分}\\& \text{其中每一个元素都是等价类}\\& \text{每个等价类都是这个划分的一个划分块} \end{aligned}

      # 偏序关系

      # 定义

      R是自反的、反对称的、传递的\begin{aligned}& R\text{是自反的、反对称的、传递的} \end{aligned}

      # 符号

      \begin{aligned}& \preceq \end{aligned}

      # 经典例子

      • 数集上的 小于或等于关系、大于或等于关系

        • 集合的子集关系

          • 整数集上的整除关系

      # 可比

      (ab)(ba)\begin{aligned}& (a\preceq b) \lor (b\preceq a) \end{aligned}

      # 不可比

      (a⪯̸b)(b⪯̸a)\begin{aligned}& (a\not\preceq b) \land (b\not\preceq a) \end{aligned}

      # 覆盖

      b覆盖a(ab)!c(accb)\begin{aligned}& b\text{覆盖}a\Leftrightarrow(a\preceq b)\land!\exists c(a\preceq c\land c\preceq b) \end{aligned}

      # 极大元

      aA的极大元bA(abb=a)\begin{aligned}& a\text{是}A\text{的极大元}\Leftrightarrow \forall b\in A(a\preceq b\to b=a) \end{aligned}

      # 极小元

      aA的极小元bA(bab=a)\begin{aligned}& a\text{是}A\text{的极小元}\Leftrightarrow \forall b\in A(b\preceq a\to b=a) \end{aligned}

      # 最大元

      aA的最大元bA(ba)\begin{aligned}& a\text{是}A\text{的最大元}\Leftrightarrow \forall b\in A(b\preceq a) \end{aligned}

      # 最小元

      aA的最小元bA(ab)\begin{aligned}& a\text{是}A\text{的最小元}\Leftrightarrow \forall b\in A(a\preceq b) \end{aligned}

      # 偏序集

      # 定义

      (A,)orabbreviatedasA\begin{aligned}& (A,\preceq)\ \ or\ \ abbreviated\ as\ A \end{aligned}

      # 全序

      or
      线序

      # 定义

      偏序集A的任意两个元素都可比,则这个偏序集是全序或线序\begin{aligned}&\text{偏序集A的任意两个元素都可比,则这个偏序集是全序或线序} \end{aligned}

      # 关系举例 - 幂集上的:

      # 真包含关系

      • 反自反、反对称、传递

      # 恒等关系

      • 自反、对称、反对称、传递

      # 全关系

      • 自反、对称、传递

      # 空关系

      • 反自反、对称、反对称、传递
      \ No newline at end of file +离散数学基础:关系 - 离散数学基础 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 思维导图

      关系

      # 笛卡尔积

      # 定义

      A×B={a,baAbB}\begin{aligned}& A\times B=\{\langle a,b\rangle|a\in A\land b\in B\} \end{aligned}

      # 性质

      笛卡尔积运算不满足交换律\begin{aligned}& \text{笛卡尔积运算不满足交换律} \end{aligned}

      笛卡尔积运算不满足结合律\begin{aligned}& \text{笛卡尔积运算不满足结合律} \end{aligned}

      笛卡尔积运算对集合交有分配律\begin{aligned}& \text{笛卡尔积运算对集合交有分配律} \end{aligned}

      笛卡尔积运算对集合并有分配律\begin{aligned}& \text{笛卡尔积运算对集合并有分配律} \end{aligned}

      # 二元关系

      # 描述

      集合AB的二元关系是笛卡尔积A×B的子集\begin{aligned}& \text{集合}A\text{到}B\text{的二元关系是}\\& \text{笛卡尔积}A\times B\text{的子集} \end{aligned}

      集合A上的二元关系是集合A到自己的二元关系\begin{aligned}& \text{集合}A\text{上的二元关系是}\\& \text{集合A到自己的二元关系} \end{aligned}

      # 定义

      RA×B\begin{aligned}& R\subseteq A\times B \end{aligned}

      RA×A\begin{aligned}& R\subseteq A\times A \end{aligned}

      # 描述

      ab有关系R\begin{aligned}& a\text{和}b\text{有关系}R \end{aligned}

      aRb\begin{aligned}& a\ R\ b \end{aligned}

      a,bR\begin{aligned}& \langle a,b\rangle\in R \end{aligned}

      ab没有关系R\begin{aligned}& a\text{和}b\text{没有关系}R \end{aligned}

      ab\begin{aligned}& a\ \not R\ b \end{aligned}

      a,b∉R\begin{aligned}& \langle a,b\rangle\not\in R \end{aligned}

      备注:本课程的关系只考察二元关系

      # 空关系

      # 定义

      \begin{aligned}& \varnothing \end{aligned}

      # 全关系

      # 定义

      A×B\begin{aligned}& A\times B \end{aligned}

      # 恒等关系

      or
      对角关系

      # 定义

      ΔA={<a,a>aA},A\begin{aligned}& \Delta_A=\{<a,a>|a\in A\},\ \ A\neq \varnothing \end{aligned}

      # 关系矩阵

      单位矩阵\begin{aligned}& 单位矩阵 \end{aligned}

      # 自反关系

      # 定义

      aA,<a,a>R\begin{aligned}& \forall a\in A,\ <a,a>\in R \end{aligned}

      # 关系矩阵

      ΔAR\begin{aligned}& \Delta_A\subseteq R \end{aligned}

      # 反自反关系

      # 定义

      aA,<a,a>∉R\begin{aligned}& \forall a\in A,\ <a,a>\not\in R \end{aligned}

      # 关系矩阵

      ΔAR=\begin{aligned}& \Delta_A \cap R=\varnothing \end{aligned}

      # 对称关系

      # 定义

      a,bA,a,bR<b,a>R\begin{aligned}& \forall a,b\in A,\ \langle a,b\rangle\in R\to<b,a>\in R \end{aligned}

      # 关系矩阵

      R=R1\begin{aligned}& R=R^{-1} \end{aligned}

      # 反对称关系

      # 定义

      a,bA,(a,bR)(<b,a>R)a=b\begin{aligned}& \forall a,b\in A,\ (\langle a,b\rangle\in R)\land(<b,a>\in R)\to a=b \end{aligned}

      # 关系矩阵

      RR1ΔA\begin{aligned}& R\cap R^{-1}\subseteq\Delta_A \end{aligned}

      # 备注

      反对称关系一定是对称关系\begin{aligned}& 反对称关系一定是对称关系 \end{aligned}

      # 传递关系

      # 定义

      a,b,cA,(a,bR)(<b,c>R)<a,c>R\begin{aligned}& \forall a,b,c\in A,\ (\langle a,b\rangle\in R)\land(<b,c>\in R)\to <a,c>\in R \end{aligned}

      # 关系矩阵

      RR1R\begin{aligned}& R\circ R^{-1}\subseteq R \end{aligned}

      # 等价关系

      # 定义

      R是自反的、对称的、传递的\begin{aligned}& R\text{是自反的、对称的、传递的} \end{aligned}

      # 等价类

      • 描述

      a所在的等价关系R的等价类,简称a的等价类\begin{aligned}& a\text{所在的等价关系}R\text{的等价类,简称}a\text{的等价类} \end{aligned}

      • 定义

      [a]R={xA<a,x>R}\begin{aligned}& [a]_R=\{x\in A|<a,x>\in R\} \end{aligned}

      # 代表

      b[a]R,则称b为等价类[a]R的一个代表\begin{aligned}& b\in [a]_R\text{,则称}b\text{为等价类}[a]_R\text{的一个代表} \end{aligned}

      # 商集

      • 描述

      集合A关于等价关系R的商集是集合A的所有等价类构成的集合\begin{aligned}& \text{集合}A\text{关于等价关系R的商集是}\\& \text{集合A的所有等价类构成的集合} \end{aligned}

      • 定义

      A/R={[a]RaA}\begin{aligned}& A/R=\{[a]_R|a\in A\} \end{aligned}

      • 基本性质

      商集是一个集合族且是A的划分其中每一个元素都是等价类每个等价类都是这个划分的一个划分块\begin{aligned}& \text{商集是一个集合族且是}A\text{的划分}\\& \text{其中每一个元素都是等价类}\\& \text{每个等价类都是这个划分的一个划分块} \end{aligned}

      # 偏序关系

      # 定义

      R是自反的、反对称的、传递的\begin{aligned}& R\text{是自反的、反对称的、传递的} \end{aligned}

      # 符号

      \begin{aligned}& \preceq \end{aligned}

      # 经典例子

      • 数集上的 小于或等于关系、大于或等于关系

        • 集合的子集关系

          • 整数集上的整除关系

      # 可比

      (ab)(ba)\begin{aligned}& (a\preceq b) \lor (b\preceq a) \end{aligned}

      # 不可比

      (a⪯̸b)(b⪯̸a)\begin{aligned}& (a\not\preceq b) \land (b\not\preceq a) \end{aligned}

      # 覆盖

      b覆盖a(ab)!c(accb)\begin{aligned}& b\text{覆盖}a\Leftrightarrow(a\preceq b)\land!\exists c(a\preceq c\land c\preceq b) \end{aligned}

      # 极大元

      aA的极大元bA(abb=a)\begin{aligned}& a\text{是}A\text{的极大元}\Leftrightarrow \forall b\in A(a\preceq b\to b=a) \end{aligned}

      # 极小元

      aA的极小元bA(bab=a)\begin{aligned}& a\text{是}A\text{的极小元}\Leftrightarrow \forall b\in A(b\preceq a\to b=a) \end{aligned}

      # 最大元

      aA的最大元bA(ba)\begin{aligned}& a\text{是}A\text{的最大元}\Leftrightarrow \forall b\in A(b\preceq a) \end{aligned}

      # 最小元

      aA的最小元bA(ab)\begin{aligned}& a\text{是}A\text{的最小元}\Leftrightarrow \forall b\in A(a\preceq b) \end{aligned}

      # 偏序集

      # 定义

      (A,)orabbreviatedasA\begin{aligned}& (A,\preceq)\ \ or\ \ abbreviated\ as\ A \end{aligned}

      # 全序

      or
      线序

      # 定义

      偏序集A的任意两个元素都可比,则这个偏序集是全序或线序\begin{aligned}&\text{偏序集A的任意两个元素都可比,则这个偏序集是全序或线序} \end{aligned}

      # 关系举例 - 幂集上的:

      # 真包含关系

      • 反自反、反对称、传递

      # 恒等关系

      • 自反、对称、反对称、传递

      # 全关系

      • 自反、对称、传递

      # 空关系

      • 反自反、对称、反对称、传递
      \ No newline at end of file diff --git a/math/discrete-math/discrete-math-basics/problem1/index.html b/math/discrete-math/discrete-math-basics/problem1/index.html index e7d1f552..42ddb5ed 100644 --- a/math/discrete-math/discrete-math-basics/problem1/index.html +++ b/math/discrete-math/discrete-math-basics/problem1/index.html @@ -1 +1 @@ -等价关系经典计数问题 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 题面

      f:ABf:A\to B 是函数,定义 A 上的关系 R,a,bA\forall a,b \in A,a R b 当且仅当 f (a) = f (b) 。

      证明 R 是等价关系,并给出它的等价类和商集,求这样的等价关系有多少个?

      # 证明 R 是等价关系

      显然 R 是等价关系,因为对∀a, b, c\in A,f (a)=f (a), f (a)=f (b) 蕴涵 f (b) = f (a) , f (a) = f (b) 且 f (b) = f (c) 蕴涵 f (a) = f (c) ,即 R 是自反、对称、传递的。

      # 求等价类

      对任意 a\in A,[a]R={xf(x)=f(a)},A/R={[a]RaA}[a]_R= \{x∣f(x)=f(a) \},A/R=\{[a]_R∣a\in A\}

      实际上,对任意 a\in A,若 f (a)=y\in B,则[a]R=f1(y)[a]_R=f^{-1} (y)

      因此若 f 是满函数,则 A/R={f1({b})bB}A/R=\{f^{-1} (\{b\})∣b\in B\},即商集 A/R 中的等价类与 B 的元素一一对应。

      对集合 A 上的任意等价关系 R ,自然映射ρ:AA/R,ρ(a)=[a]Rρ:A→A/R,ρ(a)=[a]_R 是满函数,因此 A 上的等价关系与以 A 为定义域的满函数对应。

      设 |A|=n ,则 A 上有 m 个等价类的等价关系个数等于 A 到 Zm={0,1,,m1}Z_m=\{0, 1, ⋯, m-1\} 的满函数个数除以 m! (在 Zm 的元素作为原像的所有可能排列中选一个即可)。

      # 求等价关系个数

      设 |A|=n ,则 A 上不同的等价关系有多少个?

      等价于:设 | A|=n,则 A 上含 m 个等价类的等价关系有多少个?

      当 | A|=n, |B|=m,n≥m,A 到 B 的满函数个数是:

      mnC(m,1)(m1)n++(1)kC(m,k)(mk)n++(1)m1C(m,m1)1nm^n- C(m, 1)(m-1)^n+ ⋯+ (-1)^k C(m, k) (m-k)^n+ ⋯+ (-1)^{m-1} C(m,m-1)\cdot 1^n

      因此 n 元素集合 A 上有 m 个等价类的等价关系有:

      B(n,m)=k=0m1(1)kC(m,k)(mk)nm!B(n, m)=\frac{\sum_{k=0}^{m-1}(-1)^k C(m,k) (m-k)^n }{m!}

      从而 n 元素集合 A 上的不同等价关系个数有:

      B(n)=m=1nk=0m1(1)kC(m,k)(mk)nm!B(n)=\sum_{m=1}^n\frac{\sum_{k=0}^{m-1}(-1)^k C(m,k) (m-k)^n}{m!}

      用 B (n) 表示 n 元素集合上不同等价关系的个数,教材给出了如下递推关系式:

      B(n+1)=k=0nC(n,k)B(k)B(n+1)=\sum_{k=0}^n C(n, k)B(k)

      这个递推关系式的理解是:对于有 n+1 元素集合 (不妨假定为 {0,1, ⋯, n}) 的划分,按照最后一个元素 n 所在的划分块进行分类:

      • 若 n 不与 {0, ⋯, n-1} 的任意元素在一个划分块,即 n 单独在一个划分块,这种划分的个数就等于 {0, ⋯, n-1} 的划分个数,即等于 B (n)
      • 若 n 与 {0, ⋯, n-1} 的某 j=n-k (k=0, ⋯, n) 个元素在一个划分块,则这 j 个元素有 C (n, j) = C (n,n-k) = C (n,k) 种选择,而每种选择的划分个数等于剩下的 k 个元素构成集合的划分个数,即等于 B (k),因此有 C (n,k) B (k) 个划分

      # 根据公式计算结果

      当 | A|=3,则 A 上等价关系个数:

      1+23C(2,1)2!+33C(3,1)23+C(3,2)3!=1+3+1=51+\frac{2^3-C(2,1)}{2!}+\frac{3^3-C(3,1) 2^3+ C(3,2)}{3!}=1+3+1=5

      当 | A|=4,则 A 上等价关系个数:

      1+24C(2,1)2!+34C(3,1)24+C(3,2)3!+44C(4,1)34+C(4,2)24C(4,3)4!=151+\frac{2^4-C(2,1)}{2!}+\frac{3^4-C(3,1) 2^4+C(3,2)}{3!}+\frac{4^4-C(4,1) 3^4+C(4,2)2^4-C(4,3)}{4!}=15

      \ No newline at end of file +等价关系经典计数问题 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 题面

      f:ABf:A\to B 是函数,定义 A 上的关系 R,a,bA\forall a,b \in A,a R b 当且仅当 f (a) = f (b) 。

      证明 R 是等价关系,并给出它的等价类和商集,求这样的等价关系有多少个?

      # 证明 R 是等价关系

      显然 R 是等价关系,因为对∀a, b, c\in A,f (a)=f (a), f (a)=f (b) 蕴涵 f (b) = f (a) , f (a) = f (b) 且 f (b) = f (c) 蕴涵 f (a) = f (c) ,即 R 是自反、对称、传递的。

      # 求等价类

      对任意 a\in A,[a]R={xf(x)=f(a)},A/R={[a]RaA}[a]_R= \{x∣f(x)=f(a) \},A/R=\{[a]_R∣a\in A\}

      实际上,对任意 a\in A,若 f (a)=y\in B,则[a]R=f1(y)[a]_R=f^{-1} (y)

      因此若 f 是满函数,则 A/R={f1({b})bB}A/R=\{f^{-1} (\{b\})∣b\in B\},即商集 A/R 中的等价类与 B 的元素一一对应。

      对集合 A 上的任意等价关系 R ,自然映射ρ:AA/R,ρ(a)=[a]Rρ:A→A/R,ρ(a)=[a]_R 是满函数,因此 A 上的等价关系与以 A 为定义域的满函数对应。

      设 |A|=n ,则 A 上有 m 个等价类的等价关系个数等于 A 到 Zm={0,1,,m1}Z_m=\{0, 1, ⋯, m-1\} 的满函数个数除以 m! (在 Zm 的元素作为原像的所有可能排列中选一个即可)。

      # 求等价关系个数

      设 |A|=n ,则 A 上不同的等价关系有多少个?

      等价于:设 | A|=n,则 A 上含 m 个等价类的等价关系有多少个?

      当 | A|=n, |B|=m,n≥m,A 到 B 的满函数个数是:

      mnC(m,1)(m1)n++(1)kC(m,k)(mk)n++(1)m1C(m,m1)1nm^n- C(m, 1)(m-1)^n+ ⋯+ (-1)^k C(m, k) (m-k)^n+ ⋯+ (-1)^{m-1} C(m,m-1)\cdot 1^n

      因此 n 元素集合 A 上有 m 个等价类的等价关系有:

      B(n,m)=k=0m1(1)kC(m,k)(mk)nm!B(n, m)=\frac{\sum_{k=0}^{m-1}(-1)^k C(m,k) (m-k)^n }{m!}

      从而 n 元素集合 A 上的不同等价关系个数有:

      B(n)=m=1nk=0m1(1)kC(m,k)(mk)nm!B(n)=\sum_{m=1}^n\frac{\sum_{k=0}^{m-1}(-1)^k C(m,k) (m-k)^n}{m!}

      用 B (n) 表示 n 元素集合上不同等价关系的个数,教材给出了如下递推关系式:

      B(n+1)=k=0nC(n,k)B(k)B(n+1)=\sum_{k=0}^n C(n, k)B(k)

      这个递推关系式的理解是:对于有 n+1 元素集合 (不妨假定为 {0,1, ⋯, n}) 的划分,按照最后一个元素 n 所在的划分块进行分类:

      • 若 n 不与 {0, ⋯, n-1} 的任意元素在一个划分块,即 n 单独在一个划分块,这种划分的个数就等于 {0, ⋯, n-1} 的划分个数,即等于 B (n)
      • 若 n 与 {0, ⋯, n-1} 的某 j=n-k (k=0, ⋯, n) 个元素在一个划分块,则这 j 个元素有 C (n, j) = C (n,n-k) = C (n,k) 种选择,而每种选择的划分个数等于剩下的 k 个元素构成集合的划分个数,即等于 B (k),因此有 C (n,k) B (k) 个划分

      # 根据公式计算结果

      当 | A|=3,则 A 上等价关系个数:

      1+23C(2,1)2!+33C(3,1)23+C(3,2)3!=1+3+1=51+\frac{2^3-C(2,1)}{2!}+\frac{3^3-C(3,1) 2^3+ C(3,2)}{3!}=1+3+1=5

      当 | A|=4,则 A 上等价关系个数:

      1+24C(2,1)2!+34C(3,1)24+C(3,2)3!+44C(4,1)34+C(4,2)24C(4,3)4!=151+\frac{2^4-C(2,1)}{2!}+\frac{3^4-C(3,1) 2^4+C(3,2)}{3!}+\frac{4^4-C(4,1) 3^4+C(4,2)2^4-C(4,3)}{4!}=15

      \ No newline at end of file diff --git a/math/discrete-math/discrete-math-basics/set/index.html b/math/discrete-math/discrete-math-basics/set/index.html index 302a9653..8895adf0 100644 --- a/math/discrete-math/discrete-math-basics/set/index.html +++ b/math/discrete-math/discrete-math-basics/set/index.html @@ -1 +1 @@ -集合 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 基本概念

      # 不严格定义的概念

      # 集合

      作为整体研究的一堆东西,用大写字母 A, B, C, ⋯表示

      # 元素

      集合这一堆东西中的每一个,用小写字母 a, b, c, ⋯表示

      # 属于

      元素与集合间的关系

      • 元素 a 属于集合 A ,记为 aAa\in A
      • a 不属于 A,记为 aAa\notin A

      元素与集合间的属于关系也称为成员关系,元素是集合的成员

      # 全集

      研究范围内的所有东西,记为 U

      # 用逻辑语言严格定义的概念

      # 子集关系

      ABx(xAxB)A \subseteq B \lrArr \forall x(x\in A \to x\in B)

      # 集合相等

      A=Bx(xAxB)A = B \lrArr \forall x(x\in A \lrarr x\in B)

      或者

      A=BABBAA=B \lrArr A\subseteq B \land B \subseteq A

      # 空集

      x(x)\forall x(x\notin \varnothing)

      # 朴素集合论

      # 外延原则

      两个集合只要有完全相同的元素则是相等的集合,不考虑集合名字本身的内涵

      # 概念 (名字) 的外延

      概念 (名字) 的外延是它所指称的对象,内涵是它有区别于其他概念的属性全体

      # 集合 (名字) 的外延

      对于集合 (名字),外延是它包含的所有元素,内涵则视具体的应用而定

      # 定义集合的方法

      # 元素枚举法

      将集合的所有元素一一罗列出来

      • 适合元素比较少,或可按明显规律罗列元素时定义集合
      • 元素罗列规律明显时可使用省略号

      # 性质概括法

      用谓词概括一个集合的所有元素满足的共同性质

      # 基本形式

      A={xP(x)}A = \{x∣P(x)\}

      含义是:

      x(xAP(x))\forall x(x\in A \lrarr P(x))

      允许 P 是任意性质时有可能产生悖论:罗素悖论

      公理集合论运用子集分离原则避免悖论:

      A={xBP(x)}A=\{x\in B∣P(x)\}

      B 是已知的大集合

      # 扩展形式

      A={f(y)P(y)}A=\{f(y)∣P(y)\}

      含义是

      x(xAy(x=f(y)P(y)))\forall x(x\in A↔∃y(x=f(y)∧P(y)))

      这里 f 是一个函数,或说 f (x) 是含有自由变量 x 的表达式

      # 归纳定义法

      给出基本元素和从已有元素构造其他元素的规则

      从某种意义上说,集合的归纳定义给出了构造集合元素的算法

      # 集合的划分 (partition)

      # 定义

      设 A 是非空集合,F 是集合族,其中每个集合都是 A 的子集。说集合族 F 是 A 的划分,如果:

      • 非空:对任意的 SFS\in \mathcal{F} , S\neq \mathcal
      • 两两不交:对任意两个集合 S1,S2FS_1, S_2\in F , S1S2=S_1\cap S_2=\varnothing
      • 覆盖集合 A:F=A\cup \mathcal{F}= A

      非空集合 A 的划分 F\mathcal{F} 中的每个集合称为这个划分的一个 划分块 (block)

      # 非空集合 A 上的等价关系与它的划分有一一对应关系

      A 关于一个等价关系的商集是 A 的划分,而 A 的一个划分导出的 “在同一划分块” 关系是等价关系

      进一步,A 关于 “在同一划分块” 这个等价关系的商集就是这个划分,而 A 关于等价关系的商集作为 A 的划分所导出的 “在同一划分块” 关系就是这个等价关系本身

      # 常用集合

      # 模 m 剩余类

      是一种常用等价类

      对任意整数 aZa\in \mathbb{Z} , a 在 R 下的等价类 [a]R[a]_R 称为整数集 Z\mathbb Z 的一个(与 a 同余的)模 m 剩余类,并记为:

      a={xZxa(modm)}={xZmxa}={a+mzzZ}\overline{a}=\{x\in \mathbb Z ∣ x ≡ a(\mod m) \}=\{x\in \mathbb Z∣m∣x-a\}=\{a+mz∣z\in \mathbb Z \}

      # 模 m 剩余类的商集

      Zm={0,1,...,m1}={0,1,...,m1}\mathbb{Z}_m = \{ \overline 0,\overline 1,...,\overline{m-1} \} = \{ 0,1,...,m-1 \}

      # 有序对

      集合论定义的有序对

      从二元有序对开始定义,归纳定义 n 元有序对

      # 二元有序对

      <a,b>={{a},{a,b}}<b,a>={{b},{a,b}}<a,b>=\{\{a\},\{a,b\}\}\\ <b,a>=\{\{b\},\{a,b\}\}

      # 三元有序对

      <a,b,c>=<<a,b>,c><a,b,c>=<<a,b>,c>

      # n 元有序对

      <a1,a2,...an>=<<a1,a2,...,an1>,an><a_1,a_2,...a_n>=<<a_1,a_2,...,a_{n-1}>,a_n>

      # 有序 n 元组性质定理

      <a1,a2,...an>=<b1,b2,...bn>ai=bi,i=1,2,3,...,n<a_1,a_2,...a_n>=<b_1,b_2,...b_n> \lrArr a_i=b_i \ ,\ i=1,2,3,...,n

      \ No newline at end of file +集合 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 基本概念

      # 不严格定义的概念

      # 集合

      作为整体研究的一堆东西,用大写字母 A, B, C, ⋯表示

      # 元素

      集合这一堆东西中的每一个,用小写字母 a, b, c, ⋯表示

      # 属于

      元素与集合间的关系

      • 元素 a 属于集合 A ,记为 aAa\in A
      • a 不属于 A,记为 aAa\notin A

      元素与集合间的属于关系也称为成员关系,元素是集合的成员

      # 全集

      研究范围内的所有东西,记为 U

      # 用逻辑语言严格定义的概念

      # 子集关系

      ABx(xAxB)A \subseteq B \lrArr \forall x(x\in A \to x\in B)

      # 集合相等

      A=Bx(xAxB)A = B \lrArr \forall x(x\in A \lrarr x\in B)

      或者

      A=BABBAA=B \lrArr A\subseteq B \land B \subseteq A

      # 空集

      x(x)\forall x(x\notin \varnothing)

      # 朴素集合论

      # 外延原则

      两个集合只要有完全相同的元素则是相等的集合,不考虑集合名字本身的内涵

      # 概念 (名字) 的外延

      概念 (名字) 的外延是它所指称的对象,内涵是它有区别于其他概念的属性全体

      # 集合 (名字) 的外延

      对于集合 (名字),外延是它包含的所有元素,内涵则视具体的应用而定

      # 定义集合的方法

      # 元素枚举法

      将集合的所有元素一一罗列出来

      • 适合元素比较少,或可按明显规律罗列元素时定义集合
      • 元素罗列规律明显时可使用省略号

      # 性质概括法

      用谓词概括一个集合的所有元素满足的共同性质

      # 基本形式

      A={xP(x)}A = \{x∣P(x)\}

      含义是:

      x(xAP(x))\forall x(x\in A \lrarr P(x))

      允许 P 是任意性质时有可能产生悖论:罗素悖论

      公理集合论运用子集分离原则避免悖论:

      A={xBP(x)}A=\{x\in B∣P(x)\}

      B 是已知的大集合

      # 扩展形式

      A={f(y)P(y)}A=\{f(y)∣P(y)\}

      含义是

      x(xAy(x=f(y)P(y)))\forall x(x\in A↔∃y(x=f(y)∧P(y)))

      这里 f 是一个函数,或说 f (x) 是含有自由变量 x 的表达式

      # 归纳定义法

      给出基本元素和从已有元素构造其他元素的规则

      从某种意义上说,集合的归纳定义给出了构造集合元素的算法

      # 集合的划分 (partition)

      # 定义

      设 A 是非空集合,F 是集合族,其中每个集合都是 A 的子集。说集合族 F 是 A 的划分,如果:

      • 非空:对任意的 SFS\in \mathcal{F} , S\neq \mathcal
      • 两两不交:对任意两个集合 S1,S2FS_1, S_2\in F , S1S2=S_1\cap S_2=\varnothing
      • 覆盖集合 A:F=A\cup \mathcal{F}= A

      非空集合 A 的划分 F\mathcal{F} 中的每个集合称为这个划分的一个 划分块 (block)

      # 非空集合 A 上的等价关系与它的划分有一一对应关系

      A 关于一个等价关系的商集是 A 的划分,而 A 的一个划分导出的 “在同一划分块” 关系是等价关系

      进一步,A 关于 “在同一划分块” 这个等价关系的商集就是这个划分,而 A 关于等价关系的商集作为 A 的划分所导出的 “在同一划分块” 关系就是这个等价关系本身

      # 常用集合

      # 模 m 剩余类

      是一种常用等价类

      对任意整数 aZa\in \mathbb{Z} , a 在 R 下的等价类 [a]R[a]_R 称为整数集 Z\mathbb Z 的一个(与 a 同余的)模 m 剩余类,并记为:

      a={xZxa(modm)}={xZmxa}={a+mzzZ}\overline{a}=\{x\in \mathbb Z ∣ x ≡ a(\mod m) \}=\{x\in \mathbb Z∣m∣x-a\}=\{a+mz∣z\in \mathbb Z \}

      # 模 m 剩余类的商集

      Zm={0,1,...,m1}={0,1,...,m1}\mathbb{Z}_m = \{ \overline 0,\overline 1,...,\overline{m-1} \} = \{ 0,1,...,m-1 \}

      # 有序对

      集合论定义的有序对

      从二元有序对开始定义,归纳定义 n 元有序对

      # 二元有序对

      <a,b>={{a},{a,b}}<b,a>={{b},{a,b}}<a,b>=\{\{a\},\{a,b\}\}\\ <b,a>=\{\{b\},\{a,b\}\}

      # 三元有序对

      <a,b,c>=<<a,b>,c><a,b,c>=<<a,b>,c>

      # n 元有序对

      <a1,a2,...an>=<<a1,a2,...,an1>,an><a_1,a_2,...a_n>=<<a_1,a_2,...,a_{n-1}>,a_n>

      # 有序 n 元组性质定理

      <a1,a2,...an>=<b1,b2,...bn>ai=bi,i=1,2,3,...,n<a_1,a_2,...a_n>=<b_1,b_2,...b_n> \lrArr a_i=b_i \ ,\ i=1,2,3,...,n

      \ No newline at end of file diff --git a/math/discrete-math/graph/algebra-graph/index.html b/math/discrete-math/graph/algebra-graph/index.html index 870bf056..189da6ac 100644 --- a/math/discrete-math/graph/algebra-graph/index.html +++ b/math/discrete-math/graph/algebra-graph/index.html @@ -1 +1 @@ -图的代数表示 - 图论 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      用邻接矩阵或关联矩阵表示图,称为图的代数表示。用矩阵表示图,主要有两个优点:

      • (1) 能够把图输入到计算机中
      • (2) 可以用代数方法研究图论

      Spectral Graph Theory 是研究图和代数的一个领域

      # 邻接矩阵

      Adjaceny matrix is n×nn\times n symmetric matrix

      # 定义

      GGnn 阶图,V={v1,z2,,vn}V=\{v_1,z_2,\cdots,v_n\} ,邻接矩阵 A(G)=(aij)A(G)= (a_{ij}) ,其中:

      aij={l,vivj间边数0,vivj不邻接ai上的环数,i=ja_{ij}=\begin{cases} l,\ \ \ v_i\text{与}v_j\text{间边数}\\ 0,\ \ \ v_i\text{与}v_j\text{不邻接}\\ a_i\text{上的环数},\ \ \ i=j \end{cases}

      # 代数性质

      非负性 —— 由邻接矩阵定义知 aija_{ij} 是非负整数,即邻接矩阵是非负整数矩阵

      (无向图) 对称性 —— 显然 aij=ajia_{ij}=a_{ji} ,所以邻接矩阵是对称矩阵。

      同一图的不同形式的邻接矩阵是相似矩阵。这是因为,同图的两种不同形式矩阵可以通过交换行和相应的列变成致。

      如果 G 为简单图,则 A(G)A(G)布尔矩阵;行和 (列和) 等于对应顶点的度数;矩阵元素总和为图的总度数,也就是 GG 的边数的 2 倍

      # 连通的充要条件

      GG 连通的充要条件是:A(G)A(G) 不能与如下矩阵相似:

      (A1100A22)\begin{pmatrix} A_{11} & 0\\ 0 & A_{22} \end{pmatrix} \quad

      # 性质 (定理)

      Ak(G)=(aij(k))A^{k}(G)=(a_{ij}^{(k)}) ,则 aij(k)a_{ij}^{(k)} 表示顶点 viv_ivjv_j 的途径长度为 kk 的途径数目;


      证明:对 kk 作数学归纳法证明

      k=1k=1 时,由邻接矩阵定义;

      设结论对 k1k-1 时成立,考虑 kk 的情况:

      Ak=Ak1A=(ai1(k1)aj1+ai2(k1)aj2++ain(k1)ajn)n×n=(aij(k))A^k=A^{k-1}A=(a_{i1}^{(k-1)}a_{j1}+a_{i2}^{(k-1)}a_{j2}+\cdots+a_{in}^{(k-1)}a_{jn})_{n\times n}=(a_{ij}^{(k)})

      同时,考虑顶点 viv_ivjv_j 的途径长度为 kk 的途径,设 vmv_mviv_ivjv_j 的途径中点,且该点与 vjv_j 邻接。则 viv_ivjv_j 的经过 vmv_m 且途径长度为 kk 的途径数目为:

      aim(k1)amja_{im}^{(k-1)}a_{mj}

      所以 viv_ivjv_j 的途径长度为 kk 的途径数目为:

      ai1(k1)aj1+ai2(k1)aj2++ain(k1)ajn=aij(k)a_{i1}^{(k-1)}a_{j1}+a_{i2}^{(k-1)}a_{j2}+\cdots+a_{in}^{(k-1)}a_{jn}=a_{ij}^{(k)}


      推论:

      GG 是连通的,则对于 iji\neq jviv_ivjv_j 的距离是使 AnA^{n}aij(k)0a_{ij}^{(k)}\neq0 的最小整数

      这是显然的

      # 关联矩阵

      Incidence matrix is n×mn\times m matrix of a (n,m)(n,m) graph

      # 定义

      GG(n,m)(n,m) 图。定义 GG 的关联矩阵: M(G)=(aij)n×mM(G)=(a_{ij})_{n\times m} ,其中:aija_{ij}viv_ieje_j 关联的次数 (取值为 0,1, 或 2 (环)).

      • 关联矩阵的元素为 0,1 或 2 ;
      • 关联矩阵的每列和为 2 ; 每行的和为对应顶点度数;

      # 连通的充要条件

      无环图 GG 连通的充分必要条件𝑅(𝑀)=n1𝑅(𝑀)=n-1


      证明充分性:

      GG 不连通,假设 GG 有两个连通分支 G1G_1G2G_2 , 又设 G1G_1G2G_2 的关联矩阵分别为 𝑀1𝑀_1𝑀2𝑀_2 , 则 GG 的关联矩阵可以写为:

      M(G)=(M1M2)M(G)= \begin{pmatrix} M_1 & \\ & M_2 \end{pmatrix}

      于是 𝑅(𝑀)=V(G1)1+V(G2)1=n2𝑅(𝑀)=V(G_1)-1+V(G_2)-1=n-2 ,矛盾!所以 GG 一定连通。


      证明必要性:

      令:

      M=(m1m2mn)M= \begin{pmatrix} m_1\\ m_2\\ \vdots\\ m_n \end{pmatrix}

      由于 𝑀𝑀 中每列恰有两个 “1” 元素,所有行向量的和为 0 (模 2 加法运算,即为偶数),所以有 R(M)n1R(M)\leq n-1

      另一方面,在 MM 中任意去掉一行 mkm_k ,由于 GG连通的,因此,mkm_k 中存在元素 “1” ,这样,MM 中去掉行 mkm_k ,后的行按模 2 相加不等于零,即它们是线性无关的。所以有 R(M)n1R(M)\geq n-1

      因此,R(M)=n1R(M)=n-1

      # 基本关联矩阵

      GG 的关联矩阵中删掉任意一行后得到的矩阵可以完全决定 GG ,该矩阵称为 GG基本关联矩阵。删掉的行对应的顶点称为该基本关联矩阵的参考点

      图的关联矩阵及其性质是网络图论的基础,在电路分析中有重要应用

      图的关联矩阵比邻接矩阵大得多,不便于计算机存储。但二者都有各自的应用特点

      # 定义 2

      Incidence matrix CC is m×nm\times n matrix of a (n,m)(n,m) graph

      用来定义拉普拉斯矩阵 L=CTCL=C^{T}C

      • 每行代表一条边,每列代表一个顶点
      • 每行和为 0 ,有一个 1 和 -1 ,分别表示边的起点和终点
      • 其余元素全部为 0

      C=(e1Te2TemT)C= \begin{pmatrix} e_1^{T}\\ e_2^{T}\\ \vdots\\ e_m^{T} \end{pmatrix}

      # 度矩阵

      Degree matrix is n×nn\times n diagonal matrix

      # 定义

      度矩阵是对角阵,对角上的元素为各个顶点的度。

      ⚠️有向图中,可能会有不同的定义。一般度数为各个顶点入度与出度之和,例如拉普拉斯矩阵引入的度矩阵。

      # 拉普拉斯矩阵

      Laplacian matrix (LL) is n×nn\times n symmetric matrix

      拉普拉斯矩阵是对称矩阵,保留了图的 “无向” 的属性,丢失了 “有向” 的属性

      GG 是顶点集合为 V(G)={v1,v2,,vn}V(G)=\{v_1,v_2,\cdots,v_n\} 的图, DD 为图的度矩阵A=aijA=a_{ij}GG邻接矩阵CC 为图的关联矩阵

      定义:

      L=DA=CTCL=D-A=C^{T}C

      拉普拉斯矩阵 L=(lij)L=(l_{ij})nn 阶方阵,其中:

      lij={d(vi),i=jaij,ijl_{ij}=\begin{cases} d(v_i), & i=j\\ -a_{ij}, & i\neq j \end{cases}

      • 所有特征值为非负实数: 0λ0λ1λn10\leq\lambda_0\leq\lambda_1\leq\cdots\leq\lambda_{n-1}
      • 特征向量为实 (正交) 向量
      • 每一行、列之和都等于 0
      • xTLx0x^{T}Lx\geq0 是半正定二次型,或者说拉普拉斯矩阵 LL 是半正定矩阵

      [Fiedler, 1973] GGkk 个连通分支当且仅当:

      λ0=λ1==λk1=0\lambda_0=\lambda_1=\cdots=\lambda_{k-1}=0

      GG 显然至少有一个连通分支,所以 λ0=0\lambda_0=0

      GG 的割边 (cut edges) 数量等于:

      14xTLx=14(i,j)E(xixj)2\frac{1}{4}x^{T}Lx=\frac{1}{4}\sum_{(i,j)\in E}(x_i-x_j)^2

      (等式右侧推导在下面)

      对任意对称矩阵 MM 定义 λ2\lambda_2

      λ2=minxxTMxxTx\lambda_2=\min_{x}\frac{x^{T}Mx}{x^{T}x}

      考虑拉普拉斯矩阵 LL 对应的二次型 xTLxx^{T}Lx

      xTLx=i,j=1nLijxixj=i,j=1n(DijAij)xixj=i=1nDiixi2(i,j)E2xixj=(i,j)E(xi2+xj22xixj)=(i,j)E(xixj)2\begin{aligned} x^{T}Lx &=\sum_{i,j=1}^{n}L_{ij}x_ix_j\\ &=\sum_{i,j=1}^{n}(D_{ij}-A_{ij})x_ix_j\\ &=\sum_{i=1}^{n}D_{ii}x_i^2-\sum_{(i,j)\in E}2x_ix_j\\ &=\sum_{(i,j)\in E}(x_i^2+x_j^2-2x_ix_j)\\ &=\sum_{(i,j)\in E}(x_i-x_j)^2 \end{aligned}

      此时:

      λ2=minAll labelings of so thatxi=0(i,j)E(xixj)2ixi2\lambda_2=\min_{\text{All labelings of so that }\sum x_i=0}\frac{\sum_{(i,j)\in E}(x_i-x_j)^2}{\sum_ix_i^2}

      # 子图空间

      # 回路空间

      https://lfool.github.io/LFool-Notes/other/ 图论.html# 回路系统简介

      # 断集空间

      \ No newline at end of file +图的代数表示 - 图论 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      用邻接矩阵或关联矩阵表示图,称为图的代数表示。用矩阵表示图,主要有两个优点:

      • (1) 能够把图输入到计算机中
      • (2) 可以用代数方法研究图论

      Spectral Graph Theory 是研究图和代数的一个领域

      # 邻接矩阵

      Adjaceny matrix is n×nn\times n symmetric matrix

      # 定义

      GGnn 阶图,V={v1,z2,,vn}V=\{v_1,z_2,\cdots,v_n\} ,邻接矩阵 A(G)=(aij)A(G)= (a_{ij}) ,其中:

      aij={l,vivj间边数0,vivj不邻接ai上的环数,i=ja_{ij}=\begin{cases} l,\ \ \ v_i\text{与}v_j\text{间边数}\\ 0,\ \ \ v_i\text{与}v_j\text{不邻接}\\ a_i\text{上的环数},\ \ \ i=j \end{cases}

      # 代数性质

      非负性 —— 由邻接矩阵定义知 aija_{ij} 是非负整数,即邻接矩阵是非负整数矩阵

      (无向图) 对称性 —— 显然 aij=ajia_{ij}=a_{ji} ,所以邻接矩阵是对称矩阵。

      同一图的不同形式的邻接矩阵是相似矩阵。这是因为,同图的两种不同形式矩阵可以通过交换行和相应的列变成致。

      如果 G 为简单图,则 A(G)A(G)布尔矩阵;行和 (列和) 等于对应顶点的度数;矩阵元素总和为图的总度数,也就是 GG 的边数的 2 倍

      # 连通的充要条件

      GG 连通的充要条件是:A(G)A(G) 不能与如下矩阵相似:

      (A1100A22)\begin{pmatrix} A_{11} & 0\\ 0 & A_{22} \end{pmatrix} \quad

      # 性质 (定理)

      Ak(G)=(aij(k))A^{k}(G)=(a_{ij}^{(k)}) ,则 aij(k)a_{ij}^{(k)} 表示顶点 viv_ivjv_j 的途径长度为 kk 的途径数目;


      证明:对 kk 作数学归纳法证明

      k=1k=1 时,由邻接矩阵定义;

      设结论对 k1k-1 时成立,考虑 kk 的情况:

      Ak=Ak1A=(ai1(k1)aj1+ai2(k1)aj2++ain(k1)ajn)n×n=(aij(k))A^k=A^{k-1}A=(a_{i1}^{(k-1)}a_{j1}+a_{i2}^{(k-1)}a_{j2}+\cdots+a_{in}^{(k-1)}a_{jn})_{n\times n}=(a_{ij}^{(k)})

      同时,考虑顶点 viv_ivjv_j 的途径长度为 kk 的途径,设 vmv_mviv_ivjv_j 的途径中点,且该点与 vjv_j 邻接。则 viv_ivjv_j 的经过 vmv_m 且途径长度为 kk 的途径数目为:

      aim(k1)amja_{im}^{(k-1)}a_{mj}

      所以 viv_ivjv_j 的途径长度为 kk 的途径数目为:

      ai1(k1)aj1+ai2(k1)aj2++ain(k1)ajn=aij(k)a_{i1}^{(k-1)}a_{j1}+a_{i2}^{(k-1)}a_{j2}+\cdots+a_{in}^{(k-1)}a_{jn}=a_{ij}^{(k)}


      推论:

      GG 是连通的,则对于 iji\neq jviv_ivjv_j 的距离是使 AnA^{n}aij(k)0a_{ij}^{(k)}\neq0 的最小整数

      这是显然的

      # 关联矩阵

      Incidence matrix is n×mn\times m matrix of a (n,m)(n,m) graph

      # 定义

      GG(n,m)(n,m) 图。定义 GG 的关联矩阵: M(G)=(aij)n×mM(G)=(a_{ij})_{n\times m} ,其中:aija_{ij}viv_ieje_j 关联的次数 (取值为 0,1, 或 2 (环)).

      • 关联矩阵的元素为 0,1 或 2 ;
      • 关联矩阵的每列和为 2 ; 每行的和为对应顶点度数;

      # 连通的充要条件

      无环图 GG 连通的充分必要条件𝑅(𝑀)=n1𝑅(𝑀)=n-1


      证明充分性:

      GG 不连通,假设 GG 有两个连通分支 G1G_1G2G_2 , 又设 G1G_1G2G_2 的关联矩阵分别为 𝑀1𝑀_1𝑀2𝑀_2 , 则 GG 的关联矩阵可以写为:

      M(G)=(M1M2)M(G)= \begin{pmatrix} M_1 & \\ & M_2 \end{pmatrix}

      于是 𝑅(𝑀)=V(G1)1+V(G2)1=n2𝑅(𝑀)=V(G_1)-1+V(G_2)-1=n-2 ,矛盾!所以 GG 一定连通。


      证明必要性:

      令:

      M=(m1m2mn)M= \begin{pmatrix} m_1\\ m_2\\ \vdots\\ m_n \end{pmatrix}

      由于 𝑀𝑀 中每列恰有两个 “1” 元素,所有行向量的和为 0 (模 2 加法运算,即为偶数),所以有 R(M)n1R(M)\leq n-1

      另一方面,在 MM 中任意去掉一行 mkm_k ,由于 GG连通的,因此,mkm_k 中存在元素 “1” ,这样,MM 中去掉行 mkm_k ,后的行按模 2 相加不等于零,即它们是线性无关的。所以有 R(M)n1R(M)\geq n-1

      因此,R(M)=n1R(M)=n-1

      # 基本关联矩阵

      GG 的关联矩阵中删掉任意一行后得到的矩阵可以完全决定 GG ,该矩阵称为 GG基本关联矩阵。删掉的行对应的顶点称为该基本关联矩阵的参考点

      图的关联矩阵及其性质是网络图论的基础,在电路分析中有重要应用

      图的关联矩阵比邻接矩阵大得多,不便于计算机存储。但二者都有各自的应用特点

      # 定义 2

      Incidence matrix CC is m×nm\times n matrix of a (n,m)(n,m) graph

      用来定义拉普拉斯矩阵 L=CTCL=C^{T}C

      • 每行代表一条边,每列代表一个顶点
      • 每行和为 0 ,有一个 1 和 -1 ,分别表示边的起点和终点
      • 其余元素全部为 0

      C=(e1Te2TemT)C= \begin{pmatrix} e_1^{T}\\ e_2^{T}\\ \vdots\\ e_m^{T} \end{pmatrix}

      # 度矩阵

      Degree matrix is n×nn\times n diagonal matrix

      # 定义

      度矩阵是对角阵,对角上的元素为各个顶点的度。

      ⚠️有向图中,可能会有不同的定义。一般度数为各个顶点入度与出度之和,例如拉普拉斯矩阵引入的度矩阵。

      # 拉普拉斯矩阵

      Laplacian matrix (LL) is n×nn\times n symmetric matrix

      拉普拉斯矩阵是对称矩阵,保留了图的 “无向” 的属性,丢失了 “有向” 的属性

      GG 是顶点集合为 V(G)={v1,v2,,vn}V(G)=\{v_1,v_2,\cdots,v_n\} 的图, DD 为图的度矩阵A=aijA=a_{ij}GG邻接矩阵CC 为图的关联矩阵

      定义:

      L=DA=CTCL=D-A=C^{T}C

      拉普拉斯矩阵 L=(lij)L=(l_{ij})nn 阶方阵,其中:

      lij={d(vi),i=jaij,ijl_{ij}=\begin{cases} d(v_i), & i=j\\ -a_{ij}, & i\neq j \end{cases}

      • 所有特征值为非负实数: 0λ0λ1λn10\leq\lambda_0\leq\lambda_1\leq\cdots\leq\lambda_{n-1}
      • 特征向量为实 (正交) 向量
      • 每一行、列之和都等于 0
      • xTLx0x^{T}Lx\geq0 是半正定二次型,或者说拉普拉斯矩阵 LL 是半正定矩阵

      [Fiedler, 1973] GGkk 个连通分支当且仅当:

      λ0=λ1==λk1=0\lambda_0=\lambda_1=\cdots=\lambda_{k-1}=0

      GG 显然至少有一个连通分支,所以 λ0=0\lambda_0=0

      GG 的割边 (cut edges) 数量等于:

      14xTLx=14(i,j)E(xixj)2\frac{1}{4}x^{T}Lx=\frac{1}{4}\sum_{(i,j)\in E}(x_i-x_j)^2

      (等式右侧推导在下面)

      对任意对称矩阵 MM 定义 λ2\lambda_2

      λ2=minxxTMxxTx\lambda_2=\min_{x}\frac{x^{T}Mx}{x^{T}x}

      考虑拉普拉斯矩阵 LL 对应的二次型 xTLxx^{T}Lx

      xTLx=i,j=1nLijxixj=i,j=1n(DijAij)xixj=i=1nDiixi2(i,j)E2xixj=(i,j)E(xi2+xj22xixj)=(i,j)E(xixj)2\begin{aligned} x^{T}Lx &=\sum_{i,j=1}^{n}L_{ij}x_ix_j\\ &=\sum_{i,j=1}^{n}(D_{ij}-A_{ij})x_ix_j\\ &=\sum_{i=1}^{n}D_{ii}x_i^2-\sum_{(i,j)\in E}2x_ix_j\\ &=\sum_{(i,j)\in E}(x_i^2+x_j^2-2x_ix_j)\\ &=\sum_{(i,j)\in E}(x_i-x_j)^2 \end{aligned}

      此时:

      λ2=minAll labelings of so thatxi=0(i,j)E(xixj)2ixi2\lambda_2=\min_{\text{All labelings of so that }\sum x_i=0}\frac{\sum_{(i,j)\in E}(x_i-x_j)^2}{\sum_ix_i^2}

      # 子图空间

      # 回路空间

      https://lfool.github.io/LFool-Notes/other/ 图论.html# 回路系统简介

      # 断集空间

      \ No newline at end of file diff --git a/math/discrete-math/graph/coloring/index.html b/math/discrete-math/graph/coloring/index.html index a8cffdf3..26ef7f45 100644 --- a/math/discrete-math/graph/coloring/index.html +++ b/math/discrete-math/graph/coloring/index.html @@ -1 +1 @@ -着色问题 - 图论 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 边着色问题

      图的边着色,本质上是对应实际问题中的 “划分” 问题或 “分类” 问题。

      GG 的边进行着色,若相邻边着不同颜色,则称对 GG 进行正常边着色

      在对 GG 正常边着色时,着相同颜色的边集称为该正常边着色的一个色组

      如果能用 kk 种颜色对图 GG 进行正常边着色,称 GGkk 边可着色的

      GG 进行正常边着色需要的最少颜色数称为 GG边色数,记为:

      χ(G)\chi'(G)

      着色需要满足相邻边着不同色,所以很自然地有:(对于无环图)

      χ(G)Δ\chi'(G)\geq\Delta

      也就是边色数以最大顶点度为下限

      # 二部图

      χ(Km,n)=Δ\chi'(K_{m,n})=\Delta


      证明

      假设:

      • n>mn\gt m
        • 所以 Δ=n\Delta=n
      • X={x0,x1,,xm1}X=\{x_0,x_1,\cdots,x_{m-1}\}
      • Y={y0,y1,,yn1}Y=\{y_0,y_1,\cdots,y_{n-1}\}
      • nn 个颜色集合为:{0,1,2,,n1}\{0,1,2,\cdots,n-1\}

      π\piKm,nK_{m,n} 的一个 nn 着色方案,满足:

      xiyjE(Km,n),π(xiyj)=(i+j)(modn)\forall x_i y_j\in E(K_{m,n}),\ \ \pi(x_iy_j)=(i+j)(\bmod n)

      Km,nK_{m,n} 中任意两条邻接边 xiyjx_iy_jxiykx_iy_k ,若二者在 π\pi 中着色相同,即 π(xiyj)=π(xiyk)\pi(x_iy_j)=\pi(x_iy_k) ,则有:

      (i+j)(modn)=(i+k)(modn)j=k(i+j)(\bmod n)=(i+k)(\bmod n)\\ \Downarrow\\ j=k

      于是 xiyj=xiykx_iy_j=x_iy_k ,所以 π\pi 是一个正常的 nn 着色(满足相邻边着不同色)。也即 (X,Y)(X,Y)nn 可着色的。

      同时 χ(Km,n)Δ=n\chi'(K_{m,n})\geq\Delta=n ,所以 χ(Km,n)=n\chi'(K_{m,n})=n

      # 偶图 (哥尼定理)

      偶图 GG 的边色数:

      χ(G)=Δ\chi'(G)=\Delta


      证明可利用数学归纳法

      m=1m=1 时,Δ=1\Delta=1,有 χ(G)=Δ=1\chi'(G)=\Delta=1 成立。

      设对于小于 mm 条边的偶图来说命题成立。

      GG 是具有 mm 条边的偶图。

      uvGuv\in G , 考虑 G1=GuvG_1=G-uv, 由归纳假设有:

      χ(G1)=Δ(G1)Δ(G)\chi'(G_1)=\Delta(G_1)\leq\Delta(G)

      这说明, GG 存在一种 Δ(G)\Delta(G) 边着色方案 π\pi . 对于该着色方案,因为 uvuv 未着色,所以点 uuvv 均至少缺少一种色。


      情形 1:如果 uuvv 均缺同一种色 ii

      则在 G1+uvG_1+uv 中给 uvuv 着色 ii , 而 GG 其它边按 π\pi 方案着色。这样得到 GGΔ\Delta 着色方案,所以: χ(G)=Δ\chi'(G)=\Delta


      情形 2:如果 uu 缺色 ii , 而 vv 缺色 jj , 但不缺色 ii

      H(i,j)H(i,j) 表示 GG 中由 ii 色边与 jj 色边导出的子图。显然,该图每个分支是 ii 色边和 jj 色边交替出现的路或圈。
      对于 H(i,j)H(i,j) 中含点 vv 的分支来说,因 vv 缺色 jj , 但不缺色 ii , 所以,在 H(i,j)H(i,j) 中,点 vv 的度数为 1。这说明,H(i,j)H(i,j) 中含 vv 的分支是一条路 PP . 进一步地,我们可以说明,上面的路 PP 不含点 uu . 因为,如果 PP 含有点 uu , 那么 PP 必然是一条长度为偶数的路,这样,P+uvP+uvGG 中的奇圈,这与 GG 是偶图矛盾!

      既然 PP 不含点 uu , 所以我们可以交换 PP 中着色,而不破坏 G1G_1 的正常边着色。但交换着色后,vv 就变成缺色 jj , 但不缺色 iiuuvv 均缺色 ii , 于是由情形 1, 可以得到 GGΔ\Delta 正常边着色,即证明 χ(G)=Δ\chi'(G)=\Delta

      # 一般简单图

      # 引理

      GG 是简单图,xxyyGG 中两个不相邻的顶点,π\piGG 的一个正常 kk 边着色。若对该着色,x,yx,y 以及与 xx 相邻的点均至少缺少一种颜色,则 G+xyG+xy 也是 kk 边可着色的

      # 维津定理 (Vizing)

      若图 GG 是简单图,则 χ(G)=Δ\chi'(G)=\Deltaχ(G)=Δ+1\chi'(G)=\Delta+1


      只需要证明 χ(G)Δ+1\chi'(G)≤\Delta+1 即可。 对 GG 的边数 mm 作数学归纳证明。

      m=1m=1 时,Δ=1\Delta=1, χ(G)=1<Δ+1\chi'(G)=1<Δ+1

      设当边数少于 mm 时,结论成立。下面考虑边数为 m2m≥2 的单图 GG

      xyE(G)xy\in E(G) , 令 G1=GxyG_1=G-xy. 由归纳假设有:

      χ(G1)Δ(G1)+1Δ(G)+1\chi'(G_1)≤\Delta(G_1)+1≤\Delta(G)+1

      于是,存在 G1G_1Δ(G)+1\Delta(G)+1 正常边作色 π\pi。显然 GG 的每个顶点都至少缺少一种颜色。根据引理知 G+xyG+xyΔ(G)+1\Delta(G) +1 可着色的。即证明: χ(G)Δ(G)+1\chi'(G) ≤ \Delta(G)+1

      # 充分条件 1

      给出了 Vizing 定理结论中 χ(G)=Δ\chi'(G)=\Delta 情况的充分条件

      GG 是单图且 Δ(G)>0\Delta(G)>0。若 GG 中只有一个最大度点或恰有两个相邻的最大度点,则:

      χ(G)=Δ(G)\chi'(G)=\Delta(G)

      # 充分条件 2

      给出了 Vizing 定理结论中 χ(G)=Δ+1\chi'(G)=\Delta+1 情况的充分条件

      GG 是单图。若点数 n=2k+1n=2k+1 且边数 m>kΔm>k\Delta,则:

      χ(G)=Δ(G)+1\chi'(G)=\Delta(G)+1


      证明可利用反证法,若不然,由维津定理,χ(G)=Δ(G)\chi'(G)=\Delta(G)

      π\piGGΔ(G)\Delta(G) 正常边着色方案,对于 GG 的每个色组来说,包含的边数至多 n12=k\frac{n-1}{2}=k。这样:m(G)Δkm(G)≤\Delta k,与条件矛盾。

      # 充分条件 3

      给出了 Vizing 定理结论中 χ(G)=Δ+1\chi'(G)=\Delta+1 情况的充分条件

      GG 是奇数阶 Δ\Delta 正则单图,若 Δ>0\Delta>0,则:

      χ(G)=Δ(G)+1\chi'(G)=\Delta(G)+1


      证明:

      n=2k+1n=2k+1,因 GGΔ\Delta 正则单图,且 Δ>0\Delta>0,所以:

      m(G)=nΔ2=(2k+1)Δ2>kΔm(G)=\frac{n\Delta}{2}=\frac{(2k+1)\Delta}{2}\gt k\Delta

      由定理 χ(G)=Δ(G)+1\chi'(G)=\Delta(G)+1

      # 无环有重边图

      维津定理 (Vizing)

      设无环图 GG 中边的最大重数为 μ\mu​,则:

      χ(G)Δ(G)+μ\chi'(G)\leq\Delta(G)+\mu

      其中 \leq 边界是紧的,也就是等号是可以相等的。

      # 边着色的应用

      # 排课表问题

      X,YX,Y 分别表示教师、教学班的集合:

      X={x1,x2,,xm}Y={y1,y2,,yn}X=\{x_1,x_2,\cdots,x_m\}\\ Y=\{y_1,y_2,\cdots,y_n\}

      xix_iyjy_j 间连 pijp_{ij} 条边,得二部图 G=(X,Y)G=(X,Y)

      求最少排多少节课的问题,每节课可以有多个教学班同时上课,转化为如何在 GG 中将边集 EE 划分为互不相交的 pp 个匹配,且使得 pp 最小

      如果每个匹配中的边用同一种颜色着色,不同匹配中的边不同颜色,则问题转化为在 GG 中给每条边着色,相邻边着不同色,至少需要的颜色数

      # 比赛安排问题

      玩家为顶点,2 个玩家间进行一次比赛为一条边,求最少安排多少场比赛,每场比赛可以有多对玩家同时比赛。

      基于圈的边着色问题和顶点着色问题是完全等价的,因为边和点可互换。

      # 顶点着色

      对图 GG 的每个顶点着色,使得相邻顶点着不同颜色,称为对 GG正常顶点着色

      如果用 kk 种颜色可以对 GG 进行正常点着色,称 GGkk 可着色的

      着同一种颜色的顶点集合称为一个色组,它们彼此互不相邻,所有又称为点独立集

      GG 正常顶点着色需要的最少颜色数,称为图 GG点色数,简称色数,记为:

      χ(G)\chi(G)

      色数为 kk 的图称为 kk 色数图

      # 色数上界

      对任意的无环图 GG,均有:

      χ(G)Δ+1\chi(G)\leq\Delta+1

      任意一个顶点度数至多为 Δ\Delta, 因此,正常着色过程中,其邻点最多用去 Δ\Delta 种颜色,所以,至少还有一种色可供该点正常着色使用。


      证明 :我们对顶点数作数学归纳证明。

      n=1n=1 时,结论显然成立。

      设对顶点数少于 nn 的图来说,定理结论成立。考虑一般的 nn 阶图 GG,任取 vV(G)v\in V(G),令 G1=GvG_1=G-v, 由归纳假设:

      χ(G1)Δ(G1)+1Δ(G)+1\chi(G_1)\leq\Delta(G_1)+1\leq\Delta(G)+1

      π\piG1G_1 的一种 Δ(G1)+1\Delta(G_1)+1 正常点着色方案,因为 vv 的邻点在 π\pi 下至多用去 Δ(G)\Delta(G) 种色,所以给 vv 染上其邻点没有用过的色,就把 π\pi 扩充成了 GGΔ(G1)+1\Delta(G_1)+1 着色方案。

      # 最大色数的正常着色算法

      G=(V,E)G=(V,E)V={v1,v2,,vn}V=\{v_1,v_2,\cdots,v_n\},色集合 C={1,2,,Δ+1}C=\{1,2,\cdots,\Delta+1\},着色方案为 π\pi.

      • (1) 令 π(v1)=1\pi(v_1)=1
      • (2) for i in 1..n 循环 n1n-1 次:(若 i=ni=n,则停止)
        • 令:C(vi+1)={π(vj)ji,vjadjvi+1}C(v_{i+1})=\{\pi(v_j)|j≤i,\ v_j\ \text{adj}\ v_{i+1}\}
        • kkCC(vi+1)C-C(v_{i+1}) 中的最小整数;
        • π(vi+1)=k\pi(v_{i+1})=k

      Welsh-Powell 稍微对上面算法做了一个修改,着色时按所谓最大度优先策略,即使用上面算法时,V={v1,v2,,vn}V=\{v_1,v_2,\cdots,v_n\} 按顶点度数由大到小的次序着色。这样的着色方案起到了对上面算法的一个改进作用,有机会得到色数更小的结果。

      # 布鲁克斯定理

      给出了一些图的更小的上界

      GG 是连通的单图,并且它既不是奇圈,又不是完全图,则:

      χ(G)Δ(G)\chi(G)\leq\Delta(G)

      # 次大度

      GG 是至少有一条边的简单图,定义:

      Δ2(G)=maxuV(G)maxvN(u)d(v)d(u)d(v)\Delta_2(G)=\max_{u\in V(G)}\max_{\begin{aligned} v\in N(u)\\ d(v)\leq d(u) \end{aligned}} d(v)

      其中 N(u)N(u)GG 中点 uu 的邻域。称 Δ2(G)\Delta_2(G)GG 的次大度

      布鲁斯克定理的改进

      χ(G)Δ2(G)+1\chi(G)\leq\Delta_2(G)+1

      GG 是非空简单图,若 GG 中最大度点互不邻接,则有:

      χ(G)Δ(G)\chi(G)\leq\Delta(G)

      # 四色和五色定理

      # 四色定理

      # 五色定理

      希伍德。

      对任意简单图,都有:

      χ5\chi\leq5

      该定理说明每个平面图是 5 可着色的。根据平面图和其对偶图的关系,该定理等价于每个平面图是 5 可顶点正常着色的。

      \ No newline at end of file +着色问题 - 图论 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 边着色问题

      图的边着色,本质上是对应实际问题中的 “划分” 问题或 “分类” 问题。

      GG 的边进行着色,若相邻边着不同颜色,则称对 GG 进行正常边着色

      在对 GG 正常边着色时,着相同颜色的边集称为该正常边着色的一个色组

      如果能用 kk 种颜色对图 GG 进行正常边着色,称 GGkk 边可着色的

      GG 进行正常边着色需要的最少颜色数称为 GG边色数,记为:

      χ(G)\chi'(G)

      着色需要满足相邻边着不同色,所以很自然地有:(对于无环图)

      χ(G)Δ\chi'(G)\geq\Delta

      也就是边色数以最大顶点度为下限

      # 二部图

      χ(Km,n)=Δ\chi'(K_{m,n})=\Delta


      证明

      假设:

      • n>mn\gt m
        • 所以 Δ=n\Delta=n
      • X={x0,x1,,xm1}X=\{x_0,x_1,\cdots,x_{m-1}\}
      • Y={y0,y1,,yn1}Y=\{y_0,y_1,\cdots,y_{n-1}\}
      • nn 个颜色集合为:{0,1,2,,n1}\{0,1,2,\cdots,n-1\}

      π\piKm,nK_{m,n} 的一个 nn 着色方案,满足:

      xiyjE(Km,n),π(xiyj)=(i+j)(modn)\forall x_i y_j\in E(K_{m,n}),\ \ \pi(x_iy_j)=(i+j)(\bmod n)

      Km,nK_{m,n} 中任意两条邻接边 xiyjx_iy_jxiykx_iy_k ,若二者在 π\pi 中着色相同,即 π(xiyj)=π(xiyk)\pi(x_iy_j)=\pi(x_iy_k) ,则有:

      (i+j)(modn)=(i+k)(modn)j=k(i+j)(\bmod n)=(i+k)(\bmod n)\\ \Downarrow\\ j=k

      于是 xiyj=xiykx_iy_j=x_iy_k ,所以 π\pi 是一个正常的 nn 着色(满足相邻边着不同色)。也即 (X,Y)(X,Y)nn 可着色的。

      同时 χ(Km,n)Δ=n\chi'(K_{m,n})\geq\Delta=n ,所以 χ(Km,n)=n\chi'(K_{m,n})=n

      # 偶图 (哥尼定理)

      偶图 GG 的边色数:

      χ(G)=Δ\chi'(G)=\Delta


      证明可利用数学归纳法

      m=1m=1 时,Δ=1\Delta=1,有 χ(G)=Δ=1\chi'(G)=\Delta=1 成立。

      设对于小于 mm 条边的偶图来说命题成立。

      GG 是具有 mm 条边的偶图。

      uvGuv\in G , 考虑 G1=GuvG_1=G-uv, 由归纳假设有:

      χ(G1)=Δ(G1)Δ(G)\chi'(G_1)=\Delta(G_1)\leq\Delta(G)

      这说明, GG 存在一种 Δ(G)\Delta(G) 边着色方案 π\pi . 对于该着色方案,因为 uvuv 未着色,所以点 uuvv 均至少缺少一种色。


      情形 1:如果 uuvv 均缺同一种色 ii

      则在 G1+uvG_1+uv 中给 uvuv 着色 ii , 而 GG 其它边按 π\pi 方案着色。这样得到 GGΔ\Delta 着色方案,所以: χ(G)=Δ\chi'(G)=\Delta


      情形 2:如果 uu 缺色 ii , 而 vv 缺色 jj , 但不缺色 ii

      H(i,j)H(i,j) 表示 GG 中由 ii 色边与 jj 色边导出的子图。显然,该图每个分支是 ii 色边和 jj 色边交替出现的路或圈。
      对于 H(i,j)H(i,j) 中含点 vv 的分支来说,因 vv 缺色 jj , 但不缺色 ii , 所以,在 H(i,j)H(i,j) 中,点 vv 的度数为 1。这说明,H(i,j)H(i,j) 中含 vv 的分支是一条路 PP . 进一步地,我们可以说明,上面的路 PP 不含点 uu . 因为,如果 PP 含有点 uu , 那么 PP 必然是一条长度为偶数的路,这样,P+uvP+uvGG 中的奇圈,这与 GG 是偶图矛盾!

      既然 PP 不含点 uu , 所以我们可以交换 PP 中着色,而不破坏 G1G_1 的正常边着色。但交换着色后,vv 就变成缺色 jj , 但不缺色 iiuuvv 均缺色 ii , 于是由情形 1, 可以得到 GGΔ\Delta 正常边着色,即证明 χ(G)=Δ\chi'(G)=\Delta

      # 一般简单图

      # 引理

      GG 是简单图,xxyyGG 中两个不相邻的顶点,π\piGG 的一个正常 kk 边着色。若对该着色,x,yx,y 以及与 xx 相邻的点均至少缺少一种颜色,则 G+xyG+xy 也是 kk 边可着色的

      # 维津定理 (Vizing)

      若图 GG 是简单图,则 χ(G)=Δ\chi'(G)=\Deltaχ(G)=Δ+1\chi'(G)=\Delta+1


      只需要证明 χ(G)Δ+1\chi'(G)≤\Delta+1 即可。 对 GG 的边数 mm 作数学归纳证明。

      m=1m=1 时,Δ=1\Delta=1, χ(G)=1<Δ+1\chi'(G)=1<Δ+1

      设当边数少于 mm 时,结论成立。下面考虑边数为 m2m≥2 的单图 GG

      xyE(G)xy\in E(G) , 令 G1=GxyG_1=G-xy. 由归纳假设有:

      χ(G1)Δ(G1)+1Δ(G)+1\chi'(G_1)≤\Delta(G_1)+1≤\Delta(G)+1

      于是,存在 G1G_1Δ(G)+1\Delta(G)+1 正常边作色 π\pi。显然 GG 的每个顶点都至少缺少一种颜色。根据引理知 G+xyG+xyΔ(G)+1\Delta(G) +1 可着色的。即证明: χ(G)Δ(G)+1\chi'(G) ≤ \Delta(G)+1

      # 充分条件 1

      给出了 Vizing 定理结论中 χ(G)=Δ\chi'(G)=\Delta 情况的充分条件

      GG 是单图且 Δ(G)>0\Delta(G)>0。若 GG 中只有一个最大度点或恰有两个相邻的最大度点,则:

      χ(G)=Δ(G)\chi'(G)=\Delta(G)

      # 充分条件 2

      给出了 Vizing 定理结论中 χ(G)=Δ+1\chi'(G)=\Delta+1 情况的充分条件

      GG 是单图。若点数 n=2k+1n=2k+1 且边数 m>kΔm>k\Delta,则:

      χ(G)=Δ(G)+1\chi'(G)=\Delta(G)+1


      证明可利用反证法,若不然,由维津定理,χ(G)=Δ(G)\chi'(G)=\Delta(G)

      π\piGGΔ(G)\Delta(G) 正常边着色方案,对于 GG 的每个色组来说,包含的边数至多 n12=k\frac{n-1}{2}=k。这样:m(G)Δkm(G)≤\Delta k,与条件矛盾。

      # 充分条件 3

      给出了 Vizing 定理结论中 χ(G)=Δ+1\chi'(G)=\Delta+1 情况的充分条件

      GG 是奇数阶 Δ\Delta 正则单图,若 Δ>0\Delta>0,则:

      χ(G)=Δ(G)+1\chi'(G)=\Delta(G)+1


      证明:

      n=2k+1n=2k+1,因 GGΔ\Delta 正则单图,且 Δ>0\Delta>0,所以:

      m(G)=nΔ2=(2k+1)Δ2>kΔm(G)=\frac{n\Delta}{2}=\frac{(2k+1)\Delta}{2}\gt k\Delta

      由定理 χ(G)=Δ(G)+1\chi'(G)=\Delta(G)+1

      # 无环有重边图

      维津定理 (Vizing)

      设无环图 GG 中边的最大重数为 μ\mu​,则:

      χ(G)Δ(G)+μ\chi'(G)\leq\Delta(G)+\mu

      其中 \leq 边界是紧的,也就是等号是可以相等的。

      # 边着色的应用

      # 排课表问题

      X,YX,Y 分别表示教师、教学班的集合:

      X={x1,x2,,xm}Y={y1,y2,,yn}X=\{x_1,x_2,\cdots,x_m\}\\ Y=\{y_1,y_2,\cdots,y_n\}

      xix_iyjy_j 间连 pijp_{ij} 条边,得二部图 G=(X,Y)G=(X,Y)

      求最少排多少节课的问题,每节课可以有多个教学班同时上课,转化为如何在 GG 中将边集 EE 划分为互不相交的 pp 个匹配,且使得 pp 最小

      如果每个匹配中的边用同一种颜色着色,不同匹配中的边不同颜色,则问题转化为在 GG 中给每条边着色,相邻边着不同色,至少需要的颜色数

      # 比赛安排问题

      玩家为顶点,2 个玩家间进行一次比赛为一条边,求最少安排多少场比赛,每场比赛可以有多对玩家同时比赛。

      基于圈的边着色问题和顶点着色问题是完全等价的,因为边和点可互换。

      # 顶点着色

      对图 GG 的每个顶点着色,使得相邻顶点着不同颜色,称为对 GG正常顶点着色

      如果用 kk 种颜色可以对 GG 进行正常点着色,称 GGkk 可着色的

      着同一种颜色的顶点集合称为一个色组,它们彼此互不相邻,所有又称为点独立集

      GG 正常顶点着色需要的最少颜色数,称为图 GG点色数,简称色数,记为:

      χ(G)\chi(G)

      色数为 kk 的图称为 kk 色数图

      # 色数上界

      对任意的无环图 GG,均有:

      χ(G)Δ+1\chi(G)\leq\Delta+1

      任意一个顶点度数至多为 Δ\Delta, 因此,正常着色过程中,其邻点最多用去 Δ\Delta 种颜色,所以,至少还有一种色可供该点正常着色使用。


      证明 :我们对顶点数作数学归纳证明。

      n=1n=1 时,结论显然成立。

      设对顶点数少于 nn 的图来说,定理结论成立。考虑一般的 nn 阶图 GG,任取 vV(G)v\in V(G),令 G1=GvG_1=G-v, 由归纳假设:

      χ(G1)Δ(G1)+1Δ(G)+1\chi(G_1)\leq\Delta(G_1)+1\leq\Delta(G)+1

      π\piG1G_1 的一种 Δ(G1)+1\Delta(G_1)+1 正常点着色方案,因为 vv 的邻点在 π\pi 下至多用去 Δ(G)\Delta(G) 种色,所以给 vv 染上其邻点没有用过的色,就把 π\pi 扩充成了 GGΔ(G1)+1\Delta(G_1)+1 着色方案。

      # 最大色数的正常着色算法

      G=(V,E)G=(V,E)V={v1,v2,,vn}V=\{v_1,v_2,\cdots,v_n\},色集合 C={1,2,,Δ+1}C=\{1,2,\cdots,\Delta+1\},着色方案为 π\pi.

      • (1) 令 π(v1)=1\pi(v_1)=1
      • (2) for i in 1..n 循环 n1n-1 次:(若 i=ni=n,则停止)
        • 令:C(vi+1)={π(vj)ji,vjadjvi+1}C(v_{i+1})=\{\pi(v_j)|j≤i,\ v_j\ \text{adj}\ v_{i+1}\}
        • kkCC(vi+1)C-C(v_{i+1}) 中的最小整数;
        • π(vi+1)=k\pi(v_{i+1})=k

      Welsh-Powell 稍微对上面算法做了一个修改,着色时按所谓最大度优先策略,即使用上面算法时,V={v1,v2,,vn}V=\{v_1,v_2,\cdots,v_n\} 按顶点度数由大到小的次序着色。这样的着色方案起到了对上面算法的一个改进作用,有机会得到色数更小的结果。

      # 布鲁克斯定理

      给出了一些图的更小的上界

      GG 是连通的单图,并且它既不是奇圈,又不是完全图,则:

      χ(G)Δ(G)\chi(G)\leq\Delta(G)

      # 次大度

      GG 是至少有一条边的简单图,定义:

      Δ2(G)=maxuV(G)maxvN(u)d(v)d(u)d(v)\Delta_2(G)=\max_{u\in V(G)}\max_{\begin{aligned} v\in N(u)\\ d(v)\leq d(u) \end{aligned}} d(v)

      其中 N(u)N(u)GG 中点 uu 的邻域。称 Δ2(G)\Delta_2(G)GG 的次大度

      布鲁斯克定理的改进

      χ(G)Δ2(G)+1\chi(G)\leq\Delta_2(G)+1

      GG 是非空简单图,若 GG 中最大度点互不邻接,则有:

      χ(G)Δ(G)\chi(G)\leq\Delta(G)

      # 四色和五色定理

      # 四色定理

      # 五色定理

      希伍德。

      对任意简单图,都有:

      χ5\chi\leq5

      该定理说明每个平面图是 5 可着色的。根据平面图和其对偶图的关系,该定理等价于每个平面图是 5 可顶点正常着色的。

      \ No newline at end of file diff --git a/math/discrete-math/graph/connectivity/index.html b/math/discrete-math/graph/connectivity/index.html index 944d911e..ecd482b5 100644 --- a/math/discrete-math/graph/connectivity/index.html +++ b/math/discrete-math/graph/connectivity/index.html @@ -1 +1 @@ -图的连通性 - 图论 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 割边

      # 严格定义

      如果 ω(Ge)>ω(G)\omega(G-e)\gt\omega(G) ,则 eeGG 的一条割边

      # 充要条件

      eeGG 的割边当且仅当 ee 不在 GG 的任何圈中。


      必要性:

      假设 eeGG 的割边且 eeGG 的某圈中


      充分性:

      假设 ee 不在 GG 的任何圈中且 ee 不是 GG 的割边,则 GeG-e 连通。

      于是 GeG-e 中存在一条 (u,v)(u,v)ll ,显然 lel\cup e 就是 GG 的一个圈,与 ee 不在 GG 的任何圈中矛盾!

      # 推论 1

      eeGG 的一条边,若 ee 包含于 GG 的某圈中,则 GeG-e 连通。


      证明:若 GeG-e 不连通,则 ee 就是割边,这就与割边的充要条件矛盾。

      # 推论 2

      GG 的每个顶点的度数均为偶数,则 GG 没有割边;


      若不然,设 e=ue=uGG 的割边。则 GeG-e 的含有顶点 uu (或vv) 的那个分支中点 uu (或vv) 的度数为奇数,而其余点的度数为偶数,与握手定理推论相矛盾!

      # 推论 3

      GGkk 正则二部图 (k2)(k≥2) ,则 GG 无割边。


      若不然,设 e=ue=uGG 的割边。取 GeG-e 的其中一个分支 G1G_1 ,显然 G1G_1 中只有一个顶点的度数是 k1k-1 ,其余点的度数为 kk 。并且 G1G_1 仍然为偶图
      假若 GG 的两个顶点子集包含的顶点数分别为 mmnn ,并且包含 mm 个顶点的顶点子集包含度为 k1k-1 的那个点,那么有 km1=knkm-1= kn 。但是因 k2k≥2 ,所以等式不能成立!矛盾!

      # 割边集

      边割集跟回路、树等概念一样,是图论中重要概念。在应用上,它是电路网络图论的基本概念之一。

      破坏连通性的极小边子集

      #

      一个具有 nn 个顶点的连通图 GG ,定义 n1n-1 为该连通图的秩;

      具有 pp 个分支的图的秩定义为 npn-p ,记为 R(G)R(G)

      # 边割 (集)

      SS 是连通图 GG 的一个边子集,如果:

      • R(GS)=n2R(G-S)=n-2
      • SS 的任一真子集 SS ,有 R(GS)=n1R(G-S)=n-1

      SSGG 的一个边割集,简称 GG 的一个边割

      # 关联集

      GG 中,与顶点 vv 关联的边的集合,称为 vv关联集,记为:

      S(v)S(v)

      # 断集

      GG 中,如果 V=V1V2,V1V2=V=V_1∪V_2,V_1\cap V_2=\varnothing , E1E_1GG 中端点分属于 V1V_1V2V_2GG 的边子集,称 E1E_1GG 的一个断集。

      # 断集与关联集的关系

      任意一个断集均是若干关联集的环和 (对称差)

      E1E2=(E1E2)(E2E1)E_1\oplus E_2=(E_1-E_2)\cup(E_2-E_1)

      # 断集空间

      连通图 GG 的断集的集合作成子图空间的一个子空间,其维数为 n1n-1 ,该空间称为图的断集空间。(其基为 n1n-1 个线性无关的关联集)

      K4K_4 为例:

      K4

      其断集空间的基为 3 个线性无关的关联集:

      K4的3个线性无关的关联集

      形成的断集空间为:

      {,S(1),S(2),S(3),{a,c,d,e},{a,b,e,f},{b,c,d,f},{b,d,e}}\{\varnothing,S(1), S(2), S(3),\{a, c, d, e\},\{a, b, e, f\},\{b, c, d, f\},\{b, d, e\}\}

      # 基本 (边) 割集

      GG 是连通图,TTGG 的一棵生成树。如果 GG 的一个割集 SS 恰好包含 TT 的一条树枝,称 SSGG 的对于 TT 的一个基本 (边) 割集

      连通图 GG 的断集均可表为 GG 的对应于某生成树 TT 的基本割集的环和 (对称差)

      连通图 GG 对应于某生成树 TT 的基本割集的个数为 n1n-1 ,它们作成断集空间的一组基。

      # 割点

      # 严格定义

      GG 中,如果 E(G)E(G) 可以划分为两个非空子集 E1E_1E2E_2,使 G[E1]G[E_1]G[E2]G[E_2] 以点 vv 为公共顶点,称 vvGG 的一个割点

      # 充要条件

      # 无环非平凡图

      无环且非平凡情形下,割点与割边的定义一致

      GG 无环且非平凡,则 vvGG 的割点,当且仅当 ω(Gv)>ω(G)\omega(G-v)\gt\omega(G)


      必要性

      vvGG 的割点。则 E(G)E(G) 可划分为两个非空边子集 E1E_1E2E_2 ,使 G(E1),G(E2)G(E_1) , G(E_2) 恰好以 vv 为公共点。由于 GG 没有环,所以 G(E1),G(E2)G(E_1) , G(E_2) 分别至少包含异于 vvGG 的点,这样,GvG-v 的分支数比 GG 的分支数至少多 1,所以:ω(Gv)>ω(G)\omega(G-v)>\omega(G)


      充分性

      #

      vv 是树 TT 的顶点,则 vv 是割点,当且仅当 vv 是树的分支点(即不是叶子)

      # 无环连通图

      vv 是无环连通图 GG 的一个顶点,则 vvGG 的割点,当且仅当 V(Gv)V(G-v) 可以划分为两个非空子集 V1V_1V2V_2 ,使得对任意 xV1,vV2x\in V_1, v\in V_2 , 点 vv 在每一条 xyxy 路上

      无环非平凡连通图至少有两个非割点。

      证明:由于 GG 是无环非平凡连通图,所以存在非平凡生成树,而非平凡生成树至少两片树叶,它不能为割点,所以,它也不能为 GG 的割点。

      恰有两个非割点的连通简单图是一条路。

      证明:设 TTGG 的一棵生成树。由于 GGn2n-2 个割点,所以,TTn2n-2 个割点,即 T 只有两片树叶,所以 TT 是一条路。这说明,GG 的任意生成树为路。

      一个单图的任意生成树为路,则该图为圈或路,若为圈,则 GG 没有割点,矛盾,所以,GG 为路。

      v 是单图 G 的割点,则它不是 G 的补图的割点。

      证明:vv 是单图 GG 的割点,则 GvG-v 至少两个连通分支。现任取 x,yV(Gv)x,y\in V(\overline{G}-v) , 如果 x,yx,yGvG-v 的同一分支中,令 uu 是与 x,yx,y 处于不同分支的点,那么,通过 uu ,可说明,xxyyGvG-v 的补图中连通。若 x,yx,yGvG-v 的不同分支中,则它们在 GvG-v 的补图中邻接。所以,若 vvGG 的割点,则 vv 不是其补图的割点。

      #

      # 块 (图) 定义

      没有割点的连通图称为是一个块图,简称块GG 的一个子图 𝐵𝐵 如果:

      • 它本身是块
      • 若没有真包含 𝐵𝐵GG 的块存在(极大性 )

      BBGG 的一个块

      V(G)3|V(G)|\geq3GG 是块,当且仅当 GG 无环且任意两顶点位于同一圈上。

      vv 是图 GG 的割点当且仅当 vv 至少属于 GG 的两个不同的块

      # 块割点树

      GG 是非平凡连通图。𝐵1,𝐵2,,𝐵k𝐵_1,𝐵_2,\cdots,𝐵_kGG 的全部块,而 v1,v2,,vtv_1,v_2,\cdots,v_tGG 的全部割点。构作 GG 的块割点树 bc(G)bc(G) : 它的顶点是 GG 的块和割点,连线只在块割点之间进行,一个块和一个割点连线,当且仅当该割点是该块的一个顶点。

      # 连通度

      # 点连通度

      GG 中:

      • GG 连通:

        • 若存在顶点割,称 GG 的最小顶点割的顶点数称为 GG 的点连通度;
        • 否则称 n-1 为其点连通度. G 的点连通度记为 κ(G)\kappa(G),简记为 κ\kappa
      • GG 不连通,κ(G)=0\kappa(G)=0

      # 边连通度

      GG 中,最小边割集所含边数称为 GG 的边连通度。边连通度记为 λ(G)\lambda(G)

      GG 不连通或 GG 是平凡图,则定义 λ(G)=0\lambda(G)=0

      # k - 连通

      • κ(G)k\kappa(G)\geq kGGk - 连通的。
      • λ(G)k\lambda(G)\geq kGGk - 边连通的。

      # 惠特尼连通度定理

      κ(G)λ(G)(G)\kappa(G)\leq\lambda(G)\leq(G)

      abc,G:κ(G)=a,λ(G)=b,(G)=c\forall a\leq b\leq c\ \ ,\ \ \exist G:\\ \kappa(G)=a,\ \ \lambda(G)=b,\ \ (G)=c

      κ(G)2mn\kappa(G)\leq\lfloor\frac{2m}{n}\rfloor

      GG(n,m)(n,m) 单图,若 δ(G)n2\delta(G)≥\lfloor\frac{n}{2}\rfloor ,则 GG 连通

      # k - 连通充分条件

      GGnn 阶简单图,若对任意正整数 knk<n ,有:

      δ(G)n+k22\delta(G)\geq\frac{n+k-2}{2}

      GGkk 连通的。

      # 哈拉里图

      # 坚韧性

      C(G)C(G) 表示图 GG 的全体点割集构成的集合,非平凡非完全图的坚韧度,记作 τ(G)\tau(G) ,定义为:

      τ(G)=min{Sω(GS)SC(G)}\tau(G)=\min\{ \frac{|S|}{\omega(G-S)}\big|S\in C(G) \}

      GG 是一个非完全 n(n3)n(n≥3) 阶连通图,SC(G)S\in C(G) ,若 SS^* 满足:

      τ(G)=Sω(GS)\tau(G)=\frac{|S^*|}{\omega(G-S^*)}

      SS^*GG坚韧集

      # 敏格尔定理

      # 分离集

      uuvv 是图 GG 的两个不同顶点,SS 表示 GG 的一个顶点子集或边子集,如果 uuvv 不在 GSG-S 的同一分支上,称 SS 分离 uuvvSSuuvv分离 (点 / 边) 集

      # Menger

      n - 弧定理

      xxyy 是图 GG 中的两个不相邻点,则GG 中分离点 xxyy 的:

      • 最少点数等于 GG 中独立(内点不交)的 (x,y)(x,y) 路的最大数目;
      • 最少边数等于 GG 中边不重的 (x,y)(x,y) 路的最大数目;

      # 惠特尼定理

      一个非平凡的图 GGkk 连通 k2k\geq2 的,当且仅当 GG 的任意两个顶点间至少存在 kk 条:(以下两种条件之一)

      • 独立(内点不交)的 (u,v)(u,v) 路;
      • 边不重的 (u,v)(u,v) 路;

      GGkk 连通图,SS 是由 GG 中任意 kk 个顶点构成的集合。若图 HH 是由 GG 通过添加一个新点 ww 以及连接 wwSS 中所有顶点得到的新图,求证:HHkk - 连通的。


      证明:

      首先, GGkk 连通图,所以分离 GG 中两个不相邻顶点至少要 kk 个点;

      其次,分离 wwGG 中不在 SS 中顶点需要 kk 个顶点;

      因此 HHkk 连通的。

      GGkk - 连通图,u,v1,v2,,vku,v_1,v_2,\cdots,v_kGGk+1k+1 个不同顶点。求证:GG 中有 kk 条内点不交路 (u,vi)(1ik)(u,v_i)\ (1≤i≤k)

      对于一个阶至少为 3 的无环图 GG ,下面三个命题等价。

      • (1) GG 是 2 - 连通的;
      • (2) GG 中任意两点位于同一个圈上;
      • (3) GG 无孤立点,且任意两条边在同一个圈上;

      # 图的宽直径

      所有距离(distance)中最大的就是直径(diameter),这里都记为 d(G)d(G)

      GG 是强连通有向图,若其阶 n3n\geq3 且最大度 Δ2\Delta\geq2 ,则:

      d(G){n2,Δ=2log(Δ1)n(Δ2)+2Δ,Δ3d(G)\geq\begin{cases} \lfloor\frac{n}{2}\rfloor, & \Delta=2\\ \lceil\log_{(\Delta-1)}\frac{n(\Delta-2)+2}{\Delta}\rceil, & \Delta\geq3\\ \end{cases}

      # 路族 / 容器

      x,yV(G)x,y\in V(G) , Cw(x,y)C_w(x,y) 表示 GGww 条内点不交路的路族,ww 称为路族的宽度,Cw(x,y)C_w(x,y) 中最长路的路长成为该路族的长度,记为:l(Cw(x,y))l (C_w(x,y))

      # w 宽距离和最优路族

      x,yV(G)x,y\in V(G) , 定义 xxyy 间所有宽度为 ww 的路族长度的最小值 dw(x,y)d_w(x,y)xxyyww 宽距离,xxyy 间长度等于 ww 宽距离的路族称为 xxyy 间最优路族。

      所以,求 ww 宽距离,就是要找到最优路族。

      # 宽直径

      GGww 连通的,GG 的所有点对间的 ww 宽距离的最大值,称为 GGww 宽直径,记为 dw(G)d_w(G )

      例如:⭐️

      • nn 点圈 CnC_n:(连通度 = 2)
        • d1(Cn)=n2d_1(C_n)=\lfloor\frac{n}{2}\rfloor
        • d2(Cn)=n1d_2(C_n)=n-1
      • kk 阶完全图 KnK_n:(连通度 = n1n-1
        • d1(Kn)=1d_1(K_n)=1
        • dw(Kn)=2d_w(K_n)=2;(2wn12\leq w\leq n-1

      容错直径(了解)

      \ No newline at end of file +图的连通性 - 图论 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 割边

      # 严格定义

      如果 ω(Ge)>ω(G)\omega(G-e)\gt\omega(G) ,则 eeGG 的一条割边

      # 充要条件

      eeGG 的割边当且仅当 ee 不在 GG 的任何圈中。


      必要性:

      假设 eeGG 的割边且 eeGG 的某圈中


      充分性:

      假设 ee 不在 GG 的任何圈中且 ee 不是 GG 的割边,则 GeG-e 连通。

      于是 GeG-e 中存在一条 (u,v)(u,v)ll ,显然 lel\cup e 就是 GG 的一个圈,与 ee 不在 GG 的任何圈中矛盾!

      # 推论 1

      eeGG 的一条边,若 ee 包含于 GG 的某圈中,则 GeG-e 连通。


      证明:若 GeG-e 不连通,则 ee 就是割边,这就与割边的充要条件矛盾。

      # 推论 2

      GG 的每个顶点的度数均为偶数,则 GG 没有割边;


      若不然,设 e=ue=uGG 的割边。则 GeG-e 的含有顶点 uu (或vv) 的那个分支中点 uu (或vv) 的度数为奇数,而其余点的度数为偶数,与握手定理推论相矛盾!

      # 推论 3

      GGkk 正则二部图 (k2)(k≥2) ,则 GG 无割边。


      若不然,设 e=ue=uGG 的割边。取 GeG-e 的其中一个分支 G1G_1 ,显然 G1G_1 中只有一个顶点的度数是 k1k-1 ,其余点的度数为 kk 。并且 G1G_1 仍然为偶图
      假若 GG 的两个顶点子集包含的顶点数分别为 mmnn ,并且包含 mm 个顶点的顶点子集包含度为 k1k-1 的那个点,那么有 km1=knkm-1= kn 。但是因 k2k≥2 ,所以等式不能成立!矛盾!

      # 割边集

      边割集跟回路、树等概念一样,是图论中重要概念。在应用上,它是电路网络图论的基本概念之一。

      破坏连通性的极小边子集

      #

      一个具有 nn 个顶点的连通图 GG ,定义 n1n-1 为该连通图的秩;

      具有 pp 个分支的图的秩定义为 npn-p ,记为 R(G)R(G)

      # 边割 (集)

      SS 是连通图 GG 的一个边子集,如果:

      • R(GS)=n2R(G-S)=n-2
      • SS 的任一真子集 SS ,有 R(GS)=n1R(G-S)=n-1

      SSGG 的一个边割集,简称 GG 的一个边割

      # 关联集

      GG 中,与顶点 vv 关联的边的集合,称为 vv关联集,记为:

      S(v)S(v)

      # 断集

      GG 中,如果 V=V1V2,V1V2=V=V_1∪V_2,V_1\cap V_2=\varnothing , E1E_1GG 中端点分属于 V1V_1V2V_2GG 的边子集,称 E1E_1GG 的一个断集。

      # 断集与关联集的关系

      任意一个断集均是若干关联集的环和 (对称差)

      E1E2=(E1E2)(E2E1)E_1\oplus E_2=(E_1-E_2)\cup(E_2-E_1)

      # 断集空间

      连通图 GG 的断集的集合作成子图空间的一个子空间,其维数为 n1n-1 ,该空间称为图的断集空间。(其基为 n1n-1 个线性无关的关联集)

      K4K_4 为例:

      K4

      其断集空间的基为 3 个线性无关的关联集:

      K4的3个线性无关的关联集

      形成的断集空间为:

      {,S(1),S(2),S(3),{a,c,d,e},{a,b,e,f},{b,c,d,f},{b,d,e}}\{\varnothing,S(1), S(2), S(3),\{a, c, d, e\},\{a, b, e, f\},\{b, c, d, f\},\{b, d, e\}\}

      # 基本 (边) 割集

      GG 是连通图,TTGG 的一棵生成树。如果 GG 的一个割集 SS 恰好包含 TT 的一条树枝,称 SSGG 的对于 TT 的一个基本 (边) 割集

      连通图 GG 的断集均可表为 GG 的对应于某生成树 TT 的基本割集的环和 (对称差)

      连通图 GG 对应于某生成树 TT 的基本割集的个数为 n1n-1 ,它们作成断集空间的一组基。

      # 割点

      # 严格定义

      GG 中,如果 E(G)E(G) 可以划分为两个非空子集 E1E_1E2E_2,使 G[E1]G[E_1]G[E2]G[E_2] 以点 vv 为公共顶点,称 vvGG 的一个割点

      # 充要条件

      # 无环非平凡图

      无环且非平凡情形下,割点与割边的定义一致

      GG 无环且非平凡,则 vvGG 的割点,当且仅当 ω(Gv)>ω(G)\omega(G-v)\gt\omega(G)


      必要性

      vvGG 的割点。则 E(G)E(G) 可划分为两个非空边子集 E1E_1E2E_2 ,使 G(E1),G(E2)G(E_1) , G(E_2) 恰好以 vv 为公共点。由于 GG 没有环,所以 G(E1),G(E2)G(E_1) , G(E_2) 分别至少包含异于 vvGG 的点,这样,GvG-v 的分支数比 GG 的分支数至少多 1,所以:ω(Gv)>ω(G)\omega(G-v)>\omega(G)


      充分性

      #

      vv 是树 TT 的顶点,则 vv 是割点,当且仅当 vv 是树的分支点(即不是叶子)

      # 无环连通图

      vv 是无环连通图 GG 的一个顶点,则 vvGG 的割点,当且仅当 V(Gv)V(G-v) 可以划分为两个非空子集 V1V_1V2V_2 ,使得对任意 xV1,vV2x\in V_1, v\in V_2 , 点 vv 在每一条 xyxy 路上

      无环非平凡连通图至少有两个非割点。

      证明:由于 GG 是无环非平凡连通图,所以存在非平凡生成树,而非平凡生成树至少两片树叶,它不能为割点,所以,它也不能为 GG 的割点。

      恰有两个非割点的连通简单图是一条路。

      证明:设 TTGG 的一棵生成树。由于 GGn2n-2 个割点,所以,TTn2n-2 个割点,即 T 只有两片树叶,所以 TT 是一条路。这说明,GG 的任意生成树为路。

      一个单图的任意生成树为路,则该图为圈或路,若为圈,则 GG 没有割点,矛盾,所以,GG 为路。

      v 是单图 G 的割点,则它不是 G 的补图的割点。

      证明:vv 是单图 GG 的割点,则 GvG-v 至少两个连通分支。现任取 x,yV(Gv)x,y\in V(\overline{G}-v) , 如果 x,yx,yGvG-v 的同一分支中,令 uu 是与 x,yx,y 处于不同分支的点,那么,通过 uu ,可说明,xxyyGvG-v 的补图中连通。若 x,yx,yGvG-v 的不同分支中,则它们在 GvG-v 的补图中邻接。所以,若 vvGG 的割点,则 vv 不是其补图的割点。

      #

      # 块 (图) 定义

      没有割点的连通图称为是一个块图,简称块GG 的一个子图 𝐵𝐵 如果:

      • 它本身是块
      • 若没有真包含 𝐵𝐵GG 的块存在(极大性 )

      BBGG 的一个块

      V(G)3|V(G)|\geq3GG 是块,当且仅当 GG 无环且任意两顶点位于同一圈上。

      vv 是图 GG 的割点当且仅当 vv 至少属于 GG 的两个不同的块

      # 块割点树

      GG 是非平凡连通图。𝐵1,𝐵2,,𝐵k𝐵_1,𝐵_2,\cdots,𝐵_kGG 的全部块,而 v1,v2,,vtv_1,v_2,\cdots,v_tGG 的全部割点。构作 GG 的块割点树 bc(G)bc(G) : 它的顶点是 GG 的块和割点,连线只在块割点之间进行,一个块和一个割点连线,当且仅当该割点是该块的一个顶点。

      # 连通度

      # 点连通度

      GG 中:

      • GG 连通:

        • 若存在顶点割,称 GG 的最小顶点割的顶点数称为 GG 的点连通度;
        • 否则称 n-1 为其点连通度. G 的点连通度记为 κ(G)\kappa(G),简记为 κ\kappa
      • GG 不连通,κ(G)=0\kappa(G)=0

      # 边连通度

      GG 中,最小边割集所含边数称为 GG 的边连通度。边连通度记为 λ(G)\lambda(G)

      GG 不连通或 GG 是平凡图,则定义 λ(G)=0\lambda(G)=0

      # k - 连通

      • κ(G)k\kappa(G)\geq kGGk - 连通的。
      • λ(G)k\lambda(G)\geq kGGk - 边连通的。

      # 惠特尼连通度定理

      κ(G)λ(G)(G)\kappa(G)\leq\lambda(G)\leq(G)

      abc,G:κ(G)=a,λ(G)=b,(G)=c\forall a\leq b\leq c\ \ ,\ \ \exist G:\\ \kappa(G)=a,\ \ \lambda(G)=b,\ \ (G)=c

      κ(G)2mn\kappa(G)\leq\lfloor\frac{2m}{n}\rfloor

      GG(n,m)(n,m) 单图,若 δ(G)n2\delta(G)≥\lfloor\frac{n}{2}\rfloor ,则 GG 连通

      # k - 连通充分条件

      GGnn 阶简单图,若对任意正整数 knk<n ,有:

      δ(G)n+k22\delta(G)\geq\frac{n+k-2}{2}

      GGkk 连通的。

      # 哈拉里图

      # 坚韧性

      C(G)C(G) 表示图 GG 的全体点割集构成的集合,非平凡非完全图的坚韧度,记作 τ(G)\tau(G) ,定义为:

      τ(G)=min{Sω(GS)SC(G)}\tau(G)=\min\{ \frac{|S|}{\omega(G-S)}\big|S\in C(G) \}

      GG 是一个非完全 n(n3)n(n≥3) 阶连通图,SC(G)S\in C(G) ,若 SS^* 满足:

      τ(G)=Sω(GS)\tau(G)=\frac{|S^*|}{\omega(G-S^*)}

      SS^*GG坚韧集

      # 敏格尔定理

      # 分离集

      uuvv 是图 GG 的两个不同顶点,SS 表示 GG 的一个顶点子集或边子集,如果 uuvv 不在 GSG-S 的同一分支上,称 SS 分离 uuvvSSuuvv分离 (点 / 边) 集

      # Menger

      n - 弧定理

      xxyy 是图 GG 中的两个不相邻点,则GG 中分离点 xxyy 的:

      • 最少点数等于 GG 中独立(内点不交)的 (x,y)(x,y) 路的最大数目;
      • 最少边数等于 GG 中边不重的 (x,y)(x,y) 路的最大数目;

      # 惠特尼定理

      一个非平凡的图 GGkk 连通 k2k\geq2 的,当且仅当 GG 的任意两个顶点间至少存在 kk 条:(以下两种条件之一)

      • 独立(内点不交)的 (u,v)(u,v) 路;
      • 边不重的 (u,v)(u,v) 路;

      GGkk 连通图,SS 是由 GG 中任意 kk 个顶点构成的集合。若图 HH 是由 GG 通过添加一个新点 ww 以及连接 wwSS 中所有顶点得到的新图,求证:HHkk - 连通的。


      证明:

      首先, GGkk 连通图,所以分离 GG 中两个不相邻顶点至少要 kk 个点;

      其次,分离 wwGG 中不在 SS 中顶点需要 kk 个顶点;

      因此 HHkk 连通的。

      GGkk - 连通图,u,v1,v2,,vku,v_1,v_2,\cdots,v_kGGk+1k+1 个不同顶点。求证:GG 中有 kk 条内点不交路 (u,vi)(1ik)(u,v_i)\ (1≤i≤k)

      对于一个阶至少为 3 的无环图 GG ,下面三个命题等价。

      • (1) GG 是 2 - 连通的;
      • (2) GG 中任意两点位于同一个圈上;
      • (3) GG 无孤立点,且任意两条边在同一个圈上;

      # 图的宽直径

      所有距离(distance)中最大的就是直径(diameter),这里都记为 d(G)d(G)

      GG 是强连通有向图,若其阶 n3n\geq3 且最大度 Δ2\Delta\geq2 ,则:

      d(G){n2,Δ=2log(Δ1)n(Δ2)+2Δ,Δ3d(G)\geq\begin{cases} \lfloor\frac{n}{2}\rfloor, & \Delta=2\\ \lceil\log_{(\Delta-1)}\frac{n(\Delta-2)+2}{\Delta}\rceil, & \Delta\geq3\\ \end{cases}

      # 路族 / 容器

      x,yV(G)x,y\in V(G) , Cw(x,y)C_w(x,y) 表示 GGww 条内点不交路的路族,ww 称为路族的宽度,Cw(x,y)C_w(x,y) 中最长路的路长成为该路族的长度,记为:l(Cw(x,y))l (C_w(x,y))

      # w 宽距离和最优路族

      x,yV(G)x,y\in V(G) , 定义 xxyy 间所有宽度为 ww 的路族长度的最小值 dw(x,y)d_w(x,y)xxyyww 宽距离,xxyy 间长度等于 ww 宽距离的路族称为 xxyy 间最优路族。

      所以,求 ww 宽距离,就是要找到最优路族。

      # 宽直径

      GGww 连通的,GG 的所有点对间的 ww 宽距离的最大值,称为 GGww 宽直径,记为 dw(G)d_w(G )

      例如:⭐️

      • nn 点圈 CnC_n:(连通度 = 2)
        • d1(Cn)=n2d_1(C_n)=\lfloor\frac{n}{2}\rfloor
        • d2(Cn)=n1d_2(C_n)=n-1
      • kk 阶完全图 KnK_n:(连通度 = n1n-1
        • d1(Kn)=1d_1(K_n)=1
        • dw(Kn)=2d_w(K_n)=2;(2wn12\leq w\leq n-1

      容错直径(了解)

      \ No newline at end of file diff --git a/math/discrete-math/graph/euler_hamilton/index.html b/math/discrete-math/graph/euler_hamilton/index.html index a17a40b2..96c640bd 100644 --- a/math/discrete-math/graph/euler_hamilton/index.html +++ b/math/discrete-math/graph/euler_hamilton/index.html @@ -1 +1 @@ -欧拉图与哈密顿图 - 图论 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 欧拉图

      # 定义

      欧拉图存在欧拉闭迹,半欧拉图只存在欧拉迹

      若能遍历完所有的边但是没法回到起始点,称为非欧拉图但是有欧拉迹

      # 欧拉图

      假定 GG 是一个连通图,且是欧拉图,则下列命题等价:

      • GG 是欧拉图
      • GG 的每个点的度数是偶数
      • GG 的边集能划分为边不重的圈的并
      • GG 存在欧拉闭迹)

      # 半欧拉图

      假定 GG 是一个连通图,且是半欧拉图,则下列命题等价:

      • GG 是半欧拉图
      • GG 有且仅有 2 个点的度数是奇数
      • GG 存在欧拉迹)

      # 小结论💡

      • nn 满足什么条件时,完全图 KnK_n 是欧拉图? nn 为奇数
      • nn 满足什么条件时,nn 方体 QnQ_n 是欧拉图? nn 为偶数
      • 若完全二部图 Ka,bK_{a,b} 为欧拉图,aabb 需满足什么条件? a,ba,b 均为偶数
      • 假设图 GG 恰好有两个连通分支,并且每个连通分支都是欧拉图,若要将 GG 变为欧拉图,最少需要添加几条边? 最少需要添加 2 条边
      • 欧拉图、半欧拉图是否存在割边? 欧拉图不存在割边,半欧拉图存在割边

      # Fleury 算法

      弗勒里算法解决了在欧拉图中求出一条具体欧拉环游的方法,核心思想是尽可能避割边行走

      # 算法流程

      • (1)任意选取一个顶点 v0v_0 ,置 w0=v0w_0=v_0
      • (2)假设迹 wi=v0e1v1eiviw_i=v_0e_1v_1\cdots e_iv_i 已经确定,按如下方法从 E{e1,e2,,ei}E-\{e_1,e_2,\cdots,e_{i}\} 选一个 ei+1e_{i+1}
        • ei+1e_{i+1}viv_i 相关联;
        • 除非没有其他边可选,否则 ei+1e_{i+1} 不能是 Gi=G{e1,e2,,ei}G_i=G-\{e_1,e_2,\cdots,e_{i}\}割边
      • (3)若(2)无法进行则算法停止

      利用 Fluery 算法可以求一个半欧拉图的欧拉迹,半欧拉图有且仅有 2 个奇度顶点 u,vu,v ,在这 2 个点之间增加一条边 mm ,就可以得到一个欧拉图,然后从其中一个奇度顶点,例如 uu ,开始求欧拉环游。得到的欧拉环游去掉 mm 就是从 uuvv 的欧拉迹。

      # 欧拉图中扩展欧拉环游充要条件

      GG 是非平凡的欧拉图,且 vV(G)v\in V(G) ,则 GG 的每条具有起点 vv 的迹都能扩展成 GG 的欧拉环游当且仅当 GvG-v 是森林。

      # 中国邮递员问题

      1962,中国数学家管梅谷提出并解决了 “中国邮路问题”

      即最优环游问题:在一个连通具有非负权的赋权图 GG 中找到一条包含每条边(允许重复)且边权之和最小的闭途径,称之为最优 (欧拉) 环游

      • 若图 GG 是一个欧拉图,则找出 GG 的欧拉环游即可
      • 对一般图,其解法为:添加重复边以使 GG 成为欧拉图 GG^* ,并使添加的重复边的边权之和为最小,再求 GG^* 的欧拉回路

      管梅谷的结论:

      假定 GG^* 是在图 GG 中添加一些重复边得到的欧拉图,则 GG^* 具有最小权值的充要条件是:

      • GG 的每一条边最多被添加一次
      • 对于 GG^* 的每个圈来说,该圈新添加的边的总权值不超过该圈总权值的一半

      证明:必要性

      GG 中某条边在 GG^* 中被添加的次数超过 1,则去掉其中两条重复的边,我们将得到一个总权值更小,且以 GG 为生成子图的欧拉图

      上述与 “ GG^* 总权值最小” 相矛盾,因此每条边最多被添加一次

      假定在 GG^* 中存在某个圈使得该圈新添加的边的总权值大于该圈权值的一半,不妨设为 CC

      那么在 GG^* 中,将 CC 上新添加的边全部去掉,然后将原圈未添加新边的边都添加一条重复边

      这样的操作使得该圈所有点的度数不变或改变 2,相应的图仍然是欧拉图,但是权值更小,这与 “ GG^* 总权值最小” 相矛盾

      这个必要性的证明给出了最优欧拉环游的构造方法

      # 半欧拉图最优欧拉环游

      一个非负权的边赋权图 GG 中只有两个奇度顶点 uuvv , 设计一个求其最优欧拉环游的算法如下:

      • (1) 在 uuvv 间求出一条最短路 PP; (最短路算法)
      • (2) 在最短路 PP 上,给每条边添加一条重复边得 GG 的欧拉图 GG^*
      • (3) 在 GG 的欧拉图 GG^* 中用 Fleury 算法求出一条欧拉环游;

      证明

      uuvvGG 的两个奇度顶点,GG^*GG 的任意一个欧拉图。

      考虑 G[EE]G^*[E^*-E], 显然它只有两个奇数顶点 uuvv, 当然它们必须在 G[EE]G^*[E^*-E] 的同一个分支中,因此,存在 (u,v)(u,v)PP^*

      eEEw(e)w(P)w(P)\sum_{e\in E^*-E}w(e)\geq w(P^*)\geq w(P)

      # 哈密顿图

      # 定义

      # 哈姆顿图

      如果经过图 GG 的每个顶点恰好一次后能够回到出发点,称这样的图为哈密尔顿图,简称 HH。所经过的闭途径是 GG 的一个生成圈,称为 GG哈密尔顿圈,简称 HH

      # 半哈密顿图

      不需回到出发点

      如果存在经过 GG 的每个顶点恰好一次的路,称这样的图为半哈密尔顿图,称该路为 GG哈密尔顿路,简称 HH

      # 小结论💡

      • n3n\geq3 时,完全图 KnK_n 是否为哈密尔顿图?
      • n2n\geq2 时, 方体 QnQ_n 是否为哈密尔顿图?
      • 若完全二部图 Ka,bK_{a,b} 为哈密尔顿图,aabb 需满足什么条件?a=b2\Rightarrow a=b\geq2
      • 是否存在一个具有奇数个顶点的连通图,它既是二部图,也是哈密尔顿图? 不存在,否则二部图中出现了奇圈
      • 若二部图是哈密尔顿图,则它的二部划分 (X,Y)(X,Y) 满足什么条件?X=Y\Rightarrow|X|=|Y|

      哈密顿图目前为止没有充要条件,实际上图的 HH 性判定是 NP - 困难问题,下面介绍一个必要条件和一些充分条件

      # 必要条件

      GGHH 图,则对于 VV 的每个非空真子集 SS,均有:

      ω(GS)S\omega(G-S)\leq|S|

      💡别忘了 ω(...)\omega(...) 的意思是连通分支数,这里还容易得到 HH 图不存在割点

      只是必要条件而不是充分条件,经典例子 —— 彼得森图

      用于判断非 HH 图:SV,ω(GS)>S\exist S\subset V,\ \ \omega(G-S)\gt|S| ,则 GG 不是 HH 图。

      # 充分条件

      # Dirac

      对于 n3n≥3 的简单图 GG , 如果 GG 中有:

      δ(G)n2\delta(G)\geq\frac{n}{2}

      那么 GGHH 图。

      # Ore

      对于 n3n≥3 的单图 GG , 如果 GG 中的任意两个不相邻顶点 uuvv ,有:

      d(u)+d(v)nd(u)+d(v)\geq n

      那么 GGHH 图。

      该定理证明和 Dirac 定理可以完全一致!

      该定理的条件是紧的。例如:设 GG 是由 Kk+1Κ_{k+1} 的一个顶点和另一个 Kk+1Κ_{k+1} 的一个顶点重合得到的图,那么对于 GG 的任意两个不相邻顶点 uuvv,有:

      d(u)+d(v)=2k=n1d(u)+d(v)=2k=n-1

      GG 是非 HH 图。

      # Bondy

      # 引理

      对于单图 GG ,如果 GG 中有两个不相邻顶点 uuvv ,满足:d(u)+d(v)nd(u)+d(v)≥n,那么 GGHH 图当且仅当 G+uvG+uvHH 图。

      # 闭图

      nn 阶简单图中,若对 d(u)+d(v)nd(u)+d(v)≥n 的任意一对顶点 uuvv ,均有 uadjvu\ \text{adj}\ v , 则称 GG 是闭图。

      # 引理

      G1G_1G2G_2 是同一个点集 VV 的两个闭图,则 G1G2G_1\cap G_2 是闭图,但 G1G2G_1\cup G_2 不一定是闭图。

      # 闭包

      G\overline G 是图 GG 的闭包,如果它是包含 GG 的极小闭图,即对 H∀H,若有 GHGG\subseteq H \subset\overline G,则 HH 不是闭图。

      • 如果 GG 本身是闭图,则其闭包是它本身;
      • 否则由定义可以通过在度和 n\geq n 的不相邻顶点对间加边来构造 GG 的闭图;加边之后还要继续检查是否需要加边。

      GG 的闭包是唯一的。

      # 闭包定理

      由闭包定理也可以推出 Dirac 和 Ore 定理

      GGHH 图当且仅当它的闭包是 HH

      # Chavatal

      度序列判定法

      HH 图充分条件

      设简单图 GG 的度序列是 d(d1,d2,,dn)d(d_1,d_2,\cdots,d_n),这里,d1d2dnd_1≤d_2≤⋯≤d_n,并且 n3n≥3。若对任意的 m<n2m<\frac{n}{2}

      • 或有 dm>md_m>m
      • 或有 dnmnmd_{n-m}≥n-m

      GGHH 图。(GG 的闭包是完全图!证明也是证明这个)

      # TSP

      # 边交换

      # 最优 H 圈下界

      可以通过如下方法求出最优 HH 圈的一个下界:(不是下确界,不一定达得到!)

      (1) 在 GG 中删掉一点 vv (任意的) 得图 G1G_1

      (2) 在图 G1G_1 中求出一棵最小生成树 TT

      (3) 在 vv 的关联边中选出两条权值最小者 e1e_1e2e_2

      HHGG 的最优圈,则有权值下界:

      W(H)W(T)+W(e1)+W(e2)W(H)\geq W(T)+W(e_1)+W(e_2)

      \ No newline at end of file +欧拉图与哈密顿图 - 图论 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 欧拉图

      # 定义

      欧拉图存在欧拉闭迹,半欧拉图只存在欧拉迹

      若能遍历完所有的边但是没法回到起始点,称为非欧拉图但是有欧拉迹

      # 欧拉图

      假定 GG 是一个连通图,且是欧拉图,则下列命题等价:

      • GG 是欧拉图
      • GG 的每个点的度数是偶数
      • GG 的边集能划分为边不重的圈的并
      • GG 存在欧拉闭迹)

      # 半欧拉图

      假定 GG 是一个连通图,且是半欧拉图,则下列命题等价:

      • GG 是半欧拉图
      • GG 有且仅有 2 个点的度数是奇数
      • GG 存在欧拉迹)

      # 小结论💡

      • nn 满足什么条件时,完全图 KnK_n 是欧拉图? nn 为奇数
      • nn 满足什么条件时,nn 方体 QnQ_n 是欧拉图? nn 为偶数
      • 若完全二部图 Ka,bK_{a,b} 为欧拉图,aabb 需满足什么条件? a,ba,b 均为偶数
      • 假设图 GG 恰好有两个连通分支,并且每个连通分支都是欧拉图,若要将 GG 变为欧拉图,最少需要添加几条边? 最少需要添加 2 条边
      • 欧拉图、半欧拉图是否存在割边? 欧拉图不存在割边,半欧拉图存在割边

      # Fleury 算法

      弗勒里算法解决了在欧拉图中求出一条具体欧拉环游的方法,核心思想是尽可能避割边行走

      # 算法流程

      • (1)任意选取一个顶点 v0v_0 ,置 w0=v0w_0=v_0
      • (2)假设迹 wi=v0e1v1eiviw_i=v_0e_1v_1\cdots e_iv_i 已经确定,按如下方法从 E{e1,e2,,ei}E-\{e_1,e_2,\cdots,e_{i}\} 选一个 ei+1e_{i+1}
        • ei+1e_{i+1}viv_i 相关联;
        • 除非没有其他边可选,否则 ei+1e_{i+1} 不能是 Gi=G{e1,e2,,ei}G_i=G-\{e_1,e_2,\cdots,e_{i}\}割边
      • (3)若(2)无法进行则算法停止

      利用 Fluery 算法可以求一个半欧拉图的欧拉迹,半欧拉图有且仅有 2 个奇度顶点 u,vu,v ,在这 2 个点之间增加一条边 mm ,就可以得到一个欧拉图,然后从其中一个奇度顶点,例如 uu ,开始求欧拉环游。得到的欧拉环游去掉 mm 就是从 uuvv 的欧拉迹。

      # 欧拉图中扩展欧拉环游充要条件

      GG 是非平凡的欧拉图,且 vV(G)v\in V(G) ,则 GG 的每条具有起点 vv 的迹都能扩展成 GG 的欧拉环游当且仅当 GvG-v 是森林。

      # 中国邮递员问题

      1962,中国数学家管梅谷提出并解决了 “中国邮路问题”

      即最优环游问题:在一个连通具有非负权的赋权图 GG 中找到一条包含每条边(允许重复)且边权之和最小的闭途径,称之为最优 (欧拉) 环游

      • 若图 GG 是一个欧拉图,则找出 GG 的欧拉环游即可
      • 对一般图,其解法为:添加重复边以使 GG 成为欧拉图 GG^* ,并使添加的重复边的边权之和为最小,再求 GG^* 的欧拉回路

      管梅谷的结论:

      假定 GG^* 是在图 GG 中添加一些重复边得到的欧拉图,则 GG^* 具有最小权值的充要条件是:

      • GG 的每一条边最多被添加一次
      • 对于 GG^* 的每个圈来说,该圈新添加的边的总权值不超过该圈总权值的一半

      证明:必要性

      GG 中某条边在 GG^* 中被添加的次数超过 1,则去掉其中两条重复的边,我们将得到一个总权值更小,且以 GG 为生成子图的欧拉图

      上述与 “ GG^* 总权值最小” 相矛盾,因此每条边最多被添加一次

      假定在 GG^* 中存在某个圈使得该圈新添加的边的总权值大于该圈权值的一半,不妨设为 CC

      那么在 GG^* 中,将 CC 上新添加的边全部去掉,然后将原圈未添加新边的边都添加一条重复边

      这样的操作使得该圈所有点的度数不变或改变 2,相应的图仍然是欧拉图,但是权值更小,这与 “ GG^* 总权值最小” 相矛盾

      这个必要性的证明给出了最优欧拉环游的构造方法

      # 半欧拉图最优欧拉环游

      一个非负权的边赋权图 GG 中只有两个奇度顶点 uuvv , 设计一个求其最优欧拉环游的算法如下:

      • (1) 在 uuvv 间求出一条最短路 PP; (最短路算法)
      • (2) 在最短路 PP 上,给每条边添加一条重复边得 GG 的欧拉图 GG^*
      • (3) 在 GG 的欧拉图 GG^* 中用 Fleury 算法求出一条欧拉环游;

      证明

      uuvvGG 的两个奇度顶点,GG^*GG 的任意一个欧拉图。

      考虑 G[EE]G^*[E^*-E], 显然它只有两个奇数顶点 uuvv, 当然它们必须在 G[EE]G^*[E^*-E] 的同一个分支中,因此,存在 (u,v)(u,v)PP^*

      eEEw(e)w(P)w(P)\sum_{e\in E^*-E}w(e)\geq w(P^*)\geq w(P)

      # 哈密顿图

      # 定义

      # 哈姆顿图

      如果经过图 GG 的每个顶点恰好一次后能够回到出发点,称这样的图为哈密尔顿图,简称 HH。所经过的闭途径是 GG 的一个生成圈,称为 GG哈密尔顿圈,简称 HH

      # 半哈密顿图

      不需回到出发点

      如果存在经过 GG 的每个顶点恰好一次的路,称这样的图为半哈密尔顿图,称该路为 GG哈密尔顿路,简称 HH

      # 小结论💡

      • n3n\geq3 时,完全图 KnK_n 是否为哈密尔顿图?
      • n2n\geq2 时, 方体 QnQ_n 是否为哈密尔顿图?
      • 若完全二部图 Ka,bK_{a,b} 为哈密尔顿图,aabb 需满足什么条件?a=b2\Rightarrow a=b\geq2
      • 是否存在一个具有奇数个顶点的连通图,它既是二部图,也是哈密尔顿图? 不存在,否则二部图中出现了奇圈
      • 若二部图是哈密尔顿图,则它的二部划分 (X,Y)(X,Y) 满足什么条件?X=Y\Rightarrow|X|=|Y|

      哈密顿图目前为止没有充要条件,实际上图的 HH 性判定是 NP - 困难问题,下面介绍一个必要条件和一些充分条件

      # 必要条件

      GGHH 图,则对于 VV 的每个非空真子集 SS,均有:

      ω(GS)S\omega(G-S)\leq|S|

      💡别忘了 ω(...)\omega(...) 的意思是连通分支数,这里还容易得到 HH 图不存在割点

      只是必要条件而不是充分条件,经典例子 —— 彼得森图

      用于判断非 HH 图:SV,ω(GS)>S\exist S\subset V,\ \ \omega(G-S)\gt|S| ,则 GG 不是 HH 图。

      # 充分条件

      # Dirac

      对于 n3n≥3 的简单图 GG , 如果 GG 中有:

      δ(G)n2\delta(G)\geq\frac{n}{2}

      那么 GGHH 图。

      # Ore

      对于 n3n≥3 的单图 GG , 如果 GG 中的任意两个不相邻顶点 uuvv ,有:

      d(u)+d(v)nd(u)+d(v)\geq n

      那么 GGHH 图。

      该定理证明和 Dirac 定理可以完全一致!

      该定理的条件是紧的。例如:设 GG 是由 Kk+1Κ_{k+1} 的一个顶点和另一个 Kk+1Κ_{k+1} 的一个顶点重合得到的图,那么对于 GG 的任意两个不相邻顶点 uuvv,有:

      d(u)+d(v)=2k=n1d(u)+d(v)=2k=n-1

      GG 是非 HH 图。

      # Bondy

      # 引理

      对于单图 GG ,如果 GG 中有两个不相邻顶点 uuvv ,满足:d(u)+d(v)nd(u)+d(v)≥n,那么 GGHH 图当且仅当 G+uvG+uvHH 图。

      # 闭图

      nn 阶简单图中,若对 d(u)+d(v)nd(u)+d(v)≥n 的任意一对顶点 uuvv ,均有 uadjvu\ \text{adj}\ v , 则称 GG 是闭图。

      # 引理

      G1G_1G2G_2 是同一个点集 VV 的两个闭图,则 G1G2G_1\cap G_2 是闭图,但 G1G2G_1\cup G_2 不一定是闭图。

      # 闭包

      G\overline G 是图 GG 的闭包,如果它是包含 GG 的极小闭图,即对 H∀H,若有 GHGG\subseteq H \subset\overline G,则 HH 不是闭图。

      • 如果 GG 本身是闭图,则其闭包是它本身;
      • 否则由定义可以通过在度和 n\geq n 的不相邻顶点对间加边来构造 GG 的闭图;加边之后还要继续检查是否需要加边。

      GG 的闭包是唯一的。

      # 闭包定理

      由闭包定理也可以推出 Dirac 和 Ore 定理

      GGHH 图当且仅当它的闭包是 HH

      # Chavatal

      度序列判定法

      HH 图充分条件

      设简单图 GG 的度序列是 d(d1,d2,,dn)d(d_1,d_2,\cdots,d_n),这里,d1d2dnd_1≤d_2≤⋯≤d_n,并且 n3n≥3。若对任意的 m<n2m<\frac{n}{2}

      • 或有 dm>md_m>m
      • 或有 dnmnmd_{n-m}≥n-m

      GGHH 图。(GG 的闭包是完全图!证明也是证明这个)

      # TSP

      # 边交换

      # 最优 H 圈下界

      可以通过如下方法求出最优 HH 圈的一个下界:(不是下确界,不一定达得到!)

      (1) 在 GG 中删掉一点 vv (任意的) 得图 G1G_1

      (2) 在图 G1G_1 中求出一棵最小生成树 TT

      (3) 在 vv 的关联边中选出两条权值最小者 e1e_1e2e_2

      HHGG 的最优圈,则有权值下界:

      W(H)W(T)+W(e1)+W(e2)W(H)\geq W(T)+W(e_1)+W(e_2)

      \ No newline at end of file diff --git a/math/discrete-math/graph/graph-basics/index.html b/math/discrete-math/graph/graph-basics/index.html index f35e0aad..6d5b9e83 100644 --- a/math/discrete-math/graph/graph-basics/index.html +++ b/math/discrete-math/graph/graph-basics/index.html @@ -1 +1 @@ -图的基本概念 - 图论 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 图的基础知识

      # 图的定义

      一 个 图 GG 定 义 为 一 个 有 序 对 (V , E), 记 为 G = ( V , E ), 其 中:

      1. V 是一个非空集合,称为顶点集或边集,其元素称为项点或点
      2. E 是由 V 中的点组成的无序点对构成的集合,称为边集,其元素称为边,且同一 点对在 E 中可出现多次。

      GG顶点集也记为 V (G)边集也记为 E (G)

      顶点集和边集都有限的图称为有限图

      只有一个项点而无边的图称为平凡图。其他所有的图都称为非平凡图

      做题往往需要先排除平凡图

      边集为空的图称为空图

      GG顶点数 (或阶数) 和边数可分别用符号 n(G)m(G) 表示。

      连接两个相同顶点 的边的条数,叫做边的重数。重数大于 1 的边称为重边

      端点重合为一点的边称为

      既没有环也没有重边的图称为简单图。其他所有的图都称为复合图

      边记为 uv,也可记 uv 为 e ,即 e = uv。此时称 u 和 v 是 e 的端点,并称 u 和 v 相邻,u (或 v) 与 e 相关联

      若两条边有一个共同的端点,则称这两条边相邻

      若用小圆点代表点, 连线代表边,则可将一个图用 “图形” 来表示。

      # 图的同构

      设 有 两 个 图 G1 = (V1 , E1 ) 和 G2 = (V2 , E2 ), 若 在 其 项 点 集 合 之 间 存 在 双 射 , 即 存
      在一一对应的关系,使得边之间有如下的关系:

      u1u2,v1v2,u1,v1V1,u2,v2V2u1v1E1u2v2E2设 u_1 \lrarr u_2 , v_1 \lrarr v_2 ,\ \ \ u_1 ,v_1\in V_1 ,\ \ \ u_2 , v_2 \in V_2 \\ u_1 v_1 \in E_1 \lrArr u_2 v_2 \in E_2

      u1v1重数=u2v2重数u_1 v_1 重数 = u_2 v_2 重数

      则称两图 G1 , G2 同构 , 记为:

      G1G2G_1 \cong G_2

      同构关系就是一种等价关系,形成等价类

      # 完全图

      每两个不同的顶点之问都有一条边相连的简单图称为完全图

      完全图是简单图的上限,空图则是下限

      在同构意义下,n 个顶点的完全图只有一个,记为 Kn ,也叫 n 阶完全图。

      所谓具有二分类 (X, Y) 的偶图 (或二部图) 是指:一个图,它的点集可以分解为两个 (非空) 子集 X 和 Y ,使得每条边的一个端点在 X 中,另一个端点在 Y 中。

      完全偶图是指具有二分类 (X , Y) 的简单偶图 , 其中 X 的每个项点与 Y 的每个项点相连,若 |X|=m ,|Y|=n ,则这样的偶图记为 Km,n

      # 补图

      对于一个简单图 G= (V, E),令集合

      E1={uvuv,u,vV}E_1=\{uv|u\neq v ,\ \ u,v\in V\}

      则图 H=(VE/E1)H=(VE/E_1) 称为 GG补图 ,记为:

      H=G=(V,E/E1)H=\overline G=(V,E/E_1)

      如果一个图和自己的补图是同构的,则称这个图是自补的,并记为:

      GGG\cong \overline G

      # 自补图性质

      若 n 阶 图 GG 是 自补 的 ( 即 GGG\cong \overline G ), 则 n=0,1(mod4)n=0,1(\mathrm{mod} 4)

      # 正则图

      G 的顶点的度 d (v) 是指 GG 中与 v 关联的边的数目,每个环计算两次。

      δ(G)\delta(G)Δ(G)\Delta(G) 分别表示 G 的项点的最小度最大度

      为方便,奇数度的顶点称为奇点,偶数度的顶点称偶点

      设 G = (V,E) 为简单图,如果对所有 vVv\in V ,有 d (v) = k ,称图 GG k - 正则图

      完全图 Kn 和完全偶图 Kn,m 均是正则图。

      # 握手定理⭐️

      图 G = (V , E) 中 所 有 项 点 的 度 的 和 等 于 边 数 m 的 2 倍 , 即

      vVd(v)=2m\sum_{v\in V}d(v)=2m

      也叫:握手定理,图论第一定理

      # 推论 1

      在任何图中,奇点个数为偶数。

      # 推论 2

      正则图的阶数和度数不同时为奇数。

      # 推论 3⭐️

      由握手定理有:

      nδ<vV(G)d(v)=2mnΔδ2mnΔn\delta\lt\sum_{v\in V(G)}d(v)=2m\leq n\Delta\\ \delta\leq\frac{2m}{n}\leq\Delta

      # 可图数组

      一个图 GG 的各个点的度 d1,d2,,dnd_1,d_2,\cdots,d_n 构 成 的 非 负 整 数 组 (d1,d2,,dn)(d_1,d_2,\cdots,d_n) 称为 GG度序列

      度序列通常以度数非递增的顺序列出?

      若对一个非负整数组 (d1,d2,,dn)(d_1,d_2,\cdots,d_n) 满足 mZ,i=1ndi=2m\exist m \in \mathbb Z,\sum_{i=1}^{n}d_i=2m (数组和为偶数),存在一个简单图 GG 以该数组为度序列,则称这个数组是可图的,也叫这个数组为图数组 / 图序列

      关于图序列我们研究三个问题:

      • 存在问题 —— 什么样的数组是图序列
      • 计数问题 —— 一个图序列对应多少个不同构的图
      • 唯一性问题 —— 怎样的图序列对应唯一一个同构的图

      # 必要条件

      非负整数组 (d1,d2,,dn)(d_1,d_2,\cdots,d_n) 是图序列的一个必要条件是:

      i=1ndi是偶数,或者:2i=1ndi\sum_{i=1}^{n}d_i \text{是偶数,或者:} 2|\sum_{i=1}^{n}d_i

      另一个必要条件是:(可简单图化)

      din1d_i\leq n-1

      # 图序列相关定理

      # Havel-Hakimi ⭐️

      设有非负整数组 Π=(d1,d2,,dn)\Pi =(d_1 , d_2 , \cdots , d_n) ,且 i=1ndi\sum_{i=1}^{n}d_i 是一个偶数,n1d1d2dnn-1\geq d_1\geq d_2 \geq \cdots\geq d_nΠ\Pi 是可图(可简单图化)的充要条件为:

      Π=(d21,d31,,dd1+11,dd1+2,,dn)\Pi'=(d_2-1,d_3-1,\cdots,d_{d_1+1}-1,d_{d_1+2},\cdots,d_n)

      是可图的(是图序列)。


      对任意一个序列,判断是否可图的步骤如下:(当然先确保满足可图的必要条件)

      1. 按递减排序
      2. 去掉第一个元素 d1d_1 ,后面 d1d_1 个元素依次减 1️⃣(1-1
      3. 重复前面两个步骤 ,直到:
        • 只剩一个点,则该序列是可图的,即是图序列
        • 减 1️⃣后出现负数,则该序列是不可图的,即不是图序列

      # 中证明充分性:

      # 情形 1

      v1v_1 与点 v2,v3,,vd+1v_2,v_3,\cdots,v_{d+1} 邻接

      Gv1G-v_1 的度序列正好 Π1\Pi_1

      # 情形 2

      v1v_1 与点 v2,v3,,vd+1v_2,v_3,\cdots,v_{d+1} 的某些顶点邻接

      作如下假设:

      • v1v_1vj0v_{j_0} 邻接,但当 k>j0k\gt j_0 时,v1v_1vkv_k 不邻接;
      • v1v_1vi0v_{i_0} 不邻接,但当 k<i0k\lt i_0 时,v1v_1vkv_k 邻接;

      进行这样的操作:

      • 去掉边 v1vj0v_1 v_{j_0}vi0vmv_{i_0}v_m
      • 加上边 vj0vmv_{j_0}v_m 和 v_1v_

      显然新图与原来的度序列相同,但是,但 j0j_0 减小了, i0i_0 增大了!

      如此循环下去,j0=i0j_0=i_0 时 情形 2 就可以变成情形 1

      # 厄多斯定理

      非负整数组:

      π=(d1,d2,,dn),d1d2dn,i=1ndi=2m\pi = (d_1,d_2,\cdots,d_n),d_1\geq d_2 \geq d_n,\sum_{i=1}^{n}d_i=2m

      是图序列的充分必要条件是:

      i=1rdir(r1)+i=r+1nmin{r,di},1rn1\sum_{i=1}^{r}d_i\leq r(r-1)+\sum_{i=r+1}^{n}\text{min}\{r,d_i\},\ \ \ 1\leq r\leq n-1

      证明非常困难捏

      # 定理?

      一个满足 d2=dn1d_2=d_{n-1}图序列 π=(d1,d2,,dn)\pi=(d_1,d_2,\cdots,d_n)唯一图序列的充分必要条件时下列条件之一满足:

      • d1=dn,dn{1,n1,n2}d_1=d_n,\ \ d_n\in \{ 1,n-1,n-2 \}
      • d1=dn=2,n=5d_1=d_n=2,\ \ n=5
      • d1>d2=dn=1d_1\gt d_2=d_n=1
      • d1>d2=dn=2,d1{n1,n2}d_1\gt d_2=d_n=2,\ \ d_1\in\{n-1,n-2\}
      • n2=d1=dn1>dnn-2=d_1=d_{n-1}\gt d_n
      • n3=d1=dn1>dn=1n-3=d_1=d_{n-1}\gt d_n=1
      • n1=d1>d2=dn=3,n=6n-1=d_1\gt d_2=d_{n}=3,\ \ n=6

      # 定理 - 简单图度数不可能互不相同

      一个简单图 GGnn 个点的度不能互不相同

      证明: 因为图 G 为简单图,所以:Δ(G)n1\Delta(G)\leq n - 1


      情形 1:若 GG 没有孤立点,则 1d(v)n1,vV(G)1 ≤ d(v)≤ n - 1,\ \ \ ∀v \in V(G) , 由鸽笼原理:必有两顶点度数相同;


      情形 2:若 GG 只有一个孤立点,设 G1G_1 表示 G 去掉孤立点后的部分,则:

      1d(v)n2,vV(G1)1 ≤ d(v)≤ n - 2,\ \ \ ∀v \in V(G_1)

      由鸽笼原理:在 G1G_1 里必有两顶点度数相同;


      情形 3:若 GG 只有两个以上的孤立点,则定理显然成立。


      # 频序列

      nn 阶图 GG 的各点的度取了 ss 个不同的非负整数 d1,d2,,dsd_1,d_2,\cdots,d_s 。 又 设 度 为 did_i 的 点 有 bib_i 个 (i=1,2,,s)i=1,2,\cdots,s) , 则有 i=1sbi=n\sum_{i=1}^{s}b_i =n 。故非负整数组 (d1,d2,,dsd_1,d_2,\cdots,d_s) 是 nn 的一个划分,称为 GG频序列

      # 性质

      一个 nn 阶图 GG 和它的补图有相同的频序列

      # 拓扑不变量

      GG拓扑不变量是指与图 GG 有关的一个数或数组 (向量)。它对于与图 GG 同构的所有图来说,不会发生改变。

      一个图 GG 可以对应很多拓扑不变量。如果某组不变量可完全决定一个图,称它为不变量的完全集

      # 图的运算

      # 子图和真子图

      如果 V(H)V(G),E(H)E(G)V(H) \subseteq V(G),E(H)\subseteq E(G) ,且 HH 中边的重数不超过 GG 中对应边的重数 , 则称 HHGG子图,记为 HGH \subseteq G 。有时又称 GGHH母图

      HGH\subseteq G ,但 HGH\neq G 时,则记为 HGH\subset G ,且称 HHGG真子图

      # 生成子图

      GG生成子图是指满足 V(H)=V(G)V (H) = V (G ) 的子图 HH。也就是包含所有顶点但不包含所有边的子图。

      # 计数性质

      简单图 G=(n,m)G=(n,m) 的所有不同的生成子图个数是 2m2^m (包括 GG 本身和空图)。

      # 导出子图

      假设 VV'VV 的一个非空子集。以 VV' 为顶点集,以两端点均在 VV' 中的边的全体为边集所组成的子图,称为 GG 的由 VV' 导出的子图,记为 G[V]G[V'],简称为 GG(点) 导出子图

      假设 EE'EE 的非空子集。以 EE' 为边集,以 EE' 中边的端点全体为顶点集所组成的子图称为 GG 的由 EE' 导出的子图,记为 G[E]G[E'],简称为 GG边导出子图

      # 删点运算

      (点) 导出子图 G[V\V]G[V\backslash V'] 记为 GVG-V'。它是 GG 中删除 VV' 中的项点以及与这些项点相关联的边所得到的子图。若 V={v}V'=\{v\} ,则把 G{v}G-\{v\} 简记为 GvG-v

      # 删边运算

      边集为 E\EE\backslash E'GG 的边导出子图简记为 GEG-E' 。若 E={e}E'=\{e\} ,则把 GeG-{e} 简记为 GeG-e

      ⚠️删边运算会删掉那些度数变为 0 的顶点⚠️


      G1G_1G2G_2GG 的子图。若 G1G_1G2G_2 无公共顶点,则称它们是不相交

      G1G_1G2G_2 无公共边,则称它们是边不重

      # 并运算

      G1G_1G2G_2并图 G1UG2G_1UG_2 是指 GG 的一个子图:

      • 其顶点集为 V(G1)V(G2)V(G_1)\cup V(G_2)
      • 其边集为 E(G1)E(G2)E(G_1)\cup E(G_2)

      如果 G1G_1G2G_2 是不相交的,有时就记其并图为 G1+G2G_1+G_2

      # 交运算

      G1G_1G2G_2交图 G1G2G_1\cap G_2 ,是指 GG 的一个子图:

      • 其顶点集为 V(G1)V(G2)V(G_1)\cap V(G_2)
      • 其边集为 E(G1)E(G2)E(G_1)\cap E(G_2)

      此时 G1G_1G2G_2 至少要有一个公共顶点!

      # 差运算

      G1G_1G2G_2 G1G2G_1-G_2 是由 G1G_1 中去掉 G2G_2 中的边组成的图 。

      没有去掉那些边的端点!即使剩下 0 度数端点仍要保留!

      # 对称差 / 环和差

      G1G_1G2G_2对称差 G1ΔG2G_1 \Delta G_2G1G2G_1 \cup G_2 去掉 G1G2G_1 \cap G_2 所得到的图,即 :

      G1ΔG2=(G1G2)(G1G2)=(G1G2)(G2G1)G_1 \Delta G_2 = (G_1 \cup G_2)-(G_1 \cap G_2) = (G_1 - G_2) \cup (G_2-G_1)

      # 联运算

      在不相交的 G1G_1G2G_2 的并图 G1G2G_1 \cup G_2 中,把 G1G_1 的每个项点和 G2G_2 的每个项点连接起来所得到的 图称为 G1G_1G2G_2联图,记为 G1G2G_1 \lor G_2


      uiadjviu_i\ \mathrm{adj}\ v_i 表示 uiu_iviv_i 邻接

      # (笛卡尔) 积运算

      G1=(V1,E1),G2=(V2,E2)G_1 =(V_1 , E_1),G_2 =(V_2 ,E_2)对点集 V=V1×V2V=V_1 \times V_2 (笛卡尔集)中任意两个点 u=(u1,u2)u=(u_1,u_2)v=(v1,v2)v=(v_1,v_2) ,当以下式子成立时:

      (u1=v1u2adjv2)(u2=v2u1adjv1)(u_1 =v_1\land u_2\ \mathrm{adj}\ v_2)\lor(u_2=v_2\land u_1\ \mathrm{adj}\ v_1)

      就把 uuvv 连接起来所得到的图 GG 称为 G1G_1G2G_2积图,记为 G=G1×G2G=G_1 \times G_2

      # 合成运算

      Gi=(V1,E1)G_i=(V_1,E_1)G2=(V2,E2)G_2=(V_2,E_2) , 对点集 V=V1×V2V=V_1 \times V_2 (笛卡尔集)中任意两个点 u=(u1,u2)u=(u_1,u_2)v=(v1,v2)v=(v_1,v_2) ,当以下式子成立时:

      (u1adjv1)(u1=v1u2adjv2)(u_1\ \mathrm{adj}\ v_1)\lor(u_1=v_1\land u_2\ \mathrm{adj}\ v_2)

      就把 uuvv 连接起来所得到的图 GG 称为 G1G_1G2G_2合成图,记为 G=G1[G2]G=G_1[G_2]

      G1[G2]G_1[G_2]G2[G1]G_2[G_1] 可能是同构的,也可能是不同构的


      积运算和合成运算中,得到的点集 VV 的定义都是相同的,都是笛卡尔集 V=V1×V2V=V_1 \times V_2 ;但是边集的定义有所不同


      运算点的数目边的数目
      G1G2G_1\cup G_2n1+n2n_1 + n_2m1+m2m_1 + m_2
      G1G2G_1\lor G_2n1+n2n_1 + n_2m1+m2+n1n2m_1 + m_2 +n_1 n_2
      G1×G2G_1\times G_2n1n2n_1 n_2n1m2+n2m1n_1m_2 + n_2m_1
      合成 G1[G2]G_1[G_2]n1n2n_1 n_2n1m2+n22m1n_1m_2 + {n_2}^2m_1

      # 方体

      一族特别重要的图称为方体,它用积来定义最为自然。

      nn 方体 QnQ_n 递推地定义为:

      • Q1=K2Q_1=K_2
      • Qn=K2×Qn1Q_n=K_2\times Q_{n-1}

      QnQ_n2n2^n 个点,它的点可以用二进制串 a1a2ana_1 a_2 \cdots a_n 来标定,其中 ai{0,1}a_i\in\{0,1\}

      QnQ_n 两个点的二进制表示式中只有一位不同,则它们邻接

      2方体

      3方体

      # 路与图的连通性

      # 途径、迹、路

      一个有限非空序列:

      w=v0e1v1e2v2ekvkw=v_0\ e_1\ v_1\ e_2\ v_2\cdots e_k\ v_k

      它的项交替地为顶点和边,使得对 1ik1\leq i\leq keie_i ,的端点是 vi1v_{i-1}viv_i、 称 ww 是从 v0v_0vkv_k 的一条途径,或一条 (v0,vk)(v_0,v_k) 途径

      途径中边数称为途径的长度

      v0v_0vkv_k 分别称为途径的起点终点,其余顶点称为途径的内部点

      一条途径的起点与终点重合时叫做闭途径

      边不重复的途径称为图的一条,起点与终点重合时叫做闭迹,也称为回路

      顶点不重复的途径称为图的一条,起点与终点重合时叫做。显然顶点不重复时边也不重复,所以迹是包含路的。

      起点与终点重合的途径、迹、路分别称为图的闭途径、闭迹与圈。闭迹也称为回路

      长度为 kk 的圈称为 kk 圈,kk 为奇数时称为奇圈kk 为偶数时称为偶圈

      # 圈的充分条件

      δ2\delta ≥2,则 GG 中必然含有圈。

      只就连通图证明即可!

      W=v1v2vk1vkW=v_1 v_2\cdots v_{k-1}v_kGG 中的一条最长路。由于 δ2\delta≥2,所以 vkv_k 必然有相异于 vk1v_{k-1} 的邻接顶点。

      WW 是连通图 GG 中最长路,所以,这样的邻接点必然是 v1v2vk2v_1 v_2\cdots v_{k-2} 中之一。设该点为 vmv_m ,则 vmvm+1vkvmv_m v_{m+1}\cdots v_k v_mGG 中圈。

      # 偶图的充要条件

      一个图是二部图 (偶图) 当且当它不包含奇圈


      证明必要性:

      GG 是具有二分类 (X,Y)(X,Y) 的偶图,并且 C=v0v1vkv0C=v_0 v_1\cdots v_k v_0GG 的一个圈

      不失一般性,可假定 v0Xv_0\in X

      一般说来,v2iX,v2i+1Yv_{2i}\in X,v_{2i+1}\in Y

      又因为v0Xv_0\in X ,所以 vkYv_k\in Y,由此即得 CC 是偶圈


      证明充分性:

      GG 中任意选取点 uu,定义 VV 的分类如下:

      • X={xd(u,x)是偶数,xV(G)}X=\{x|d(u,x)\text{是偶数},x\in V(G)\}
      • Y={yd(u,y)是奇数,yV(G)}Y=\{y|d(u,y)\text{是奇数},y\in V(G)\}

      (接下来证明 XX 中任意两点 v,wv,w 不邻接)

      v,wv,wXX 中任意两个顶点,PP 是一条最短 (u,v)(u,v) 路,而 QQ 是一条最短 (u,w)(u,w) 路,设 u1u_1PPQQ 的最后一个交点:

      偶图充分必要条件充分性证明

      由于 P,QP,Q 是最短路,所以,P,QP,Quuu1u_1 段长度相同,因此奇偶性相同

      P,QP,Q 的长均是偶数,所以,P,QP,Qu1vu_1 v 段和 u1wu_1 w 段奇偶性相同

      如果 v,wv,w 邻接则可得到奇圈,矛盾!

      # 两顶点的距离

      图中顶点 uuvv 的距离: uuvv 间最短路的长度称为 uuvv 间距离。记为:

      d(u,v)d(u,v)

      如果 uuvv 间不存在路,定义:

      d(u,v)=0d(u,v)=0

      # 两顶点的连通性

      GG 中点 uuvv 说是连通的,如果 uuvv存在通路。否则称 uuvv 不连通

      点的连通关系是等价关系

      非连通图中每一个极大连通部分,称为 GG连通分支

      GG 的连通分支的个数,称为 GG分支数,记为:

      ω(G)\omega(G)

      # 图的连通性

      如果图 GG 中任意两点是连通的,称 GG连通图,否则,称 GG非连通图

      # 连通图的性质

      nn 阶连通图中:

      1. 至少有 n1n-1 条边
      2. 如果边数大于 n1n-1,则至少有一条闭迹
      3. 如果恰有 n1n-1 条边,则至少有一个奇度点

      (2)证明:

      GG 中没有 11 度顶点,由握手定理:

      2m=vV(G)d(v)2nmnm>n12m=\sum_{v\in V(G)}d(v)\geq 2n \rArr m\geq n \rArr m \gt n-1


      (3)证明:

      若不然,GG 中顶点度数至少为 22,于是由握手定理:

      2m=v(G)d(v)2nmnm>n12m=\sum_{v\in(G)}d(v) \geq 2n \rArr m ≥n \rArr m > n-1

      这与 GG 中恰有 n1n-1 条边矛盾!

      # 补图的连通性

      若图 GG 是不连通的,则它的补图 G\overline G 是连通图.


      证明:设 u,vu,vGG 的任意两个顶点:

      • uuvvGG 中不邻接,则在 G\overline G 中它们邻接,从而 G\overline G 是连通的
      • uuvvGG 中邻接,它们属于 GG 的同一分支;在另一个分支中有一点 ww,在 G\overline Guuvv 均与 w 邻接,即 uwvuwv 是一条通道,从而 G\overline G 是连通的

      # 连通图充分条件 1

      设图 GGnn 阶图,若 GG 中任意两个不相邻的点 uuvv,有:

      d(u)+d(v)n1d(u)+d(v)\geq n-1

      GG 是连通的,且 d(G)2d(G)\leq 2


      证明:对 GG 中任意两点 xxyy,一定存在一条长度至多为 22 的连接 xxyy 的路

      xyE(G)xy\in E(G) 时上述论断显然成立;

      xyE(G)xy\notin E(G) 时:

      可以证明,存在点 ww,它与 xxyy 同时邻接。反证法:

      若不然,在 GG 的剩下 n2n-2 个顶点中,假设:

      • kk 个与 xx 邻接,但与 yy 不邻接;
      • ll 个与 yy 邻接,但与 xx 不邻接;
      • mm 个顶点和 x,yx,y 均不邻接。

      则:d(x)=kd(x)=kd(y)=ld(y)=l

      由于 k+l+m=n2k+l+m=n-2

      所以 d(x)+d(y)=nm2n2d(x)+d(y)=n-m-2\leq n-2 ,矛盾!


      # 连通图充分条件 2

      GGnn 阶图,若 δn12\delta≥\frac{n-1}{2} ,则 GG 连通


      证明:

      对 G 中任意两个不相邻顶点 u 与 v,有:

      d(u)+d(v)n12+n12=n1d(u)+d(v)\geq\frac{n-1}{2}+\frac{n-1}{2}=n-1

      所以,G 是连通的。

      该定理的界是紧的 (Sharpness)。即不能再修改!

      例如:设 G 由两个分支作成的图,两个分支均为 KmK_m ,则 G 中不相邻顶点度数之和恰为 n-2 . (n=2m)

      # 图的直径

      连通图 G 的直径定义为

      d(G)=max{d(u,v)u,vV(G)}d(G) = \text{max}\{d(u,v)|u,v \in V(G)\}

      如果 G 不连通,图 G 的直径定义为 d(G)=d(G) = \infin

      # 直径相关性质

      设 G 是具有 m 条边的 n 阶单图,若 G 的直径为 2 且 δ=n2\delta=n-2 ,则 m2n4m≥2n-4


      证明:

      d(v)=Δ=n2d(v)=\Delta=n-2 ,设 v 的邻接点为 v1,v2,,vn2v_1,v_2,\cdots,v_{n-2} ,u 是剩下的一个项点。

      由于 d(G)=2d(G)=2 且 u 不能和 v 邻接,所以 u 至少和 v1,v2,,vn2v_1,v_2,\cdots,v_{n-2} 中的一个顶点邻接。否则有 d(G)>2d(G)>2 ; 不妨假设 u 和 v1,v2,,vkv_1,v_2,\cdots,v_{k} 邻接。

      为了保证 u 到各点距离不超过 2 , vk+1,,vn2v_{k+1},\cdots,v_{n-2} 这些頂点的每一个必须和前面 v1,v2,,vkv_1,v_2,\cdots,v_{k} 中某点邻接,这样,图中至少又有 n-2 条边。总共至少有 2n-4 条边。

      \ No newline at end of file +图的基本概念 - 图论 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 图的基础知识

      # 图的定义

      一 个 图 GG 定 义 为 一 个 有 序 对 (V , E), 记 为 G = ( V , E ), 其 中:

      1. V 是一个非空集合,称为顶点集或边集,其元素称为项点或点
      2. E 是由 V 中的点组成的无序点对构成的集合,称为边集,其元素称为边,且同一 点对在 E 中可出现多次。

      GG顶点集也记为 V (G)边集也记为 E (G)

      顶点集和边集都有限的图称为有限图

      只有一个项点而无边的图称为平凡图。其他所有的图都称为非平凡图

      做题往往需要先排除平凡图

      边集为空的图称为空图

      GG顶点数 (或阶数) 和边数可分别用符号 n(G)m(G) 表示。

      连接两个相同顶点 的边的条数,叫做边的重数。重数大于 1 的边称为重边

      端点重合为一点的边称为

      既没有环也没有重边的图称为简单图。其他所有的图都称为复合图

      边记为 uv,也可记 uv 为 e ,即 e = uv。此时称 u 和 v 是 e 的端点,并称 u 和 v 相邻,u (或 v) 与 e 相关联

      若两条边有一个共同的端点,则称这两条边相邻

      若用小圆点代表点, 连线代表边,则可将一个图用 “图形” 来表示。

      # 图的同构

      设 有 两 个 图 G1 = (V1 , E1 ) 和 G2 = (V2 , E2 ), 若 在 其 项 点 集 合 之 间 存 在 双 射 , 即 存
      在一一对应的关系,使得边之间有如下的关系:

      u1u2,v1v2,u1,v1V1,u2,v2V2u1v1E1u2v2E2设 u_1 \lrarr u_2 , v_1 \lrarr v_2 ,\ \ \ u_1 ,v_1\in V_1 ,\ \ \ u_2 , v_2 \in V_2 \\ u_1 v_1 \in E_1 \lrArr u_2 v_2 \in E_2

      u1v1重数=u2v2重数u_1 v_1 重数 = u_2 v_2 重数

      则称两图 G1 , G2 同构 , 记为:

      G1G2G_1 \cong G_2

      同构关系就是一种等价关系,形成等价类

      # 完全图

      每两个不同的顶点之问都有一条边相连的简单图称为完全图

      完全图是简单图的上限,空图则是下限

      在同构意义下,n 个顶点的完全图只有一个,记为 Kn ,也叫 n 阶完全图。

      所谓具有二分类 (X, Y) 的偶图 (或二部图) 是指:一个图,它的点集可以分解为两个 (非空) 子集 X 和 Y ,使得每条边的一个端点在 X 中,另一个端点在 Y 中。

      完全偶图是指具有二分类 (X , Y) 的简单偶图 , 其中 X 的每个项点与 Y 的每个项点相连,若 |X|=m ,|Y|=n ,则这样的偶图记为 Km,n

      # 补图

      对于一个简单图 G= (V, E),令集合

      E1={uvuv,u,vV}E_1=\{uv|u\neq v ,\ \ u,v\in V\}

      则图 H=(VE/E1)H=(VE/E_1) 称为 GG补图 ,记为:

      H=G=(V,E/E1)H=\overline G=(V,E/E_1)

      如果一个图和自己的补图是同构的,则称这个图是自补的,并记为:

      GGG\cong \overline G

      # 自补图性质

      若 n 阶 图 GG 是 自补 的 ( 即 GGG\cong \overline G ), 则 n=0,1(mod4)n=0,1(\mathrm{mod} 4)

      # 正则图

      G 的顶点的度 d (v) 是指 GG 中与 v 关联的边的数目,每个环计算两次。

      δ(G)\delta(G)Δ(G)\Delta(G) 分别表示 G 的项点的最小度最大度

      为方便,奇数度的顶点称为奇点,偶数度的顶点称偶点

      设 G = (V,E) 为简单图,如果对所有 vVv\in V ,有 d (v) = k ,称图 GG k - 正则图

      完全图 Kn 和完全偶图 Kn,m 均是正则图。

      # 握手定理⭐️

      图 G = (V , E) 中 所 有 项 点 的 度 的 和 等 于 边 数 m 的 2 倍 , 即

      vVd(v)=2m\sum_{v\in V}d(v)=2m

      也叫:握手定理,图论第一定理

      # 推论 1

      在任何图中,奇点个数为偶数。

      # 推论 2

      正则图的阶数和度数不同时为奇数。

      # 推论 3⭐️

      由握手定理有:

      nδ<vV(G)d(v)=2mnΔδ2mnΔn\delta\lt\sum_{v\in V(G)}d(v)=2m\leq n\Delta\\ \delta\leq\frac{2m}{n}\leq\Delta

      # 可图数组

      一个图 GG 的各个点的度 d1,d2,,dnd_1,d_2,\cdots,d_n 构 成 的 非 负 整 数 组 (d1,d2,,dn)(d_1,d_2,\cdots,d_n) 称为 GG度序列

      度序列通常以度数非递增的顺序列出?

      若对一个非负整数组 (d1,d2,,dn)(d_1,d_2,\cdots,d_n) 满足 mZ,i=1ndi=2m\exist m \in \mathbb Z,\sum_{i=1}^{n}d_i=2m (数组和为偶数),存在一个简单图 GG 以该数组为度序列,则称这个数组是可图的,也叫这个数组为图数组 / 图序列

      关于图序列我们研究三个问题:

      • 存在问题 —— 什么样的数组是图序列
      • 计数问题 —— 一个图序列对应多少个不同构的图
      • 唯一性问题 —— 怎样的图序列对应唯一一个同构的图

      # 必要条件

      非负整数组 (d1,d2,,dn)(d_1,d_2,\cdots,d_n) 是图序列的一个必要条件是:

      i=1ndi是偶数,或者:2i=1ndi\sum_{i=1}^{n}d_i \text{是偶数,或者:} 2|\sum_{i=1}^{n}d_i

      另一个必要条件是:(可简单图化)

      din1d_i\leq n-1

      # 图序列相关定理

      # Havel-Hakimi ⭐️

      设有非负整数组 Π=(d1,d2,,dn)\Pi =(d_1 , d_2 , \cdots , d_n) ,且 i=1ndi\sum_{i=1}^{n}d_i 是一个偶数,n1d1d2dnn-1\geq d_1\geq d_2 \geq \cdots\geq d_nΠ\Pi 是可图(可简单图化)的充要条件为:

      Π=(d21,d31,,dd1+11,dd1+2,,dn)\Pi'=(d_2-1,d_3-1,\cdots,d_{d_1+1}-1,d_{d_1+2},\cdots,d_n)

      是可图的(是图序列)。


      对任意一个序列,判断是否可图的步骤如下:(当然先确保满足可图的必要条件)

      1. 按递减排序
      2. 去掉第一个元素 d1d_1 ,后面 d1d_1 个元素依次减 1️⃣(1-1
      3. 重复前面两个步骤 ,直到:
        • 只剩一个点,则该序列是可图的,即是图序列
        • 减 1️⃣后出现负数,则该序列是不可图的,即不是图序列

      # 中证明充分性:

      # 情形 1

      v1v_1 与点 v2,v3,,vd+1v_2,v_3,\cdots,v_{d+1} 邻接

      Gv1G-v_1 的度序列正好 Π1\Pi_1

      # 情形 2

      v1v_1 与点 v2,v3,,vd+1v_2,v_3,\cdots,v_{d+1} 的某些顶点邻接

      作如下假设:

      • v1v_1vj0v_{j_0} 邻接,但当 k>j0k\gt j_0 时,v1v_1vkv_k 不邻接;
      • v1v_1vi0v_{i_0} 不邻接,但当 k<i0k\lt i_0 时,v1v_1vkv_k 邻接;

      进行这样的操作:

      • 去掉边 v1vj0v_1 v_{j_0}vi0vmv_{i_0}v_m
      • 加上边 vj0vmv_{j_0}v_m 和 v_1v_

      显然新图与原来的度序列相同,但是,但 j0j_0 减小了, i0i_0 增大了!

      如此循环下去,j0=i0j_0=i_0 时 情形 2 就可以变成情形 1

      # 厄多斯定理

      非负整数组:

      π=(d1,d2,,dn),d1d2dn,i=1ndi=2m\pi = (d_1,d_2,\cdots,d_n),d_1\geq d_2 \geq d_n,\sum_{i=1}^{n}d_i=2m

      是图序列的充分必要条件是:

      i=1rdir(r1)+i=r+1nmin{r,di},1rn1\sum_{i=1}^{r}d_i\leq r(r-1)+\sum_{i=r+1}^{n}\text{min}\{r,d_i\},\ \ \ 1\leq r\leq n-1

      证明非常困难捏

      # 定理?

      一个满足 d2=dn1d_2=d_{n-1}图序列 π=(d1,d2,,dn)\pi=(d_1,d_2,\cdots,d_n)唯一图序列的充分必要条件时下列条件之一满足:

      • d1=dn,dn{1,n1,n2}d_1=d_n,\ \ d_n\in \{ 1,n-1,n-2 \}
      • d1=dn=2,n=5d_1=d_n=2,\ \ n=5
      • d1>d2=dn=1d_1\gt d_2=d_n=1
      • d1>d2=dn=2,d1{n1,n2}d_1\gt d_2=d_n=2,\ \ d_1\in\{n-1,n-2\}
      • n2=d1=dn1>dnn-2=d_1=d_{n-1}\gt d_n
      • n3=d1=dn1>dn=1n-3=d_1=d_{n-1}\gt d_n=1
      • n1=d1>d2=dn=3,n=6n-1=d_1\gt d_2=d_{n}=3,\ \ n=6

      # 定理 - 简单图度数不可能互不相同

      一个简单图 GGnn 个点的度不能互不相同

      证明: 因为图 G 为简单图,所以:Δ(G)n1\Delta(G)\leq n - 1


      情形 1:若 GG 没有孤立点,则 1d(v)n1,vV(G)1 ≤ d(v)≤ n - 1,\ \ \ ∀v \in V(G) , 由鸽笼原理:必有两顶点度数相同;


      情形 2:若 GG 只有一个孤立点,设 G1G_1 表示 G 去掉孤立点后的部分,则:

      1d(v)n2,vV(G1)1 ≤ d(v)≤ n - 2,\ \ \ ∀v \in V(G_1)

      由鸽笼原理:在 G1G_1 里必有两顶点度数相同;


      情形 3:若 GG 只有两个以上的孤立点,则定理显然成立。


      # 频序列

      nn 阶图 GG 的各点的度取了 ss 个不同的非负整数 d1,d2,,dsd_1,d_2,\cdots,d_s 。 又 设 度 为 did_i 的 点 有 bib_i 个 (i=1,2,,s)i=1,2,\cdots,s) , 则有 i=1sbi=n\sum_{i=1}^{s}b_i =n 。故非负整数组 (d1,d2,,dsd_1,d_2,\cdots,d_s) 是 nn 的一个划分,称为 GG频序列

      # 性质

      一个 nn 阶图 GG 和它的补图有相同的频序列

      # 拓扑不变量

      GG拓扑不变量是指与图 GG 有关的一个数或数组 (向量)。它对于与图 GG 同构的所有图来说,不会发生改变。

      一个图 GG 可以对应很多拓扑不变量。如果某组不变量可完全决定一个图,称它为不变量的完全集

      # 图的运算

      # 子图和真子图

      如果 V(H)V(G),E(H)E(G)V(H) \subseteq V(G),E(H)\subseteq E(G) ,且 HH 中边的重数不超过 GG 中对应边的重数 , 则称 HHGG子图,记为 HGH \subseteq G 。有时又称 GGHH母图

      HGH\subseteq G ,但 HGH\neq G 时,则记为 HGH\subset G ,且称 HHGG真子图

      # 生成子图

      GG生成子图是指满足 V(H)=V(G)V (H) = V (G ) 的子图 HH。也就是包含所有顶点但不包含所有边的子图。

      # 计数性质

      简单图 G=(n,m)G=(n,m) 的所有不同的生成子图个数是 2m2^m (包括 GG 本身和空图)。

      # 导出子图

      假设 VV'VV 的一个非空子集。以 VV' 为顶点集,以两端点均在 VV' 中的边的全体为边集所组成的子图,称为 GG 的由 VV' 导出的子图,记为 G[V]G[V'],简称为 GG(点) 导出子图

      假设 EE'EE 的非空子集。以 EE' 为边集,以 EE' 中边的端点全体为顶点集所组成的子图称为 GG 的由 EE' 导出的子图,记为 G[E]G[E'],简称为 GG边导出子图

      # 删点运算

      (点) 导出子图 G[V\V]G[V\backslash V'] 记为 GVG-V'。它是 GG 中删除 VV' 中的项点以及与这些项点相关联的边所得到的子图。若 V={v}V'=\{v\} ,则把 G{v}G-\{v\} 简记为 GvG-v

      # 删边运算

      边集为 E\EE\backslash E'GG 的边导出子图简记为 GEG-E' 。若 E={e}E'=\{e\} ,则把 GeG-{e} 简记为 GeG-e

      ⚠️删边运算会删掉那些度数变为 0 的顶点⚠️


      G1G_1G2G_2GG 的子图。若 G1G_1G2G_2 无公共顶点,则称它们是不相交

      G1G_1G2G_2 无公共边,则称它们是边不重

      # 并运算

      G1G_1G2G_2并图 G1UG2G_1UG_2 是指 GG 的一个子图:

      • 其顶点集为 V(G1)V(G2)V(G_1)\cup V(G_2)
      • 其边集为 E(G1)E(G2)E(G_1)\cup E(G_2)

      如果 G1G_1G2G_2 是不相交的,有时就记其并图为 G1+G2G_1+G_2

      # 交运算

      G1G_1G2G_2交图 G1G2G_1\cap G_2 ,是指 GG 的一个子图:

      • 其顶点集为 V(G1)V(G2)V(G_1)\cap V(G_2)
      • 其边集为 E(G1)E(G2)E(G_1)\cap E(G_2)

      此时 G1G_1G2G_2 至少要有一个公共顶点!

      # 差运算

      G1G_1G2G_2 G1G2G_1-G_2 是由 G1G_1 中去掉 G2G_2 中的边组成的图 。

      没有去掉那些边的端点!即使剩下 0 度数端点仍要保留!

      # 对称差 / 环和差

      G1G_1G2G_2对称差 G1ΔG2G_1 \Delta G_2G1G2G_1 \cup G_2 去掉 G1G2G_1 \cap G_2 所得到的图,即 :

      G1ΔG2=(G1G2)(G1G2)=(G1G2)(G2G1)G_1 \Delta G_2 = (G_1 \cup G_2)-(G_1 \cap G_2) = (G_1 - G_2) \cup (G_2-G_1)

      # 联运算

      在不相交的 G1G_1G2G_2 的并图 G1G2G_1 \cup G_2 中,把 G1G_1 的每个项点和 G2G_2 的每个项点连接起来所得到的 图称为 G1G_1G2G_2联图,记为 G1G2G_1 \lor G_2


      uiadjviu_i\ \mathrm{adj}\ v_i 表示 uiu_iviv_i 邻接

      # (笛卡尔) 积运算

      G1=(V1,E1),G2=(V2,E2)G_1 =(V_1 , E_1),G_2 =(V_2 ,E_2)对点集 V=V1×V2V=V_1 \times V_2 (笛卡尔集)中任意两个点 u=(u1,u2)u=(u_1,u_2)v=(v1,v2)v=(v_1,v_2) ,当以下式子成立时:

      (u1=v1u2adjv2)(u2=v2u1adjv1)(u_1 =v_1\land u_2\ \mathrm{adj}\ v_2)\lor(u_2=v_2\land u_1\ \mathrm{adj}\ v_1)

      就把 uuvv 连接起来所得到的图 GG 称为 G1G_1G2G_2积图,记为 G=G1×G2G=G_1 \times G_2

      # 合成运算

      Gi=(V1,E1)G_i=(V_1,E_1)G2=(V2,E2)G_2=(V_2,E_2) , 对点集 V=V1×V2V=V_1 \times V_2 (笛卡尔集)中任意两个点 u=(u1,u2)u=(u_1,u_2)v=(v1,v2)v=(v_1,v_2) ,当以下式子成立时:

      (u1adjv1)(u1=v1u2adjv2)(u_1\ \mathrm{adj}\ v_1)\lor(u_1=v_1\land u_2\ \mathrm{adj}\ v_2)

      就把 uuvv 连接起来所得到的图 GG 称为 G1G_1G2G_2合成图,记为 G=G1[G2]G=G_1[G_2]

      G1[G2]G_1[G_2]G2[G1]G_2[G_1] 可能是同构的,也可能是不同构的


      积运算和合成运算中,得到的点集 VV 的定义都是相同的,都是笛卡尔集 V=V1×V2V=V_1 \times V_2 ;但是边集的定义有所不同


      运算点的数目边的数目
      G1G2G_1\cup G_2n1+n2n_1 + n_2m1+m2m_1 + m_2
      G1G2G_1\lor G_2n1+n2n_1 + n_2m1+m2+n1n2m_1 + m_2 +n_1 n_2
      G1×G2G_1\times G_2n1n2n_1 n_2n1m2+n2m1n_1m_2 + n_2m_1
      合成 G1[G2]G_1[G_2]n1n2n_1 n_2n1m2+n22m1n_1m_2 + {n_2}^2m_1

      # 方体

      一族特别重要的图称为方体,它用积来定义最为自然。

      nn 方体 QnQ_n 递推地定义为:

      • Q1=K2Q_1=K_2
      • Qn=K2×Qn1Q_n=K_2\times Q_{n-1}

      QnQ_n2n2^n 个点,它的点可以用二进制串 a1a2ana_1 a_2 \cdots a_n 来标定,其中 ai{0,1}a_i\in\{0,1\}

      QnQ_n 两个点的二进制表示式中只有一位不同,则它们邻接

      2方体

      3方体

      # 路与图的连通性

      # 途径、迹、路

      一个有限非空序列:

      w=v0e1v1e2v2ekvkw=v_0\ e_1\ v_1\ e_2\ v_2\cdots e_k\ v_k

      它的项交替地为顶点和边,使得对 1ik1\leq i\leq keie_i ,的端点是 vi1v_{i-1}viv_i、 称 ww 是从 v0v_0vkv_k 的一条途径,或一条 (v0,vk)(v_0,v_k) 途径

      途径中边数称为途径的长度

      v0v_0vkv_k 分别称为途径的起点终点,其余顶点称为途径的内部点

      一条途径的起点与终点重合时叫做闭途径

      边不重复的途径称为图的一条,起点与终点重合时叫做闭迹,也称为回路

      顶点不重复的途径称为图的一条,起点与终点重合时叫做。显然顶点不重复时边也不重复,所以迹是包含路的。

      起点与终点重合的途径、迹、路分别称为图的闭途径、闭迹与圈。闭迹也称为回路

      长度为 kk 的圈称为 kk 圈,kk 为奇数时称为奇圈kk 为偶数时称为偶圈

      # 圈的充分条件

      δ2\delta ≥2,则 GG 中必然含有圈。

      只就连通图证明即可!

      W=v1v2vk1vkW=v_1 v_2\cdots v_{k-1}v_kGG 中的一条最长路。由于 δ2\delta≥2,所以 vkv_k 必然有相异于 vk1v_{k-1} 的邻接顶点。

      WW 是连通图 GG 中最长路,所以,这样的邻接点必然是 v1v2vk2v_1 v_2\cdots v_{k-2} 中之一。设该点为 vmv_m ,则 vmvm+1vkvmv_m v_{m+1}\cdots v_k v_mGG 中圈。

      # 偶图的充要条件

      一个图是二部图 (偶图) 当且当它不包含奇圈


      证明必要性:

      GG 是具有二分类 (X,Y)(X,Y) 的偶图,并且 C=v0v1vkv0C=v_0 v_1\cdots v_k v_0GG 的一个圈

      不失一般性,可假定 v0Xv_0\in X

      一般说来,v2iX,v2i+1Yv_{2i}\in X,v_{2i+1}\in Y

      又因为v0Xv_0\in X ,所以 vkYv_k\in Y,由此即得 CC 是偶圈


      证明充分性:

      GG 中任意选取点 uu,定义 VV 的分类如下:

      • X={xd(u,x)是偶数,xV(G)}X=\{x|d(u,x)\text{是偶数},x\in V(G)\}
      • Y={yd(u,y)是奇数,yV(G)}Y=\{y|d(u,y)\text{是奇数},y\in V(G)\}

      (接下来证明 XX 中任意两点 v,wv,w 不邻接)

      v,wv,wXX 中任意两个顶点,PP 是一条最短 (u,v)(u,v) 路,而 QQ 是一条最短 (u,w)(u,w) 路,设 u1u_1PPQQ 的最后一个交点:

      偶图充分必要条件充分性证明

      由于 P,QP,Q 是最短路,所以,P,QP,Quuu1u_1 段长度相同,因此奇偶性相同

      P,QP,Q 的长均是偶数,所以,P,QP,Qu1vu_1 v 段和 u1wu_1 w 段奇偶性相同

      如果 v,wv,w 邻接则可得到奇圈,矛盾!

      # 两顶点的距离

      图中顶点 uuvv 的距离: uuvv 间最短路的长度称为 uuvv 间距离。记为:

      d(u,v)d(u,v)

      如果 uuvv 间不存在路,定义:

      d(u,v)=0d(u,v)=0

      # 两顶点的连通性

      GG 中点 uuvv 说是连通的,如果 uuvv存在通路。否则称 uuvv 不连通

      点的连通关系是等价关系

      非连通图中每一个极大连通部分,称为 GG连通分支

      GG 的连通分支的个数,称为 GG分支数,记为:

      ω(G)\omega(G)

      # 图的连通性

      如果图 GG 中任意两点是连通的,称 GG连通图,否则,称 GG非连通图

      # 连通图的性质

      nn 阶连通图中:

      1. 至少有 n1n-1 条边
      2. 如果边数大于 n1n-1,则至少有一条闭迹
      3. 如果恰有 n1n-1 条边,则至少有一个奇度点

      (2)证明:

      GG 中没有 11 度顶点,由握手定理:

      2m=vV(G)d(v)2nmnm>n12m=\sum_{v\in V(G)}d(v)\geq 2n \rArr m\geq n \rArr m \gt n-1


      (3)证明:

      若不然,GG 中顶点度数至少为 22,于是由握手定理:

      2m=v(G)d(v)2nmnm>n12m=\sum_{v\in(G)}d(v) \geq 2n \rArr m ≥n \rArr m > n-1

      这与 GG 中恰有 n1n-1 条边矛盾!

      # 补图的连通性

      若图 GG 是不连通的,则它的补图 G\overline G 是连通图.


      证明:设 u,vu,vGG 的任意两个顶点:

      • uuvvGG 中不邻接,则在 G\overline G 中它们邻接,从而 G\overline G 是连通的
      • uuvvGG 中邻接,它们属于 GG 的同一分支;在另一个分支中有一点 ww,在 G\overline Guuvv 均与 w 邻接,即 uwvuwv 是一条通道,从而 G\overline G 是连通的

      # 连通图充分条件 1

      设图 GGnn 阶图,若 GG 中任意两个不相邻的点 uuvv,有:

      d(u)+d(v)n1d(u)+d(v)\geq n-1

      GG 是连通的,且 d(G)2d(G)\leq 2


      证明:对 GG 中任意两点 xxyy,一定存在一条长度至多为 22 的连接 xxyy 的路

      xyE(G)xy\in E(G) 时上述论断显然成立;

      xyE(G)xy\notin E(G) 时:

      可以证明,存在点 ww,它与 xxyy 同时邻接。反证法:

      若不然,在 GG 的剩下 n2n-2 个顶点中,假设:

      • kk 个与 xx 邻接,但与 yy 不邻接;
      • ll 个与 yy 邻接,但与 xx 不邻接;
      • mm 个顶点和 x,yx,y 均不邻接。

      则:d(x)=kd(x)=kd(y)=ld(y)=l

      由于 k+l+m=n2k+l+m=n-2

      所以 d(x)+d(y)=nm2n2d(x)+d(y)=n-m-2\leq n-2 ,矛盾!


      # 连通图充分条件 2

      GGnn 阶图,若 δn12\delta≥\frac{n-1}{2} ,则 GG 连通


      证明:

      对 G 中任意两个不相邻顶点 u 与 v,有:

      d(u)+d(v)n12+n12=n1d(u)+d(v)\geq\frac{n-1}{2}+\frac{n-1}{2}=n-1

      所以,G 是连通的。

      该定理的界是紧的 (Sharpness)。即不能再修改!

      例如:设 G 由两个分支作成的图,两个分支均为 KmK_m ,则 G 中不相邻顶点度数之和恰为 n-2 . (n=2m)

      # 图的直径

      连通图 G 的直径定义为

      d(G)=max{d(u,v)u,vV(G)}d(G) = \text{max}\{d(u,v)|u,v \in V(G)\}

      如果 G 不连通,图 G 的直径定义为 d(G)=d(G) = \infin

      # 直径相关性质

      设 G 是具有 m 条边的 n 阶单图,若 G 的直径为 2 且 δ=n2\delta=n-2 ,则 m2n4m≥2n-4


      证明:

      d(v)=Δ=n2d(v)=\Delta=n-2 ,设 v 的邻接点为 v1,v2,,vn2v_1,v_2,\cdots,v_{n-2} ,u 是剩下的一个项点。

      由于 d(G)=2d(G)=2 且 u 不能和 v 邻接,所以 u 至少和 v1,v2,,vn2v_1,v_2,\cdots,v_{n-2} 中的一个顶点邻接。否则有 d(G)>2d(G)>2 ; 不妨假设 u 和 v1,v2,,vkv_1,v_2,\cdots,v_{k} 邻接。

      为了保证 u 到各点距离不超过 2 , vk+1,,vn2v_{k+1},\cdots,v_{n-2} 这些頂点的每一个必须和前面 v1,v2,,vkv_1,v_2,\cdots,v_{k} 中某点邻接,这样,图中至少又有 n-2 条边。总共至少有 2n-4 条边。

      \ No newline at end of file diff --git a/math/discrete-math/graph/match/index.html b/math/discrete-math/graph/match/index.html index e77222ed..244cd4cf 100644 --- a/math/discrete-math/graph/match/index.html +++ b/math/discrete-math/graph/match/index.html @@ -1 +1 @@ -匹配 - 图论 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 匹配

      # 匹配基础概念

      匹配 MM —— 如果 MM 是图 GG 的边子集 (不含环),且 MM 中的任意两条边没有共同顶点,则称 MMGG 的一个匹配,或对集,或边独立集。

      如果 GG 中顶点是 GG 的匹配 MM 中某条边的端点,称它为 MM 饱和点,否则为 MM 非饱和点

      最大匹配 MM (无向图定义) —— 如果 MM 是图 GG 的包含边数最多的匹配,称 MMGG 的一个最大匹配。

      特别是,若最大匹配饱和了 GG 的所有顶点,称它为 GG 的一个完美匹配

      MM 交错路 —— 如果 MM 是图 GG 的匹配, GG 中一条由 MM 中的边和非 MM 中的边交错形成的路,称为 GG 中的一条 MM 交错路。

      特别地,若 MM 交错路的起点与终点都是 MM 非饱和点,称这种 MM 交错路为 MM 可扩路

      # 贝尔热定理

      Berge

      GG 的匹配 MM 是最大匹配,当且仅当 GG 不包含 MM 可扩路。

      # HALL 定理

      完美匹配的充要条件,将 XX 视为需求,YY 视为供给,可以理解为供给必须满足需求。

      G=(X,Y)G=(X,Y) 是偶图,则 GG 存在饱和 XX 每个顶点的完美匹配的充要条件是:

      SX,N(S)S\forall S\subseteq X,\ \ |N(S)|\geq|S|

      其中 N(S)N(S) 表示 SS 的邻集(图 GG 中所有与 SS 相邻接顶点的集合),N(S)N(S) 一定是 YY 的子集。

      G=(X,Y)G=(X,Y) 存在饱和 XX 每个顶点的匹配也常说成存在由 XXYY 的匹配 。

      ⭐️推论:若 GGk(k>0)k(k\gt0) 正则偶图,则 GG 存在完美匹配。

      # 典例

      # 例 1

      证明每个 kk 方体都是 kk 正则偶图。

      事实上,由 kk 方体的构造: kk 方体有 2k2k 个顶点,每个顶点可以用长度为 kk 的二进制码来表示,两个顶点连线当且仅当代表两个顶点的二进制码只有一位坐标不同。

      如果我们划分 kk 方体的 2k2k 个顶点,把坐标之和为偶数的顶点归入 XX,否则归入 YY 。显然,XX 中顶点互不邻接,YY 中顶点也如此。所以 kk 方体是偶图。

      又不难知道 kk 方体的每个顶点度数为 kk , 所以 kk 方体是 kk 正则偶图。

      由推论: kk 方体存在完美匹配。

      直接在 k 方体中找出完美匹配。

      kk 方体顶点二进制码为 x1,x2,,xkx_1,x_2,\cdots,x_k , 我们取 x1,x2,,xk1,0x_1,x_2,\cdots,x_{k-1},0 , 和

      (x1,x2,,xk1,1)(x-1,x_2,\cdots,x_{k-1},1) 之间的全体边所成之集为 MM

      显然,MM 中的边均不相邻接,所以作成 kk 方体的匹配,又容易知道:M=2k1|M|=2^{k-1},所以 MM 是完美匹配。

      # 例 2

      𝐾2𝑛𝐾_{2𝑛}𝐾𝑛,𝑛𝐾_{𝑛,𝑛} 中不同的完美匹配的个数

      𝐾2𝑛𝐾_{2𝑛} 的任意一个顶点有 2𝑛12𝑛-1 种不同的方法被匹配。所以 𝐾2𝑛𝐾_{2𝑛} 的不同完美匹配个数等于 (2𝑛1)𝐾2𝑛2(2𝑛-1)𝐾_{2𝑛-2} , 如此推下去,可以归纳出 𝐾2𝑛𝐾_{2𝑛} 的不同完美匹配个数为:(2𝑛1)!!(2𝑛-1)!!

      同样的推导方法可归纳出 𝐾𝑛,𝑛𝐾_{𝑛,𝑛} 的不同完美匹配个数为:𝑛!𝑛!

      # 例 3

      证明树至多存在一个完美匹配。

      证明:若不然,设 𝑀1𝑀_1𝑀2𝑀_2 是树 TT 的两个不同的完美匹配,那么 𝑀1Δ𝑀2𝑀_1\Delta𝑀_2≠\varnothing, 容易知道:𝑇[𝑀1Δ𝑀2]𝑇[𝑀_1\Delta 𝑀_2] 每个非空部分顶点度数为 2 ,即它存在圈,于是推出 TT 中有圈,矛盾。

      # 图的点覆盖

      GG 的一个顶点子集 KK 称为 GG 的一个点覆盖,如果 GG 的每条边都至少有一个端点在 KK 中。GG 的一个包含点数最少的点覆盖称为 GG 的最小点覆盖,其包含的点数称为 GG 的覆盖数,记为 α(G)\alpha(G)

      ⭐️设 MMGG 的匹配,KKGG 的覆盖,若 M=K|M|=|K| , 则 MM 是最大匹配,而 KK 是最小覆盖。

      # 哥尼定理

      偶图的点覆盖与偶图匹配间的关系

      在偶图中,最大匹配的边数等于最小覆盖的顶点数。

      # 托特定理

      GG 有完美匹配当且仅当对 VV 的任意非空真子集 SS , 有:

      o(GS)So(G-S)\leq|S|

      o(GS)o(G-S) 表示奇分支数目(有奇数个顶点的分支)

      # 彼得森定理

      哥尼定理的推论,是完美匹配的充分条件而不是必要条件⚠️

      没有割边的 3 正则图存在完美匹配

      # 匈牙利算法

      可以解决问题:

      • 在无权偶图中寻找完美匹配
      • 在有权偶图中寻找最优匹配
        • 在有权偶图中寻找最小匹配(权值和最小)
        • 在有权偶图中寻找最大匹配(权值和最大,通过所有权值取反转化为最小匹配问题)。

      G=(X,Y)G=(X,Y),匈牙利算法需要满足约束:X=Y|X|=|Y|

      基本思想

      从任意初始匹配 M0M_0 出发,通过寻求一条 M0M_0 可扩路 PP ,令 M1=M0ΔE(P)M_1=M_0\Delta E(P) ,得到比 M0M_0 更大的匹配 M1M_1

      1965 年,Edmonds 首先提出:用扎根于 MM 非饱和点 uuMM 交错树的生长来求 MM 可扩路。

      # 无权偶图完美匹配

      # M 交错树

      定义 设 G=(X,Y)G=(X,Y)MMGG 的匹配,uuMM 非饱和点。称树 HHGG 的扎根于点 uuMM 交错树,如果:

      • uV(H)u\in V(H)
      • 对任意 vV(H)v\in V(H)(u,v)(u,v) 路是 MM 交错路;

      扎根于 MM 非饱和点 uuMM 交错树 HH 有两种情形:

      • 情形 1: 除点 uu 外,HH 中所有点为 MM 饱和点,且在 MM 上配对;
      • 情形 2: HH 包含除 uu 外的 MM 非饱和点。

      # 匈牙利算法

      MM 是初始匹配。HH 是扎根于 MM 非饱和点 uu 的交错树。令:S=V(H)XS=V(H)\cap XT=V(H)YT=V(H)\cap Y

      • (a)
        • MM 饱和 XX 所有顶点,停止;
        • 否则,设 uuXXMM 非饱和顶点,置 S={u}S=\{u\}T=T=\varnothing
      • (b)
        • N(S)=TN(S)=T,则 GG 中不存在完美匹配;
        • 否则设 yN(S)Ty\in N(S)-T
      • (c)
        • yyMM 饱和点,且 yzMyz\in M,置 S=S{z}S=S\cup\{z\}T=T{y}T=T\cup \{y\},转(b);
        • 否则,设 PPMM 可扩路,置 M=MΔE(P)M=M\Delta E(P),转(a)

      # 有权图最优匹配

      # 可行顶点标号

      G=(X,Y)G=(X,Y) ,若对 xX,yY\forall x\in X,\forall y\in Y,有:

      l(x)+l(y)w(xy)l(x)+l(y)\geq w(xy)

      则称 ll 是赋权完全偶图 GG可行顶点标号

      一个简单常用的可行顶点标号:

      {l(x)=maxyYw(xy),xXl(y)=0,yY\begin{cases} l(x)=\max_{y\in Y}w(xy),&x\in X\\ l(y)=0,&y\in Y \end{cases}

      # 相等子图

      ll 是赋权完全偶图 G=(X,Y)G=(X,Y) 的可行顶点标号,令:

      El={xyE(G)l(x)+l(y)=w(xy)}E_l=\{xy\in E(G)|l(x)+l(y)=w(xy)\}

      Gl=G[El]G_l=G[E_l]GG 的对应于 ll相等子图

      # Kuhn 算法

      Kuhn 采用顶点标号修改策略,找到了求最优匹配好算法如下

      ⚠️ 求的是权值和最大的匹配⚠️

      给一初始顶点标号 ll ,在相等子图 GlG_l 中任选一个匹配 MM

      (1)

      • XXMM 饱和的,则 MM 是最优匹配;
      • 否则,令 uu 是一个 MM 非饱和点,置 S={u}S=\{u\}T=T=\varnothing

      (2)

      • TNGl(S)T\sub N_{G_l}(S),转(3);
      • 否则,计算:

      αl=minxS,yT{l(x)+l(y)w(xy)}\alpha_l=\min_{x\in S,y\notin T}\{l(x)+l(y)-w(xy)\}

      修改 ll 如下:

      l={l(v)αl,vSl(v)+αl,vTl(v),othersl=\begin{cases} l(v)-\alpha_l,&v\in S\\ l(v)+\alpha_l,&v\in T\\ l(v),&\text{others}\\ \end{cases}

      给出新的可行顶点标号,在新标号下重新开始。

      (3)在 NGl(S)\TN_{G_l}(S)\backslash T 中选择点 yy

      • yyMM 饱和的,yzMyz\in M,则置 S=S{z}S=S\cup\{z\}T=T{y}T=T\cup\{y\},转(2);
      • 否则,设 PPGlG_lMM 可扩路,置 M=MΔE(P)M=M\Delta E(P),转(1)

      该算法把上面原来的匈牙利算法用于其中,主要是用来判定和求完美匹配。

      \ No newline at end of file +匹配 - 图论 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 匹配

      # 匹配基础概念

      匹配 MM —— 如果 MM 是图 GG 的边子集 (不含环),且 MM 中的任意两条边没有共同顶点,则称 MMGG 的一个匹配,或对集,或边独立集。

      如果 GG 中顶点是 GG 的匹配 MM 中某条边的端点,称它为 MM 饱和点,否则为 MM 非饱和点

      最大匹配 MM (无向图定义) —— 如果 MM 是图 GG 的包含边数最多的匹配,称 MMGG 的一个最大匹配。

      特别是,若最大匹配饱和了 GG 的所有顶点,称它为 GG 的一个完美匹配

      MM 交错路 —— 如果 MM 是图 GG 的匹配, GG 中一条由 MM 中的边和非 MM 中的边交错形成的路,称为 GG 中的一条 MM 交错路。

      特别地,若 MM 交错路的起点与终点都是 MM 非饱和点,称这种 MM 交错路为 MM 可扩路

      # 贝尔热定理

      Berge

      GG 的匹配 MM 是最大匹配,当且仅当 GG 不包含 MM 可扩路。

      # HALL 定理

      完美匹配的充要条件,将 XX 视为需求,YY 视为供给,可以理解为供给必须满足需求。

      G=(X,Y)G=(X,Y) 是偶图,则 GG 存在饱和 XX 每个顶点的完美匹配的充要条件是:

      SX,N(S)S\forall S\subseteq X,\ \ |N(S)|\geq|S|

      其中 N(S)N(S) 表示 SS 的邻集(图 GG 中所有与 SS 相邻接顶点的集合),N(S)N(S) 一定是 YY 的子集。

      G=(X,Y)G=(X,Y) 存在饱和 XX 每个顶点的匹配也常说成存在由 XXYY 的匹配 。

      ⭐️推论:若 GGk(k>0)k(k\gt0) 正则偶图,则 GG 存在完美匹配。

      # 典例

      # 例 1

      证明每个 kk 方体都是 kk 正则偶图。

      事实上,由 kk 方体的构造: kk 方体有 2k2k 个顶点,每个顶点可以用长度为 kk 的二进制码来表示,两个顶点连线当且仅当代表两个顶点的二进制码只有一位坐标不同。

      如果我们划分 kk 方体的 2k2k 个顶点,把坐标之和为偶数的顶点归入 XX,否则归入 YY 。显然,XX 中顶点互不邻接,YY 中顶点也如此。所以 kk 方体是偶图。

      又不难知道 kk 方体的每个顶点度数为 kk , 所以 kk 方体是 kk 正则偶图。

      由推论: kk 方体存在完美匹配。

      直接在 k 方体中找出完美匹配。

      kk 方体顶点二进制码为 x1,x2,,xkx_1,x_2,\cdots,x_k , 我们取 x1,x2,,xk1,0x_1,x_2,\cdots,x_{k-1},0 , 和

      (x1,x2,,xk1,1)(x-1,x_2,\cdots,x_{k-1},1) 之间的全体边所成之集为 MM

      显然,MM 中的边均不相邻接,所以作成 kk 方体的匹配,又容易知道:M=2k1|M|=2^{k-1},所以 MM 是完美匹配。

      # 例 2

      𝐾2𝑛𝐾_{2𝑛}𝐾𝑛,𝑛𝐾_{𝑛,𝑛} 中不同的完美匹配的个数

      𝐾2𝑛𝐾_{2𝑛} 的任意一个顶点有 2𝑛12𝑛-1 种不同的方法被匹配。所以 𝐾2𝑛𝐾_{2𝑛} 的不同完美匹配个数等于 (2𝑛1)𝐾2𝑛2(2𝑛-1)𝐾_{2𝑛-2} , 如此推下去,可以归纳出 𝐾2𝑛𝐾_{2𝑛} 的不同完美匹配个数为:(2𝑛1)!!(2𝑛-1)!!

      同样的推导方法可归纳出 𝐾𝑛,𝑛𝐾_{𝑛,𝑛} 的不同完美匹配个数为:𝑛!𝑛!

      # 例 3

      证明树至多存在一个完美匹配。

      证明:若不然,设 𝑀1𝑀_1𝑀2𝑀_2 是树 TT 的两个不同的完美匹配,那么 𝑀1Δ𝑀2𝑀_1\Delta𝑀_2≠\varnothing, 容易知道:𝑇[𝑀1Δ𝑀2]𝑇[𝑀_1\Delta 𝑀_2] 每个非空部分顶点度数为 2 ,即它存在圈,于是推出 TT 中有圈,矛盾。

      # 图的点覆盖

      GG 的一个顶点子集 KK 称为 GG 的一个点覆盖,如果 GG 的每条边都至少有一个端点在 KK 中。GG 的一个包含点数最少的点覆盖称为 GG 的最小点覆盖,其包含的点数称为 GG 的覆盖数,记为 α(G)\alpha(G)

      ⭐️设 MMGG 的匹配,KKGG 的覆盖,若 M=K|M|=|K| , 则 MM 是最大匹配,而 KK 是最小覆盖。

      # 哥尼定理

      偶图的点覆盖与偶图匹配间的关系

      在偶图中,最大匹配的边数等于最小覆盖的顶点数。

      # 托特定理

      GG 有完美匹配当且仅当对 VV 的任意非空真子集 SS , 有:

      o(GS)So(G-S)\leq|S|

      o(GS)o(G-S) 表示奇分支数目(有奇数个顶点的分支)

      # 彼得森定理

      哥尼定理的推论,是完美匹配的充分条件而不是必要条件⚠️

      没有割边的 3 正则图存在完美匹配

      # 匈牙利算法

      可以解决问题:

      • 在无权偶图中寻找完美匹配
      • 在有权偶图中寻找最优匹配
        • 在有权偶图中寻找最小匹配(权值和最小)
        • 在有权偶图中寻找最大匹配(权值和最大,通过所有权值取反转化为最小匹配问题)。

      G=(X,Y)G=(X,Y),匈牙利算法需要满足约束:X=Y|X|=|Y|

      基本思想

      从任意初始匹配 M0M_0 出发,通过寻求一条 M0M_0 可扩路 PP ,令 M1=M0ΔE(P)M_1=M_0\Delta E(P) ,得到比 M0M_0 更大的匹配 M1M_1

      1965 年,Edmonds 首先提出:用扎根于 MM 非饱和点 uuMM 交错树的生长来求 MM 可扩路。

      # 无权偶图完美匹配

      # M 交错树

      定义 设 G=(X,Y)G=(X,Y)MMGG 的匹配,uuMM 非饱和点。称树 HHGG 的扎根于点 uuMM 交错树,如果:

      • uV(H)u\in V(H)
      • 对任意 vV(H)v\in V(H)(u,v)(u,v) 路是 MM 交错路;

      扎根于 MM 非饱和点 uuMM 交错树 HH 有两种情形:

      • 情形 1: 除点 uu 外,HH 中所有点为 MM 饱和点,且在 MM 上配对;
      • 情形 2: HH 包含除 uu 外的 MM 非饱和点。

      # 匈牙利算法

      MM 是初始匹配。HH 是扎根于 MM 非饱和点 uu 的交错树。令:S=V(H)XS=V(H)\cap XT=V(H)YT=V(H)\cap Y

      • (a)
        • MM 饱和 XX 所有顶点,停止;
        • 否则,设 uuXXMM 非饱和顶点,置 S={u}S=\{u\}T=T=\varnothing
      • (b)
        • N(S)=TN(S)=T,则 GG 中不存在完美匹配;
        • 否则设 yN(S)Ty\in N(S)-T
      • (c)
        • yyMM 饱和点,且 yzMyz\in M,置 S=S{z}S=S\cup\{z\}T=T{y}T=T\cup \{y\},转(b);
        • 否则,设 PPMM 可扩路,置 M=MΔE(P)M=M\Delta E(P),转(a)

      # 有权图最优匹配

      # 可行顶点标号

      G=(X,Y)G=(X,Y) ,若对 xX,yY\forall x\in X,\forall y\in Y,有:

      l(x)+l(y)w(xy)l(x)+l(y)\geq w(xy)

      则称 ll 是赋权完全偶图 GG可行顶点标号

      一个简单常用的可行顶点标号:

      {l(x)=maxyYw(xy),xXl(y)=0,yY\begin{cases} l(x)=\max_{y\in Y}w(xy),&x\in X\\ l(y)=0,&y\in Y \end{cases}

      # 相等子图

      ll 是赋权完全偶图 G=(X,Y)G=(X,Y) 的可行顶点标号,令:

      El={xyE(G)l(x)+l(y)=w(xy)}E_l=\{xy\in E(G)|l(x)+l(y)=w(xy)\}

      Gl=G[El]G_l=G[E_l]GG 的对应于 ll相等子图

      # Kuhn 算法

      Kuhn 采用顶点标号修改策略,找到了求最优匹配好算法如下

      ⚠️ 求的是权值和最大的匹配⚠️

      给一初始顶点标号 ll ,在相等子图 GlG_l 中任选一个匹配 MM

      (1)

      • XXMM 饱和的,则 MM 是最优匹配;
      • 否则,令 uu 是一个 MM 非饱和点,置 S={u}S=\{u\}T=T=\varnothing

      (2)

      • TNGl(S)T\sub N_{G_l}(S),转(3);
      • 否则,计算:

      αl=minxS,yT{l(x)+l(y)w(xy)}\alpha_l=\min_{x\in S,y\notin T}\{l(x)+l(y)-w(xy)\}

      修改 ll 如下:

      l={l(v)αl,vSl(v)+αl,vTl(v),othersl=\begin{cases} l(v)-\alpha_l,&v\in S\\ l(v)+\alpha_l,&v\in T\\ l(v),&\text{others}\\ \end{cases}

      给出新的可行顶点标号,在新标号下重新开始。

      (3)在 NGl(S)\TN_{G_l}(S)\backslash T 中选择点 yy

      • yyMM 饱和的,yzMyz\in M,则置 S=S{z}S=S\cup\{z\}T=T{y}T=T\cup\{y\},转(2);
      • 否则,设 PPGlG_lMM 可扩路,置 M=MΔE(P)M=M\Delta E(P),转(1)

      该算法把上面原来的匈牙利算法用于其中,主要是用来判定和求完美匹配。

      \ No newline at end of file diff --git a/math/discrete-math/graph/planar-graph/index.html b/math/discrete-math/graph/planar-graph/index.html index 1b2ef0bf..d0f68ba7 100644 --- a/math/discrete-math/graph/planar-graph/index.html +++ b/math/discrete-math/graph/planar-graph/index.html @@ -1 +1 @@ -平面图 - 图论 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      如果能把图 GG 画在平面上,使得除顶点外,边与边之间没有交叉,称 GG 可嵌入平面,或称 GG 是可平面图

      可平面图 GG 的边不交叉的一种画法,称为 GG 的一种平面嵌入GG 的平面嵌入表示的图称为平面图

      可平面图概念和平面图概念有时可以等同看待;

      图的平面性问题主要涉及如下几个方面:

      • 平面图的性质
      • 平面图的判定
      • 平面嵌入方法 (平面性算法)
      • 涉及图的平面性问题的拓扑不变量

      # 平面图的性质

      一个平面图 GG 把平面分成若干连通片,这些连通片称为 GG区域,或 GG 的一个GG 的面组成的集合用 Φ\Phi 表示。

      面积有限的区域称为平面图 GG内部面,否则称为 GG外部面

      GG 中,顶点和边都与某个给定区域关联的子图,称为该面的边界。某面 ff 的边界中含有的边数 (割边计算 2 次⚠️) 称为该面 ff次数,记 degf\deg f

      # 平面图的次数公式

      G=(n,m)G=(n,m) 是平面图,则:

      fΦdeg(f)=2m\sum_{f\in\Phi}\deg(f)=2m


      证明:

      GG 的任意一条边 ee, 如果 ee 是某面割边,那么由面的次数定义,该边给 GG 的总次数贡献 2 次;如果 ee 不是割边,那么,它必然是两个面的公共边,因此,由面的次数定义,它也给总次数贡献 2 次。

      # 连通平面图的欧拉公式

      G=(n,m)G=(n,m)连通平面图,φ\varphiGG 的面数,则:

      nm+φ=2n-m+\varphi=2


      证明:

      情形 1,如果 GG 是树。

      那么 m=n1m=n-1, 𝜑=1。在这种情况下,容易验证,定理中的恒等式是成立的。

      情形 2, GG 不是树的连通平面图。

      假设在这种情形下,欧拉恒等式不成立。则存在一个含有最少边数的连通平面图 GG,使得它不满足欧拉恒等式。设这个最少边数连通平面图 G=(n,m)G=(n,m),面数为 𝜑,则:

      nm+φ2n-m+\varphi\neq2

      因为 GG 不是树,所以存在非割边 ee。显然,GeG-e 是连通平面图,边数为 m1m-1,顶点数为 nn,面数为 𝜑-1。由最少性假设GeG-e 满足欧拉等式:

      n(m1)+(φ1)=2nm+φ=2\begin{aligned} n-(m-1)+(\varphi-1)&=2\\ n-m+\varphi&=2 \end{aligned}

      于是矛盾,假设不成立。

      # 非连通平面图的欧拉公式

      G=(n,m)G=(n,m)kk 个连通分支的平面图,φ\varphiGG 的面数,则:

      nm+φ=k+1n-m+\varphi=k+1


      证明:

      对第 i(1ik)i(1≤i≤k) 个分支来说,设顶点数为 nin_i,边数为 mim_i,面数为 𝜑_i,由欧拉公式:

      nimi+φi=2i=1k(nimi+φi)=2ki=1knii=1kmi+i=1kφi=2k\begin{aligned} n_i-m_i+\varphi_i&=2\\ \sum_{i=1}^{k}(n_i-m_i+\varphi_i)&=2k\\ \sum_{i=1}^{k}n_i-\sum_{i=1}^{k}m_i+\sum_{i=1}^{k}\varphi_i&=2k \end{aligned}

      同时:(扣除重复计算的 k1k-1 个外部面)

      i=1kni=n,i=1kmi=m,i=1kφi=φ+k1\sum_{i=1}^{k}n_i=n,\ \ \sum_{i=1}^{k}m_i=m,\ \ \sum_{i=1}^{k}\varphi_i=\varphi+k-1

      于是得到:

      nm+(φ+k1)=2knm+φ=k+1\begin{aligned} n-m+(\varphi+k-1)&=2k\\ n-m+\varphi&=k+1 \end{aligned}

      GG 是具有 nn 个点 mm 条边 𝜑 个面的连通平面图,如果对 GG 的每个面 ff,有 degfl3\deg f≥l≥3,则:

      mll2(n2)m\leq\frac{l}{l-2}(n-2)

      这是连通平面图的必要条件,不是充分条件!

      GG 是具有 nn 个点 mm 条边 𝜑 个面的连通平面图,有:

      m3n6m\leq3n-6

      GG 是具有 nn 个点 mm 条边 𝜑 个面的连通平面图,如果对 GG 的每个面 ff,有 degf=l\deg f=l,则:

      m(l2)=l(n2)m(l-2)=l(n-2)

      GG 是具有 nn 个点 mm 条边 𝜑 个面的连通平面图,有:

      δ5\delta\leq5

      该结论是证明 “5 色定理” 的出发点

      一个连通平面图是 22 连通的,当且仅当它的每个面的边界是圈。

      # 图的嵌入性问题

      # 曲面嵌入

      # 球面嵌入

      ⭐️ GG 可球面嵌入与 GG 可平面嵌入等价

      我们实际上对图的嵌入性问题也只考虑这两个。

      # 环面嵌入

      # 定向曲面嵌入

      # 3 维空间嵌入

      所有图均可嵌入 R3R^3 中。

      # 凸多面体与平面图

      一个多面体称为凸多面体,如果在体上任取两点,其连线均在体上。

      凸多面体的一维骨架:把一个凸多面体压缩在平面上,得到一个对应的平面图,该平面图称为该凸多面体的一维骨架。

      存在且只存在 5 种正多面体:它们是正四、六、八、十二、二十面体

      # 平面图的判定

      # 同胚

      • 在图 GG 的边上插入一个新的 22 度顶点,使一条边分成两条边,则称将图 GG 在 2 度顶点内扩充
      • 去掉图 的一个 22 度顶点,使这个 22 度顶点关联的两条边合成一条边,则称将 GG 在 2 度顶点内收缩

      两个图 G1G_1G2G_2,如果 G1G2G_1\cong G_2,或者通过反复在 22 度顶点内扩充和收缩它们能变成同构的,则称 G2G_2G2G_2同胚的,或 G1G_1G2G_2 22 度顶点内是同构的

      ⭐️图的可平面性在同胚意义下不变。

      # 库拉托夫斯基定理

      GG 是可平面的当且仅当它不含与 K5K_5K3,3K_{3,3} 同胚的子图

      库拉托夫斯基定理可以等价叙述为:「图 GG 是非可平面的当且仅当它含有与 K5K_5K3,3K_{3,3} 同胚的子图」

      给定图 GG,去掉 GG 中的环 (若有的话),将 GG 中的重边 (若有的话) 用单边代替,称这样所得的图为 GG基础简单图

      • GG 是可平面图当且仅当其基础简单图是可平面图
      • GG 是可平面图当且仅当它的每个块是可平面图

      # 初等收缩

      uvuv 是简单图 GG 的一条边。去掉该边,重合其端点,再删去由此产生的环和重边。这一过程称为图 GG初等收缩收缩边 uvuv 的运算,并记所得之图为 G/uvG/uv

      一个图 GG 可收缩到 HH,是指 HH 可从 GG 通过一系列初等收缩而得到。

      # 瓦格纳定理

      简单图 GG 是可平面图当且仅当它不含可收缩到 K5K_5K3,3K_{3,3} 的子图。

      该定理和库拉托夫斯基定理是等价的。

      至少有 9 个点的简单可平面图的补图是不可平面的,而 9 是这种数目中最小的一个

      # 平面性的拓扑不变量

      # 亏格

      # 环柄

      在边交叉处建立的 “立交桥”,通过环柄使得一条边经过 “桥下”,另一条边经过 “桥上”,使二者分开。

      # 亏格定义

      若通过加上 kk 个环柄可将图 GG 嵌入球面,则 kk 得最小值称为 GG亏格,记为:

      γ(G)\gamma(G)

      • GG 是可平面图,则 γ(G)=0\gamma(G)=0
      • 同胚的图是亏格相等;
      • γ(K5)=1\gamma(K_5)=1

      # 引入亏格的欧拉公式

      对一个亏格为 γ\gamma,有 nn 个顶点,mm 条边和 φ\varphi 个面的多面体或连通图,有:

      nm+φ=22γn-m+\varphi=2-2\gamma

      # 结论

      GG 是一个有 nn 个顶点,mm 条边和 φ\varphi 个面的多面体或连通图,有:

      • γm6n22\gamma\geq\frac{m}{6}-\frac{n-2}{2}
      • GG 无三角形,则 γm4n22\gamma\geq\frac{m}{4}-\frac{n-2}{2}
      • GG 每个面是三角形,则 m=3(n2+2γ)m=3(n-2+2\gamma)
      • GG 每个面是四边形,则 m=2(n2+2γ)m=2(n-2+2\gamma)

      # 厚度

      若图 GGkk 个可平面子图的并等于 ,则称 kk 的最小值为 GG厚度,记为

      GG 是可平面图当且仅当 θ(G)=1\theta(G)=1

      # 叉数

      GG 画在平面上时相交的边对的最少数目称为 GG叉数,记为:

      η(G)\eta(G)

      GG 是可平面图当且仅当 η(G)=0\eta(G)=0

      # 糙度

      GG 中边不重的不可平面子图的最多数目称为 GG糙度,记为:

      ζ(G)\zeta(G)

      # 平面性算法

      HH 是图 GG 的一个子图,在 E(G)\E(H)E(G)\backslash E(H) 上定义关系 \sim 如下:e1e2e_1\sim e_2 当且仅当存在一条途径 WW,使得:

      • WW 的第一条边与最后一条边分别是 e1e_1e2e_2
      • WW 的内部顶点与 HH 不相交

      易证关系 \sim 具有自反性,对称性和传递性,从而是 E(G)\E(H)E(G)\backslash E(H) 上的一个等价关系

      此等价关系的等价类导出的 GE(H)G-E(H) 的边导出子图称为 HH - 片段,或者 GG 关于 HH 的桥。片段或桥与 HH 的公共顶点称为附着顶点

      • BBHH - 片段,则 BB 是连通图
      • BB 的任何两个顶点都有和 HH 的内部不相交的路相连接
      • 不计 HH 的顶点,任意两 HH - 片段没有公共顶点

      HH 是图 GG 的一个圈,图 GG 的两个 HH - 片段 B1B_1B2B_2冲突的,如果

      • B1B_1B2B_2HH 上有三个公共的附着顶点;或
      • HH 上存在四个顺序排列的顶点 v1,v2,v3,v4v_1,v_2,v_3,v_4 使得 v1,v3v_1,v_3B1B_1 的附着顶点并且 v2,v4v_2,v_4B2B_2 的附着顶点

      冲突的两个片段无法同时平面嵌入到同一个面中

      HH 是图 GG 的一个圈,以图 GGHH - 片段为顶点,顶点间连一条边当且仅当对应的 HH - 片段是冲突的,把这样得到的图称为 HH 的冲突图

      HH 是图 GG 的可平面子图,是 H~\tilde H 的一种平面嵌入。若 GG 也是可平面图,且存在 GG 的一个平面嵌入 H~\tilde H,使得:

      H~G~\tilde H\subseteq\tilde G

      则称 H~\tilde HGG 容许的。

      GG 是可平面的当且仅当对 GG 的每个圈 HH,其冲突图是二部图

      HH 是图 GG 的一个可平面子图,HH'HH 的一个平面嵌入。假定 BB 是子图 HH 的任一片段,若 BBHH 的所有附着顶点都位于 HH' 中某个面 ff 的边界上,则称 BBHH' 的面 ff 中是可画入的,否则,称为不可画入的。令:

      F(B,H)={ffH的面且Bf中可画入}F(B,H)=\{f|f\text{是}H'\text{的面且}B\text{在}f\text{中可画入}\}

      假定 HH' 如实线所示,则片段 B3B_3 在外部面上是可画入的,而 B2B_2 对面 f2f_2f3f_3 均为不可画入的,且 F(B1,H)={f1,f3}F(B_1,H)=\{f_1,f_3\}

      可画入示例

      # 算法流程

      如果 GG 非可平面,通过算法可以得到判定;如果 GG 是可平面图,通过算法,可以给出一种平面嵌入形式。

      GG 是至少有三个顶点的简单块,取 GG 的任意一个圈 HH,求出 HH 的一个平面嵌入。若无圈,则 GG 是一棵树,一定可平面。

      初始取 GG 的一个圈 H1H _1,并作平面嵌入 H~1\tilde H_1。假设 HiH_i 已确定,下面确定 Hi+1H_{i+1},算法流程如下:

      1. 判断 E(G)\E(Hi)=E(G)\backslash E(H_i)=\varnothing
        • 若是空集
          • 🖐则停,返回 GG 可平面。
        • 否则
          1. 确定 HiH_i 的所有片段 (桥),
          2. 对每个片段 (桥) BB,求集合 F(B,Hi)F(B,H_i)
      2. 判断是否存在片段 BB,使 F(B,H~i)=F(B,\tilde H_i)=\varnothing
        • 若存在
          • 🖐则停 ,返回 GG 不可平面。
        • 否则
          1. HiH_i 的所有片段中确定一个使 F(B,H~i)|F(B,\tilde H_i)| 最小的片段 BB
            • (⭐️这 2 步的选取具有随机性,算法的随机性来自于这一步)
          2. 并取 fF(B,H~i)f\in F(B,\tilde H_i)
          3. 在片段 BB 上取一条连接 HiH_i 上两个附着点的路 PiP_i
          4. PiP_i 画在 H~i\tilde H_i 的面 ff 内得到 Hi+1=HiPiH_{i+1}=H_i\cup P_i
      3. i=i+1i=i+1,转第 1
      \ No newline at end of file +平面图 - 图论 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      如果能把图 GG 画在平面上,使得除顶点外,边与边之间没有交叉,称 GG 可嵌入平面,或称 GG 是可平面图

      可平面图 GG 的边不交叉的一种画法,称为 GG 的一种平面嵌入GG 的平面嵌入表示的图称为平面图

      可平面图概念和平面图概念有时可以等同看待;

      图的平面性问题主要涉及如下几个方面:

      • 平面图的性质
      • 平面图的判定
      • 平面嵌入方法 (平面性算法)
      • 涉及图的平面性问题的拓扑不变量

      # 平面图的性质

      一个平面图 GG 把平面分成若干连通片,这些连通片称为 GG区域,或 GG 的一个GG 的面组成的集合用 Φ\Phi 表示。

      面积有限的区域称为平面图 GG内部面,否则称为 GG外部面

      GG 中,顶点和边都与某个给定区域关联的子图,称为该面的边界。某面 ff 的边界中含有的边数 (割边计算 2 次⚠️) 称为该面 ff次数,记 degf\deg f

      # 平面图的次数公式

      G=(n,m)G=(n,m) 是平面图,则:

      fΦdeg(f)=2m\sum_{f\in\Phi}\deg(f)=2m


      证明:

      GG 的任意一条边 ee, 如果 ee 是某面割边,那么由面的次数定义,该边给 GG 的总次数贡献 2 次;如果 ee 不是割边,那么,它必然是两个面的公共边,因此,由面的次数定义,它也给总次数贡献 2 次。

      # 连通平面图的欧拉公式

      G=(n,m)G=(n,m)连通平面图,φ\varphiGG 的面数,则:

      nm+φ=2n-m+\varphi=2


      证明:

      情形 1,如果 GG 是树。

      那么 m=n1m=n-1, 𝜑=1。在这种情况下,容易验证,定理中的恒等式是成立的。

      情形 2, GG 不是树的连通平面图。

      假设在这种情形下,欧拉恒等式不成立。则存在一个含有最少边数的连通平面图 GG,使得它不满足欧拉恒等式。设这个最少边数连通平面图 G=(n,m)G=(n,m),面数为 𝜑,则:

      nm+φ2n-m+\varphi\neq2

      因为 GG 不是树,所以存在非割边 ee。显然,GeG-e 是连通平面图,边数为 m1m-1,顶点数为 nn,面数为 𝜑-1。由最少性假设GeG-e 满足欧拉等式:

      n(m1)+(φ1)=2nm+φ=2\begin{aligned} n-(m-1)+(\varphi-1)&=2\\ n-m+\varphi&=2 \end{aligned}

      于是矛盾,假设不成立。

      # 非连通平面图的欧拉公式

      G=(n,m)G=(n,m)kk 个连通分支的平面图,φ\varphiGG 的面数,则:

      nm+φ=k+1n-m+\varphi=k+1


      证明:

      对第 i(1ik)i(1≤i≤k) 个分支来说,设顶点数为 nin_i,边数为 mim_i,面数为 𝜑_i,由欧拉公式:

      nimi+φi=2i=1k(nimi+φi)=2ki=1knii=1kmi+i=1kφi=2k\begin{aligned} n_i-m_i+\varphi_i&=2\\ \sum_{i=1}^{k}(n_i-m_i+\varphi_i)&=2k\\ \sum_{i=1}^{k}n_i-\sum_{i=1}^{k}m_i+\sum_{i=1}^{k}\varphi_i&=2k \end{aligned}

      同时:(扣除重复计算的 k1k-1 个外部面)

      i=1kni=n,i=1kmi=m,i=1kφi=φ+k1\sum_{i=1}^{k}n_i=n,\ \ \sum_{i=1}^{k}m_i=m,\ \ \sum_{i=1}^{k}\varphi_i=\varphi+k-1

      于是得到:

      nm+(φ+k1)=2knm+φ=k+1\begin{aligned} n-m+(\varphi+k-1)&=2k\\ n-m+\varphi&=k+1 \end{aligned}

      GG 是具有 nn 个点 mm 条边 𝜑 个面的连通平面图,如果对 GG 的每个面 ff,有 degfl3\deg f≥l≥3,则:

      mll2(n2)m\leq\frac{l}{l-2}(n-2)

      这是连通平面图的必要条件,不是充分条件!

      GG 是具有 nn 个点 mm 条边 𝜑 个面的连通平面图,有:

      m3n6m\leq3n-6

      GG 是具有 nn 个点 mm 条边 𝜑 个面的连通平面图,如果对 GG 的每个面 ff,有 degf=l\deg f=l,则:

      m(l2)=l(n2)m(l-2)=l(n-2)

      GG 是具有 nn 个点 mm 条边 𝜑 个面的连通平面图,有:

      δ5\delta\leq5

      该结论是证明 “5 色定理” 的出发点

      一个连通平面图是 22 连通的,当且仅当它的每个面的边界是圈。

      # 图的嵌入性问题

      # 曲面嵌入

      # 球面嵌入

      ⭐️ GG 可球面嵌入与 GG 可平面嵌入等价

      我们实际上对图的嵌入性问题也只考虑这两个。

      # 环面嵌入

      # 定向曲面嵌入

      # 3 维空间嵌入

      所有图均可嵌入 R3R^3 中。

      # 凸多面体与平面图

      一个多面体称为凸多面体,如果在体上任取两点,其连线均在体上。

      凸多面体的一维骨架:把一个凸多面体压缩在平面上,得到一个对应的平面图,该平面图称为该凸多面体的一维骨架。

      存在且只存在 5 种正多面体:它们是正四、六、八、十二、二十面体

      # 平面图的判定

      # 同胚

      • 在图 GG 的边上插入一个新的 22 度顶点,使一条边分成两条边,则称将图 GG 在 2 度顶点内扩充
      • 去掉图 的一个 22 度顶点,使这个 22 度顶点关联的两条边合成一条边,则称将 GG 在 2 度顶点内收缩

      两个图 G1G_1G2G_2,如果 G1G2G_1\cong G_2,或者通过反复在 22 度顶点内扩充和收缩它们能变成同构的,则称 G2G_2G2G_2同胚的,或 G1G_1G2G_2 22 度顶点内是同构的

      ⭐️图的可平面性在同胚意义下不变。

      # 库拉托夫斯基定理

      GG 是可平面的当且仅当它不含与 K5K_5K3,3K_{3,3} 同胚的子图

      库拉托夫斯基定理可以等价叙述为:「图 GG 是非可平面的当且仅当它含有与 K5K_5K3,3K_{3,3} 同胚的子图」

      给定图 GG,去掉 GG 中的环 (若有的话),将 GG 中的重边 (若有的话) 用单边代替,称这样所得的图为 GG基础简单图

      • GG 是可平面图当且仅当其基础简单图是可平面图
      • GG 是可平面图当且仅当它的每个块是可平面图

      # 初等收缩

      uvuv 是简单图 GG 的一条边。去掉该边,重合其端点,再删去由此产生的环和重边。这一过程称为图 GG初等收缩收缩边 uvuv 的运算,并记所得之图为 G/uvG/uv

      一个图 GG 可收缩到 HH,是指 HH 可从 GG 通过一系列初等收缩而得到。

      # 瓦格纳定理

      简单图 GG 是可平面图当且仅当它不含可收缩到 K5K_5K3,3K_{3,3} 的子图。

      该定理和库拉托夫斯基定理是等价的。

      至少有 9 个点的简单可平面图的补图是不可平面的,而 9 是这种数目中最小的一个

      # 平面性的拓扑不变量

      # 亏格

      # 环柄

      在边交叉处建立的 “立交桥”,通过环柄使得一条边经过 “桥下”,另一条边经过 “桥上”,使二者分开。

      # 亏格定义

      若通过加上 kk 个环柄可将图 GG 嵌入球面,则 kk 得最小值称为 GG亏格,记为:

      γ(G)\gamma(G)

      • GG 是可平面图,则 γ(G)=0\gamma(G)=0
      • 同胚的图是亏格相等;
      • γ(K5)=1\gamma(K_5)=1

      # 引入亏格的欧拉公式

      对一个亏格为 γ\gamma,有 nn 个顶点,mm 条边和 φ\varphi 个面的多面体或连通图,有:

      nm+φ=22γn-m+\varphi=2-2\gamma

      # 结论

      GG 是一个有 nn 个顶点,mm 条边和 φ\varphi 个面的多面体或连通图,有:

      • γm6n22\gamma\geq\frac{m}{6}-\frac{n-2}{2}
      • GG 无三角形,则 γm4n22\gamma\geq\frac{m}{4}-\frac{n-2}{2}
      • GG 每个面是三角形,则 m=3(n2+2γ)m=3(n-2+2\gamma)
      • GG 每个面是四边形,则 m=2(n2+2γ)m=2(n-2+2\gamma)

      # 厚度

      若图 GGkk 个可平面子图的并等于 ,则称 kk 的最小值为 GG厚度,记为

      GG 是可平面图当且仅当 θ(G)=1\theta(G)=1

      # 叉数

      GG 画在平面上时相交的边对的最少数目称为 GG叉数,记为:

      η(G)\eta(G)

      GG 是可平面图当且仅当 η(G)=0\eta(G)=0

      # 糙度

      GG 中边不重的不可平面子图的最多数目称为 GG糙度,记为:

      ζ(G)\zeta(G)

      # 平面性算法

      HH 是图 GG 的一个子图,在 E(G)\E(H)E(G)\backslash E(H) 上定义关系 \sim 如下:e1e2e_1\sim e_2 当且仅当存在一条途径 WW,使得:

      • WW 的第一条边与最后一条边分别是 e1e_1e2e_2
      • WW 的内部顶点与 HH 不相交

      易证关系 \sim 具有自反性,对称性和传递性,从而是 E(G)\E(H)E(G)\backslash E(H) 上的一个等价关系

      此等价关系的等价类导出的 GE(H)G-E(H) 的边导出子图称为 HH - 片段,或者 GG 关于 HH 的桥。片段或桥与 HH 的公共顶点称为附着顶点

      • BBHH - 片段,则 BB 是连通图
      • BB 的任何两个顶点都有和 HH 的内部不相交的路相连接
      • 不计 HH 的顶点,任意两 HH - 片段没有公共顶点

      HH 是图 GG 的一个圈,图 GG 的两个 HH - 片段 B1B_1B2B_2冲突的,如果

      • B1B_1B2B_2HH 上有三个公共的附着顶点;或
      • HH 上存在四个顺序排列的顶点 v1,v2,v3,v4v_1,v_2,v_3,v_4 使得 v1,v3v_1,v_3B1B_1 的附着顶点并且 v2,v4v_2,v_4B2B_2 的附着顶点

      冲突的两个片段无法同时平面嵌入到同一个面中

      HH 是图 GG 的一个圈,以图 GGHH - 片段为顶点,顶点间连一条边当且仅当对应的 HH - 片段是冲突的,把这样得到的图称为 HH 的冲突图

      HH 是图 GG 的可平面子图,是 H~\tilde H 的一种平面嵌入。若 GG 也是可平面图,且存在 GG 的一个平面嵌入 H~\tilde H,使得:

      H~G~\tilde H\subseteq\tilde G

      则称 H~\tilde HGG 容许的。

      GG 是可平面的当且仅当对 GG 的每个圈 HH,其冲突图是二部图

      HH 是图 GG 的一个可平面子图,HH'HH 的一个平面嵌入。假定 BB 是子图 HH 的任一片段,若 BBHH 的所有附着顶点都位于 HH' 中某个面 ff 的边界上,则称 BBHH' 的面 ff 中是可画入的,否则,称为不可画入的。令:

      F(B,H)={ffH的面且Bf中可画入}F(B,H)=\{f|f\text{是}H'\text{的面且}B\text{在}f\text{中可画入}\}

      假定 HH' 如实线所示,则片段 B3B_3 在外部面上是可画入的,而 B2B_2 对面 f2f_2f3f_3 均为不可画入的,且 F(B1,H)={f1,f3}F(B_1,H)=\{f_1,f_3\}

      可画入示例

      # 算法流程

      如果 GG 非可平面,通过算法可以得到判定;如果 GG 是可平面图,通过算法,可以给出一种平面嵌入形式。

      GG 是至少有三个顶点的简单块,取 GG 的任意一个圈 HH,求出 HH 的一个平面嵌入。若无圈,则 GG 是一棵树,一定可平面。

      初始取 GG 的一个圈 H1H _1,并作平面嵌入 H~1\tilde H_1。假设 HiH_i 已确定,下面确定 Hi+1H_{i+1},算法流程如下:

      1. 判断 E(G)\E(Hi)=E(G)\backslash E(H_i)=\varnothing
        • 若是空集
          • 🖐则停,返回 GG 可平面。
        • 否则
          1. 确定 HiH_i 的所有片段 (桥),
          2. 对每个片段 (桥) BB,求集合 F(B,Hi)F(B,H_i)
      2. 判断是否存在片段 BB,使 F(B,H~i)=F(B,\tilde H_i)=\varnothing
        • 若存在
          • 🖐则停 ,返回 GG 不可平面。
        • 否则
          1. HiH_i 的所有片段中确定一个使 F(B,H~i)|F(B,\tilde H_i)| 最小的片段 BB
            • (⭐️这 2 步的选取具有随机性,算法的随机性来自于这一步)
          2. 并取 fF(B,H~i)f\in F(B,\tilde H_i)
          3. 在片段 BB 上取一条连接 HiH_i 上两个附着点的路 PiP_i
          4. PiP_i 画在 H~i\tilde H_i 的面 ff 内得到 Hi+1=HiPiH_{i+1}=H_i\cup P_i
      3. i=i+1i=i+1,转第 1
      \ No newline at end of file diff --git a/math/discrete-math/graph/shortest-path-algorithms/index.html b/math/discrete-math/graph/shortest-path-algorithms/index.html index 49b79e15..ca934b3c 100644 --- a/math/discrete-math/graph/shortest-path-algorithms/index.html +++ b/math/discrete-math/graph/shortest-path-algorithms/index.html @@ -1 +1 @@ -最短路径算法 - 图论 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      This article ism't finished yet...

      # 顶点标号法

      Dantzig 算法,1959 年,旦捷希 (Dantzig) 发现了在赋权图中求由点 a 到点 b 的最短路好算法,称为顶点标号法。

      和弗洛伊德算法非常非常像... ,在这里补充一下 Floyid 算法对邻接矩阵求最短距离矩阵过程,这个过程和 Dantzig 几乎一致(完全一致好吧,考试可能会考?):

      • 按顺序一列一列看,看第 ii 列时:
        • 按顺序一行一行看,看第 jj 行时,若 ajia_{ji}\neq\infin 则:
          • 看第 jj 列,看 aji+akja_{ji}+a_{kj} 是否是新的 iikk 的最短距离

      # 数据结构

      • t(an)t(a_n) : 点 ana_n 的标号值,表示点 a1=aa_1=aana_n 的最短路长度
      • Ai={a1,a2,,ai}A_i =\{a_1,a_2,\cdots,a_i\} : 已经标号的顶点集合
      • TiT_i : aaaia_i 的最短路上的边集合

      # 算法步骤

      1. 记:

        • a=a1a=a_1 ,
        • t(a1)=0t(a_1)=0 ,
        • A1={a1}A_1=\{a_1\} ,
        • T=T=\varnothing ;
      2. 若已经得到 Ai={a,a2,,ai}A_i=\{a,a_2,\cdots,a_i\} , 且对于 1ni1≤n\leq i , 已知 t(an)t(a_n)每一个 anAia_n\in A_i , 求一点:

        bn(i)N(an)Ai=Bn(i)b_n^{(i)}\in N(a_n)-A_i=B_n^{(i)}

        使得:

        l(anbn(i))=minvBn(i)l(anv)l(a_n b_n^{(i)})=\min_{v\in B_n^{(i)}}l(a_n v)

        这里 ii 表示第 ii 轮,N(an)N(a_n) 表示与 ana_n 邻接的点组成的集合,N 表示 Neighbour

      3. 设有 jj , 1ji1≤j\leq i , 而 bj(i)b_{j}^{(i)} 是使 t(aj)+l(ajbj(i))t(a_{j})+l(a_{j}b_{j}^{(i)}) 取最小值,令:

        • ai+1=bj(i)a_{i+1}=b_{j}^{(i)}
        • t(ai+1)=t(aj)+l(ajai+1)t(a_{i+1})= t(a_{j})+l(a_{j}a_{i+1})
        • Ti+1=Ti{ajai+1}T_{i+1}=T_i\cup\{a_{j}a_{i+1}\}
        • ai+1=ba_{i+1}=b , 停止;
        • 否则,记 Ai+1=Ai{ai+1}A_{i+1}=A_i\cup\{a_{i+1}\}, 转 (2)

      # 时间复杂度

      对第 ii 次循环:

      • 步骤 (2) 要进行 ii 次比较运算
      • 步骤 (3) 要进行 ii 次加法与 ii 次比较运算

      所以,该次循环运算量为 3i3i

      所以,在最坏的情况下,运算量为 n2n^2 级,是好算法

      # 完备性证明

      定理 1:算法中的函数 t(an)t(a_n) 给出了 aaaia_i 的距离
      证明:对 ii 作数学归纳法

      1. i=1i=1 时结论显然成立;
      2. 设对所有的 jj1ji1\leq j\leq i 时,t(aj)=d(a,aj)t(a_j)= d(a,a_j)
      3. 考虑 j=i+1j=i+1

      顶点标记法完备性证明

      于是 d=d(a,ai+1)d=d(a,a_{i+1})

      又令 vnv_n 是 P 中第一个不在 AiA_{i} 中的点。由于 ai+1Aia_{i+1} \notin A_{i} , 所以这样的点存在

      因为 v0Aiv_0\in A_{i} ,所以 n1n\geq 1

      记 P 中 aavn+1v_{n+1} 一段长为 ll , 而 aavnv_{n} 的一段长为 l1l_1

      由归纳假设有: l1t(vn)l_1\geq t(v_{n}) ,进而有:

      d=d(a,ai+1)l=l1+l(vnvn+1)t(vn)+l(vnvn+1)d=d(a,a_{i+1})\geq l=l_1+l(v_{n}v_{n+1})\geq t(v_{n})+l(v_{n}v_{n+1})

      算法中,当第 ii 轮中已知 Ai={a1,a2,,ai}A_{i}=\{a_1,a_2,\cdots,a_{i}\} 要给 ai+1a_{i+1} 标号时,其中要选择 bn(i)b_{n}^{(i)} ,满足:

      l(vnbn(i))l(vnvn+1)l(v_{n}b_{n}^{(i)})\leq l(v_{n}v_{n+1})

      だから:

      dt(vn)+l(vnvn+1)t(vn)+l(vnbn(i))d\geq t(v_{n})+l(v_{n}v_{n+1})\geq t(v_{n})+l(v_{n}b_{n}^{(i)})

      又由算法最终对点 aia_i 的标号值的选择方法知;

      dt(vn)+l(vnbn(i))t(aj)+l(ajai+1)t(ai+1)d\geq t(v_{n})+l(v_{n}b_{n}^{(i)})\geq t(a_{j})+l(a_{j}a_{i+1})\geq t(a_{i+1})

      另一方面,由算法可知存在一条长度为 t(ai)t(a_i) 的联结 aaaia_i 的路,所以:

      t(ai+1)d(a,ai+1)t(a_{i+1})\geq d(a,a_{i+1})

      从而得到 t(ai+1)d(a,ai+1)t(ai+1)t(a_{i+1})\geq d(a,a_{i+1})\geq t(a_{i+1}) ,即得到:t(ai+1)=d(a,ai+1)t(a_{i+1})=d(a,a_{i+1})

      # 应用举例

      # 分酒

      某两人有一只 8 升的酒壶装满了酒,还有两只空酒壶,分别为 5 升和 3 升,求最少的操作次数能均分酒

      解:设 x1,x2,x3x_1,x_2,x_3 分别表示 8,5,3 升酒壶中的酒量。则

      x1+x2+x3=8,x18,x25,x33x_1+x_2+x_3=8,\ \ \ x_1≤8,x_2≤5,x_3≤3

      容易算出 (x1,x2,x3)(x_1,x_2,x_3) 的组合形式共 24 种

      每种组合用一个点表示,两点连线,当且仅当可通过倒酒的方式相互变换。若各边赋权为 1,则问题转化为在该图中求 (8,0,0)(8,0,0)(4,4,0)(4,4,0) 的一条最短路。结果如下:

      (8,0,0)(3,5,0)(3,2,3)(6,2,0)(6,0,2)(1,5,2)(1,4,3)(4,4,0)(8,0,0)\to(3,5,0)\to(3,2,3)\to(6,2,0)\to(6,0,2)\to(1,5,2)\to(1,4,3)\to(4,4,0)

      这个问题给定了初始状态和目标状态,也可以转化为人工智能中的智能规划问题

      # 狼羊过河

      在一河岸有狼,羊和卷心菜。摆渡人要将它们渡过河去,由于船太小,每次只能载一样东西。由于狼羊,羊卷心菜不能单独相处。问摆渡人至少要多少次才能将其渡过河?

      人,狼,羊,菜所有组合形式为:

      C40+C41+C42+C43+C44=24=16C_4^0+C_4^1+C_4^2+C_4^3+C_4^4=2^4=16

      但是以下组合不能允许出现:狼羊菜,羊菜,狼羊,人,人狼,人菜,共 6 种;

      岸上只能允许出现 10 种组合:人狼羊菜,人狼羊,人狼菜,人羊,空,菜,羊,狼,狼菜,人羊菜;

      每种情况用点表示,两点连线,当且仅当两种情况可用载人 (或加一物) 的渡船相互转变,每条边赋权为 1 。于是,问题转化为求由顶点 “人狼羊菜” 到顶点 “空” 的一条最短路问题。结果为:

      人狼羊菜狼菜人狼菜人狼羊人羊\text{人狼羊菜}\to\text{狼菜}\to\text{人狼菜}\to\text{狼}\to\text{人狼羊}\to\text{羊}\to\text{人羊}\to\text{空}

      \ No newline at end of file +最短路径算法 - 图论 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      This article ism't finished yet...

      # 顶点标号法

      Dantzig 算法,1959 年,旦捷希 (Dantzig) 发现了在赋权图中求由点 a 到点 b 的最短路好算法,称为顶点标号法。

      和弗洛伊德算法非常非常像... ,在这里补充一下 Floyid 算法对邻接矩阵求最短距离矩阵过程,这个过程和 Dantzig 几乎一致(完全一致好吧,考试可能会考?):

      • 按顺序一列一列看,看第 ii 列时:
        • 按顺序一行一行看,看第 jj 行时,若 ajia_{ji}\neq\infin 则:
          • 看第 jj 列,看 aji+akja_{ji}+a_{kj} 是否是新的 iikk 的最短距离

      # 数据结构

      • t(an)t(a_n) : 点 ana_n 的标号值,表示点 a1=aa_1=aana_n 的最短路长度
      • Ai={a1,a2,,ai}A_i =\{a_1,a_2,\cdots,a_i\} : 已经标号的顶点集合
      • TiT_i : aaaia_i 的最短路上的边集合

      # 算法步骤

      1. 记:

        • a=a1a=a_1 ,
        • t(a1)=0t(a_1)=0 ,
        • A1={a1}A_1=\{a_1\} ,
        • T=T=\varnothing ;
      2. 若已经得到 Ai={a,a2,,ai}A_i=\{a,a_2,\cdots,a_i\} , 且对于 1ni1≤n\leq i , 已知 t(an)t(a_n)每一个 anAia_n\in A_i , 求一点:

        bn(i)N(an)Ai=Bn(i)b_n^{(i)}\in N(a_n)-A_i=B_n^{(i)}

        使得:

        l(anbn(i))=minvBn(i)l(anv)l(a_n b_n^{(i)})=\min_{v\in B_n^{(i)}}l(a_n v)

        这里 ii 表示第 ii 轮,N(an)N(a_n) 表示与 ana_n 邻接的点组成的集合,N 表示 Neighbour

      3. 设有 jj , 1ji1≤j\leq i , 而 bj(i)b_{j}^{(i)} 是使 t(aj)+l(ajbj(i))t(a_{j})+l(a_{j}b_{j}^{(i)}) 取最小值,令:

        • ai+1=bj(i)a_{i+1}=b_{j}^{(i)}
        • t(ai+1)=t(aj)+l(ajai+1)t(a_{i+1})= t(a_{j})+l(a_{j}a_{i+1})
        • Ti+1=Ti{ajai+1}T_{i+1}=T_i\cup\{a_{j}a_{i+1}\}
        • ai+1=ba_{i+1}=b , 停止;
        • 否则,记 Ai+1=Ai{ai+1}A_{i+1}=A_i\cup\{a_{i+1}\}, 转 (2)

      # 时间复杂度

      对第 ii 次循环:

      • 步骤 (2) 要进行 ii 次比较运算
      • 步骤 (3) 要进行 ii 次加法与 ii 次比较运算

      所以,该次循环运算量为 3i3i

      所以,在最坏的情况下,运算量为 n2n^2 级,是好算法

      # 完备性证明

      定理 1:算法中的函数 t(an)t(a_n) 给出了 aaaia_i 的距离
      证明:对 ii 作数学归纳法

      1. i=1i=1 时结论显然成立;
      2. 设对所有的 jj1ji1\leq j\leq i 时,t(aj)=d(a,aj)t(a_j)= d(a,a_j)
      3. 考虑 j=i+1j=i+1

      顶点标记法完备性证明

      于是 d=d(a,ai+1)d=d(a,a_{i+1})

      又令 vnv_n 是 P 中第一个不在 AiA_{i} 中的点。由于 ai+1Aia_{i+1} \notin A_{i} , 所以这样的点存在

      因为 v0Aiv_0\in A_{i} ,所以 n1n\geq 1

      记 P 中 aavn+1v_{n+1} 一段长为 ll , 而 aavnv_{n} 的一段长为 l1l_1

      由归纳假设有: l1t(vn)l_1\geq t(v_{n}) ,进而有:

      d=d(a,ai+1)l=l1+l(vnvn+1)t(vn)+l(vnvn+1)d=d(a,a_{i+1})\geq l=l_1+l(v_{n}v_{n+1})\geq t(v_{n})+l(v_{n}v_{n+1})

      算法中,当第 ii 轮中已知 Ai={a1,a2,,ai}A_{i}=\{a_1,a_2,\cdots,a_{i}\} 要给 ai+1a_{i+1} 标号时,其中要选择 bn(i)b_{n}^{(i)} ,满足:

      l(vnbn(i))l(vnvn+1)l(v_{n}b_{n}^{(i)})\leq l(v_{n}v_{n+1})

      だから:

      dt(vn)+l(vnvn+1)t(vn)+l(vnbn(i))d\geq t(v_{n})+l(v_{n}v_{n+1})\geq t(v_{n})+l(v_{n}b_{n}^{(i)})

      又由算法最终对点 aia_i 的标号值的选择方法知;

      dt(vn)+l(vnbn(i))t(aj)+l(ajai+1)t(ai+1)d\geq t(v_{n})+l(v_{n}b_{n}^{(i)})\geq t(a_{j})+l(a_{j}a_{i+1})\geq t(a_{i+1})

      另一方面,由算法可知存在一条长度为 t(ai)t(a_i) 的联结 aaaia_i 的路,所以:

      t(ai+1)d(a,ai+1)t(a_{i+1})\geq d(a,a_{i+1})

      从而得到 t(ai+1)d(a,ai+1)t(ai+1)t(a_{i+1})\geq d(a,a_{i+1})\geq t(a_{i+1}) ,即得到:t(ai+1)=d(a,ai+1)t(a_{i+1})=d(a,a_{i+1})

      # 应用举例

      # 分酒

      某两人有一只 8 升的酒壶装满了酒,还有两只空酒壶,分别为 5 升和 3 升,求最少的操作次数能均分酒

      解:设 x1,x2,x3x_1,x_2,x_3 分别表示 8,5,3 升酒壶中的酒量。则

      x1+x2+x3=8,x18,x25,x33x_1+x_2+x_3=8,\ \ \ x_1≤8,x_2≤5,x_3≤3

      容易算出 (x1,x2,x3)(x_1,x_2,x_3) 的组合形式共 24 种

      每种组合用一个点表示,两点连线,当且仅当可通过倒酒的方式相互变换。若各边赋权为 1,则问题转化为在该图中求 (8,0,0)(8,0,0)(4,4,0)(4,4,0) 的一条最短路。结果如下:

      (8,0,0)(3,5,0)(3,2,3)(6,2,0)(6,0,2)(1,5,2)(1,4,3)(4,4,0)(8,0,0)\to(3,5,0)\to(3,2,3)\to(6,2,0)\to(6,0,2)\to(1,5,2)\to(1,4,3)\to(4,4,0)

      这个问题给定了初始状态和目标状态,也可以转化为人工智能中的智能规划问题

      # 狼羊过河

      在一河岸有狼,羊和卷心菜。摆渡人要将它们渡过河去,由于船太小,每次只能载一样东西。由于狼羊,羊卷心菜不能单独相处。问摆渡人至少要多少次才能将其渡过河?

      人,狼,羊,菜所有组合形式为:

      C40+C41+C42+C43+C44=24=16C_4^0+C_4^1+C_4^2+C_4^3+C_4^4=2^4=16

      但是以下组合不能允许出现:狼羊菜,羊菜,狼羊,人,人狼,人菜,共 6 种;

      岸上只能允许出现 10 种组合:人狼羊菜,人狼羊,人狼菜,人羊,空,菜,羊,狼,狼菜,人羊菜;

      每种情况用点表示,两点连线,当且仅当两种情况可用载人 (或加一物) 的渡船相互转变,每条边赋权为 1 。于是,问题转化为求由顶点 “人狼羊菜” 到顶点 “空” 的一条最短路问题。结果为:

      人狼羊菜狼菜人狼菜人狼羊人羊\text{人狼羊菜}\to\text{狼菜}\to\text{人狼菜}\to\text{狼}\to\text{人狼羊}\to\text{羊}\to\text{人羊}\to\text{空}

      \ No newline at end of file diff --git a/math/discrete-math/graph/spectral-clustering/index.html b/math/discrete-math/graph/spectral-clustering/index.html index aa6bb47a..b9b8cd8b 100644 --- a/math/discrete-math/graph/spectral-clustering/index.html +++ b/math/discrete-math/graph/spectral-clustering/index.html @@ -1,4 +1,4 @@ -Spectral Clustering (谱聚类) - 图论 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      This article isn't finished yet...

      Graph Partitioning

      Bi-partitioning task

      # Minmal-cut

      # Normalized-cut

      Criterion: Normalized-cut [Shi-Malik, '97]

      Define: Connectivity between groups relative to the density of each group

      ncut(A,B)=cut(A,B)vol(A)+cut(A,B)vol(B)ncut(\mathbf{A},\mathbf{B})=\frac{cut(\mathbf{A},\mathbf{B})}{vol(\mathbf{A})}+\frac{cut(\mathbf{A},\mathbf{B})}{vol(\mathbf{B})}

      vol(A)vol(\mathbf{A}) : total weight of the edges with at least one endpoint in A\mathbf{A} :

      vol(A)=iAkivol(\mathbf{A})=\sum_{i\in\mathbf{A}}k_i

      The purpose of this criterion is to produce more balanced partitions.

      Spectral Graph Theory:

      Analyze the "spectrum" of matrix(s) representing GG

      Spectrum: Eigenvectors xix_i of a graph, ordered by the magnitude(strength) of their corresponding eigenvalues λi\lambda_i :

      Λ={λ1,λ2,,λn}λ1λ2λn\Lambda=\{\lambda_1,\lambda_2,\cdots,\lambda_n\}\\ \lambda_1\leq\lambda_2\leq\cdots\leq\lambda_n

      dd-regular : the degree of each vertex in the graph is dd

      If GG is not connected, for example, GG has 2 components, each dd-regular.

      每一个特征向量表现了图的划分方式

      What are some eigenvectors?

      # Spectral Partitioning Algorithm

      # 算法流程

      # Pre-processing

      根据图构建拉普拉斯矩阵 LL

      # Decomposition

      * 分解

      LL 的第 2 小的特征值 λ1\lambda_1 (λ0=0\lambda_0=0) 和特征向量 q1\vec{q_1}

      This article isn't finished yet...

      Graph Partitioning

      Bi-partitioning task

      # Minmal-cut

      # Normalized-cut

      Criterion: Normalized-cut [Shi-Malik, '97]

      Define: Connectivity between groups relative to the density of each group

      ncut(A,B)=cut(A,B)vol(A)+cut(A,B)vol(B)ncut(\mathbf{A},\mathbf{B})=\frac{cut(\mathbf{A},\mathbf{B})}{vol(\mathbf{A})}+\frac{cut(\mathbf{A},\mathbf{B})}{vol(\mathbf{B})}

      vol(A)vol(\mathbf{A}) : total weight of the edges with at least one endpoint in A\mathbf{A} :

      vol(A)=iAkivol(\mathbf{A})=\sum_{i\in\mathbf{A}}k_i

      The purpose of this criterion is to produce more balanced partitions.

      Spectral Graph Theory:

      Analyze the "spectrum" of matrix(s) representing GG

      Spectrum: Eigenvectors xix_i of a graph, ordered by the magnitude(strength) of their corresponding eigenvalues λi\lambda_i :

      Λ={λ1,λ2,,λn}λ1λ2λn\Lambda=\{\lambda_1,\lambda_2,\cdots,\lambda_n\}\\ \lambda_1\leq\lambda_2\leq\cdots\leq\lambda_n

      dd-regular : the degree of each vertex in the graph is dd

      If GG is not connected, for example, GG has 2 components, each dd-regular.

      每一个特征向量表现了图的划分方式

      What are some eigenvectors?

      # Spectral Partitioning Algorithm

      # 算法流程

      # Pre-processing

      根据图构建拉普拉斯矩阵 LL

      # Decomposition

      * 分解

      LL 的第 2 小的特征值 λ1\lambda_1 (λ0=0\lambda_0=0) 和特征向量 q1\vec{q_1}nn 个参数对应到 nn 个顶点,可以画图,将参数作为纵坐标,顶点标号作为横坐标,结合图像进行分组 (grouping)

      \ No newline at end of file +c-16-25.333-24-45-24-59z"/>nn 个参数对应到 nn 个顶点,可以画图,将参数作为纵坐标,顶点标号作为横坐标,结合图像进行分组 (grouping)

      \ No newline at end of file diff --git a/math/discrete-math/graph/tree/index.html b/math/discrete-math/graph/tree/index.html index 451d4c1b..9abfc633 100644 --- a/math/discrete-math/graph/tree/index.html +++ b/math/discrete-math/graph/tree/index.html @@ -1 +1 @@ -树 - 图论 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 树的基本性质

      # 树的叶子数

      TT(n,m)(n,m) 树,TT 中有 nin_i 个度为 i,(1ik)i,(1\leq i\leq k) 的点,且有 ni=n\sum n_i=n ,则有:n1=2+n3+2n4++(k2)nkn_1=2+n_3+2n_4+\cdots+(k-2)n_k

      证明:由 m=n1m=n-1 得:

      m=(n1+n2++np)1m=(n_1+n_2+\cdots+n_p)-1

      又由握手定理得:

      2m=n+2n2++knk2m=n+2n_2+\cdots+kn_k

      由上面两等式得:

      n1=2+n3+2n4++(k2)nkn_1=2+n_3+2n_4+\cdots+(k-2)n_k

      # 森林的分支数

      具有 kk 个分支的森林有 nkn-k 条边。


      证明:

      设森林 GGkk 个分支为 Ti(1ik)T_i(1≤i\leq k) ,对每个分支,使用定理 3 得

      m(Ti)=ni1(ni=V(Ti))m(T_i)=n_i-1(n_i=|V(T_i)|)

      所以:

      m(G)=i=1km(Ti)=nkm(G)=\sum_{i=1}^{k}m(T_i)=n-k

      # 图的边数下限

      每个 nn 阶连通图的边数至少为 n1n-1.

      证明:

      (1) 如果 nn 阶连通图 GG 没有一度顶点,那么由握手定理有:

      m(G)=12vV(G)d(v)nm(G)=\frac{1}{2}\sum_{v\in V(G)}d(v)\geq n


      (2) 如果 GG 有一度顶点:

      对顶点数作数学归纳。

      n=1n=1 时,结论显然

      设当 n=kn=k 时,结论成立。

      n=k+1n=k+1 时,设 uuGG 的一度顶点,则 GuG-u 为具有 kk 个顶点的连通图

      (2.1) 若 GuG-u 有一度顶点,则由归纳假设,其边数至少 k1k-1 ,于是 GG 的边数至少有 kk 条;

      (2.2) 如果 GuG-u 没有一度顶点,由握手定理有:

      m(Gu)=12vV(Gu)d(v)km(G-u)=\frac{1}{2}\sum_{v\in V(G-u)}d(v)\geq k

      所以,GG 至少有 k+1k+1 条边。

      而当 GG 是树时,边数恰为 n1n-1 .

      所以 n 阶连通图 G 至少有 n-1 条边。

      所以,树也被称为最小连通图。

      任意树 TT 的两个不邻接顶点之间添加一条边后,可以得到唯一圈


      证明:

      uuvv 是树 TT 的任意两个不邻接顶点,由定理 2 知:有唯一路 PP 连接 uuvv ;于是 P{uv}P\cup\{uv\} 是一圈。

      显然,由 PP 的唯一性也就决定了 P{uv}P\cup\{uv\} 的唯一性。

      # 树的叶子数下限

      GG 是树且 Δk\Delta≥k ,则 GG 至少有 kk 个一度顶点(叶子顶点)


      证明:反证法,假设 GG 有至多 k1k-1 个叶子顶点

      2m(G)=vV(G)d(v)k1+k+2(nk)=2n1>2n22m(G)=\sum_{v\in V(G)}d(v)\geq k-1+k+2(n-k)=2n-1\gt 2n-2

      所以 m(G)>n1m(G)\gt n-1 ,与 GG 是树矛盾!

      # 森林的路分解

      GG 是森林且恰有 2k2k奇度顶点,则在 GG 中有 kk 条边不重合的路 P1,P2,,PkP_1,P_2,\cdots,P_k 使得:

      E(G)=E(P1)E(P2)E(Pk)E(G)=E(P_1)\cup E(P_2)\cup\cdots\cup E(P_k)

      证明:对 kk 作数学归纳。

      k=1k=1 时,GG 只有两个奇数度顶点,此时,容易证明,GG 是一条路;

      设当 k=tk=t 时,结论成立。令 k=t+1k=t+1

      GG 中一个分支中取两个一度项点 uuvv ,令 PP 是连接该两个项点的唯一路,则 GPG-P 是有 2t2t 个奇数顶点的森林,由归纳假设,它可以分解 tt 条边不重合的路之并,所以 GG 可以分解为 t+1t+1 条边不重合的路之并。

      对图作某种形式的分解,是图论的一个研究对象,它在网络结构分析中具有重要作用。

      # 树的同构子图

      TTkk 阶树。若图 GG 满足 δk1\delta≥k-1 ,则 TT 同构于 GG 的某个子图。

      证明:对 kk 作数学归纳

      k=1k=1 时,结论显然。

      假设对 k1,(k3)k-1,(k ≥3) 的每颗树 TT ,以及最小度至少为 k2k-2 的每个图 HHT1T_1 同构于 HH 的某个子图 FF

      现在设 TTkk 阶树,且图 GG 满足 δk1\delta≥k-1 ,证明 TT 同构于 GG 的某个子图:

      uuTT 的树叶,vvuu 的邻接顶点。则 TuT-uk1k-1 阶树。

      由于 δ(G)k1>k2\delta(G)≥k-1>k-2 ,由归纳假设,TuT-u 同构于 GG 的某个子图 FF

      树的同构子图证明

      vv 是与 TTvv 相对应的 FF 中的点,由于 dG(v1)k1d_{G(v_1)}\geq k-1 ,所以 vvGG 中一定有相异于 FF 中的邻点 ww ,作 F{u1w}F\cup\{u_1w\} ,则该子图和 TT 同构。

      # 树的度序列问题

      在第一章中,介绍了判定一个非增非负序列是否为简单图的度序列定理。下面介绍一个判定非增非负序列是否为树的度序列的简单方法。

      S={d1,d2,,dn}S=\{d_1,d_2,\cdots,d_n\}nn 个正整数序列,它们满足:

      • d1d2dnd_1\geq d_2\geq\cdots\geq d_n
      • di=2(n1)\sum di=2(n-1)

      则存在一颗树 TT ,其度序列为 SS


      证明:对 nn 作数学归纳。

      n=1,2n=1,2 时,结论显然。

      假设对 n=kn=k 时结论成立。设 n=k+1n=k+1,

      首先,序列中至少一个数为 1,否则,序列和大于 2k2k ,与条件相矛盾!

      所以,dk+1=1d_{k+1}=1

      我们从序列中删掉 d1d_1dk+1d_{k+1} ,增加数 d=di1d^*=d_i-1 放在它应该在的位置。得到序列 SS ,该序列含 kk 个数,序列和为 2(k1)2(k-1)

      由归纳假设,存在树 TT ,它的度序列为 SiS_i

      现在,增加结点 vv ,把它和 T1T_1 中点 dd^* 相连得到树 TT 为所求

      # 树的中心与形心

      # 中心

      1. 图的顶点的离心率 e(v)=max{d(u,v)uV(G)}e(v)=\max\{d(u,v)|u\in V(G)\}
        • 图的直径最大离心率
      2. 图的半径 r(G)=min{e(v)vV(G)}r(G)=\min\{e(v)|v\in V(G)\}
      3. 图的中心点离心率等于半径的点
      4. 图的中心:全体中心点的集合

      对树 TT 的阶数 nn 作归纳证明。

      n=1,2n=1,2 时,结论显然成立

      设对 n<k,(k3)n<k,(k≥3) 的树结论成立,设 TTkk 阶树

      容易知道,删掉 TT 的所有叶,得到的树 TT ,的每个点的离心率比它们在 TT 中离心率减少 1

      又因 TT 的叶不能是中心点,所以 TT 的中心点在 T1T_1

      这样,若点 uu 的离心率在 TT 中最小,则在 T1T_1 中依然最小,即说明 TT 的中心点是 T1T_1 的中心点,反之亦然。

      # 形心

      uu 是树 TT 的任意一个顶点,树 TT 在顶点 uu 的分支是指包含 uu 作为一个叶点的极大子树,其分支数为顶点 uu 的度数;

      1. uu:树 TTuu 点的分支中边的最大数目称为;
      2. TT形心点:树 TT权值最小的点
      3. TT形心:全体形心点的集合

      每一棵树有一个由一个点两个邻接的点组成的形心。

      # 生成树

      # 生成树的性质

      每个连通图至少包含一棵生成树


      证明:

      如果连通图 GG 是树,则其本身是一棵生成树;

      若连通图 GG 中有圈 CC ,则去掉 CC 中一条边后得到的图仍然是连通的,这样不断去掉 GG 中圈,最后得到一个 GG 的无圈连通子图 TT ,它为 GG 的一棵生成树。

      定理 1 的证明实际上给出了连通图 GG 的生成树的求法,该方法称为破圈法

      推论

      GG(n,m)(n,m) 连通图,则 mn1m≥n-1

      连通图 GG 的生成树一般不唯一⚠️

      # 生成树的计数

      # 凯莱递推计数法

      凯莱 (Cayley 1821-1895): 剑桥大学数学教授,著名代数学家,发表论文数仅次于 Erdos,Euler,Cauchy. 著名成果是 1854 年定义了抽象群,并且得到著名定理:任意一个群都和一个变换群同构。同时,他也是一名出色的律师,作律师 14 年期间,发表 200 多篇数学论文,著名定理也是在该期间发表的。

      GG 的边 ee 称为被收缩,是指删掉 ee 后,把 ee 的两个端点重合,如此得到的图记为G\cdote;

      τ(G)\tau(G) 表示 GG 的生成树颗数。

      τ(G)=τ(Ge)+τ(Ge)\tau(G)=\tau(G-e)+\tau(G\cdot e)


      证明:对于 GG 的一条边 ee 来说,GG 的生成树中包含边 ee 的棵数为 GeG\cdot e ,而不包含 ee 的棵数为 GeG-e

      凯莱公式的缺点是:

      • 计算量很大
      • 不能具体指出每棵生成树

      # 关联矩阵计数法

      n×m 矩阵的一个阶数为 min{n,m}\min\{n,m\} 的子方阵,称为它的一个主子阵;主子阵的行列式称为主子行列式

      显然,当 n<mn<m 时,n×m 矩阵 CmnC_m^n 个主子阵。

      AmA_m 是连通图 GG 的基本关联矩阵的主子阵,则 AmA_m 非奇异的充分必要条件是相应于 AmA_m 的列的那些边构成 GG 的一棵生成树。

      • 该方法的优点是不仅指出生成树棵数,而且能绘出所有不同生成树;
      • 缺点是找所有非奇异主子阵计算量太大!

      # 矩阵树定理

      该定理是由物理学家克希荷夫提出的。他于 1824 年出生于普鲁士的哥尼斯堡。1845 年因宣布著名的克希荷夫电流电压定律而闻名,1847 年大学毕业时发表了生成树计数文章,给出了矩阵树定理。他的一生主要花在实验物理上。担任过德国柏林数学物理会主席职务

      GG 的生成树棵数为拉普拉斯矩阵 LL 的任意一个元素的代数余子式。

      # 最小生成树

      # Kruskal 算法

      克鲁斯克尔 (Kruskal):1928 年生,一家 3 弟兄都是数学家 1954 年在普林斯顿大学获博士学位,导师是 ErdÖs, 他大部分研究工作数学和语言学,主要在贝尔实验室工作。1956 年发表包含克鲁斯克尔算论文,使他名声大振

      GG 中的最小边开始,进行避圈式扩张。

      # 算法流程

      1. 选择边 e1e_1 , 使得其权值最小;
      2. 若已经选定边 e1,e2,,eke_1,e_2,\cdots,e_k ,则从 E{e1,e2,,ek}E-\{e_1,e_2,\cdots,e_k\} 中选择边 ek+1e_{k+1} , 使得:
        • [e1,e2,,ek+1][e_1,e_2,\cdots,e_{k+1}] 为无圈图
        • ek+1e_{k+1} 的权值 w(ek+1)w(e_{k+1}) 尽可能小。
      3. 当 (2) 不能进行时,停止。

      # 完备性证明

      克鲁斯克尔算法得到的任何生成树一定是最小生成树。证明:

      GG 是一个 nn 阶连通赋权图,用 T=G[{e1,e2,,en1}]T^*=G[\{e_1,e_2,\cdots,e_{n-1}\}](导出子图)表示由克鲁斯克尔算法得到的一棵生成树,我们证明:它是最小生成树

      TTGG 的一棵最小生成树。若 TTT^*≠T.

      由克鲁斯克尔算法容易知道:TTT\cap T^*≠\varnothing.

      于是令 f(T)=kf(T)=k 表示 TT^* 中的边 eie_i 不在 TT 中的最小 ii 值。即可令 T=G[{e1,e2,,ek1,ek,,en1}]T=G[\{e_1,e_2,\cdots,e_{k-1},e'_k,\cdots,e'_{n-1}\}](导出子图)

      考虑:TekT∪e_k , 则由树的性质,它必然为 GG 中圈 CC .

      T1=TekeT_1=T∪e_k-e , 容易知道:T1T_1 还为 GG 的一棵生成树。

      ee 是圈 CC 的在 TT 中,但不在 TT^* 中的边。

      由克鲁斯克尔算法知道:w(e)w(ek)w(e)≥w(e_k) .

      所以:w(T)w(T1)w(T)≥w(T_1) .

      这说明 T1T_1 是最小树,但这与 f(T)f(T) 的选取假设矛盾!所以:T=TT=T^*

      # 算法案例

      1. 选一条边 e1e_1 , 使得 w(e1)w(e_1) 尽可能小;
      2. 若边 e1,e2,,eie_1,e_2,\cdots,e_i 已经选定,则用下述方法从 E\{e1,e2,,ei}E\backslash\{e_1,e_2,\cdots,e_i\} 中选取边 e_
        • (a) G[{e1,e2,,ei+1}]G[\{e_1,e_2,\cdots,e_{i+1}\}] 为不相交路之并;
        • (b) w(ei+1)w(e_{i+1}) 是满足 (a) 的尽可能小的权。
      3. 当 (2) 不能继续执行时停止。

      该方法不能得到一条最小生成路

      # 管梅谷的破圈法

      在克鲁斯克尔算法基础上,我国著名数学家管梅谷教授于 1975 年提出了最小生成树的破圈法。

      从赋权图 GG 的任意圈开始,去掉该圈中权值最大的一条边,称为破圈。

      不断破圈,直到 GG 中没有圈为止,最后剩下的 GG 的子图为 GG 的最小生成树

      # Prim 算法

      Prim 算法是由 Prim 在 1957 年提出的一个著名算法。作者因此而出名。Prim (1921---) 1949 年在普林斯顿大学获博士学位,是 Sandia 公司副总裁。

      Kruskal 关注边,Prim 关注点

      对于连通赋权图 GG 的任意一个顶点 uu ,选择与点 uu 关联的且权值最小的边作为最小生成树的第一条边 e1e_1 ;

      在接下来的边 e2,e3,,en1,e_2,e_3,\cdots,e_{n-1}, 在与一条已经选取的边只有一个公共端点的的所有边中,选取权值最小的边。

      # 树图

      连通图 GG 的树图是指这样的图,它的顶点是 GG 的生成树 T1,T2,,TτT_1,T_2,\cdots,T_\tauTiT_iTjT_j 相连当且仅当它们恰有 n2n-2 条公共边。

      # 连通性

      任何连通图的树图是连通图。


      证明:只需证明,对任意 TiT_iTjT_j ,在树图中存在连接它们的路即可!

      对任意 TiT_iTjT_j , 设 e1,e2,,ek(k<n2)e_1,e_2,\cdots,e_k\ (k<n-2) 是它们的公共边。

      由树的性质:ek+1E(Ti)∃e'_{k+1}\in E(T_i) , 但 ek+1∉E(Tj)e'_{k+1}\not\in E(T_j) , 使得:Tj+ek+1T_j +e'_{k+1} 有唯一圈。

      该圈中: ek+1E(Tj)∃e_{k+1}\in E(T_j) , 但 ek+1∉E(Ti)e_{k+1}\not\in E(T_i)

      作: Ti+1=Tiek+1+ek+1T_{i+1}=T_i-e'_{k+1}+e_{k+1} ,则 TiT_iTi+1T_{i+1}n2n-2 条边相同,于是,它们邻接。

      此时,Ti+1T_{i+1}TjT_jk+1k+1 条边相同。

      如此这样作下去,可以得到连接 TiT_iTjT_j 的一条路为:Ti,Ti+1,,TjT_i, T_{i+1},\cdots,T_j

      所以,连通图 GG 的树图是连通的。

      \ No newline at end of file +树 - 图论 - 离散数学 - 数学 | Balloon Party = 風船のパーティー = fuusen no party

      # 树的基本性质

      # 树的叶子数

      TT(n,m)(n,m) 树,TT 中有 nin_i 个度为 i,(1ik)i,(1\leq i\leq k) 的点,且有 ni=n\sum n_i=n ,则有:n1=2+n3+2n4++(k2)nkn_1=2+n_3+2n_4+\cdots+(k-2)n_k

      证明:由 m=n1m=n-1 得:

      m=(n1+n2++np)1m=(n_1+n_2+\cdots+n_p)-1

      又由握手定理得:

      2m=n+2n2++knk2m=n+2n_2+\cdots+kn_k

      由上面两等式得:

      n1=2+n3+2n4++(k2)nkn_1=2+n_3+2n_4+\cdots+(k-2)n_k

      # 森林的分支数

      具有 kk 个分支的森林有 nkn-k 条边。


      证明:

      设森林 GGkk 个分支为 Ti(1ik)T_i(1≤i\leq k) ,对每个分支,使用定理 3 得

      m(Ti)=ni1(ni=V(Ti))m(T_i)=n_i-1(n_i=|V(T_i)|)

      所以:

      m(G)=i=1km(Ti)=nkm(G)=\sum_{i=1}^{k}m(T_i)=n-k

      # 图的边数下限

      每个 nn 阶连通图的边数至少为 n1n-1.

      证明:

      (1) 如果 nn 阶连通图 GG 没有一度顶点,那么由握手定理有:

      m(G)=12vV(G)d(v)nm(G)=\frac{1}{2}\sum_{v\in V(G)}d(v)\geq n


      (2) 如果 GG 有一度顶点:

      对顶点数作数学归纳。

      n=1n=1 时,结论显然

      设当 n=kn=k 时,结论成立。

      n=k+1n=k+1 时,设 uuGG 的一度顶点,则 GuG-u 为具有 kk 个顶点的连通图

      (2.1) 若 GuG-u 有一度顶点,则由归纳假设,其边数至少 k1k-1 ,于是 GG 的边数至少有 kk 条;

      (2.2) 如果 GuG-u 没有一度顶点,由握手定理有:

      m(Gu)=12vV(Gu)d(v)km(G-u)=\frac{1}{2}\sum_{v\in V(G-u)}d(v)\geq k

      所以,GG 至少有 k+1k+1 条边。

      而当 GG 是树时,边数恰为 n1n-1 .

      所以 n 阶连通图 G 至少有 n-1 条边。

      所以,树也被称为最小连通图。

      任意树 TT 的两个不邻接顶点之间添加一条边后,可以得到唯一圈


      证明:

      uuvv 是树 TT 的任意两个不邻接顶点,由定理 2 知:有唯一路 PP 连接 uuvv ;于是 P{uv}P\cup\{uv\} 是一圈。

      显然,由 PP 的唯一性也就决定了 P{uv}P\cup\{uv\} 的唯一性。

      # 树的叶子数下限

      GG 是树且 Δk\Delta≥k ,则 GG 至少有 kk 个一度顶点(叶子顶点)


      证明:反证法,假设 GG 有至多 k1k-1 个叶子顶点

      2m(G)=vV(G)d(v)k1+k+2(nk)=2n1>2n22m(G)=\sum_{v\in V(G)}d(v)\geq k-1+k+2(n-k)=2n-1\gt 2n-2

      所以 m(G)>n1m(G)\gt n-1 ,与 GG 是树矛盾!

      # 森林的路分解

      GG 是森林且恰有 2k2k奇度顶点,则在 GG 中有 kk 条边不重合的路 P1,P2,,PkP_1,P_2,\cdots,P_k 使得:

      E(G)=E(P1)E(P2)E(Pk)E(G)=E(P_1)\cup E(P_2)\cup\cdots\cup E(P_k)

      证明:对 kk 作数学归纳。

      k=1k=1 时,GG 只有两个奇数度顶点,此时,容易证明,GG 是一条路;

      设当 k=tk=t 时,结论成立。令 k=t+1k=t+1

      GG 中一个分支中取两个一度项点 uuvv ,令 PP 是连接该两个项点的唯一路,则 GPG-P 是有 2t2t 个奇数顶点的森林,由归纳假设,它可以分解 tt 条边不重合的路之并,所以 GG 可以分解为 t+1t+1 条边不重合的路之并。

      对图作某种形式的分解,是图论的一个研究对象,它在网络结构分析中具有重要作用。

      # 树的同构子图

      TTkk 阶树。若图 GG 满足 δk1\delta≥k-1 ,则 TT 同构于 GG 的某个子图。

      证明:对 kk 作数学归纳

      k=1k=1 时,结论显然。

      假设对 k1,(k3)k-1,(k ≥3) 的每颗树 TT ,以及最小度至少为 k2k-2 的每个图 HHT1T_1 同构于 HH 的某个子图 FF

      现在设 TTkk 阶树,且图 GG 满足 δk1\delta≥k-1 ,证明 TT 同构于 GG 的某个子图:

      uuTT 的树叶,vvuu 的邻接顶点。则 TuT-uk1k-1 阶树。

      由于 δ(G)k1>k2\delta(G)≥k-1>k-2 ,由归纳假设,TuT-u 同构于 GG 的某个子图 FF

      树的同构子图证明

      vv 是与 TTvv 相对应的 FF 中的点,由于 dG(v1)k1d_{G(v_1)}\geq k-1 ,所以 vvGG 中一定有相异于 FF 中的邻点 ww ,作 F{u1w}F\cup\{u_1w\} ,则该子图和 TT 同构。

      # 树的度序列问题

      在第一章中,介绍了判定一个非增非负序列是否为简单图的度序列定理。下面介绍一个判定非增非负序列是否为树的度序列的简单方法。

      S={d1,d2,,dn}S=\{d_1,d_2,\cdots,d_n\}nn 个正整数序列,它们满足:

      • d1d2dnd_1\geq d_2\geq\cdots\geq d_n
      • di=2(n1)\sum di=2(n-1)

      则存在一颗树 TT ,其度序列为 SS


      证明:对 nn 作数学归纳。

      n=1,2n=1,2 时,结论显然。

      假设对 n=kn=k 时结论成立。设 n=k+1n=k+1,

      首先,序列中至少一个数为 1,否则,序列和大于 2k2k ,与条件相矛盾!

      所以,dk+1=1d_{k+1}=1

      我们从序列中删掉 d1d_1dk+1d_{k+1} ,增加数 d=di1d^*=d_i-1 放在它应该在的位置。得到序列 SS ,该序列含 kk 个数,序列和为 2(k1)2(k-1)

      由归纳假设,存在树 TT ,它的度序列为 SiS_i

      现在,增加结点 vv ,把它和 T1T_1 中点 dd^* 相连得到树 TT 为所求

      # 树的中心与形心

      # 中心

      1. 图的顶点的离心率 e(v)=max{d(u,v)uV(G)}e(v)=\max\{d(u,v)|u\in V(G)\}
        • 图的直径最大离心率
      2. 图的半径 r(G)=min{e(v)vV(G)}r(G)=\min\{e(v)|v\in V(G)\}
      3. 图的中心点离心率等于半径的点
      4. 图的中心:全体中心点的集合

      对树 TT 的阶数 nn 作归纳证明。

      n=1,2n=1,2 时,结论显然成立

      设对 n<k,(k3)n<k,(k≥3) 的树结论成立,设 TTkk 阶树

      容易知道,删掉 TT 的所有叶,得到的树 TT ,的每个点的离心率比它们在 TT 中离心率减少 1

      又因 TT 的叶不能是中心点,所以 TT 的中心点在 T1T_1

      这样,若点 uu 的离心率在 TT 中最小,则在 T1T_1 中依然最小,即说明 TT 的中心点是 T1T_1 的中心点,反之亦然。

      # 形心

      uu 是树 TT 的任意一个顶点,树 TT 在顶点 uu 的分支是指包含 uu 作为一个叶点的极大子树,其分支数为顶点 uu 的度数;

      1. uu:树 TTuu 点的分支中边的最大数目称为;
      2. TT形心点:树 TT权值最小的点
      3. TT形心:全体形心点的集合

      每一棵树有一个由一个点两个邻接的点组成的形心。

      # 生成树

      # 生成树的性质

      每个连通图至少包含一棵生成树


      证明:

      如果连通图 GG 是树,则其本身是一棵生成树;

      若连通图 GG 中有圈 CC ,则去掉 CC 中一条边后得到的图仍然是连通的,这样不断去掉 GG 中圈,最后得到一个 GG 的无圈连通子图 TT ,它为 GG 的一棵生成树。

      定理 1 的证明实际上给出了连通图 GG 的生成树的求法,该方法称为破圈法

      推论

      GG(n,m)(n,m) 连通图,则 mn1m≥n-1

      连通图 GG 的生成树一般不唯一⚠️

      # 生成树的计数

      # 凯莱递推计数法

      凯莱 (Cayley 1821-1895): 剑桥大学数学教授,著名代数学家,发表论文数仅次于 Erdos,Euler,Cauchy. 著名成果是 1854 年定义了抽象群,并且得到著名定理:任意一个群都和一个变换群同构。同时,他也是一名出色的律师,作律师 14 年期间,发表 200 多篇数学论文,著名定理也是在该期间发表的。

      GG 的边 ee 称为被收缩,是指删掉 ee 后,把 ee 的两个端点重合,如此得到的图记为G\cdote;

      τ(G)\tau(G) 表示 GG 的生成树颗数。

      τ(G)=τ(Ge)+τ(Ge)\tau(G)=\tau(G-e)+\tau(G\cdot e)


      证明:对于 GG 的一条边 ee 来说,GG 的生成树中包含边 ee 的棵数为 GeG\cdot e ,而不包含 ee 的棵数为 GeG-e

      凯莱公式的缺点是:

      • 计算量很大
      • 不能具体指出每棵生成树

      # 关联矩阵计数法

      n×m 矩阵的一个阶数为 min{n,m}\min\{n,m\} 的子方阵,称为它的一个主子阵;主子阵的行列式称为主子行列式

      显然,当 n<mn<m 时,n×m 矩阵 CmnC_m^n 个主子阵。

      AmA_m 是连通图 GG 的基本关联矩阵的主子阵,则 AmA_m 非奇异的充分必要条件是相应于 AmA_m 的列的那些边构成 GG 的一棵生成树。

      • 该方法的优点是不仅指出生成树棵数,而且能绘出所有不同生成树;
      • 缺点是找所有非奇异主子阵计算量太大!

      # 矩阵树定理

      该定理是由物理学家克希荷夫提出的。他于 1824 年出生于普鲁士的哥尼斯堡。1845 年因宣布著名的克希荷夫电流电压定律而闻名,1847 年大学毕业时发表了生成树计数文章,给出了矩阵树定理。他的一生主要花在实验物理上。担任过德国柏林数学物理会主席职务

      GG 的生成树棵数为拉普拉斯矩阵 LL 的任意一个元素的代数余子式。

      # 最小生成树

      # Kruskal 算法

      克鲁斯克尔 (Kruskal):1928 年生,一家 3 弟兄都是数学家 1954 年在普林斯顿大学获博士学位,导师是 ErdÖs, 他大部分研究工作数学和语言学,主要在贝尔实验室工作。1956 年发表包含克鲁斯克尔算论文,使他名声大振

      GG 中的最小边开始,进行避圈式扩张。

      # 算法流程

      1. 选择边 e1e_1 , 使得其权值最小;
      2. 若已经选定边 e1,e2,,eke_1,e_2,\cdots,e_k ,则从 E{e1,e2,,ek}E-\{e_1,e_2,\cdots,e_k\} 中选择边 ek+1e_{k+1} , 使得:
        • [e1,e2,,ek+1][e_1,e_2,\cdots,e_{k+1}] 为无圈图
        • ek+1e_{k+1} 的权值 w(ek+1)w(e_{k+1}) 尽可能小。
      3. 当 (2) 不能进行时,停止。

      # 完备性证明

      克鲁斯克尔算法得到的任何生成树一定是最小生成树。证明:

      GG 是一个 nn 阶连通赋权图,用 T=G[{e1,e2,,en1}]T^*=G[\{e_1,e_2,\cdots,e_{n-1}\}](导出子图)表示由克鲁斯克尔算法得到的一棵生成树,我们证明:它是最小生成树

      TTGG 的一棵最小生成树。若 TTT^*≠T.

      由克鲁斯克尔算法容易知道:TTT\cap T^*≠\varnothing.

      于是令 f(T)=kf(T)=k 表示 TT^* 中的边 eie_i 不在 TT 中的最小 ii 值。即可令 T=G[{e1,e2,,ek1,ek,,en1}]T=G[\{e_1,e_2,\cdots,e_{k-1},e'_k,\cdots,e'_{n-1}\}](导出子图)

      考虑:TekT∪e_k , 则由树的性质,它必然为 GG 中圈 CC .

      T1=TekeT_1=T∪e_k-e , 容易知道:T1T_1 还为 GG 的一棵生成树。

      ee 是圈 CC 的在 TT 中,但不在 TT^* 中的边。

      由克鲁斯克尔算法知道:w(e)w(ek)w(e)≥w(e_k) .

      所以:w(T)w(T1)w(T)≥w(T_1) .

      这说明 T1T_1 是最小树,但这与 f(T)f(T) 的选取假设矛盾!所以:T=TT=T^*

      # 算法案例

      1. 选一条边 e1e_1 , 使得 w(e1)w(e_1) 尽可能小;
      2. 若边 e1,e2,,eie_1,e_2,\cdots,e_i 已经选定,则用下述方法从 E\{e1,e2,,ei}E\backslash\{e_1,e_2,\cdots,e_i\} 中选取边 e_
        • (a) G[{e1,e2,,ei+1}]G[\{e_1,e_2,\cdots,e_{i+1}\}] 为不相交路之并;
        • (b) w(ei+1)w(e_{i+1}) 是满足 (a) 的尽可能小的权。
      3. 当 (2) 不能继续执行时停止。

      该方法不能得到一条最小生成路

      # 管梅谷的破圈法

      在克鲁斯克尔算法基础上,我国著名数学家管梅谷教授于 1975 年提出了最小生成树的破圈法。

      从赋权图 GG 的任意圈开始,去掉该圈中权值最大的一条边,称为破圈。

      不断破圈,直到 GG 中没有圈为止,最后剩下的 GG 的子图为 GG 的最小生成树

      # Prim 算法

      Prim 算法是由 Prim 在 1957 年提出的一个著名算法。作者因此而出名。Prim (1921---) 1949 年在普林斯顿大学获博士学位,是 Sandia 公司副总裁。

      Kruskal 关注边,Prim 关注点

      对于连通赋权图 GG 的任意一个顶点 uu ,选择与点 uu 关联的且权值最小的边作为最小生成树的第一条边 e1e_1 ;

      在接下来的边 e2,e3,,en1,e_2,e_3,\cdots,e_{n-1}, 在与一条已经选取的边只有一个公共端点的的所有边中,选取权值最小的边。

      # 树图

      连通图 GG 的树图是指这样的图,它的顶点是 GG 的生成树 T1,T2,,TτT_1,T_2,\cdots,T_\tauTiT_iTjT_j 相连当且仅当它们恰有 n2n-2 条公共边。

      # 连通性

      任何连通图的树图是连通图。


      证明:只需证明,对任意 TiT_iTjT_j ,在树图中存在连接它们的路即可!

      对任意 TiT_iTjT_j , 设 e1,e2,,ek(k<n2)e_1,e_2,\cdots,e_k\ (k<n-2) 是它们的公共边。

      由树的性质:ek+1E(Ti)∃e'_{k+1}\in E(T_i) , 但 ek+1∉E(Tj)e'_{k+1}\not\in E(T_j) , 使得:Tj+ek+1T_j +e'_{k+1} 有唯一圈。

      该圈中: ek+1E(Tj)∃e_{k+1}\in E(T_j) , 但 ek+1∉E(Ti)e_{k+1}\not\in E(T_i)

      作: Ti+1=Tiek+1+ek+1T_{i+1}=T_i-e'_{k+1}+e_{k+1} ,则 TiT_iTi+1T_{i+1}n2n-2 条边相同,于是,它们邻接。

      此时,Ti+1T_{i+1}TjT_jk+1k+1 条边相同。

      如此这样作下去,可以得到连接 TiT_iTjT_j 的一条路为:Ti,Ti+1,,TjT_i, T_{i+1},\cdots,T_j

      所以,连通图 GG 的树图是连通的。

      \ No newline at end of file diff --git a/page/10/index.html b/page/10/index.html index 1dac35f6..32b8ae7c 100644 --- a/page/10/index.html +++ b/page/10/index.html @@ -1 +1 @@ -Balloon Party = 風船のパーティー = fuusen no party
      14k words 13 mins.

      YatCPU - - - lab1 - - - lab2 - - - lab3 - - - lab4 # 测试用例及其波形图分析 # SayGoodbyeTest src/test/scala/riscv/BoardTest.scala 其中 Top 模块来自: # 测试用例的功能 用于烧板验证,但由于 CPU 还未能实现中断,该程序只能通过 LED 灯闪烁判断 CPU 能否正常工作 在 lab1 中该测试用例可以用于检查 CPU 及其内部各个模块、模块内的端口信号是否有完整地实现、初始化,即 &quot;Fully...
      9.3k words 8 mins.

      YatCPU - - - lab1 - - - lab2 - - - lab3 - - - lab4 # 测试用例及其波形图分析 # SayGoodbyeTest src/test/scala/riscv/BoardTest.scala 其中 Top 模块来自: 测试执行程序来自 csrc/say_goodbye.c : # 测试用例的功能 与 lab2 中 BoardSayGoodbyeTest 功能相似 测试能否正常执行打印 &quot;Never gonna give you up~ Never gonna let you down~\nNever gonna...
      6.6k words 6 mins.

      YatCPU - - - lab1 - - - lab2 - - - lab3 - - - lab4 # 测试用例及其波形图分析 # BoardSayGoodbyeTest src/test/scala/riscv/BoardTest.scala 其中 Top 模块来自: 测试执行程序来自 csrc/say_goodbye.c : # 测试用例的功能 测试能否正常执行打印 &quot;Never gonna give you up~ Never gonna let you down~\nNever gonna run around and~ desert...
      4.9k words 4 mins.

      YatCPU - - - lab1 - - - lab2 - - - lab3 - - - lab4 # 测试用例及其波形图分析 # SayGoodbyeTest src/test/scala/riscv/BoardTest.scala 其中 Top 模块来自: 测试执行程序来自 csrc/say_goodbye.c : # 测试用例的功能 测试能否正常执行打印 &quot;Never gonna give you up~ Never gonna let you down~\nNever gonna run around and~ desert...
      148 words 1 mins.

      这里是我 2023 年大二上半学期的离散数学基础课程期末复习的几天中整理的一些知识的思维导图 逻辑、图论的部分没有整理,主要包括集合、关系、代数等内容 离散数学基础 - 整理: --- 排列与组合 --- 组合计数基本原理 --- 排列组合计数问题 --- 递推关系式 --- 关系 --- 集合与关系的运算 --- 函数 --- 代数系统
      3.5k words 3 mins.

      离散数学基础 - 整理: --- 排列与组合 --- 组合计数基本原理 --- 排列组合计数问题 --- 递推关系式 --- 关系 --- 集合与关系的运算 --- 函数 --- 代数系统 # 思维导图 # 递推关系式相关概念 # 定义 用序列中某些前面的项ai,0≤i&lt;n表示第n项an的等式\text{用序列中某些前面的项}a_i,0\leq i\lt n\text{表示第}n\text{项}a_n\text{的等式} 用序列中某些前面的项ai​,0≤i&lt;n表示第n项an​的等式 #...
      8.2k words 7 mins.

      离散数学基础 - 整理: --- 排列与组合 --- 组合计数基本原理 --- 排列组合计数问题 --- 递推关系式 --- 关系 --- 集合与关系的运算 --- 函数 --- 代数系统 # 思维导图 # 二元运算 封闭性 # 定义 f:S×S→S是集合S的运算,则称集合S对运算f封闭\begin{aligned}&amp; f:S\times S\to S...
      7.2k words 7 mins.

      离散数学基础 - 整理: --- 排列与组合 --- 组合计数基本原理 --- 排列组合计数问题 --- 递推关系式 --- 关系 --- 集合与关系的运算 --- 函数 --- 代数系统 # 函数 (全函数) # 描述 集合A到B的函数,是A×笛卡尔积的一类子集集合A到A的函数也称为A上的函数定义域的每个元素都存在陪域的唯一元素与之对应\begin{aligned} &amp;\text{集合A到B的函数,是}A\times...
      6.6k words 6 mins.

      离散数学基础 - 整理: --- 排列与组合 --- 组合计数基本原理 --- 排列组合计数问题 --- 递推关系式 --- 关系 --- 集合与关系的运算 --- 函数 --- 代数系统 # 思维导图 # 并 # 定义 R∪S={&lt;a,b&gt;∣&lt;a,b&gt;∈R  ∨&lt;a,b&gt;∈S}\begin{aligned}&amp; R\cup S =\{&lt;a,b&gt;|&lt;a,b&gt;\in R\ \ \lor...
      \ No newline at end of file +Balloon Party = 風船のパーティー = fuusen no party
      14k words 13 mins.

      YatCPU - - - lab1 - - - lab2 - - - lab3 - - - lab4 # 测试用例及其波形图分析 # SayGoodbyeTest src/test/scala/riscv/BoardTest.scala 其中 Top 模块来自: # 测试用例的功能 用于烧板验证,但由于 CPU 还未能实现中断,该程序只能通过 LED 灯闪烁判断 CPU 能否正常工作 在 lab1 中该测试用例可以用于检查 CPU 及其内部各个模块、模块内的端口信号是否有完整地实现、初始化,即 &quot;Fully...
      6.6k words 6 mins.

      YatCPU - - - lab1 - - - lab2 - - - lab3 - - - lab4 # 测试用例及其波形图分析 # BoardSayGoodbyeTest src/test/scala/riscv/BoardTest.scala 其中 Top 模块来自: 测试执行程序来自 csrc/say_goodbye.c : # 测试用例的功能 测试能否正常执行打印 &quot;Never gonna give you up~ Never gonna let you down~\nNever gonna run around and~ desert...
      4.9k words 4 mins.

      YatCPU - - - lab1 - - - lab2 - - - lab3 - - - lab4 # 测试用例及其波形图分析 # SayGoodbyeTest src/test/scala/riscv/BoardTest.scala 其中 Top 模块来自: 测试执行程序来自 csrc/say_goodbye.c : # 测试用例的功能 测试能否正常执行打印 &quot;Never gonna give you up~ Never gonna let you down~\nNever gonna run around and~ desert...
      9.3k words 8 mins.

      YatCPU - - - lab1 - - - lab2 - - - lab3 - - - lab4 # 测试用例及其波形图分析 # SayGoodbyeTest src/test/scala/riscv/BoardTest.scala 其中 Top 模块来自: 测试执行程序来自 csrc/say_goodbye.c : # 测试用例的功能 与 lab2 中 BoardSayGoodbyeTest 功能相似 测试能否正常执行打印 &quot;Never gonna give you up~ Never gonna let you down~\nNever gonna...
      148 words 1 mins.

      这里是我 2023 年大二上半学期的离散数学基础课程期末复习的几天中整理的一些知识的思维导图 逻辑、图论的部分没有整理,主要包括集合、关系、代数等内容 离散数学基础 - 整理: --- 排列与组合 --- 组合计数基本原理 --- 排列组合计数问题 --- 递推关系式 --- 关系 --- 集合与关系的运算 --- 函数 --- 代数系统
      8.2k words 7 mins.

      离散数学基础 - 整理: --- 排列与组合 --- 组合计数基本原理 --- 排列组合计数问题 --- 递推关系式 --- 关系 --- 集合与关系的运算 --- 函数 --- 代数系统 # 思维导图 # 二元运算 封闭性 # 定义 f:S×S→S是集合S的运算,则称集合S对运算f封闭\begin{aligned}&amp; f:S\times S\to S...
      7.2k words 7 mins.

      离散数学基础 - 整理: --- 排列与组合 --- 组合计数基本原理 --- 排列组合计数问题 --- 递推关系式 --- 关系 --- 集合与关系的运算 --- 函数 --- 代数系统 # 函数 (全函数) # 描述 集合A到B的函数,是A×笛卡尔积的一类子集集合A到A的函数也称为A上的函数定义域的每个元素都存在陪域的唯一元素与之对应\begin{aligned} &amp;\text{集合A到B的函数,是}A\times...
      6.6k words 6 mins.

      离散数学基础 - 整理: --- 排列与组合 --- 组合计数基本原理 --- 排列组合计数问题 --- 递推关系式 --- 关系 --- 集合与关系的运算 --- 函数 --- 代数系统 # 思维导图 # 并 # 定义 R∪S={&lt;a,b&gt;∣&lt;a,b&gt;∈R  ∨&lt;a,b&gt;∈S}\begin{aligned}&amp; R\cup S =\{&lt;a,b&gt;|&lt;a,b&gt;\in R\ \ \lor...
      3.4k words 3 mins.

      离散数学基础 - 整理: --- 排列与组合 --- 组合计数基本原理 --- 排列组合计数问题 --- 递推关系式 --- 关系 --- 集合与关系的运算 --- 函数 --- 代数系统 # 思维导图 # 排列 # 记号 P(n,r)=Pnr=AnrP(n,r)=P_n^r=A_n^r P(n,r)=Pnr​=Anr​ # 描述 n 个 (可区别的) 物体 n 个物体的 r - 排列 n 个物体的 n - 排列,或 n 个物体的全排列 集合 S,|S|=n S 的 r - 排列 S 的 n - 排列,或 S 的全排列 #...
      \ No newline at end of file diff --git a/page/11/index.html b/page/11/index.html index eabe8fa3..67e0e12a 100644 --- a/page/11/index.html +++ b/page/11/index.html @@ -1 +1 @@ -Balloon Party = 風船のパーティー = fuusen no party
      3.4k words 3 mins.

      离散数学基础 - 整理: --- 排列与组合 --- 组合计数基本原理 --- 排列组合计数问题 --- 递推关系式 --- 关系 --- 集合与关系的运算 --- 函数 --- 代数系统 # 思维导图 # 排列 # 记号 P(n,r)=Pnr=AnrP(n,r)=P_n^r=A_n^r P(n,r)=Pnr​=Anr​ # 描述 n 个 (可区别的) 物体 n 个物体的 r - 排列 n 个物体的 n - 排列,或 n 个物体的全排列 集合 S,|S|=n S 的 r - 排列 S 的 n - 排列,或 S 的全排列 #...
      4.8k words 4 mins.

      离散数学基础 - 整理: --- 排列与组合 --- 组合计数基本原理 --- 排列组合计数问题 --- 递推关系式 --- 关系 --- 集合与关系的运算 --- 函数 --- 代数系统 # 思维导图 # 常用引理 # 引理 1 # 公式 ∣AB‾∣=∣A−B∣=∣A∣−∣AB∣| A\overline{B} |=| A-B | = |A| -| A B| ∣AB∣=∣A−B∣=∣A∣−∣AB∣ AB‾=A−B=A−ABA\overline{B} = A - B = A - A B AB=A−B=A−AB # 证明 略 # 容斥原理 # 2...
      5.2k words 5 mins.

      离散数学基础 - 整理: --- 排列与组合 --- 组合计数基本原理 --- 排列组合计数问题 --- 递推关系式 --- 关系 --- 集合与关系的运算 --- 函数 --- 代数系统 # 思维导图 # 笛卡尔积 # 定义 A×B={⟨a,b⟩∣a∈A∧b∈B}\begin{aligned}&amp; A\times B=\{\langle a,b\rangle|a\in A\land b\in B\} \end{aligned} ​A×B={⟨a,b⟩∣a∈A∧b∈B}​ #...
      928 words 1 mins.

      # 思维导图 # 为什么要刷新? # DRAM 存储位元的特点 # 靠电容上的电荷存储效应记忆信息,虽然有 MOS 高电阻 (1012∼1015Ω10^{12} \sim 10^{15} \Omega1012∼1015Ω),仍会泄漏电荷 # 为保证所存信息的正确性,需要用充电的方法及时使所有位元的电容上电荷恢复到泄漏前的状态 # DRAM 刷新的有关参数 # 刷新周期 Trc (refresh cycle) 对同一存储位元连续两次刷新,仍能保证鉴别出原存信息的最大允许间隔时间,即在 Trc 内必须对每个单元刷新一遍 一般为 ms 级,亦称为刷新间隔时间 在 Trc...
      3.6k words 3 mins.

      # 思维导图 # 基本术语 # 记忆单元 / 存储位元 / 位元 (Cell) 具有两种稳态的能够表示二进制数 0 和 1 的物理器件 # 存储单元 / 编址单位 / 寻址单位 (Addressing Unit) 存储器中具有相同地址的那些位构成一个存储单元,又称为一个编址单位 # 存储体 / 存储矩阵 / 存储阵列 (Bank) 所有存储单元构成一个存储阵列 # 存储器地址寄存器 (Memory Address Register – MAR) 用于存放主存单元地址的寄存器 # 存储器数据寄存器 (Memory Data Register – MDR) 用于存放主存单元中数据的寄存器 #...
      2.4k words 2 mins.

      # 思维导图 # 分区方案 # 简单分区: 原理:使用长度不等的固定长分区,当一个进程调入主存时,分配给它一个能容纳的最小分区 缺点:固定长度的分区,可能会浪费 主存空间。多数情况下,进程对分区大小的需求不可能和提供的分区大小一样 # 可变长分区(Partitioning) 原理:分配的分区大小与进程所需大小一样 特点:开始较好 ,但到最后存储器中会有许多碎片。时间越长,存储器的碎片会越来越多,存储器的利用率下降 程序员自己手动管理内存,可以改善内存碎片化问题(例如一次性 malloc 或 new、stl 新建容器好几 kb 大小…… #...
      4.7k words 4 mins.

      # 思维导图 # Cache 的结构 # Cache 是小容量、高速缓冲存储器,由 SRAM 组成 # 一般将 Cache 和主存的存储空间都划分为若干大小相同的块并映射 把主存划分成大小相等的主存块 (Block) Cache 中存放一个主存块的对应单位称为行 (line) 或槽 (Slot) 或项 (Entry) 或块 (Block),一段 Cache 行包括: Valid 位,1 位 LRU 位 Dirty 位,1 位,采用 Write Back (写回、一次性写、回写) 时需要 Tag 位 Data 数据 主存块 (Block) 与 Cache 中的 行 / 槽 /...
      1.2k words 1 mins.

      # 思维导图 # CPU (Processor) # Control 控制器 指令执行过程中,数据所经过的路径 (包括路径中的部件)—— 指令的执行部件 控制器的基本功能 取指令 (控制指令流出 — PC) 分析指令 (控制指令分析 — IR) 执行指令,发出各种操作命令 (控制指令执行 — REGs 和 ALU) 确定下一条指令的地址 (控制指令流向 —PC) 执行环境的建立与保护 (控制执行环境的维护 —FLAGs/PSW) # Datapath 数据通路 对指令进行译码,生成指令对应的控制信号,控制数据通路的动作,能对指令的执行部件发出控制信号 ——...
      2.8k words 3 mins.

      # 思维导图 CPU # 单周期 CPU # 单周期控制器 控制信号在整个指令执行过程中保持不变 真值表反映了指令和控制信号的关系 按照真值表就可以实现控制器! # 多周期 CPU # 多周期控制器功能描述方式 有限状态机 采用组合逻辑设计方法用硬连线路 (PLA) 实现 微程序 用 ROM 存放微程序实现 # MIPS 各指令的周期数: 划分关键是: 所有指令均需要 IF,ID,EX 这三个周期 需要访存的指令额外需要一个周期 MEM(ID 内的访存不算,所以只有 Load/Store) 需要写回寄存器的指令额外需要一个周期 WB R-Type...
      2.1k words 2 mins.

      # 思维导图 # 异常和中断的概念 # 异常: 异常来自于 cpu 内部的正在执行的指令本身 # 中断: 中断来自于 cpu 外部的硬件触发 # 统称为 “中断”: 内中断 (内部异常) CPU 自己产生而不通过中断请求线请求,皆为不可屏蔽中断 外中断 (外部中断) 通过中断请求线 INTR 和 NMI 来实现 # 内部 “异常”:CPU 内发生的意外事件或特殊事件 # 按发生原因分为硬故障中断和程序性中断两类 硬故障中断:如电源掉电、硬件线路故障等 程序性中断:执行某条指令时发生的 “异常 (Exception)”,如 溢出 缺页 越界 越权 非法指令 除数为...
      \ No newline at end of file +Balloon Party = 風船のパーティー = fuusen no party
      3.5k words 3 mins.

      离散数学基础 - 整理: --- 排列与组合 --- 组合计数基本原理 --- 排列组合计数问题 --- 递推关系式 --- 关系 --- 集合与关系的运算 --- 函数 --- 代数系统 # 思维导图 # 递推关系式相关概念 # 定义 用序列中某些前面的项ai,0≤i&lt;n表示第n项an的等式\text{用序列中某些前面的项}a_i,0\leq i\lt n\text{表示第}n\text{项}a_n\text{的等式} 用序列中某些前面的项ai​,0≤i&lt;n表示第n项an​的等式 #...
      5.2k words 5 mins.

      离散数学基础 - 整理: --- 排列与组合 --- 组合计数基本原理 --- 排列组合计数问题 --- 递推关系式 --- 关系 --- 集合与关系的运算 --- 函数 --- 代数系统 # 思维导图 # 笛卡尔积 # 定义 A×B={⟨a,b⟩∣a∈A∧b∈B}\begin{aligned}&amp; A\times B=\{\langle a,b\rangle|a\in A\land b\in B\} \end{aligned} ​A×B={⟨a,b⟩∣a∈A∧b∈B}​ #...
      4.8k words 4 mins.

      离散数学基础 - 整理: --- 排列与组合 --- 组合计数基本原理 --- 排列组合计数问题 --- 递推关系式 --- 关系 --- 集合与关系的运算 --- 函数 --- 代数系统 # 思维导图 # 常用引理 # 引理 1 # 公式 ∣AB‾∣=∣A−B∣=∣A∣−∣AB∣| A\overline{B} |=| A-B | = |A| -| A B| ∣AB∣=∣A−B∣=∣A∣−∣AB∣ AB‾=A−B=A−ABA\overline{B} = A - B = A - A B AB=A−B=A−AB # 证明 略 # 容斥原理 # 2...
      928 words 1 mins.

      # 思维导图 # 为什么要刷新? # DRAM 存储位元的特点 # 靠电容上的电荷存储效应记忆信息,虽然有 MOS 高电阻 (1012∼1015Ω10^{12} \sim 10^{15} \Omega1012∼1015Ω),仍会泄漏电荷 # 为保证所存信息的正确性,需要用充电的方法及时使所有位元的电容上电荷恢复到泄漏前的状态 # DRAM 刷新的有关参数 # 刷新周期 Trc (refresh cycle) 对同一存储位元连续两次刷新,仍能保证鉴别出原存信息的最大允许间隔时间,即在 Trc 内必须对每个单元刷新一遍 一般为 ms 级,亦称为刷新间隔时间 在 Trc...
      3.6k words 3 mins.

      # 思维导图 # 基本术语 # 记忆单元 / 存储位元 / 位元 (Cell) 具有两种稳态的能够表示二进制数 0 和 1 的物理器件 # 存储单元 / 编址单位 / 寻址单位 (Addressing Unit) 存储器中具有相同地址的那些位构成一个存储单元,又称为一个编址单位 # 存储体 / 存储矩阵 / 存储阵列 (Bank) 所有存储单元构成一个存储阵列 # 存储器地址寄存器 (Memory Address Register – MAR) 用于存放主存单元地址的寄存器 # 存储器数据寄存器 (Memory Data Register – MDR) 用于存放主存单元中数据的寄存器 #...
      2.4k words 2 mins.

      # 思维导图 # 分区方案 # 简单分区: 原理:使用长度不等的固定长分区,当一个进程调入主存时,分配给它一个能容纳的最小分区 缺点:固定长度的分区,可能会浪费 主存空间。多数情况下,进程对分区大小的需求不可能和提供的分区大小一样 # 可变长分区(Partitioning) 原理:分配的分区大小与进程所需大小一样 特点:开始较好 ,但到最后存储器中会有许多碎片。时间越长,存储器的碎片会越来越多,存储器的利用率下降 程序员自己手动管理内存,可以改善内存碎片化问题(例如一次性 malloc 或 new、stl 新建容器好几 kb 大小…… #...
      4.7k words 4 mins.

      # 思维导图 # Cache 的结构 # Cache 是小容量、高速缓冲存储器,由 SRAM 组成 # 一般将 Cache 和主存的存储空间都划分为若干大小相同的块并映射 把主存划分成大小相等的主存块 (Block) Cache 中存放一个主存块的对应单位称为行 (line) 或槽 (Slot) 或项 (Entry) 或块 (Block),一段 Cache 行包括: Valid 位,1 位 LRU 位 Dirty 位,1 位,采用 Write Back (写回、一次性写、回写) 时需要 Tag 位 Data 数据 主存块 (Block) 与 Cache 中的 行 / 槽 /...
      1.2k words 1 mins.

      # 思维导图 # CPU (Processor) # Control 控制器 指令执行过程中,数据所经过的路径 (包括路径中的部件)—— 指令的执行部件 控制器的基本功能 取指令 (控制指令流出 — PC) 分析指令 (控制指令分析 — IR) 执行指令,发出各种操作命令 (控制指令执行 — REGs 和 ALU) 确定下一条指令的地址 (控制指令流向 —PC) 执行环境的建立与保护 (控制执行环境的维护 —FLAGs/PSW) # Datapath 数据通路 对指令进行译码,生成指令对应的控制信号,控制数据通路的动作,能对指令的执行部件发出控制信号 ——...
      2.8k words 3 mins.

      # 思维导图 CPU # 单周期 CPU # 单周期控制器 控制信号在整个指令执行过程中保持不变 真值表反映了指令和控制信号的关系 按照真值表就可以实现控制器! # 多周期 CPU # 多周期控制器功能描述方式 有限状态机 采用组合逻辑设计方法用硬连线路 (PLA) 实现 微程序 用 ROM 存放微程序实现 # MIPS 各指令的周期数: 划分关键是: 所有指令均需要 IF,ID,EX 这三个周期 需要访存的指令额外需要一个周期 MEM(ID 内的访存不算,所以只有 Load/Store) 需要写回寄存器的指令额外需要一个周期 WB R-Type...
      2.1k words 2 mins.

      # 思维导图 # 异常和中断的概念 # 异常: 异常来自于 cpu 内部的正在执行的指令本身 # 中断: 中断来自于 cpu 外部的硬件触发 # 统称为 “中断”: 内中断 (内部异常) CPU 自己产生而不通过中断请求线请求,皆为不可屏蔽中断 外中断 (外部中断) 通过中断请求线 INTR 和 NMI 来实现 # 内部 “异常”:CPU 内发生的意外事件或特殊事件 # 按发生原因分为硬故障中断和程序性中断两类 硬故障中断:如电源掉电、硬件线路故障等 程序性中断:执行某条指令时发生的 “异常 (Exception)”,如 溢出 缺页 越界 越权 非法指令 除数为...
      \ No newline at end of file diff --git a/page/12/index.html b/page/12/index.html index 0e439b74..d19ec40f 100644 --- a/page/12/index.html +++ b/page/12/index.html @@ -1 +1 @@ -Balloon Party = 風船のパーティー = fuusen no party
      2.7k words 2 mins.

      # 思维导图 # 补码 # 符号部分同原码 数的最高位为符号位,0 表示正数,1 表示负数 # 数字部分与它的符号位有关 对于正数,补码数值部分与原码数值部分相同 对于负数,补码数值部分是将原码数值部分按位取反再加 1 ,即在反码数值部分基础上加 1 # 阶码 # 补码和移码的关系:符号位相反、数值位相同 阶码用移码表示,阶码加减运算后得到补码,再将符号位取反即可得到运算后的阶码 移码的和、差 = 真值的和、差的补码 # 补码 E_1 的 (mod 2^n) n 位移码: [E_1] 移 = 2^(n-1) + E_1 # 补码 E_1 的 (mod 2^n) n...
      2.1k words 2 mins.

      # 思维导图 # 两大类型 # CISC (1) 指令系统复杂 (2) 指令周期长 (3) 各种指令都能访问存储器 (4) 有专用寄存器(寻址快) (5) 采用微程序控制 (6) 难以进行编译优化生成高效目标代码 (7) 指令长度不等长, 变长指令字 (Expanding Opcodes) # RISC (1) 简化的指令系统 (2) 指令周期短 (3) 有专门的访存指令如 load、store, 以寄存器 - 寄存器方式工作 (三地址指令是 RISC 风格) (4) 采用大量通用寄存器,以减少访存次数 (5) 采用组合逻辑电路控制,不用或少用微程序控制 (6)...
      2k words 2 mins.

      # 思维导图 # 完成单个任务的时间 # 响应时间 (response time): 完成单个任务所需的总时间,由 2 部分组成 响应时间短的场合: 事务处理系统 (存 / 取款的速度要快) CPU 执行时间 (CPU time) 执行时间 (Execution time) CPU 真正花费在程序执行上的时间 用户 CPU 时间: 用来运行用户代码的时间 系统 CPU 时间: 为执行用户程序而需运行一些操作系统代码的时间 其他时间 等待 I/O 操作完成 CPU 花在其他用户程序的时间 # 单位时间完成的任务量 # 吞吐率...
      124 words 1 mins.

      # 思维导图 # 采用二进制表示机器指令和数据 # 硬件系统由 5 大部分组成 # 输入设备 # 控制器 # 运算器 # 存储器 # 输出设备 # 程序和数据预先存放在存储器中,按地址访问存储器 # 操作时根据程序中指令的执行顺序,从存储器中取出指令或数据,由控制器解释执行、运算器完成运算
      1.4k words 1 mins.

      # 定义 最小生成树 Minimum Spanning Tree 问题 等价问题:寻找一个带权无向图中某一点到另一个点的最短路径 / 权最小的路径 注意:当各边有相同权值时,由于选择的随意性,产生的生成树可能不唯一。 # Kruskal (克鲁斯卡尔) 算法 以点为主导,利用最小堆和并查集 对所有边按权值从小到大排序,逐个添加不形成回路的边,直到包含所有的顶点。 # Prim (普里姆) 算法 以边为主导 贪心思想,不断选最小权值的边 从某一顶点出发,选择与它关联的具有最小权值的边,将其顶点加入到生成树顶点集合 U1U_1U1​ 中,剩余顶点集合为...
      12k words 11 mins.

      # 思维导图 # 绪论部分 # 第一章 世界的物质性及发展规律 # 第二章 实践与认识及其发展规律 # 第三章 人类社会及其发展规律 # 第四章 资本主义的本质及规律 # 第六章社会主义的发展及其规律(本章仅供学习参考,不作考试要求) # 第七章 共产主义是人类最崇高的社会理想 # 大纲 # 绪论部分 #...
      32k words 30 mins.

      # 思维导图 # 绪论部分 # 第一章 世界的物质性及发展规律 # 第二章 实践与认识及其发展规律 # 第三章 人类社会及其发展规律 # 第四章 资本主义的本质及规律 # 第五章 资本主义的发展及其趋势 # 第六章社会主义的发展及其规律(本章仅供学习参考,不作考试要求) # 第七章 共产主义是人类最崇高的社会理想 # 大纲 # 绪论部分 #...
      450 words 1 mins.

      # 三种表达式 前缀表达式 / Prefix Notation 波兰式 / Polish Notation 中缀表达式 / Infix Notation (中缀表达式才需要有括号) 后缀表达式 / Postfix Notation 逆波兰式 / Reverse Polish Notation # 三种表达式的相互转化 # 括号法 通用方法,略 # 表达式树法 通用方法,略 # 栈方法 专用于: 中缀 -&gt; 前缀 / 后缀 很像,注意区别,对照记忆 # 中缀 -&gt;...
      448 words 1 mins.

      # 循环队列 对于一个容量为 mmm 的循环队列 实际存储空间为 m+1m+1m+1 初始状态 / 判空条件: rear==frontrear == frontrear==front 判满条件:(rear+1)%m==front(rear+1)\%m==front(rear+1)%m==front 入队操作: 伪代码新元素加入队尾;队尾指针 + 1; 出队操作: 伪代码访问队头元素;队头指针 + 1; 任意时刻队列内包含的元素数量为: (m+rear−front)%m(m+rear-front)\%m(m+rear−front)%m #...
      2k words 2 mins.

      # 定义 寻找一个带权有向图中某一点到另一个点的最短路径 / 权最小的路径 当然以下算法也适用于无向图 # Floyd (弗洛伊德) 算法 可以算出所有点之间的最短距离 c++//dist 初始化为邻接矩阵,若 i 没有指向 j 的边,则应有 dist [i][j]=MAX_INT (表示无穷大的数)void floyd()&#123; for(int k = 0; k &lt; n; k ++)&#123; // 作为循环中间点的 k 必须放在最外一层循环 for(int i = 0; i &lt; n; i ++)&#123; for(int j...
      \ No newline at end of file +Balloon Party = 風船のパーティー = fuusen no party
      2.7k words 2 mins.

      # 思维导图 # 补码 # 符号部分同原码 数的最高位为符号位,0 表示正数,1 表示负数 # 数字部分与它的符号位有关 对于正数,补码数值部分与原码数值部分相同 对于负数,补码数值部分是将原码数值部分按位取反再加 1 ,即在反码数值部分基础上加 1 # 阶码 # 补码和移码的关系:符号位相反、数值位相同 阶码用移码表示,阶码加减运算后得到补码,再将符号位取反即可得到运算后的阶码 移码的和、差 = 真值的和、差的补码 # 补码 E_1 的 (mod 2^n) n 位移码: [E_1] 移 = 2^(n-1) + E_1 # 补码 E_1 的 (mod 2^n) n...
      2.1k words 2 mins.

      # 思维导图 # 两大类型 # CISC (1) 指令系统复杂 (2) 指令周期长 (3) 各种指令都能访问存储器 (4) 有专用寄存器(寻址快) (5) 采用微程序控制 (6) 难以进行编译优化生成高效目标代码 (7) 指令长度不等长, 变长指令字 (Expanding Opcodes) # RISC (1) 简化的指令系统 (2) 指令周期短 (3) 有专门的访存指令如 load、store, 以寄存器 - 寄存器方式工作 (三地址指令是 RISC 风格) (4) 采用大量通用寄存器,以减少访存次数 (5) 采用组合逻辑电路控制,不用或少用微程序控制 (6)...
      2k words 2 mins.

      # 思维导图 # 完成单个任务的时间 # 响应时间 (response time): 完成单个任务所需的总时间,由 2 部分组成 响应时间短的场合: 事务处理系统 (存 / 取款的速度要快) CPU 执行时间 (CPU time) 执行时间 (Execution time) CPU 真正花费在程序执行上的时间 用户 CPU 时间: 用来运行用户代码的时间 系统 CPU 时间: 为执行用户程序而需运行一些操作系统代码的时间 其他时间 等待 I/O 操作完成 CPU 花在其他用户程序的时间 # 单位时间完成的任务量 # 吞吐率...
      124 words 1 mins.

      # 思维导图 # 采用二进制表示机器指令和数据 # 硬件系统由 5 大部分组成 # 输入设备 # 控制器 # 运算器 # 存储器 # 输出设备 # 程序和数据预先存放在存储器中,按地址访问存储器 # 操作时根据程序中指令的执行顺序,从存储器中取出指令或数据,由控制器解释执行、运算器完成运算
      1.4k words 1 mins.

      # 定义 最小生成树 Minimum Spanning Tree 问题 等价问题:寻找一个带权无向图中某一点到另一个点的最短路径 / 权最小的路径 注意:当各边有相同权值时,由于选择的随意性,产生的生成树可能不唯一。 # Kruskal (克鲁斯卡尔) 算法 以点为主导,利用最小堆和并查集 对所有边按权值从小到大排序,逐个添加不形成回路的边,直到包含所有的顶点。 # Prim (普里姆) 算法 以边为主导 贪心思想,不断选最小权值的边 从某一顶点出发,选择与它关联的具有最小权值的边,将其顶点加入到生成树顶点集合 U1U_1U1​ 中,剩余顶点集合为...
      32k words 30 mins.

      # 思维导图 # 绪论部分 # 第一章 世界的物质性及发展规律 # 第二章 实践与认识及其发展规律 # 第三章 人类社会及其发展规律 # 第四章 资本主义的本质及规律 # 第五章 资本主义的发展及其趋势 # 第六章社会主义的发展及其规律(本章仅供学习参考,不作考试要求) # 第七章 共产主义是人类最崇高的社会理想 # 大纲 # 绪论部分 #...
      12k words 11 mins.

      # 思维导图 # 绪论部分 # 第一章 世界的物质性及发展规律 # 第二章 实践与认识及其发展规律 # 第三章 人类社会及其发展规律 # 第四章 资本主义的本质及规律 # 第六章社会主义的发展及其规律(本章仅供学习参考,不作考试要求) # 第七章 共产主义是人类最崇高的社会理想 # 大纲 # 绪论部分 #...
      450 words 1 mins.

      # 三种表达式 前缀表达式 / Prefix Notation 波兰式 / Polish Notation 中缀表达式 / Infix Notation (中缀表达式才需要有括号) 后缀表达式 / Postfix Notation 逆波兰式 / Reverse Polish Notation # 三种表达式的相互转化 # 括号法 通用方法,略 # 表达式树法 通用方法,略 # 栈方法 专用于: 中缀 -&gt; 前缀 / 后缀 很像,注意区别,对照记忆 # 中缀 -&gt;...
      2k words 2 mins.

      # 定义 寻找一个带权有向图中某一点到另一个点的最短路径 / 权最小的路径 当然以下算法也适用于无向图 # Floyd (弗洛伊德) 算法 可以算出所有点之间的最短距离 c++//dist 初始化为邻接矩阵,若 i 没有指向 j 的边,则应有 dist [i][j]=MAX_INT (表示无穷大的数)void floyd()&#123; for(int k = 0; k &lt; n; k ++)&#123; // 作为循环中间点的 k 必须放在最外一层循环 for(int i = 0; i &lt; n; i ++)&#123; for(int j...
      448 words 1 mins.

      # 循环队列 对于一个容量为 mmm 的循环队列 实际存储空间为 m+1m+1m+1 初始状态 / 判空条件: rear==frontrear == frontrear==front 判满条件:(rear+1)%m==front(rear+1)\%m==front(rear+1)%m==front 入队操作: 伪代码新元素加入队尾;队尾指针 + 1; 出队操作: 伪代码访问队头元素;队头指针 + 1; 任意时刻队列内包含的元素数量为: (m+rear−front)%m(m+rear-front)\%m(m+rear−front)%m #...
      \ No newline at end of file diff --git a/page/13/index.html b/page/13/index.html index 2a5a20d5..85e13b1e 100644 --- a/page/13/index.html +++ b/page/13/index.html @@ -1 +1 @@ -Balloon Party = 風船のパーティー = fuusen no party
      1.1k words 1 mins.

      # 图的存储结构: AM: Adjacent Matrix 邻接矩阵 AL: Adjacent List 邻接表 RAL: Reverse Adjacent List 逆邻接表 TL: Triple List 三元组顺序表 (往往是行逻辑链接的,性能更好) CL: Cross List 十字链表 # 图按存储结构分为: AMGraph: Adjacent Matrix Graph ALGraph: Adjacent List Graph TLGraph: Triple List Graph RALGraph: Reverse Adjacent List Graph CLGraph:...
      3.1k words 3 mins.

      # AOV: Activity On Vertex 略(不考) # AOE: Activity On Edge 与 AOV 网相对应的是 AOE (Activity On Edge) ,是边表示活动的有向无环图,如图所示。图中顶点表示事件 (Event),每个事件表示在其前的所有活动已经完成,其后的活动可以开始;弧表示活动,弧上的权值表示相应活动所需的时间或费用 与 AOE 有关的研究问题 完成整个工程至少需要多少时间? 哪些活动是影响工程进度 (费用) 的关键? 工程完成最短时间:从起点到终点的最长路径长度...
      12k words 11 mins.

      # Scala # import 在 Scala 中,import 语句用于引入其他类、对象或特质,以便在当前作用域中可以直接访问它们的成员。下面是一些关于 Scala 中 import 的常见用法: 基本用法 a// 导入单个类import scala.collection.mutable.ListBuffer// 导入整个包import scala.collection.mutable._// 重命名导入的类 / 对象 / 特质import java.util.&#123;ArrayList => JArrayList, HashMap =>...
      1k words 1 mins.

      # Multiway Tree 多叉树任意节点的所有子树也都是有顺序的 多叉树可以按固定的方法向二叉树转化: 对所有节点只保留与最左侧子节点的连接,删除其他连接 从左到右依次连接同一层的兄弟节点 (siblings) # B-Tree Banlanced Multiway Tree, 顾名思义,B - 树是一种平衡的多路查找树,是平衡二叉树的外延概念。 B-Tree 是为外部查找(如磁盘)设计的一种平衡查找树。 系统从磁盘读取数据到内存时是以存储块 (block) 为基本单位的,位于同一个磁盘块中的数据会被一次性读取出来,而不是需要什么取什么。B-Tree...
      9.5k words 9 mins.

      # 二叉树的一些规范 (考研) 节点的度数:节点出发指向下一层节点的边的数量 (出度) N0,N1,N2N_0,N_1,N_2N0​,N1​,N2​:分别表示度数为 1,2,3 的顶点数量 # 结论 任意二叉树满足: n=N0+N1+N2n=N_0+N_1+N_2n=N0​+N1​+N2​ n−1=0×N0+1×N1+2×N2=N1+2N2n-1=0\times N_0+1\times N_1+2\times...
      5.4k words 5 mins.

      # 哈希表 / 散列表 应用哈希函数,由记录的关键字确定记录在表中的地址,并将记录放入此地址,这样构成的表叫哈希表 # 哈希查找 / 散列查找 利用哈希函数进行查找的过程叫哈希查找 # 哈希映射函数 / 散列函数 在记录的关键字与记录的存储地址之间建立的一种对应关系叫哈希函数 # 原始 hash 函数 简单一点的 hash 算法就是直接取模 (除留余数法)。 高级一点的 hash 算法会模乘以一个大素数来将源数据的分布规律变得不那么显著,也就是说,不管输入的是一串分布很紧凑的数字序列还是很稀疏的数字序列,生成的结果都是非常分散的数字序列。 linux 内核代码里面的这个 hash...
      1.5k words 1 mins.

      基排序 / 桶排序 / 数字排序 # 原理 需要频繁进行分组重排,(类似于归并)适用于链表 可分为两种: MSD,最高位优先 (Most Significant Digit first) LSD,最低位优先 (Least Significant Digit first) # 代码 c++//Definition for singly-linked list.struct ListNode &#123; int val; ListNode *next; ListNode() : val(0), next(nullptr) &#123;&#125;...
      3.8k words 3 mins.

      区分:堆排序的堆不是堆栈的堆 # 原理 堆排序可以视为一种聪明的选择排序。 堆排序适合数组这样的数据结构。 选择排序需要不断在未排序部分找最大 / 小值然后放在已排序部分后面,堆排序只是将 “找最值” 的部分用 “调整堆” 代替,调整好的堆的堆顶就是我们想要的最值。 堆排序基于二叉树结构,堆是一种按一定规律存储数据的二叉树。利用堆最值位于堆顶的特点,不断将堆顶的最值和堆最后一个元素交换(堆最后一个元素后面都是已排序部分),然后重新调整未排序部分使其再变回一个堆。 # 最大堆 / 小根堆 / 小顶堆 最大值在根节点 / 堆顶 结点的键值都小于等于其父结点的键值 排降序建最大堆 # 最小堆...
      \ No newline at end of file +Balloon Party = 風船のパーティー = fuusen no party
      1.1k words 1 mins.

      # 图的存储结构: AM: Adjacent Matrix 邻接矩阵 AL: Adjacent List 邻接表 RAL: Reverse Adjacent List 逆邻接表 TL: Triple List 三元组顺序表 (往往是行逻辑链接的,性能更好) CL: Cross List 十字链表 # 图按存储结构分为: AMGraph: Adjacent Matrix Graph ALGraph: Adjacent List Graph TLGraph: Triple List Graph RALGraph: Reverse Adjacent List Graph CLGraph:...
      3.1k words 3 mins.

      # AOV: Activity On Vertex 略(不考) # AOE: Activity On Edge 与 AOV 网相对应的是 AOE (Activity On Edge) ,是边表示活动的有向无环图,如图所示。图中顶点表示事件 (Event),每个事件表示在其前的所有活动已经完成,其后的活动可以开始;弧表示活动,弧上的权值表示相应活动所需的时间或费用 与 AOE 有关的研究问题 完成整个工程至少需要多少时间? 哪些活动是影响工程进度 (费用) 的关键? 工程完成最短时间:从起点到终点的最长路径长度...
      12k words 11 mins.

      # Scala # import 在 Scala 中,import 语句用于引入其他类、对象或特质,以便在当前作用域中可以直接访问它们的成员。下面是一些关于 Scala 中 import 的常见用法: 基本用法 a// 导入单个类import scala.collection.mutable.ListBuffer// 导入整个包import scala.collection.mutable._// 重命名导入的类 / 对象 / 特质import java.util.&#123;ArrayList => JArrayList, HashMap =>...
      1k words 1 mins.

      # Multiway Tree 多叉树任意节点的所有子树也都是有顺序的 多叉树可以按固定的方法向二叉树转化: 对所有节点只保留与最左侧子节点的连接,删除其他连接 从左到右依次连接同一层的兄弟节点 (siblings) # B-Tree Banlanced Multiway Tree, 顾名思义,B - 树是一种平衡的多路查找树,是平衡二叉树的外延概念。 B-Tree 是为外部查找(如磁盘)设计的一种平衡查找树。 系统从磁盘读取数据到内存时是以存储块 (block) 为基本单位的,位于同一个磁盘块中的数据会被一次性读取出来,而不是需要什么取什么。B-Tree...
      9.5k words 9 mins.

      # 二叉树的一些规范 (考研) 节点的度数:节点出发指向下一层节点的边的数量 (出度) N0,N1,N2N_0,N_1,N_2N0​,N1​,N2​:分别表示度数为 1,2,3 的顶点数量 # 结论 任意二叉树满足: n=N0+N1+N2n=N_0+N_1+N_2n=N0​+N1​+N2​ n−1=0×N0+1×N1+2×N2=N1+2N2n-1=0\times N_0+1\times N_1+2\times...
      5.4k words 5 mins.

      # 哈希表 / 散列表 应用哈希函数,由记录的关键字确定记录在表中的地址,并将记录放入此地址,这样构成的表叫哈希表 # 哈希查找 / 散列查找 利用哈希函数进行查找的过程叫哈希查找 # 哈希映射函数 / 散列函数 在记录的关键字与记录的存储地址之间建立的一种对应关系叫哈希函数 # 原始 hash 函数 简单一点的 hash 算法就是直接取模 (除留余数法)。 高级一点的 hash 算法会模乘以一个大素数来将源数据的分布规律变得不那么显著,也就是说,不管输入的是一串分布很紧凑的数字序列还是很稀疏的数字序列,生成的结果都是非常分散的数字序列。 linux 内核代码里面的这个 hash...
      1.5k words 1 mins.

      基排序 / 桶排序 / 数字排序 # 原理 需要频繁进行分组重排,(类似于归并)适用于链表 可分为两种: MSD,最高位优先 (Most Significant Digit first) LSD,最低位优先 (Least Significant Digit first) # 代码 c++//Definition for singly-linked list.struct ListNode &#123; int val; ListNode *next; ListNode() : val(0), next(nullptr) &#123;&#125;...
      3.8k words 3 mins.

      区分:堆排序的堆不是堆栈的堆 # 原理 堆排序可以视为一种聪明的选择排序。 堆排序适合数组这样的数据结构。 选择排序需要不断在未排序部分找最大 / 小值然后放在已排序部分后面,堆排序只是将 “找最值” 的部分用 “调整堆” 代替,调整好的堆的堆顶就是我们想要的最值。 堆排序基于二叉树结构,堆是一种按一定规律存储数据的二叉树。利用堆最值位于堆顶的特点,不断将堆顶的最值和堆最后一个元素交换(堆最后一个元素后面都是已排序部分),然后重新调整未排序部分使其再变回一个堆。 # 最大堆 / 小根堆 / 小顶堆 最大值在根节点 / 堆顶 结点的键值都小于等于其父结点的键值 排降序建最大堆 # 最小堆...
      \ No newline at end of file diff --git a/page/2/index.html b/page/2/index.html index a68fd175..60bf3fc6 100644 --- a/page/2/index.html +++ b/page/2/index.html @@ -1 +1 @@ -Balloon Party = 風船のパーティー = fuusen no party
      2k words 2 mins.

      # 素理想 非交换环上也可以定义素理想、极大理想,但这里只考虑交换环上的素理想和极大理想! # 定义 设 RRR 是交换环,PPP 是 RRR 的真理想。若对任意 a,b∈Ra,b\in Ra,b∈R,ab∈Pab\in Pab∈P 蕴涵 a∈Pa\in Pa∈P 或 b∈Pb\in Pb∈P ,则称 PPP 为 RRR 的素理想 (prime ideal)。 素理想的概念 b 本质上来自数论中的基本结论:若 ppp 为素数,则 p|ab\Rightarrow p|a\or p|b。 # 整数环的素理想 设 nnn...
      887 words 1 mins.

      # 采样定理 略 # ADC # 运算放大器 运算放大器是一种线性放大器。 两个输入 反相 同相 和一个输出 特点: 很高的电压增益 很大的输入阻抗 很低的输出阻抗 运算放大器的 3 种使用方式: 用做反相放大器时,图中,虚地处电压为 0 V ,由于很大的输入阻抗没有电流流入运算放大器,输入电压处 VinV_{in}Vin​ 所有电流流向输出电压处 VoutV_{out}Vout​ ,可得: VoutVin=−RfRi\frac{V_{out}}{V_{in}}=-\frac{R_f}{R_i} Vin​Vout​​=−Ri​Rf​​ 其中 RfR_fRf​...
      18k words 16 mins.

      # 公式表 # 基本变换对 常用 (双边) z 变换对: # 二阶系统 # 性质表 双边 z 变换的性质: 单边 z 变换的性质: # 双边 z 变换 # 定义 X(z)=∑n=−∞+∞x[n]z−nX(z)=\sum_{n=-\infin}^{+\infin}x[n]z^{-n} X(z)=n=−∞∑+∞​x[n]z−n 称为 x[n]x[n]x[n] 的 z 变换,后面简记为 zT,其中 z=rejωz=re^{j\omega}z=rejω 为复数。 若 r=1r=1r=1 ,z=ejωz=e^{j\omega}z=ejω 位于单位圆上,则为...
      2.5k words 2 mins.

      今天因为校青马班的活动又跑到南校开会、参观团一大。中涂我也不能用电脑,于是无聊之际,手机打开了一直感兴趣的《饿殍:明末千里行》的游戏录播,看了前面就上头了。于是一直到凌晨 3 点,打完了 2 个 TE ,非常有感触,于是一边听着 ED 写下本篇文章作记录。(即使第二天有早八我也不管了!) 这是我玩的第二篇国产的国产文字冒险游戏。(上一部是《OPUS: 龙脉长歌》,这两部观感都非常好)《饿殍》难怪这么火,是有些原因的: 首先作为一个全年龄向的游戏,受众确实更加广泛 人物立绘、CG...
      288 words 1 mins.

      * 星号是没完全看完 持续更新中...... # 2023 # 寒假: EVA 旧版 凉宫春日 Angel Beats! Little Busters Air 86 - 不存在的战区 ISLAND 斩赤红之瞳 可塑性记忆 虚构推理 冰海战记 魔圆 魔纪 想要成为影之实力者 # 一些短的: 快要坏掉的八音盒 星之梦 + 星之人 # 大一下: Canon * 时光沙漏 安达与岛村 终将成为你 天国大魔境 # 暑假: 处刑少女的生存手册 Happy Sugar Life # 大二上: mygo * 黑之契约者 * Fate Zero # 2024 # 寒假 死亡笔记 #...
      4.3k words 4 mins.

      # 匹配 # 匹配基础概念 匹配 MMM —— 如果 MMM 是图 GGG 的边子集 (不含环),且 MMM 中的任意两条边没有共同顶点,则称 MMM 是 GGG 的一个匹配,或对集,或边独立集。 如果 GGG 中顶点是 GGG 的匹配 MMM 中某条边的端点,称它为 MMM 饱和点,否则为 MMM 非饱和点。 最大匹配 MMM (无向图定义) —— 如果 MMM 是图 GGG 的包含边数最多的匹配,称 MMM 是 GGG 的一个最大匹配。 特别是,若最大匹配饱和了 GGG 的所有顶点,称它为 GGG 的一个完美匹配。 MMM 交错路 —— 如果 MMM 是图 GGG 的匹配, GGG...
      2.1k words 2 mins.

      两类主要的半导体存储器是 RAM 和 ROM。 RAM (随机访问存储器) 类型的存储器在等量时间内可以访问所有的地址,并且可以按照任何顺序来选择这些地址以执行读或者写操作。所有的 RAM 都具有读和写的能力。因为 RAM 在电源关闭时会丢失所存储的数据,所以它是易失性内存。 RAM 系列 RAM 的两种类别是静 RAM (SRAM) 和动态 RAM (DRAM) 。当直流电源移走后, SRAM 和 DRAM 都会丢失存储的数据,因此被归类为易失性存储器。 静态 RAM 通常使用锁存器作为存储元件,因而只要加上直流电源,就可以永远地存储数据。 异步 SRAM (ASRAM) 同步...
      6.7k words 6 mins.

      冯・诺伊曼计算机体系决定了操作系统需要内存管理 # 虚拟内存物理实现 连续分配 单一连续分配 分区 固定分区分配 动态分区分配 非连续分配 段式 页式 段页式 ⭐️内部碎片和外部碎片 内部碎片 是已经被分配给某个进程的,该进程没有利用的 固定分区分配产生这种碎片 外部碎片 是无法被分配给任何进程的,不属于任何进程的 动态分区分配产生这种碎片 可以通过紧凑技术克服,需要动态重定位寄存器硬件支持 # 分区 (连续分配) #...
      9.7k words 9 mins.

      # 环的相关定义 设 RRR 是非空集合,如果在 RRR 上定义了两个二元运算 “+++”(称为加法)和 “ ⋅\cdot⋅ ”(称为乘法),且满足: (1) RRR 关于加法 +++ 构成交换群(即加群) (2) RRR 关于乘法 ⋅\cdot⋅ 构成半群,即乘法满足结合律:∀a,b,c∈R,  a⋅(b⋅c)=(a⋅b)⋅c\forall a,b,c\in R,\ \ a\cdot(b\cdot c)=(a\cdot b)\cdot c∀a,b,c∈R,  a⋅(b⋅c)=(a⋅b)⋅c; (3) 乘法...
      \ No newline at end of file +Balloon Party = 風船のパーティー = fuusen no party
      2k words 2 mins.

      # 素理想 非交换环上也可以定义素理想、极大理想,但这里只考虑交换环上的素理想和极大理想! # 定义 设 RRR 是交换环,PPP 是 RRR 的真理想。若对任意 a,b∈Ra,b\in Ra,b∈R,ab∈Pab\in Pab∈P 蕴涵 a∈Pa\in Pa∈P 或 b∈Pb\in Pb∈P ,则称 PPP 为 RRR 的素理想 (prime ideal)。 素理想的概念 b 本质上来自数论中的基本结论:若 ppp 为素数,则 p|ab\Rightarrow p|a\or p|b。 # 整数环的素理想 设 nnn...
      887 words 1 mins.

      # 采样定理 略 # ADC # 运算放大器 运算放大器是一种线性放大器。 两个输入 反相 同相 和一个输出 特点: 很高的电压增益 很大的输入阻抗 很低的输出阻抗 运算放大器的 3 种使用方式: 用做反相放大器时,图中,虚地处电压为 0 V ,由于很大的输入阻抗没有电流流入运算放大器,输入电压处 VinV_{in}Vin​ 所有电流流向输出电压处 VoutV_{out}Vout​ ,可得: VoutVin=−RfRi\frac{V_{out}}{V_{in}}=-\frac{R_f}{R_i} Vin​Vout​​=−Ri​Rf​​ 其中 RfR_fRf​...
      18k words 16 mins.

      # 公式表 # 基本变换对 常用 (双边) z 变换对: # 二阶系统 # 性质表 双边 z 变换的性质: 单边 z 变换的性质: # 双边 z 变换 # 定义 X(z)=∑n=−∞+∞x[n]z−nX(z)=\sum_{n=-\infin}^{+\infin}x[n]z^{-n} X(z)=n=−∞∑+∞​x[n]z−n 称为 x[n]x[n]x[n] 的 z 变换,后面简记为 zT,其中 z=rejωz=re^{j\omega}z=rejω 为复数。 若 r=1r=1r=1 ,z=ejωz=e^{j\omega}z=ejω 位于单位圆上,则为...
      2.5k words 2 mins.

      今天因为校青马班的活动又跑到南校开会、参观团一大。中涂我也不能用电脑,于是无聊之际,手机打开了一直感兴趣的《饿殍:明末千里行》的游戏录播,看了前面就上头了。于是一直到凌晨 3 点,打完了 2 个 TE ,非常有感触,于是一边听着 ED 写下本篇文章作记录。(即使第二天有早八我也不管了!) 这是我玩的第二篇国产的国产文字冒险游戏。(上一部是《OPUS: 龙脉长歌》,这两部观感都非常好)《饿殍》难怪这么火,是有些原因的: 首先作为一个全年龄向的游戏,受众确实更加广泛 人物立绘、CG...
      288 words 1 mins.

      * 星号是没完全看完 持续更新中...... # 2023 # 寒假: EVA 旧版 凉宫春日 Angel Beats! Little Busters Air 86 - 不存在的战区 ISLAND 斩赤红之瞳 可塑性记忆 虚构推理 冰海战记 魔圆 魔纪 想要成为影之实力者 # 一些短的: 快要坏掉的八音盒 星之梦 + 星之人 # 大一下: Canon * 时光沙漏 安达与岛村 终将成为你 天国大魔境 # 暑假: 处刑少女的生存手册 Happy Sugar Life # 大二上: mygo * 黑之契约者 * Fate Zero # 2024 # 寒假 死亡笔记 #...
      4.3k words 4 mins.

      # 匹配 # 匹配基础概念 匹配 MMM —— 如果 MMM 是图 GGG 的边子集 (不含环),且 MMM 中的任意两条边没有共同顶点,则称 MMM 是 GGG 的一个匹配,或对集,或边独立集。 如果 GGG 中顶点是 GGG 的匹配 MMM 中某条边的端点,称它为 MMM 饱和点,否则为 MMM 非饱和点。 最大匹配 MMM (无向图定义) —— 如果 MMM 是图 GGG 的包含边数最多的匹配,称 MMM 是 GGG 的一个最大匹配。 特别是,若最大匹配饱和了 GGG 的所有顶点,称它为 GGG 的一个完美匹配。 MMM 交错路 —— 如果 MMM 是图 GGG 的匹配, GGG...
      2.1k words 2 mins.

      两类主要的半导体存储器是 RAM 和 ROM。 RAM (随机访问存储器) 类型的存储器在等量时间内可以访问所有的地址,并且可以按照任何顺序来选择这些地址以执行读或者写操作。所有的 RAM 都具有读和写的能力。因为 RAM 在电源关闭时会丢失所存储的数据,所以它是易失性内存。 RAM 系列 RAM 的两种类别是静 RAM (SRAM) 和动态 RAM (DRAM) 。当直流电源移走后, SRAM 和 DRAM 都会丢失存储的数据,因此被归类为易失性存储器。 静态 RAM 通常使用锁存器作为存储元件,因而只要加上直流电源,就可以永远地存储数据。 异步 SRAM (ASRAM) 同步...
      6.7k words 6 mins.

      冯・诺伊曼计算机体系决定了操作系统需要内存管理 # 虚拟内存物理实现 连续分配 单一连续分配 分区 固定分区分配 动态分区分配 非连续分配 段式 页式 段页式 ⭐️内部碎片和外部碎片 内部碎片 是已经被分配给某个进程的,该进程没有利用的 固定分区分配产生这种碎片 外部碎片 是无法被分配给任何进程的,不属于任何进程的 动态分区分配产生这种碎片 可以通过紧凑技术克服,需要动态重定位寄存器硬件支持 # 分区 (连续分配) #...
      4.2k words 4 mins.

      # 欧拉图 # 定义 欧拉图存在欧拉闭迹,半欧拉图只存在欧拉迹 若能遍历完所有的边但是没法回到起始点,称为非欧拉图但是有欧拉迹 # 欧拉图 假定 GGG 是一个连通图,且是欧拉图,则下列命题等价: GGG 是欧拉图 GGG 的每个点的度数是偶数 GGG 的边集能划分为边不重的圈的并 (GGG 存在欧拉闭迹) # 半欧拉图 假定 GGG 是一个连通图,且是半欧拉图,则下列命题等价: GGG 是半欧拉图 GGG 有且仅有 2 个点的度数是奇数 (GGG 存在欧拉迹) # 小结论💡 当 nnn 满足什么条件时,完全图 KnK_nKn​ 是欧拉图? nnn 为奇数 当 nnn...
      \ No newline at end of file diff --git a/page/3/index.html b/page/3/index.html index a88fa1b6..2ec906ea 100644 --- a/page/3/index.html +++ b/page/3/index.html @@ -1 +1 @@ -Balloon Party = 風船のパーティー = fuusen no party
      4.2k words 4 mins.

      # 欧拉图 # 定义 欧拉图存在欧拉闭迹,半欧拉图只存在欧拉迹 若能遍历完所有的边但是没法回到起始点,称为非欧拉图但是有欧拉迹 # 欧拉图 假定 GGG 是一个连通图,且是欧拉图,则下列命题等价: GGG 是欧拉图 GGG 的每个点的度数是偶数 GGG 的边集能划分为边不重的圈的并 (GGG 存在欧拉闭迹) # 半欧拉图 假定 GGG 是一个连通图,且是半欧拉图,则下列命题等价: GGG 是半欧拉图 GGG 有且仅有 2 个点的度数是奇数 (GGG 存在欧拉迹) # 小结论💡 当 nnn 满足什么条件时,完全图 KnK_nKn​ 是欧拉图? nnn 为奇数 当 nnn...
      2.9k words 3 mins.

      PVE 版本:8.1.4 ,显卡:NVIDIA GTX 745 # 宿主机配置 # IOMMU shellnano /etc/default/grub将 GRUB_CMDLINE_LINUX_DEFAULT=&quot;...&quot; 中的内容修改为如下: shellGRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt video=efifb:off"准确来说是在 &quot;...&quot; 原来的内容后面增加这些内容,其中: quiet...
      3.3k words 3 mins.

      # Intro 死锁的必要条件 互斥:一次只有一个进程使用一个资源,其他进程不能访问分配给其他进程的资源 占有等待 (持有且等待):当一个进程等待其他进程时,继续占有已分配的资源 非抢占:不能强行抢占进程已占有的资源 循环等待:存在一个闭合的进程链,每个进程至少占有此链中下一个进程所需的一个资源前三个只会导致死锁的可能性,而最后一个循环等待是导致死锁的 “最终极条件” 处理死锁的方法: 确保系统永远不会进入死锁状态 锁预防,在 OS 设计阶段就设计成不会出现死锁 死锁避免,在 OS...
      46k words 42 mins.

      年轻人的第一场 CTF ,学到了很多,比较走运拿了第五。最遗憾的是密码学板块了,认真学了不少抽象代数但还是没有做出几题。 队友们:(我起了个整活队名,其实是抄袭另一个叫做 “憧憬成为 CTFer” 的 ) # AI # Network Reverse 网络结构长这样: Sequential( (0): Conv2d(3, 4, kernel_size=(2, 2), stride=(1, 1)) (1): GELU(approximate='none') (2): Conv2d(4, 8, kernel_size=(5, 5), stride=(1, 1)) (3):...
      15k words 14 mins.

      # 公式表 # 基本变换对 # 性质表 # 双边拉普拉斯变换 # 定义 X(s)=∫−∞+∞x(t)e−stdtX(s)=\int_{-\infin}^{+\infin}x(t)e^{-st}dt X(s)=∫−∞+∞​x(t)e−stdt 称为 x(t)x(t)x(t) 的拉普拉斯变换,后面简记为 LT,其中 s=σ+jωs=\sigma+j\omegas=σ+jω 为复数。 若 σ=0\sigma=0σ=0 ,s=jωs=j\omegas=jω 为纯虚数则为傅里叶变换,也就是说连续时间傅里叶变换是双边拉普拉斯变换在 𝜎=0...
      6.2k words 6 mins.

      # 割边 # 严格定义 如果 ω(G−e)&gt;ω(G)\omega(G-e)\gt\omega(G)ω(G−e)&gt;ω(G) ,则 eee 为 GGG 的一条割边或桥。 # 充要条件 eee 是 GGG 的割边当且仅当 eee 不在 GGG 的任何圈中。 必要性: 假设 eee 是 GGG 的割边且 eee 在 GGG 的某圈中 充分性: 假设 eee 不在 GGG 的任何圈中且 eee 不是 GGG 的割边,则 G−eG-eG−e 连通。 于是 G−eG-eG−e 中存在一条 (u,v)(u,v)(u,v) 路 lll ,显然...
      1.6k words 1 mins.

      SageMath 🔧 一个非常好用的工具 # 扩展维纳攻击 当私钥过小时,能够对 NNN 进行分解。维纳证明了: d&lt;13N14(q&lt;p&lt;2q)d\lt\frac{1}{3}N^{1\over 4}\\ (q\lt p\lt 2q) d&lt;31​N41​(q&lt;p&lt;2q) 的时候,一定能够对 NNN 进行分解。 # 格规约 # LLL Lenstra–Lenstra–Lovász 基于格的约简算法,它将输入矩阵转换为其最简形式。 使用 LLL...
      8.8k words 8 mins.

      # 概述 # 机器学习范式 监督学习(归纳学习) 给定训练数据 training data 和期望的输出(标签)desired outputs (with labels) 半监督学习 给定训练数据 training data 和部分期望的输出 some labels 无监督学习 仅给定训练数据 training data without labels 强化学习 Reinforce Learning (RL) 从序列决策中获取奖励 observations and periodic rewards as the agent takes sequential actions; #...
      \ No newline at end of file +Balloon Party = 風船のパーティー = fuusen no party
      9.7k words 9 mins.

      # 环的相关定义 设 RRR 是非空集合,如果在 RRR 上定义了两个二元运算 “+++”(称为加法)和 “ ⋅\cdot⋅ ”(称为乘法),且满足: (1) RRR 关于加法 +++ 构成交换群(即加群) (2) RRR 关于乘法 ⋅\cdot⋅ 构成半群,即乘法满足结合律:∀a,b,c∈R,  a⋅(b⋅c)=(a⋅b)⋅c\forall a,b,c\in R,\ \ a\cdot(b\cdot c)=(a\cdot b)\cdot c∀a,b,c∈R,  a⋅(b⋅c)=(a⋅b)⋅c; (3) 乘法...
      2.9k words 3 mins.

      PVE 版本:8.1.4 ,显卡:NVIDIA GTX 745 # 宿主机配置 # IOMMU shellnano /etc/default/grub将 GRUB_CMDLINE_LINUX_DEFAULT=&quot;...&quot; 中的内容修改为如下: shellGRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt video=efifb:off"准确来说是在 &quot;...&quot; 原来的内容后面增加这些内容,其中: quiet...
      3.3k words 3 mins.

      # Intro 死锁的必要条件 互斥:一次只有一个进程使用一个资源,其他进程不能访问分配给其他进程的资源 占有等待 (持有且等待):当一个进程等待其他进程时,继续占有已分配的资源 非抢占:不能强行抢占进程已占有的资源 循环等待:存在一个闭合的进程链,每个进程至少占有此链中下一个进程所需的一个资源前三个只会导致死锁的可能性,而最后一个循环等待是导致死锁的 “最终极条件” 处理死锁的方法: 确保系统永远不会进入死锁状态 锁预防,在 OS 设计阶段就设计成不会出现死锁 死锁避免,在 OS...
      46k words 42 mins.

      年轻人的第一场 CTF ,学到了很多,比较走运拿了第五。最遗憾的是密码学板块了,认真学了不少抽象代数但还是没有做出几题。 队友们:(我起了个整活队名,其实是抄袭另一个叫做 “憧憬成为 CTFer” 的 ) # AI # Network Reverse 网络结构长这样: Sequential( (0): Conv2d(3, 4, kernel_size=(2, 2), stride=(1, 1)) (1): GELU(approximate='none') (2): Conv2d(4, 8, kernel_size=(5, 5), stride=(1, 1)) (3):...
      15k words 14 mins.

      # 公式表 # 基本变换对 # 性质表 # 双边拉普拉斯变换 # 定义 X(s)=∫−∞+∞x(t)e−stdtX(s)=\int_{-\infin}^{+\infin}x(t)e^{-st}dt X(s)=∫−∞+∞​x(t)e−stdt 称为 x(t)x(t)x(t) 的拉普拉斯变换,后面简记为 LT,其中 s=σ+jωs=\sigma+j\omegas=σ+jω 为复数。 若 σ=0\sigma=0σ=0 ,s=jωs=j\omegas=jω 为纯虚数则为傅里叶变换,也就是说连续时间傅里叶变换是双边拉普拉斯变换在 𝜎=0...
      6.2k words 6 mins.

      # 割边 # 严格定义 如果 ω(G−e)&gt;ω(G)\omega(G-e)\gt\omega(G)ω(G−e)&gt;ω(G) ,则 eee 为 GGG 的一条割边或桥。 # 充要条件 eee 是 GGG 的割边当且仅当 eee 不在 GGG 的任何圈中。 必要性: 假设 eee 是 GGG 的割边且 eee 在 GGG 的某圈中 充分性: 假设 eee 不在 GGG 的任何圈中且 eee 不是 GGG 的割边,则 G−eG-eG−e 连通。 于是 G−eG-eG−e 中存在一条 (u,v)(u,v)(u,v) 路 lll ,显然...
      1.6k words 1 mins.

      SageMath 🔧 一个非常好用的工具 # 扩展维纳攻击 当私钥过小时,能够对 NNN 进行分解。维纳证明了: d&lt;13N14(q&lt;p&lt;2q)d\lt\frac{1}{3}N^{1\over 4}\\ (q\lt p\lt 2q) d&lt;31​N41​(q&lt;p&lt;2q) 的时候,一定能够对 NNN 进行分解。 # 格规约 # LLL Lenstra–Lenstra–Lovász 基于格的约简算法,它将输入矩阵转换为其最简形式。 使用 LLL...
      8.8k words 8 mins.

      # 概述 # 机器学习范式 监督学习(归纳学习) 给定训练数据 training data 和期望的输出(标签)desired outputs (with labels) 半监督学习 给定训练数据 training data 和部分期望的输出 some labels 无监督学习 仅给定训练数据 training data without labels 强化学习 Reinforce Learning (RL) 从序列决策中获取奖励 observations and periodic rewards as the agent takes sequential actions; #...
      \ No newline at end of file diff --git a/page/4/index.html b/page/4/index.html index 0c0ce103..cab41a23 100644 --- a/page/4/index.html +++ b/page/4/index.html @@ -1 +1 @@ -Balloon Party = 風船のパーティー = fuusen no party
      2.5k words 2 mins.

      部署了一个 overleaf 玩,目的需求是做一个共享文档,作为腾讯文档、知识库的替代品 注册管理员账号的时候,出现了报错: alertSession error. Please check you have cookies enabled. If the problem persists, try clearing your cache and cookies.查阅这个 issue 后,得到了解决方案,将 config/variables.env 这里注释掉: variables.env # SHARELATEX_BEHIND_PROXY=true#...
      4.6k words 4 mins.

      # 群的同态 # 定义 设 GGG 与 G′G&#x27;G′ 是两个群,函数 φ:G→G′φ:G→G&#x27;φ:G→G′ 如果满足: ∀a,b∈G,  φ(ab)=φ(a)φ(b)∀a,b\in G,\ \ φ(ab)= φ(a)φ(b) ∀a,b∈G,  φ(ab)=φ(a)φ(b) 则 φφφ 是群 GGG 到 G′G&#x27;G′ 的同态 (homomorphism)(一个函数) φ(a)φ(b)φ(a)φ(b)φ(a)φ(b) 是 G′G&#x27;G′ 中的运算,而 ababab 是 GGG 中的运算 考察同态...
      7.3k words 7 mins.

      # 树的基本性质 # 树的叶子数 设 TTT 为 (n,m)(n,m)(n,m) 树,TTT 中有 nin_ini​ 个度为 i,(1≤i≤k)i,(1\leq i\leq k)i,(1≤i≤k) 的点,且有 ∑ni=n\sum n_i=n∑ni​=n ,则有:n1=2+n3+2n4+⋯+(k−2)nkn_1=2+n_3+2n_4+\cdots+(k-2)n_kn1​=2+n3​+2n4​+⋯+(k−2)nk​。 证明:由 m=n−1m=n-1m=n−1...
      6k words 5 mins.

      # 证书相关文件格式 证书 (Certificate) - .cer 、 .crt 私钥 (Private Key) - .key 证书签名请求 (Certificate signing request) - .csr 证书吊销列表 (Certificate Revocation List) - .crl 以上除了 .crl 均可以使用这两种编码方式,从而有这样的后缀: base64 编码 - .pem 二进制编码 (少见) - .der 为了给我们的网页应用使用 https 协议,我们需要得到有效的第三方认证的证书以及对应的私钥。 CA,certificate...
      3.6k words 3 mins.

      # 智能体 # 定义 Agent 是指驻留在某一环境下能够自主(Autonomous)、灵活(Flexible)地执行动作以满足设计目标的行为实体。 上述定义具有如下二个特点。 (1) 定义方式 : Agent 概念定义是基于 Agent 的外部可观察行为特征,而不是其内部的结构 (2) 抽象层次 : Agent 概念更加贴近于人们对现实世界(而不是计算机世界)中行为实体的理解 # 特点 # 驻留性 # 自主性 智能体能在没有人类或其他智能体的干涉和指导的情况下运行,并能根据其内部状态和感知到的环境信息来决定该实施什么样的动作,进而控制自身的行为 #...
      8.4k words 8 mins.

      # 调度相关概念 为什么需要调度? 释放被阻塞、挂起的进程占用的 CPU 资源 实现 I/O 操作和 CPU 并行执行( I/O 密集型和 CPU 密集型) 调度的层次、类型 处理器 / CPU 调度⭐️(进程调度的主要内容) 作业调度 /long-term scheduling / 长程调度 / 高级调度 The decision to add to the pool of processes to be executed 内存调度 /medium-term scheduling / 中程调度 / 中级调度 The decision to add to the number of...
      14k words 13 mins.

      # 公式表 # 基本傅里叶变换对 # 性质 # 非周期信号 # FT 公式推导 定义 x~[n]\widetilde{x}[n]x[n] 为 x[n]x[n]x[n] 的周期延拓,以 NNN 为周期,x[n]x[n]x[n] 是 x~[n]\widetilde{x}[n]x[n] 的一个周期。 当 T→∞T\to\infinT→∞ 时,在 (−∞,+∞)(-\infin,+\infin)(−∞,+∞) 内 x~[n]=x[n]\widetilde{x}[n]=x[n]x[n]=x[n] ;在该极限情况下有...
      2.3k words 2 mins.

      # 归纳总结 缩写: CTFS—— 连续时间傅里叶级数 DTFS—— 离散时间傅里叶级数 CTFT—— 连续时间傅里叶变换 DTFT—— 离散时间傅里叶变换 一图归纳: 信号在时域的特性和在频域的特性之间存在以下对应关系: 时域的周期性 —— 频域的离散性 时域的非周期性 —— 频域的连续性 时域的离散性 —— 频域的周期性 时域的连续性 —— 频域的非周期性 # CTFT 的对偶 若 x(t)⟷CTFTX(jω)x(t)\stackrel{CTFT}{\longleftrightarrow}X(j\omega)x(t)⟷CTFT​X(jω)...
      8.8k words 8 mins.

      # 正规子群 # 定义 设 HHH 是群 GGG 的子群 (⚠️得先是子群),如果 ∀a∈G∀a\in G∀a∈G 都有 Ha=aHHa=aHHa=aH ,则称 HHH 是 GGG 的正规子群 (normal subgroup) 或不变子群 (invariant subgroup),记作: H⊴GH\unlhd G H⊴G 条件 Ha=aHHa=aHHa=aH 仅表示两个集合 HaHaHa 与 aHaHaH 相等。不能错误地认为,由 Ha=aHHa=aHHa=aH 可推出对 HHH 的任意元素 hhh 有 ha=ahha=ahha=ah。 正确的理解是:对任意...
      \ No newline at end of file +Balloon Party = 風船のパーティー = fuusen no party
      2.5k words 2 mins.

      部署了一个 overleaf 玩,目的需求是做一个共享文档,作为腾讯文档、知识库的替代品 注册管理员账号的时候,出现了报错: alertSession error. Please check you have cookies enabled. If the problem persists, try clearing your cache and cookies.查阅这个 issue 后,得到了解决方案,将 config/variables.env 这里注释掉: variables.env # SHARELATEX_BEHIND_PROXY=true#...
      4.6k words 4 mins.

      # 群的同态 # 定义 设 GGG 与 G′G&#x27;G′ 是两个群,函数 φ:G→G′φ:G→G&#x27;φ:G→G′ 如果满足: ∀a,b∈G,  φ(ab)=φ(a)φ(b)∀a,b\in G,\ \ φ(ab)= φ(a)φ(b) ∀a,b∈G,  φ(ab)=φ(a)φ(b) 则 φφφ 是群 GGG 到 G′G&#x27;G′ 的同态 (homomorphism)(一个函数) φ(a)φ(b)φ(a)φ(b)φ(a)φ(b) 是 G′G&#x27;G′ 中的运算,而 ababab 是 GGG 中的运算 考察同态...
      7.3k words 7 mins.

      # 树的基本性质 # 树的叶子数 设 TTT 为 (n,m)(n,m)(n,m) 树,TTT 中有 nin_ini​ 个度为 i,(1≤i≤k)i,(1\leq i\leq k)i,(1≤i≤k) 的点,且有 ∑ni=n\sum n_i=n∑ni​=n ,则有:n1=2+n3+2n4+⋯+(k−2)nkn_1=2+n_3+2n_4+\cdots+(k-2)n_kn1​=2+n3​+2n4​+⋯+(k−2)nk​。 证明:由 m=n−1m=n-1m=n−1...
      6k words 5 mins.

      # 证书相关文件格式 证书 (Certificate) - .cer 、 .crt 私钥 (Private Key) - .key 证书签名请求 (Certificate signing request) - .csr 证书吊销列表 (Certificate Revocation List) - .crl 以上除了 .crl 均可以使用这两种编码方式,从而有这样的后缀: base64 编码 - .pem 二进制编码 (少见) - .der 为了给我们的网页应用使用 https 协议,我们需要得到有效的第三方认证的证书以及对应的私钥。 CA,certificate...
      3.6k words 3 mins.

      # 智能体 # 定义 Agent 是指驻留在某一环境下能够自主(Autonomous)、灵活(Flexible)地执行动作以满足设计目标的行为实体。 上述定义具有如下二个特点。 (1) 定义方式 : Agent 概念定义是基于 Agent 的外部可观察行为特征,而不是其内部的结构 (2) 抽象层次 : Agent 概念更加贴近于人们对现实世界(而不是计算机世界)中行为实体的理解 # 特点 # 驻留性 # 自主性 智能体能在没有人类或其他智能体的干涉和指导的情况下运行,并能根据其内部状态和感知到的环境信息来决定该实施什么样的动作,进而控制自身的行为 #...
      8.4k words 8 mins.

      # 调度相关概念 为什么需要调度? 释放被阻塞、挂起的进程占用的 CPU 资源 实现 I/O 操作和 CPU 并行执行( I/O 密集型和 CPU 密集型) 调度的层次、类型 处理器 / CPU 调度⭐️(进程调度的主要内容) 作业调度 /long-term scheduling / 长程调度 / 高级调度 The decision to add to the pool of processes to be executed 内存调度 /medium-term scheduling / 中程调度 / 中级调度 The decision to add to the number of...
      14k words 13 mins.

      # 公式表 # 基本傅里叶变换对 # 性质 # 非周期信号 # FT 公式推导 定义 x~[n]\widetilde{x}[n]x[n] 为 x[n]x[n]x[n] 的周期延拓,以 NNN 为周期,x[n]x[n]x[n] 是 x~[n]\widetilde{x}[n]x[n] 的一个周期。 当 T→∞T\to\infinT→∞ 时,在 (−∞,+∞)(-\infin,+\infin)(−∞,+∞) 内 x~[n]=x[n]\widetilde{x}[n]=x[n]x[n]=x[n] ;在该极限情况下有...
      2.3k words 2 mins.

      # 归纳总结 缩写: CTFS—— 连续时间傅里叶级数 DTFS—— 离散时间傅里叶级数 CTFT—— 连续时间傅里叶变换 DTFT—— 离散时间傅里叶变换 一图归纳: 信号在时域的特性和在频域的特性之间存在以下对应关系: 时域的周期性 —— 频域的离散性 时域的非周期性 —— 频域的连续性 时域的离散性 —— 频域的周期性 时域的连续性 —— 频域的非周期性 # CTFT 的对偶 若 x(t)⟷CTFTX(jω)x(t)\stackrel{CTFT}{\longleftrightarrow}X(j\omega)x(t)⟷CTFT​X(jω)...
      8.8k words 8 mins.

      # 正规子群 # 定义 设 HHH 是群 GGG 的子群 (⚠️得先是子群),如果 ∀a∈G∀a\in G∀a∈G 都有 Ha=aHHa=aHHa=aH ,则称 HHH 是 GGG 的正规子群 (normal subgroup) 或不变子群 (invariant subgroup),记作: H⊴GH\unlhd G H⊴G 条件 Ha=aHHa=aHHa=aH 仅表示两个集合 HaHaHa 与 aHaHaH 相等。不能错误地认为,由 Ha=aHHa=aHHa=aH 可推出对 HHH 的任意元素 hhh 有 ha=ahha=ahha=ah。 正确的理解是:对任意...
      \ No newline at end of file diff --git a/page/5/index.html b/page/5/index.html index 17d07d1e..b167aef7 100644 --- a/page/5/index.html +++ b/page/5/index.html @@ -1 +1 @@ -Balloon Party = 風船のパーティー = fuusen no party
      4.9k words 4 mins.

      用邻接矩阵或关联矩阵表示图,称为图的代数表示。用矩阵表示图,主要有两个优点: (1) 能够把图输入到计算机中 (2) 可以用代数方法研究图论 Spectral Graph Theory 是研究图和代数的一个领域 # 邻接矩阵 Adjaceny matrix is n×nn\times nn×n symmetric matrix # 定义 设 GGG 为 nnn 阶图,V={v1,z2,⋯ ,vn}V=\{v_1,z_2,\cdots,v_n\}V={v1​,z2​,⋯,vn​} ,邻接矩阵 A(G)=(aij)A(G)=...
      1.4k words 1 mins.

      This article isn't finished yet... Graph Partitioning Bi-partitioning task # Minmal-cut # Normalized-cut Criterion: Normalized-cut [Shi-Malik, '97] Define: Connectivity between groups relative to the density of each...
      5.8k words 5 mins.

      按照所用知识的确定性,可以分为确定性和不确定性推理: 确定性推理是建立在经典逻辑基础上的,经典逻辑的基础之一就是集合论。这在很多实际情况中是很难做到的,如高、矮、胖、瘦就很难精确地分开; 不确定性推理就是从不确定性初始证据出发,通过运用不确定性的知识,最终推出具有一定程度的不确定性但却是合理或者近乎合理的结论的思维过程。 常识(common...
      11k words 10 mins.

      # 群子集的乘积运算 # 定义 设 AAA 和 BBB 是群 GGG 的两个非空子集,称集合: AB={ab∣a∈A,b∈B}AB = \{ab|a\in A, b\in B \} AB={ab∣a∈A,b∈B} 为群的子集 AAA 与 BBB 的乘积 (product) 如果 g∈Gg\in Gg∈G 为群 GGG 的一个元素,A={g}A=\{g\}A={g} ,则: ABABAB 简记为 gB={gb∣b∈B}gB = \{gb|b\in B\}gB={gb∣b∈B}; BABABA 简记为...
      5.6k words 5 mins.

      基本框架 数字电路 组合逻辑电路 以门电路为基本单元 时序逻辑电路 以触发器为基本单元 # 组合逻辑电路基础 Programmable Logic Device : PLD —— 可编程逻辑器件 # 特点 功能上,任意时刻的输出仅仅取决于该时刻的输入,与电路原来的状态无关; 结构上,组合逻辑电路不含有存储单元(记忆单元),只有从输入到输出的通路,没有反馈环路 # 分析方法 给定一个组合逻辑电路,分析其电路逻辑功能: 根据电路图,从输入到输出逐级分析,得到输出与输入的逻辑函数式; 对得到的逻辑函数式进行化简、形式变换或列出真值表,最后分析其逻辑功能; # 设计方法 Step...
      12k words 11 mins.

      This article isn't finished yet... # 严格备选 (Strict Alternation) # PetersonSolution # 互斥锁 互斥锁是一种外部强加的控制方案,或者说是全局控制; 获得锁: 伪代码acquire &#123; while (!available) ; /* busy wait */ available = false;&#125;释放锁: 伪代码release &#123; available = true;&#125;利用互斥锁的临界区问题解决方案: 伪代码while (true)...
      23k words 21 mins.

      # 公式表 # 傅里叶变换性质 # 基本傅里叶变换对 连续时间非周期信号傅里叶变换的推导基本思想 非周期函数可以通过周期性延拓得到周期函数 周期函数可以令基波周期趋于无穷大得到连续的非周期函数 对于周期性矩形脉冲信号: ak=2T1TSa(kπ2T1T)Tak=2T1Sa(ωT1)\begin{aligned} a_k &amp;= \frac{2T_1}{T}\text{Sa}(k\pi\frac{2T_1}{T})\\ Ta_k &amp;= 2T_1\text{Sa}(\omega...
      3k words 3 mins.

      # 置换群的定义 设 S={1,2,⋯ ,n}S=\{1,2,\cdots,n\}S={1,2,⋯,n} ; S 上的任意双函数 σ:S→S\sigma:S\to Sσ:S→S 称为 S 上的一个 n 元置换 (permutation),记为: σ=(12⋯nσ(1)σ(2)⋯σ(n))\sigma= \begin{pmatrix} 1 &amp; 2 &amp; \cdots &amp; n \\ \sigma(1) &amp; \sigma(2)...
      \ No newline at end of file +Balloon Party = 風船のパーティー = fuusen no party
      4.9k words 4 mins.

      用邻接矩阵或关联矩阵表示图,称为图的代数表示。用矩阵表示图,主要有两个优点: (1) 能够把图输入到计算机中 (2) 可以用代数方法研究图论 Spectral Graph Theory 是研究图和代数的一个领域 # 邻接矩阵 Adjaceny matrix is n×nn\times nn×n symmetric matrix # 定义 设 GGG 为 nnn 阶图,V={v1,z2,⋯ ,vn}V=\{v_1,z_2,\cdots,v_n\}V={v1​,z2​,⋯,vn​} ,邻接矩阵 A(G)=(aij)A(G)=...
      1.4k words 1 mins.

      This article isn't finished yet... Graph Partitioning Bi-partitioning task # Minmal-cut # Normalized-cut Criterion: Normalized-cut [Shi-Malik, '97] Define: Connectivity between groups relative to the density of each...
      5.8k words 5 mins.

      按照所用知识的确定性,可以分为确定性和不确定性推理: 确定性推理是建立在经典逻辑基础上的,经典逻辑的基础之一就是集合论。这在很多实际情况中是很难做到的,如高、矮、胖、瘦就很难精确地分开; 不确定性推理就是从不确定性初始证据出发,通过运用不确定性的知识,最终推出具有一定程度的不确定性但却是合理或者近乎合理的结论的思维过程。 常识(common...
      11k words 10 mins.

      # 群子集的乘积运算 # 定义 设 AAA 和 BBB 是群 GGG 的两个非空子集,称集合: AB={ab∣a∈A,b∈B}AB = \{ab|a\in A, b\in B \} AB={ab∣a∈A,b∈B} 为群的子集 AAA 与 BBB 的乘积 (product) 如果 g∈Gg\in Gg∈G 为群 GGG 的一个元素,A={g}A=\{g\}A={g} ,则: ABABAB 简记为 gB={gb∣b∈B}gB = \{gb|b\in B\}gB={gb∣b∈B}; BABABA 简记为...
      5.6k words 5 mins.

      基本框架 数字电路 组合逻辑电路 以门电路为基本单元 时序逻辑电路 以触发器为基本单元 # 组合逻辑电路基础 Programmable Logic Device : PLD —— 可编程逻辑器件 # 特点 功能上,任意时刻的输出仅仅取决于该时刻的输入,与电路原来的状态无关; 结构上,组合逻辑电路不含有存储单元(记忆单元),只有从输入到输出的通路,没有反馈环路 # 分析方法 给定一个组合逻辑电路,分析其电路逻辑功能: 根据电路图,从输入到输出逐级分析,得到输出与输入的逻辑函数式; 对得到的逻辑函数式进行化简、形式变换或列出真值表,最后分析其逻辑功能; # 设计方法 Step...
      12k words 11 mins.

      This article isn't finished yet... # 严格备选 (Strict Alternation) # PetersonSolution # 互斥锁 互斥锁是一种外部强加的控制方案,或者说是全局控制; 获得锁: 伪代码acquire &#123; while (!available) ; /* busy wait */ available = false;&#125;释放锁: 伪代码release &#123; available = true;&#125;利用互斥锁的临界区问题解决方案: 伪代码while (true)...
      23k words 21 mins.

      # 公式表 # 傅里叶变换性质 # 基本傅里叶变换对 连续时间非周期信号傅里叶变换的推导基本思想 非周期函数可以通过周期性延拓得到周期函数 周期函数可以令基波周期趋于无穷大得到连续的非周期函数 对于周期性矩形脉冲信号: ak=2T1TSa(kπ2T1T)Tak=2T1Sa(ωT1)\begin{aligned} a_k &amp;= \frac{2T_1}{T}\text{Sa}(k\pi\frac{2T_1}{T})\\ Ta_k &amp;= 2T_1\text{Sa}(\omega...
      3k words 3 mins.

      # 置换群的定义 设 S={1,2,⋯ ,n}S=\{1,2,\cdots,n\}S={1,2,⋯,n} ; S 上的任意双函数 σ:S→S\sigma:S\to Sσ:S→S 称为 S 上的一个 n 元置换 (permutation),记为: σ=(12⋯nσ(1)σ(2)⋯σ(n))\sigma= \begin{pmatrix} 1 &amp; 2 &amp; \cdots &amp; n \\ \sigma(1) &amp; \sigma(2)...
      \ No newline at end of file diff --git a/page/6/index.html b/page/6/index.html index 8c5f454d..f303ce89 100644 --- a/page/6/index.html +++ b/page/6/index.html @@ -1 +1 @@ -Balloon Party = 風船のパーティー = fuusen no party
      3.9k words 4 mins.

      This article ism't finished yet... # 顶点标号法 Dantzig 算法,1959 年,旦捷希 (Dantzig) 发现了在赋权图中求由点 a 到点 b 的最短路好算法,称为顶点标号法。 和弗洛伊德算法非常非常像... ,在这里补充一下 Floyid 算法对邻接矩阵求最短距离矩阵过程,这个过程和 Dantzig 几乎一致(完全一致好吧,考试可能会考?): 按顺序一列一列看,看第 iii 列时: 按顺序一行一行看,看第 jjj 行时,若 aji≠∞a_{ji}\neq\infinaji​=∞ 则: 看第 jjj 列,看...
      1.3k words 1 mins.

      这是老师布置的一个小作业,让我们在 linux 内核源码里增加自定义的系统调用程序,用这篇文章记录一下完整的操作过程; 这样扩展 Linux 内核的传统方式需要每次都重新编译内核,更现代的方式是使用 eBPF 使用清华镜像源下载 linux 内核 5.10.19 版本,解压然后进入解压目录: shellwget https://mirrors.tuna.tsinghua.edu.cn/kernel/v5.x/linux-5.10.19.tar.gz......tar -zxvf linux-5.10.19.tar.gz......cd linux-5.10.19在 kernel/sys.c...
      14k words 13 mins.

      # 搜索相关概念 对于给定的问题,智能系统的行为一般是找到能够达到所希望目标的动作序列,并使其所付出的代价最小、性能最好。 基于给定的问题,问题求解的第一步是目标的表示。 搜索就是找到智能系统的动作序列的过程。 搜索算法的: 输入是给定的问题 搜索什么(目标) 在哪里搜索(搜索空间) 和通常的搜索空间不同,人工智能中大多数问题的状态空间在问题求解之前不是全部知道的 输出是表示为动作序列的方案。 一旦有了方案,就可以执行该方案所给出的动作了。(执行阶段) 求解问题包括: 目标表示 搜索 执行 #...
      1.5k words 1 mins.

      # 基本概念 !!! 可能会在选择填空题中考察 上拉 —— 使输出钳位至高电平 下拉 —— 使输出钳位至低电平; 灌电流 —— 输出为低电平时,负载电流从外部电路注入输出端口; 拉电流 —— 输出为高电平时,负载电流从输出端口流出到外部电路; 当门电路没有外部的有源输入信号,而是输入端口与地之间接入一个电阻时: 关门电阻 —— 能够维持门电路输出高电平的电阻的最大值; 开门电阻 —— 能够维持门电路输出低电平的电阻的最小值; (联想 TTL 反相器的输入端负载特性曲线) 扇入系数 —— 门电路允许的输入端的个数; 扇出系数 —— 门电路允许驱动的同类型负载门的个数; 高阻态...
      15k words 13 mins.

      # 连续时间周期信号的傅里叶级数表示 # 连续时间傅里叶级数 成谐波关系的复指数信号集:ejkω0t,   k=0,±1,±2,⋯e^{jk\omega_0 t},\ \ \ k=0,\pm 1,\pm 2,\cdotsejkω0​t,   k=0,±1,±2,⋯...
      3k words 3 mins.

      # 宿主与虚拟机之间的网络问题 我们的两台宿主居然都 ping 不到虚拟机,导致后续 haproxy 代理转发后出现所有虚拟机 server 都是 down 状态 原因应该是宿主只有一个校园网网段的 ip,但是虚拟机只有实验室局域网网段的 ip 这个问题需要配置宿主节点的网络,可以在 PVE 控制面板修改 网络 / Network: 实际上就是编辑该节点的: /etc/network/interfaces 配置文件 应该需要配置虚拟网卡才能解决,但是我们的一台服务器有两张网卡(图中 eno1 eno2) 所以我们最后的解决方案给服务器插了多一条网线,配置该网卡 ip 为实验室局域网的...
      953 words 1 mins.

      # VMware 或 VirtualBox 导出虚拟机 导出之前可以参考以下几个因素,避免后续麻烦: 虚拟机由 VMware 或 VirtualBox 导出,磁盘镜像有可能是 vmdk 格式,如果从 KVM 管理器导出,可能是 qcow2 格式。最流行的虚拟机导出格式是 OVF 标准,但实际上由于 OVF 标准本身不完善,以及虚拟机管理器导出的众多非标准扩展信息,跨管理器使用 OVF 往往受很多限制。 除了格式不兼容之外,如果虚拟机管理器之间的虚拟硬件设备差别太大,也可能导致虚拟机镜像导入失败。特别是 Windows 虚拟机,对于硬件变化特别敏感。为解决这一问题,可以在导出 Windows...
      3k words 3 mins.

      # 前言 在 Matrix 实验室用电子垃圾搭了一个小集群。 起因是 jygg 拿了一台被淘汰的存储型服务器给 cjl 玩,(据说是以前买来发现性能太差了,于是就把里面的 64T 的硬盘全部拿走了装到别的服务器上了,这台就废弃了),cjl 整了个 500g 的机械硬盘给服务器装上了,同时把不知为啥留在这里的一个台式 PC 给我玩,然后索性就装上了 PVE,在 jygg 的帮助下非常顺利搭了一个两台物理机组成的集群。 # 安装 PVE 到官网下载 PVE,这是一个只有 1G 大小左右的基于 debian 的装好了 proxmox 相关软件、服务的镜像,然后用 U 盘给物理机安装。 安装过程可以用...
      9.6k words 9 mins.

      # 群 (Group) 的定义 如果集合 G 及其二元运算 ⋅\cdot⋅ 满足下面的性质,则称 (G,⋅)(G,\cdot )(G,⋅) 是群: 二元运算 ⋅\cdot⋅ 满足结合律:即 ∀a,b,c∈G∀a,b,c\in G∀a,b,c∈G 有 (a⋅b)⋅c=a⋅(b⋅c)(a\cdot b)\cdot c=a\cdot(b\cdot c)(a⋅b)⋅c=a⋅(b⋅c); 有单位元 eee,即存在 e∈Ge\in Ge∈G,使得 ∀a∈G∀a\in G∀a∈G 有 e⋅a=a⋅e=ae\cdot...
      \ No newline at end of file +Balloon Party = 風船のパーティー = fuusen no party
      3.9k words 4 mins.

      This article ism't finished yet... # 顶点标号法 Dantzig 算法,1959 年,旦捷希 (Dantzig) 发现了在赋权图中求由点 a 到点 b 的最短路好算法,称为顶点标号法。 和弗洛伊德算法非常非常像... ,在这里补充一下 Floyid 算法对邻接矩阵求最短距离矩阵过程,这个过程和 Dantzig 几乎一致(完全一致好吧,考试可能会考?): 按顺序一列一列看,看第 iii 列时: 按顺序一行一行看,看第 jjj 行时,若 aji≠∞a_{ji}\neq\infinaji​=∞ 则: 看第 jjj 列,看...
      1.3k words 1 mins.

      这是老师布置的一个小作业,让我们在 linux 内核源码里增加自定义的系统调用程序,用这篇文章记录一下完整的操作过程; 这样扩展 Linux 内核的传统方式需要每次都重新编译内核,更现代的方式是使用 eBPF 使用清华镜像源下载 linux 内核 5.10.19 版本,解压然后进入解压目录: shellwget https://mirrors.tuna.tsinghua.edu.cn/kernel/v5.x/linux-5.10.19.tar.gz......tar -zxvf linux-5.10.19.tar.gz......cd linux-5.10.19在 kernel/sys.c...
      14k words 13 mins.

      # 搜索相关概念 对于给定的问题,智能系统的行为一般是找到能够达到所希望目标的动作序列,并使其所付出的代价最小、性能最好。 基于给定的问题,问题求解的第一步是目标的表示。 搜索就是找到智能系统的动作序列的过程。 搜索算法的: 输入是给定的问题 搜索什么(目标) 在哪里搜索(搜索空间) 和通常的搜索空间不同,人工智能中大多数问题的状态空间在问题求解之前不是全部知道的 输出是表示为动作序列的方案。 一旦有了方案,就可以执行该方案所给出的动作了。(执行阶段) 求解问题包括: 目标表示 搜索 执行 #...
      1.5k words 1 mins.

      # 基本概念 !!! 可能会在选择填空题中考察 上拉 —— 使输出钳位至高电平 下拉 —— 使输出钳位至低电平; 灌电流 —— 输出为低电平时,负载电流从外部电路注入输出端口; 拉电流 —— 输出为高电平时,负载电流从输出端口流出到外部电路; 当门电路没有外部的有源输入信号,而是输入端口与地之间接入一个电阻时: 关门电阻 —— 能够维持门电路输出高电平的电阻的最大值; 开门电阻 —— 能够维持门电路输出低电平的电阻的最小值; (联想 TTL 反相器的输入端负载特性曲线) 扇入系数 —— 门电路允许的输入端的个数; 扇出系数 —— 门电路允许驱动的同类型负载门的个数; 高阻态...
      15k words 13 mins.

      # 连续时间周期信号的傅里叶级数表示 # 连续时间傅里叶级数 成谐波关系的复指数信号集:ejkω0t,   k=0,±1,±2,⋯e^{jk\omega_0 t},\ \ \ k=0,\pm 1,\pm 2,\cdotsejkω0​t,   k=0,±1,±2,⋯...
      3k words 3 mins.

      # 宿主与虚拟机之间的网络问题 我们的两台宿主居然都 ping 不到虚拟机,导致后续 haproxy 代理转发后出现所有虚拟机 server 都是 down 状态 原因应该是宿主只有一个校园网网段的 ip,但是虚拟机只有实验室局域网网段的 ip 这个问题需要配置宿主节点的网络,可以在 PVE 控制面板修改 网络 / Network: 实际上就是编辑该节点的: /etc/network/interfaces 配置文件 应该需要配置虚拟网卡才能解决,但是我们的一台服务器有两张网卡(图中 eno1 eno2) 所以我们最后的解决方案给服务器插了多一条网线,配置该网卡 ip 为实验室局域网的...
      953 words 1 mins.

      # VMware 或 VirtualBox 导出虚拟机 导出之前可以参考以下几个因素,避免后续麻烦: 虚拟机由 VMware 或 VirtualBox 导出,磁盘镜像有可能是 vmdk 格式,如果从 KVM 管理器导出,可能是 qcow2 格式。最流行的虚拟机导出格式是 OVF 标准,但实际上由于 OVF 标准本身不完善,以及虚拟机管理器导出的众多非标准扩展信息,跨管理器使用 OVF 往往受很多限制。 除了格式不兼容之外,如果虚拟机管理器之间的虚拟硬件设备差别太大,也可能导致虚拟机镜像导入失败。特别是 Windows 虚拟机,对于硬件变化特别敏感。为解决这一问题,可以在导出 Windows...
      3k words 3 mins.

      # 前言 在 Matrix 实验室用电子垃圾搭了一个小集群。 起因是 jygg 拿了一台被淘汰的存储型服务器给 cjl 玩,(据说是以前买来发现性能太差了,于是就把里面的 64T 的硬盘全部拿走了装到别的服务器上了,这台就废弃了),cjl 整了个 500g 的机械硬盘给服务器装上了,同时把不知为啥留在这里的一个台式 PC 给我玩,然后索性就装上了 PVE,在 jygg 的帮助下非常顺利搭了一个两台物理机组成的集群。 # 安装 PVE 到官网下载 PVE,这是一个只有 1G 大小左右的基于 debian 的装好了 proxmox 相关软件、服务的镜像,然后用 U 盘给物理机安装。 安装过程可以用...
      9.6k words 9 mins.

      # 群 (Group) 的定义 如果集合 G 及其二元运算 ⋅\cdot⋅ 满足下面的性质,则称 (G,⋅)(G,\cdot )(G,⋅) 是群: 二元运算 ⋅\cdot⋅ 满足结合律:即 ∀a,b,c∈G∀a,b,c\in G∀a,b,c∈G 有 (a⋅b)⋅c=a⋅(b⋅c)(a\cdot b)\cdot c=a\cdot(b\cdot c)(a⋅b)⋅c=a⋅(b⋅c); 有单位元 eee,即存在 e∈Ge\in Ge∈G,使得 ∀a∈G∀a\in G∀a∈G 有 e⋅a=a⋅e=ae\cdot...
      \ No newline at end of file diff --git a/page/7/index.html b/page/7/index.html index b74fb13e..5b9d0b90 100644 --- a/page/7/index.html +++ b/page/7/index.html @@ -1 +1 @@ -Balloon Party = 風船のパーティー = fuusen no party
      460 words 1 mins.

      想在这里特别地感谢你!想在这里特别地感谢你! 想在这里特别地感谢你! 每一句“生日快乐”每一句“生日快乐” 每一句“生日快乐” 就算只是一句“生日快乐”就算只是一句“生日快乐” 就算只是一句“生日快乐” 都让我非常幸福!都让我非常幸福! 都让我非常幸福! 特别感谢:特别感谢: 特别感谢: Luv thank you LDY thank you kazegairoman thank you CJL thank...
      5.2k words 5 mins.

      # 线程的基本概念 # 为什么需要线程 有的进程可能需要 “同时” 做很多事,而传统的进程只能串行地执行一系列程序。为此,引入了 “线程”,来增加并发度。 大多数现代应用程序都是多线程的,线程在应用程序中运行,应用程序的多个任务可以由单独的线程实现 如 Web 浏览器: 更新显示 获取数据 拼写检查 响应网络请求 进程创建很重载,而线程创建很轻量; 可以简化代码,提高效率; 内核 (作为内核程序进程) 通常是多线程的,多个线程在内核中运行,每个线程执行一个特定的任务; 现代服务器 —— 多线程服务器,可以同时处理多个并发请求 #...
      17k words 16 mins.

      Linear Time Invariant 线性时不变 基本信号应具有以下特点: 本身尽可能简单,并且用它们的线性组合能够表示尽可能广泛的信号 LTI 系统对这种信号的响应易于计算且有利于对系统的深入理解 两类有用的基本信号: 复指数信号 单位冲激信号 本章主要考虑以单位冲激信号为基本信号进行信号与系统分析 # 卷积和 # 定义 对于任意一个离散时间系统: 设离散时间系统为 LTI 的,定义单位脉冲响应 h[n]h[n]h[n] 为以单位冲激信号 δ[n]\delta[n]δ[n] 为输入时的输出: δ[n]→h[n]\delta[n]\to...
      21k words 19 mins.

      # 进程的基本概念 # 进程的定义 典型的定义: 进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位 == 一个具有独立功能的程序在一个数据集合上运行的过程 # 区分进程、程序、进程实体 程序(Program):是静态的,就是个存放在磁盘里的可执行文件,就是一系列的指令集合 静态连接 动态链接 进程(Process):是动态的,是程序的一次执行过程 进程实体(进程映像):是静态的,反应了进程在某一时刻的状态 # 进程实体的组成 一个 == 进程实体(进程映像)== 由三个部分组成: PCB 进程描述信息 进程控制和管理信息 资源分配清单 处理机状态信息(CPU...
      719 words 1 mins.

      # 环境变量文件的加载顺序 在登录 Linux 系统并启动一个 bash shell 时,默认情况下 bash 会在若干个文件中查找环境变量的设置。这些文件统称为系统环境文件。bash 检查的环境变量文件的顺序情况取决于系统运行的 shell 方式。系统运行 shell 方式一般为 4 种: 是否交互式 是否登陆式 哪些情况 是 是 通过系统用户登录默认运行的 shell 是 否 非登录交互式运行 shell 否 是 执行脚本运行非交互式 shell 否 否 无 # bash 命令启动 shell 命令 bash 启动 shell 时,可以通过选项改变其行为 shellbash...
      976 words 1 mins.

      # 环境 / 情景 MacOS 14.2 M1 用 VSCode 远程连接 Ubuntu 22.04 # 问题 在虚拟机上安装了 Enviroment Modules ,并按照官方配置文档配置了 bash 启动时自动加载 module 指令,ssh 远程登录虚拟机 'module' 指令可用,但是 VSCode 远程连接虚拟机发现 module 指令使用不了。 # 原因 在 VSCode 的 bash 中检查发现当前 shell 不是登录式的: shellshopt login_shell# 结果为 off 不是登陆式login_shell off分析发现由于 VSCode...
      12k words 11 mins.

      强烈推荐:https://hrl.boyuai.com/ # 基本概念 RL, in a nutshell, is to “learn to make good sequences of decisions through trail-and-errors” # 机器学习范式 监督 给定训练数据 training data 和期望的输出(标签)desired outputs (with labels) 半监督 给定训练数据 training data 和部分期望的输出 some labels 无监督 仅给定训练数据 training data without...
      12k words 11 mins.

      # 图的基础知识 # 图的定义 一 个 图 GGG 定 义 为 一 个 有 序 对 (V , E), 记 为 G = ( V , E ), 其 中: V 是一个非空集合,称为顶点集或边集,其元素称为项点或点 E 是由 V 中的点组成的无序点对构成的集合,称为边集,其元素称为边,且同一 点对在 E 中可出现多次。 图 GGG 的顶点集也记为 V (G),边集也记为 E (G)。 顶点集和边集都有限的图称为有限图。 只有一个项点而无边的图称为平凡图。其他所有的图都称为非平凡图。 做题往往需要先排除平凡图 边集为空的图称为空图。 图 GGG 的顶点数 (或阶数) 和边数可分别用符号 n(G)...
      2.1k words 2 mins.

      # 题面 设 f:A→Bf:A\to Bf:A→B 是函数,定义 A 上的关系 R,∀a,b∈A\forall a,b \in A∀a,b∈A,a R b 当且仅当 f (a) = f (b) 。 证明 R 是等价关系,并给出它的等价类和商集,求这样的等价关系有多少个? # 证明 R 是等价关系 显然 R 是等价关系,因为对∀a, b, c\in A,f (a)=f (a), f (a)=f (b) 蕴涵 f (b) = f (a) , f (a) = f (b) 且 f (b) = f (c) 蕴涵 f (a) = f (c) ,即 R...
      \ No newline at end of file +Balloon Party = 風船のパーティー = fuusen no party
      460 words 1 mins.

      想在这里特别地感谢你!想在这里特别地感谢你! 想在这里特别地感谢你! 每一句“生日快乐”每一句“生日快乐” 每一句“生日快乐” 就算只是一句“生日快乐”就算只是一句“生日快乐” 就算只是一句“生日快乐” 都让我非常幸福!都让我非常幸福! 都让我非常幸福! 特别感谢:特别感谢: 特别感谢: Luv thank you LDY thank you kazegairoman thank you CJL thank...
      5.2k words 5 mins.

      # 线程的基本概念 # 为什么需要线程 有的进程可能需要 “同时” 做很多事,而传统的进程只能串行地执行一系列程序。为此,引入了 “线程”,来增加并发度。 大多数现代应用程序都是多线程的,线程在应用程序中运行,应用程序的多个任务可以由单独的线程实现 如 Web 浏览器: 更新显示 获取数据 拼写检查 响应网络请求 进程创建很重载,而线程创建很轻量; 可以简化代码,提高效率; 内核 (作为内核程序进程) 通常是多线程的,多个线程在内核中运行,每个线程执行一个特定的任务; 现代服务器 —— 多线程服务器,可以同时处理多个并发请求 #...
      17k words 16 mins.

      Linear Time Invariant 线性时不变 基本信号应具有以下特点: 本身尽可能简单,并且用它们的线性组合能够表示尽可能广泛的信号 LTI 系统对这种信号的响应易于计算且有利于对系统的深入理解 两类有用的基本信号: 复指数信号 单位冲激信号 本章主要考虑以单位冲激信号为基本信号进行信号与系统分析 # 卷积和 # 定义 对于任意一个离散时间系统: 设离散时间系统为 LTI 的,定义单位脉冲响应 h[n]h[n]h[n] 为以单位冲激信号 δ[n]\delta[n]δ[n] 为输入时的输出: δ[n]→h[n]\delta[n]\to...
      21k words 19 mins.

      # 进程的基本概念 # 进程的定义 典型的定义: 进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位 == 一个具有独立功能的程序在一个数据集合上运行的过程 # 区分进程、程序、进程实体 程序(Program):是静态的,就是个存放在磁盘里的可执行文件,就是一系列的指令集合 静态连接 动态链接 进程(Process):是动态的,是程序的一次执行过程 进程实体(进程映像):是静态的,反应了进程在某一时刻的状态 # 进程实体的组成 一个 == 进程实体(进程映像)== 由三个部分组成: PCB 进程描述信息 进程控制和管理信息 资源分配清单 处理机状态信息(CPU...
      719 words 1 mins.

      # 环境变量文件的加载顺序 在登录 Linux 系统并启动一个 bash shell 时,默认情况下 bash 会在若干个文件中查找环境变量的设置。这些文件统称为系统环境文件。bash 检查的环境变量文件的顺序情况取决于系统运行的 shell 方式。系统运行 shell 方式一般为 4 种: 是否交互式 是否登陆式 哪些情况 是 是 通过系统用户登录默认运行的 shell 是 否 非登录交互式运行 shell 否 是 执行脚本运行非交互式 shell 否 否 无 # bash 命令启动 shell 命令 bash 启动 shell 时,可以通过选项改变其行为 shellbash...
      976 words 1 mins.

      # 环境 / 情景 MacOS 14.2 M1 用 VSCode 远程连接 Ubuntu 22.04 # 问题 在虚拟机上安装了 Enviroment Modules ,并按照官方配置文档配置了 bash 启动时自动加载 module 指令,ssh 远程登录虚拟机 'module' 指令可用,但是 VSCode 远程连接虚拟机发现 module 指令使用不了。 # 原因 在 VSCode 的 bash 中检查发现当前 shell 不是登录式的: shellshopt login_shell# 结果为 off 不是登陆式login_shell off分析发现由于 VSCode...
      12k words 11 mins.

      强烈推荐:https://hrl.boyuai.com/ # 基本概念 RL, in a nutshell, is to “learn to make good sequences of decisions through trail-and-errors” # 机器学习范式 监督 给定训练数据 training data 和期望的输出(标签)desired outputs (with labels) 半监督 给定训练数据 training data 和部分期望的输出 some labels 无监督 仅给定训练数据 training data without...
      2.6k words 2 mins.

      # 基本概念 # 不严格定义的概念 # 集合 作为整体研究的一堆东西,用大写字母 A, B, C, ⋯表示 # 元素 集合这一堆东西中的每一个,用小写字母 a, b, c, ⋯表示 # 属于 元素与集合间的关系 元素 a 属于集合 A ,记为 a∈Aa\in Aa∈A a 不属于 A,记为 a∉Aa\notin Aa∈/A 元素与集合间的属于关系也称为成员关系,元素是集合的成员 # 全集 研究范围内的所有东西,记为 U # 用逻辑语言严格定义的概念 # 子集关系 A⊆B⇔∀x(x∈A→x∈B)A \subseteq B \lrArr \forall...
      2.1k words 2 mins.

      # 题面 设 f:A→Bf:A\to Bf:A→B 是函数,定义 A 上的关系 R,∀a,b∈A\forall a,b \in A∀a,b∈A,a R b 当且仅当 f (a) = f (b) 。 证明 R 是等价关系,并给出它的等价类和商集,求这样的等价关系有多少个? # 证明 R 是等价关系 显然 R 是等价关系,因为对∀a, b, c\in A,f (a)=f (a), f (a)=f (b) 蕴涵 f (b) = f (a) , f (a) = f (b) 且 f (b) = f (c) 蕴涵 f (a) = f (c) ,即 R...
      \ No newline at end of file diff --git a/page/8/index.html b/page/8/index.html index 8efc701e..c3ca0127 100644 --- a/page/8/index.html +++ b/page/8/index.html @@ -1 +1 @@ -Balloon Party = 風船のパーティー = fuusen no party
      2.6k words 2 mins.

      # 基本概念 # 不严格定义的概念 # 集合 作为整体研究的一堆东西,用大写字母 A, B, C, ⋯表示 # 元素 集合这一堆东西中的每一个,用小写字母 a, b, c, ⋯表示 # 属于 元素与集合间的关系 元素 a 属于集合 A ,记为 a∈Aa\in Aa∈A a 不属于 A,记为 a∉Aa\notin Aa∈/A 元素与集合间的属于关系也称为成员关系,元素是集合的成员 # 全集 研究范围内的所有东西,记为 U # 用逻辑语言严格定义的概念 # 子集关系 A⊆B⇔∀x(x∈A→x∈B)A \subseteq B \lrArr \forall...
      5.3k words 5 mins.

      # 逻辑代数中的基本运算 # 三种基本运算 # 真值表 表征逻辑事件输入(条件)和输出(结果)之间全部可能状态的表格 与运算: A B Y 0 0 0 0 1 0 1 0 0 1 1 1 或运算: A B Y 0 0 0 0 1 1 1 0 1 1 1 1 非运算: A Y 0 1 1 0 # 其他复合逻辑运算 # 与非 “先与再非” # 或非 “先或再非” # 与或非 “先与再或再非” # 异或 XOR 不同时输出 1,相同时输出 0 A⊕B=A‾B+AB‾A\oplus...
      2.5k words 2 mins.

      # 编码的概念 广义的编码指的就是将信息从一种形式转换为另一种规范的形式; 对于数字电路,就是将现实世界中的各种物理信息转换为离散的电压序列,来表示、处理和分析信息; 事实上,进位计数制也是一种编码,用不同进制数来表示 “量”; 将数制与码制分开介绍,首先单独讲解数制是因为数制的一个重要的特点是其编码后能够参与算术运算;而一般来说码制是对非数值信息的表示; 教材中的缩写术语: MSB: Most Significant Bit,最高位 LSB: Least Significant Bit,最低位 # 二进制编码 无符号二进制编码只能表示 0...
      3.7k words 3 mins.

      # 系统的描述 # 连续 / 离散 时间系统 # 连续时间系统 输入信号与输出响应都是连续时间信号的系统。 eg: 机械系统、电路系统 # 离散时间系统 输入信号与输出响应都是离散时间信号的系统。 eg: 人口问题 # 两种描述方法 # 输入输出描述法 (微分方程、差分⽅程) 着眼于系统输入与输出的关系,适⽤用于单输入 — 单输出系统。 # 状态变量描述法 (状态⽅程、输出方程) 即可描述输入与输出的关系,还可以描述系统的内部状态 既可⽤用于单输入 — 单输出系统,⼜可⽤于多输⼊ — 多输出系统。 #...
      754 words 1 mins.

      # 数制 # 数制的概念 数制 (numerical system),又称 “计数制”,指用一组固定的符号和统一的规则来表示数值的方法; 数制关注的内容:每一位的构成(使用什么符号即数码)和进位的规则; 基本概念: 基数 —— 使用的数码的个数,即每一位最多能用多少个符号来表示;基数是 N 则称为 N 进制, 即 “逢 N 进一” 权 —— 每一位的 1 代表的大小; # 常用数制 # 不同进制的转换 # 其他进制 -&gt; 十进制 只需要按照 D=∑kiNiD=\sum k_i N^iD=∑ki​Ni 展开即可; kik_iki​ 为第 i 位的系数 NiN^iNi...
      1.9k words 2 mins.

      # 人工智能的概念 人工智能(Artificial Intelligence - AI):研究如何通过计算机技术实现一个智能体,让智能体完成类似于人类智能的行为。 # 智能体 Agent 完成智能行为的主体,是物理或抽象实体,可以感知世界并对世界施加作用。 大模型智能体 LLM Agent 在近几年随 ChatGPT 兴起的新概念 # 智能体的两大目标 能否使智能体像人一样思考、理性地思考? 能否使智能体像人一样行动、理性地行动? # 智能体可否像人一样思考 首先,需要测量人如何思考的方法:内省、心理实验、 脑成像。 #...
      12k words 11 mins.

      # 操作系统的定义 实际上操作系统没有普遍接受的定义 操作系统 (Operating System,OS)是指控制和管理整个计算机系统的硬件和软件资源,并合理地组织调度计算机的工作和资源的分配;以提供给用户和其他软件方便的接口和环境;它是计算机系统中最基本的系统软件。 # 操作系统的功能和目标 # 作为系统资源的管理者 # 提供的功能 处理机管理 存储器管理 文件管理 设备管理 # 目标 安全、高效 # 向上层提供方便易用的服务 # GUI (Graphical User Interface) 图形化用户接口 # CLI (Command Line Interface)...
      27k words 25 mins.

      # 参考资料 Rust 语言圣经 (自称) 锈书 官网 # 环境配置 更新 Rust bashrustup update卸载 Rust bashrustup self uninstall查看版本 bashrustc --version## 显示格式rustc.x.y.z([commit hash] [commit date])安装 Rust 同时还会安装文档,查看本地文档 bashrustup doc# Rust 工具 # 编译器 # rustc 只适合单文件编译 shellrustc xxx.rs &lt;output># cargo Cargo 是 Rust...
      9.6k words 9 mins.

      # 能量 / 功率 信号 # 能量信号 能量为一有界值,即 0 &lt; E &lt; + ∞,此时 P = 0 有时求 P 不好求,但是 E 好求,可以证明 E 为有界的,从而得到 P = 0 # 功率信号 功率为一有界值,即 0 &lt; P &lt; + ∞ ,此时 E = ∞ 有时求 E 不好求,但是 P 好求,可以证明 P 为有界的,从而得到 E = ∞ # 信号的分解 #...
      9.4k words 9 mins.

      # pthread 库 # 简介 pthread 是 POSIX 线程库,它是一种跨平台的线程库,可以在不同的操作系统上使用。它是 C 语言的标准库,提供了一组函数来创建、管理和同步线程。&quot;pthread&quot; 库相对于 &quot;thread&quot; 库来说,更加底层和与操作系统紧密相关。 thread 是 C11 标准提供的线程库,它是 C 的一部分。它提供了一种面向对象的方式来创建、管理和同步线程。&quot;thread&quot; 库提供了 std::thread...
      \ No newline at end of file +Balloon Party = 風船のパーティー = fuusen no party
      12k words 11 mins.

      # 图的基础知识 # 图的定义 一 个 图 GGG 定 义 为 一 个 有 序 对 (V , E), 记 为 G = ( V , E ), 其 中: V 是一个非空集合,称为顶点集或边集,其元素称为项点或点 E 是由 V 中的点组成的无序点对构成的集合,称为边集,其元素称为边,且同一 点对在 E 中可出现多次。 图 GGG 的顶点集也记为 V (G),边集也记为 E (G)。 顶点集和边集都有限的图称为有限图。 只有一个项点而无边的图称为平凡图。其他所有的图都称为非平凡图。 做题往往需要先排除平凡图 边集为空的图称为空图。 图 GGG 的顶点数 (或阶数) 和边数可分别用符号 n(G)...
      3.7k words 3 mins.

      # 系统的描述 # 连续 / 离散 时间系统 # 连续时间系统 输入信号与输出响应都是连续时间信号的系统。 eg: 机械系统、电路系统 # 离散时间系统 输入信号与输出响应都是离散时间信号的系统。 eg: 人口问题 # 两种描述方法 # 输入输出描述法 (微分方程、差分⽅程) 着眼于系统输入与输出的关系,适⽤用于单输入 — 单输出系统。 # 状态变量描述法 (状态⽅程、输出方程) 即可描述输入与输出的关系,还可以描述系统的内部状态 既可⽤用于单输入 — 单输出系统,⼜可⽤于多输⼊ — 多输出系统。 #...
      5.3k words 5 mins.

      # 逻辑代数中的基本运算 # 三种基本运算 # 真值表 表征逻辑事件输入(条件)和输出(结果)之间全部可能状态的表格 与运算: A B Y 0 0 0 0 1 0 1 0 0 1 1 1 或运算: A B Y 0 0 0 0 1 1 1 0 1 1 1 1 非运算: A Y 0 1 1 0 # 其他复合逻辑运算 # 与非 “先与再非” # 或非 “先或再非” # 与或非 “先与再或再非” # 异或 XOR 不同时输出 1,相同时输出 0 A⊕B=A‾B+AB‾A\oplus...
      2.5k words 2 mins.

      # 编码的概念 广义的编码指的就是将信息从一种形式转换为另一种规范的形式; 对于数字电路,就是将现实世界中的各种物理信息转换为离散的电压序列,来表示、处理和分析信息; 事实上,进位计数制也是一种编码,用不同进制数来表示 “量”; 将数制与码制分开介绍,首先单独讲解数制是因为数制的一个重要的特点是其编码后能够参与算术运算;而一般来说码制是对非数值信息的表示; 教材中的缩写术语: MSB: Most Significant Bit,最高位 LSB: Least Significant Bit,最低位 # 二进制编码 无符号二进制编码只能表示 0...
      754 words 1 mins.

      # 数制 # 数制的概念 数制 (numerical system),又称 “计数制”,指用一组固定的符号和统一的规则来表示数值的方法; 数制关注的内容:每一位的构成(使用什么符号即数码)和进位的规则; 基本概念: 基数 —— 使用的数码的个数,即每一位最多能用多少个符号来表示;基数是 N 则称为 N 进制, 即 “逢 N 进一” 权 —— 每一位的 1 代表的大小; # 常用数制 # 不同进制的转换 # 其他进制 -&gt; 十进制 只需要按照 D=∑kiNiD=\sum k_i N^iD=∑ki​Ni 展开即可; kik_iki​ 为第 i 位的系数 NiN^iNi...
      1.9k words 2 mins.

      # 人工智能的概念 人工智能(Artificial Intelligence - AI):研究如何通过计算机技术实现一个智能体,让智能体完成类似于人类智能的行为。 # 智能体 Agent 完成智能行为的主体,是物理或抽象实体,可以感知世界并对世界施加作用。 大模型智能体 LLM Agent 在近几年随 ChatGPT 兴起的新概念 # 智能体的两大目标 能否使智能体像人一样思考、理性地思考? 能否使智能体像人一样行动、理性地行动? # 智能体可否像人一样思考 首先,需要测量人如何思考的方法:内省、心理实验、 脑成像。 #...
      27k words 25 mins.

      # 参考资料 Rust 语言圣经 (自称) 锈书 官网 # 环境配置 更新 Rust bashrustup update卸载 Rust bashrustup self uninstall查看版本 bashrustc --version## 显示格式rustc.x.y.z([commit hash] [commit date])安装 Rust 同时还会安装文档,查看本地文档 bashrustup doc# Rust 工具 # 编译器 # rustc 只适合单文件编译 shellrustc xxx.rs &lt;output># cargo Cargo 是 Rust...
      12k words 11 mins.

      # 操作系统的定义 实际上操作系统没有普遍接受的定义 操作系统 (Operating System,OS)是指控制和管理整个计算机系统的硬件和软件资源,并合理地组织调度计算机的工作和资源的分配;以提供给用户和其他软件方便的接口和环境;它是计算机系统中最基本的系统软件。 # 操作系统的功能和目标 # 作为系统资源的管理者 # 提供的功能 处理机管理 存储器管理 文件管理 设备管理 # 目标 安全、高效 # 向上层提供方便易用的服务 # GUI (Graphical User Interface) 图形化用户接口 # CLI (Command Line Interface)...
      9.6k words 9 mins.

      # 能量 / 功率 信号 # 能量信号 能量为一有界值,即 0 &lt; E &lt; + ∞,此时 P = 0 有时求 P 不好求,但是 E 好求,可以证明 E 为有界的,从而得到 P = 0 # 功率信号 功率为一有界值,即 0 &lt; P &lt; + ∞ ,此时 E = ∞ 有时求 E 不好求,但是 P 好求,可以证明 P 为有界的,从而得到 E = ∞ # 信号的分解 #...
      9.4k words 9 mins.

      # pthread 库 # 简介 pthread 是 POSIX 线程库,它是一种跨平台的线程库,可以在不同的操作系统上使用。它是 C 语言的标准库,提供了一组函数来创建、管理和同步线程。&quot;pthread&quot; 库相对于 &quot;thread&quot; 库来说,更加底层和与操作系统紧密相关。 thread 是 C11 标准提供的线程库,它是 C 的一部分。它提供了一种面向对象的方式来创建、管理和同步线程。&quot;thread&quot; 库提供了 std::thread...
      \ No newline at end of file diff --git a/page/9/index.html b/page/9/index.html index f836bbe5..a6ff8421 100644 --- a/page/9/index.html +++ b/page/9/index.html @@ -1 +1 @@ -Balloon Party = 風船のパーティー = fuusen no party
      197 words 1 mins.

      # DBMS 数据库管理系统 DBMS 的分类: 關聯式資料庫(SQL) 非關聯式資料庫 - (nosQL /not just SQL) • MySQL • MogoDB • Oracle • Redis • PostgreSQL • DynamoDB • SQL Server • Elaticsearch 關聯式資料庫管理系統 (RDBMS) 非關聯式資料庫管理系統 (NRDBMS) SQL - Structured Query Language - 结构性询问语言
      1.4k words 1 mins.

      # require require 是 Node.js 中用于加载模块的函数。它的主要作用是将外部模块引入到当前的 JavaScript 文件中,以便在代码中使用被引入的模块的功能、变量或对象。 require 函数的基本语法是: require(moduleName);其中, moduleName 是要引入的模块的名称或路径。 require 函数的工作原理如下: 首先,Node.js 会检查 moduleName 是否是一个核心模块(Node.js 内置的模块)。如果是核心模块,Node.js 会直接加载并返回该模块的导出内容。 如果 moduleName 不是核心模块,Node.js...
      7.4k words 7 mins.

      # JSON.stringify() JSON.stringify() 是 JavaScript 中的一个方法,用于将 JavaScript 对象或值转换为 JSON 字符串。 具体作用如下: 序列化: JSON.stringify() 方法将 JavaScript 对象或值序列化为一个 JSON 字符串。序列化是指将对象的结构和数据转换为字符串的过程,使其可以在网络传输或存储中进行传递和持久化。 JSON 格式:JSON(JavaScript Object Notation)是一种常用的数据交换格式,具有简洁、易读和跨语言的特性。 JSON.stringify() 将 JavaScript...
      2.5k words 2 mins.

      # CMake 简介 CMake 官网:https://cmake.org WIKI:https://en.wikipedia.org/wiki/CMake CMake 自身也是一种编程语言,可以用它实现基本的程序逻辑,此如循环、条件分支等等,其中最典型的应用是根据工程的配置来选择性编译部分源代码,比如有些功能只有在测试版本中才会开启。 和其它的构建工具一样,CMake 的本质依然是定义各个目标之间的关联,比如您的项目由哪些可执行文件、动态库、资源文件组成,然后它们又是通过哪些源文件编译,用到了哪些外部关联等等,本身并没有编译和链接的功能。 除了基本的构建功能之外,CMake...
      237 words 1 mins.

      树莓派配置静态 ip bashsudo nano /etc/dhcpcd.conf文件末尾添加: bashinterface eth0static ip_address=192.168.134.32/24static routers=192.168.134.1static domain_name_servers=192.168.134.1 8.8.8.8其中 192.168.134.32 可以直接是路由器给树莓派分配的 ip 地址,作为静态 ip 地址 ctrl+s 保存,ctrl+x 退出,重启树莓派即可
      234 words 1 mins.

      这里是我的博客,整理收纳了一些笔记、思维导图、资料 您可以叫我 fuuzen 或者「風船」,这是我随便起的一个用的比较久的网名,没有什么特别含义。fuusen 即「ふうせん」,但这个 ID 已经在 github 被注册了,所以只好叫做 fuuzen 了 这个博客网站的名字是 Balloon Party 或者「風船のパーティー」,也是我随便起的一个名字,没有什么特别含义 如果这里所整理收纳的资料对您的学习有帮助的话,欢迎您向您的朋友们推荐本博客!也欢迎您向我指出资料中的任何错误或提出宝贵的意见!
      388 words 1 mins.

      # frp # Tailscale # Ngrok # 绑定自己的域名(要充钱) Ngrok uses the Host header sent by the browser to determine how to redirect your traffic you will need to &quot;reserve&quot; the domain you want to use in the Ngrok dashboard. Note that doing this requires a paid Ngrok plan. After reserving your...
      667 words 1 mins.

      查看 niginx 进程: ps -ef|grep nginx进程: master worker 查看 nginx 的:版本、安装目录 (--prefix)、编译参数 nginx -V重新加载配置文件: shellnginx -s reload查看配置文件 nginx.config 所在目录,验证默认配置文件,常用于检查配置文件有没有写对: nginx -t常见目录有: /etc/nginx/conf/usr/local/etc/nginx/opt/homebrew/etc/nginx停止 nginx 服务: nginx -s quit //优雅停止nginx -s...
      379 words 1 mins.

      Hexo 是一个基于 Node 框架的博客框架 pnpm install hexo-cli -g //安装hexo init blog //初始化cd blog; npm install //安装依赖blog 目录下生成静态文件(到 public 目录下,用于发布) hexo g //缩略hexo generate //一样blog 目录下清除已生成的静态文件和 cache( 到 public 目录下) hexo cleanblog 目录下本地运行 hexo 服务 hexo s //缩略hexo server //一样在 blog 目录下将...
      458 words 1 mins.

      # YatCPU 实验报告 2023 年秋季学期的计算机组成原理实验项目 YatCPU 的实验报告 # YatCPU 相关资料 YatCPU 的教学文档和仓库 2023 年秋季学期由 Tokisakix 整理的文档和仓库,新纳入了 docker 环境搭建脚本、zybo-z710 开发板移植及烧板脚本 # 实验报告 YatCPU - - - lab1 - - - lab2 - - - lab3 - - - lab4 # 关于挑战实验 阅读了 egos-2000 操作系统的文档和仓库,按照其教程实现了操作系统映像文件的编译和写入 microSD 卡的过程 但是 egos-2000...
      \ No newline at end of file +Balloon Party = 風船のパーティー = fuusen no party
      197 words 1 mins.

      # DBMS 数据库管理系统 DBMS 的分类: 關聯式資料庫(SQL) 非關聯式資料庫 - (nosQL /not just SQL) • MySQL • MogoDB • Oracle • Redis • PostgreSQL • DynamoDB • SQL Server • Elaticsearch 關聯式資料庫管理系統 (RDBMS) 非關聯式資料庫管理系統 (NRDBMS) SQL - Structured Query Language - 结构性询问语言
      1.4k words 1 mins.

      # require require 是 Node.js 中用于加载模块的函数。它的主要作用是将外部模块引入到当前的 JavaScript 文件中,以便在代码中使用被引入的模块的功能、变量或对象。 require 函数的基本语法是: require(moduleName);其中, moduleName 是要引入的模块的名称或路径。 require 函数的工作原理如下: 首先,Node.js 会检查 moduleName 是否是一个核心模块(Node.js 内置的模块)。如果是核心模块,Node.js 会直接加载并返回该模块的导出内容。 如果 moduleName 不是核心模块,Node.js...
      7.4k words 7 mins.

      # JSON.stringify() JSON.stringify() 是 JavaScript 中的一个方法,用于将 JavaScript 对象或值转换为 JSON 字符串。 具体作用如下: 序列化: JSON.stringify() 方法将 JavaScript 对象或值序列化为一个 JSON 字符串。序列化是指将对象的结构和数据转换为字符串的过程,使其可以在网络传输或存储中进行传递和持久化。 JSON 格式:JSON(JavaScript Object Notation)是一种常用的数据交换格式,具有简洁、易读和跨语言的特性。 JSON.stringify() 将 JavaScript...
      2.5k words 2 mins.

      # CMake 简介 CMake 官网:https://cmake.org WIKI:https://en.wikipedia.org/wiki/CMake CMake 自身也是一种编程语言,可以用它实现基本的程序逻辑,此如循环、条件分支等等,其中最典型的应用是根据工程的配置来选择性编译部分源代码,比如有些功能只有在测试版本中才会开启。 和其它的构建工具一样,CMake 的本质依然是定义各个目标之间的关联,比如您的项目由哪些可执行文件、动态库、资源文件组成,然后它们又是通过哪些源文件编译,用到了哪些外部关联等等,本身并没有编译和链接的功能。 除了基本的构建功能之外,CMake...
      237 words 1 mins.

      树莓派配置静态 ip bashsudo nano /etc/dhcpcd.conf文件末尾添加: bashinterface eth0static ip_address=192.168.134.32/24static routers=192.168.134.1static domain_name_servers=192.168.134.1 8.8.8.8其中 192.168.134.32 可以直接是路由器给树莓派分配的 ip 地址,作为静态 ip 地址 ctrl+s 保存,ctrl+x 退出,重启树莓派即可
      234 words 1 mins.

      这里是我的博客,整理收纳了一些笔记、思维导图、资料 您可以叫我 fuuzen 或者「風船」,这是我随便起的一个用的比较久的网名,没有什么特别含义。fuusen 即「ふうせん」,但这个 ID 已经在 github 被注册了,所以只好叫做 fuuzen 了 这个博客网站的名字是 Balloon Party 或者「風船のパーティー」,也是我随便起的一个名字,没有什么特别含义 如果这里所整理收纳的资料对您的学习有帮助的话,欢迎您向您的朋友们推荐本博客!也欢迎您向我指出资料中的任何错误或提出宝贵的意见!
      388 words 1 mins.

      # frp # Tailscale # Ngrok # 绑定自己的域名(要充钱) Ngrok uses the Host header sent by the browser to determine how to redirect your traffic you will need to &quot;reserve&quot; the domain you want to use in the Ngrok dashboard. Note that doing this requires a paid Ngrok plan. After reserving your...
      379 words 1 mins.

      Hexo 是一个基于 Node 框架的博客框架 pnpm install hexo-cli -g //安装hexo init blog //初始化cd blog; npm install //安装依赖blog 目录下生成静态文件(到 public 目录下,用于发布) hexo g //缩略hexo generate //一样blog 目录下清除已生成的静态文件和 cache( 到 public 目录下) hexo cleanblog 目录下本地运行 hexo 服务 hexo s //缩略hexo server //一样在 blog 目录下将...
      667 words 1 mins.

      查看 niginx 进程: ps -ef|grep nginx进程: master worker 查看 nginx 的:版本、安装目录 (--prefix)、编译参数 nginx -V重新加载配置文件: shellnginx -s reload查看配置文件 nginx.config 所在目录,验证默认配置文件,常用于检查配置文件有没有写对: nginx -t常见目录有: /etc/nginx/conf/usr/local/etc/nginx/opt/homebrew/etc/nginx停止 nginx 服务: nginx -s quit //优雅停止nginx -s...
      458 words 1 mins.

      # YatCPU 实验报告 2023 年秋季学期的计算机组成原理实验项目 YatCPU 的实验报告 # YatCPU 相关资料 YatCPU 的教学文档和仓库 2023 年秋季学期由 Tokisakix 整理的文档和仓库,新纳入了 docker 环境搭建脚本、zybo-z710 开发板移植及烧板脚本 # 实验报告 YatCPU - - - lab1 - - - lab2 - - - lab3 - - - lab4 # 关于挑战实验 阅读了 egos-2000 操作系统的文档和仓库,按照其教程实现了操作系统映像文件的编译和写入 microSD 卡的过程 但是 egos-2000...
      \ No newline at end of file diff --git a/rss.xml b/rss.xml index 20f1840f..d379e10a 100644 --- a/rss.xml +++ b/rss.xml @@ -769,8 +769,8 @@ _1</annotation></semantics></math></span><span class= - + Sun, 09 Jun 2024 00:00:00 +0800 + + + https://fuuzen.github.io/ie/de/shift-register/ + 移位寄存器 + https://fuuzen.github.io/ie/de/shift-register/ + + + + Fri, 31 May 2024 00:00:00 +0800 + @@ -1434,47 +1475,6 @@ t_L=0.7R_2C_1 <li>74HC161 十六进制计数器</li> <li>74HC190 十进制计数器</li> </ul> -<script type="text&#x2F;javascript" src="https://unpkg.com/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://unpkg.com/hexo-simple-mindmap@0.8.0/dist/mindmap.min.css"> ]]> - - - https://fuuzen.github.io/ie/de/shift-register/ - 移位寄存器 - https://fuuzen.github.io/ie/de/shift-register/ - - - - Fri, 31 May 2024 00:00:00 +0800 - @@ -2383,8 +2383,8 @@ A\gamma(z)&amp;=By[-1]+Cy[-2]+D\chi(z)\\ - + Fri, 24 May 2024 00:00:00 +0800 - https://fuuzen.github.io/math/discrete-math/algebra/ring/ - - https://fuuzen.github.io/math/discrete-math/algebra/ring/ + https://fuuzen.github.io/math/discrete-math/graph/euler_hamilton/ + 欧拉图与哈密顿图 + https://fuuzen.github.io/math/discrete-math/graph/euler_hamilton/ - + - - + Fri, 17 May 2024 00:00:00 +0800 - diff --git a/si-zheng/ma-yuan/ke-hou-xi-ti/index.html b/si-zheng/ma-yuan/ke-hou-xi-ti/index.html index 637984e8..c9999a3c 100644 --- a/si-zheng/ma-yuan/ke-hou-xi-ti/index.html +++ b/si-zheng/ma-yuan/ke-hou-xi-ti/index.html @@ -1 +1 @@ -马原课后习题 - 马克思主义基本原理 - 思政 | Balloon Party = 風船のパーティー = fuusen no party

      # 思维导图

      # 绪论部分

      绪论部分

      # 第一章 世界的物质性及发展规律

      第一章 世界的物质性及发展规律

      # 第二章 实践与认识及其发展规律

      第二章 实践与认识及其发展规律

      # 第三章 人类社会及其发展规律

      第三章 人类社会及其发展规律

      # 第四章 资本主义的本质及规律

      第四章 资本主义的本质及规律

      # 第五章 资本主义的发展及其趋势

      第五章 资本主义的发展及其趋势

      # 第六章社会主义的发展及其规律(本章仅供学习参考,不作考试要求)

      第六章 社会主义的发展及其规律(本章仅供学习参考,不作考试要求)

      # 第七章 共产主义是人类最崇高的社会理想

      第七章 共产主义是人类最崇高的社会理想

      # 大纲

      # 绪论部分

      # 什么是马克思主义?

      • a) 从创造者、继承者的认识成果讲,马克思主义是由马克思、恩格斯创立的,由其后继者不断丰富和发展的观点和学说的科学理论体系。

      • b) 从阶级属性讲,马克思主义是关于无产阶级解放、全人类解放和每个人自由而全面发展的学说,是指引人民创造美好生活的行动指南,具有鲜明的阶级性。

      • c) 从研究对象和主要内容讲,马克思主义是无产阶级的科学世界观和方法论,是关于自然、社会和人类思维发展的一般规律的学说,是关于社会主义必然代替资本主义、最终实现共产主义的学说。

      • d) 马克思主义哲学、马克思主义政治经济学和科学社会主义的有机统一并共同构成了马克思主义理论的主体内容。

      # 马克思主义的直接的理论来源?

      • a) 资本主义生产方式造成社会化大生产迅猛发展的同时也带来了严重的社会灾难(社会两极分化;周期性经济危机频发)

      • b) 无产阶级在反抗资产阶级剥削和压迫的斗争中,逐步走向自觉,并迫切渴望科学的理论指导

      • c) 19C 西欧三大先进思潮为马克思主义的创立提供直接的理论来源(德国古典哲学、英国古典政治经济学和英法两国的空想社会主义)

      • d) 19C 三大科学发现也为马克思主义的产生提供了自然科学前提(细胞学说、能量守恒和转化定律)

      • e) 还有主观条件,结合马恩二人的生平谈就行

      # 马克思主义的鲜明特征?

      • a) 科学性

        • a.马克思主义是对自然、社会和人类思维发展本质和规律的正确反映。它是在社会实践和科学发展的基础上产生的,并在自身发展过程中不断总结实践经验,吸取自然科学和社会科学发展的最新成就。

        • b.马克思主义具有科学的世界观和方法论基础,即辩证唯物主义和历史唯物主义,这是马克思主义的一个突出特征和理论优势,也是马克思主义科学性的重要体现。

        • c.马克思主义理论是一个逻辑严密的有机整体,它以事实为依据、以规律为对象,并以实践为检验标准。马克思主义的发展具有科学探索性,是一个不断探索和掌握客观规律的过程。

      • b) 人民性

        • a.人民至上是马克思主义的政治立场。马克思主义政党把人民放在心中最高位置,一切奋斗都致力于实现最广大人民的根本利益,这是马克思主义最鲜明的政治立场。

        • b.人民群众是历史的创造者,是社会主义事业的依靠力量,马克思主义的人民性是以阶级性为深刻基础的,是无产阶级先进性的体现。

        • c.马克思主义是关于无产阶级解放的学说。无产阶级解放和全人类解放是完全一致的。

      • c) 实践性

        • a.马克思主义具有突出的实践精神,它始终强调理论与实践的统一,始终坚持与社会主义实际运动紧密结合。马克思主义是从实践中来,到实践中去,在实践中接受检验,并随实践的发展而不断发展的学说。

        • b.从马克思主义的使命和作用来说,它不是一种纯粹解释世界的学说,而是直接服务于无产阶级和人民群众改造世界的实践活动的科学理论。

        • c.从马克思主义的内容来看,实践观点是马克思主义首要的和基本的观点,这一基本观点体现在马克思主义全部思想内容之中。

      • d) 发展性

        • a.马克思主义是不断发展的学说,具有与时俱进的理论品质。马克思主义是时代的产物,并随着时代、实践和科学的发展而不断发展。

        • b.马克思主义理论体系是开放的,它不断吸取人类最新的文明成果来充实和发展自己。

        • c.马克思主义在指导人们认识世界和改造世界的过程中,在指导社会主义事业发展的过程中,不断与时代特征和各国具体实际相结合,得到丰富和发展,并形成新的理论成果。

      # 结合当代世界所面临的课题和当代青年所肩负的使命,谈谈马克思主义的当代价值和指导意义?

      • (1)当代世界所面临的新课题和当代青年所肩负的新使命

        • a) 在经济全球化的背景下,资本主义内部矛盾越来越突出,经济政治发展的不平衡加剧了资本主义世界的两极分化,贫富差距日益扩大。20 世纪 90 年代末的东南亚金融危机以及由华盛顿开始波及全球的 2008 年全球金融危机,都暴露了资本主义的缺陷。当代世界的新课题是和平与发展,各国都希望在一个相对稳定的环境中谋求国内经济发展,提高人们的生活水平。因此,马克思主义思想对现代社会仍有指导意义。

        • b) 不同的时代有不同的历史责任与使命,当代青年是在中国改革开放新时期成长起来的,处在一个继往开来的历史时期,肩负着祖国人民更多的期望,也应肩负起民族复兴的重任。当代青年所处的时代正是社会主义现代化建设的关键时刻,中华民族的伟大复兴对当代青年提出了新的挑战,我们有责任也有义务来维护祖国的统一,保卫祖国,建设祖国。而大学生作为当代青年的主体和中坚力量,更应该发挥引领带头作用。

        • c) 总而言之,马克思主义作为具有科学性、真理性的学说,对当代青年的人生发展有重要的指引作用,有助于青年们树立正确的世界观、人生观和价值观,提高其应对和处理问题的能力。

      • (2)马克思主义的当代价值

        • ① 当代世界变化的认识工具

          • a.马克思主义给予我们观察当代世界的宏大视野。

          • b.马克思主义给予我们透视时代风云的锐利目光。

          • c.马克思主义给予我们展望未来世界的长远眼光和战略定力指引。

        • ② 当代中国发展的行动指南

          • a.马克思主义是指引当代中国发展的精神旗帜。

          • b.马克思主义是推动当代中国发展的精神动力。

          • c.马克思主义是引领当代中国实践的行动指南。

        • ③ 引领人类社会进步的科学真理

          • a.从人类历史发展的大视野来看,世界仍然处于马克思主义所指明的从资本主义走向社会主义的大时代。马克思主义所揭示的资本主义基本矛盾仍然存在,而且在近年来西方的金融危机和社会危机中呈现出某种激化的趋势。

          • b.人类的未来仍然需要马克思主义的启迪和指引。社会是在矛盾中进步的,每一个时代的社会进步总是伴随着相应的社会问题,面对当今社会的重大问题,还是需要从马克思主义中寻找智慧。

      • (3)对当代青年的指导意义

        • 青年是祖国的未来、事业的希望。青年强则国家强,青年一代有理想、有本领、有担当,国家就有前途,民族就有希望。学习马克思主义理论可以帮助青年提高分析和解决问题的能力,有助于其树立正确的世界观、人生观和价值观。当代青年在学习马克思主义的过程中,要有正确的态度和科学的方法:

          • ① 努力学习和掌握马克思主义的基本立场、观点、方法。
          • ② 坚持理论联系实际的马克思主义学风。
          • ③ 自觉将马克思主义内化于心、外化于行。

      # 阅读感受:

      • 《资本论》内容宏大,理论深奥,创造了一个崭新的思想体系。其研究世界的方法源于德国古典哲学、英法两国的空想社会主义和英国古典政治经济学。马克思吸收了黑格尔的辩证法思想,相信能够用一个辩证法公式概括人类的进化历程。他认为,所有哲学家所做的一切都在致力于解释世界,但他同时认为,问题的关键在于如何改造世界。马克思在黑格尔辩证法的基础之上,颠覆了传统的 “形而上学”,建立了一个现实中得以实践的最大的思想体系。《资本论》以唯物史观的基本思想为指导,通过深刻分析资本主义生产方式,揭示了资本主义社会发展的规律,同时也使唯物史观得到了科学的验证和进一步的丰富和发展。它运用唯物史观的观点和方法,将社会关系归结为生产关系,将生产关系归结于生产力水平,从而证明了社会形态的发展是一个不以人的意志为转移的自然历史过程。

      # 第一章 世界的物质性及发展规律

      # 马克思主义的物质范畴的理论意义

      • (1)马克思主义的物质观
        马克思主义认为,世界是物质的世界,物质是第一性,物质是不依赖于人类的意识而存在,并能为人类的意识所反映的客观存在。“物质” 范畴是唯物主义哲学关于世界本原和统一性的最高抽象,是唯物主义世界观的基石。马克思主义批判继承了以往唯物主义的传统,在总结现代自然科学重大成就的基础上,创立了辩证唯物主义的物质观。20 世纪初,列宁对物质概念做出了科学的概括:“物质是标志客观实在的哲学范畴,这种客观实在是人通过感觉感知的,它不依赖于我们的感觉而存在,为我们的感觉所复写、摄影、反映。”

      • (2)马克思主义的物质观具有深刻的理论意义

        • ① 坚持唯物主义一元论,同唯心主义一元论和二元论划清了界限。马克思主义指明了物质对于意识的独立性、根源性,以及意识对于物质的依赖性、派生性。因为意识不过是物质的反映,不能离开物质而独立存在,所以意识不可能成为世界的另一种本原。

        • ② 坚持了能动的反映论和可知论,批判了不可知论。目前世界上还有很多事物未被人类认识,但这并不意味着它们不可认识。人们已经认识到未知世界与已知世界都是客观存在的。世界上只有尚未认识之物,没有不可认识之物。

        • ③ 体现了唯物论和辩证法的统一,克服了形而上学唯物主义的缺陷。马克思主义的物质观认为,物质的唯一特性是客观实在性,既肯定了哲学物质范畴同自然科学物质结构理论的联系,又将它们相区别。从个性中看到共性,从暂时中发现永恒,从相对中找到绝对,这是马克思主义物质观体现的唯物辩证法。

        • ④ 体现了唯物主义自然观与唯物主义历史观的统一,为彻底的唯物主义奠定了理论基础。马克思主义的物质观建立了统一说明自然历史过程的唯物主义原则,揭示了自然和社会的物质性,实现了唯物主义自然观和历史观的辩证统一。

      # 物质与意识的辩证关系

      物质决定意识,意识对物质具有反作用,这种反作用就是意识的能动作用。

      • (1)物质决定意识
        意识是人脑的机能和属性,是客观世界的主观映像。物质对意识的决定作用表现在意识的起源、本质和作用上。

        • ① 从意识的起源来看,其形成和发展经历了三个阶段,即:由一切物质所具有的反应特性到低等生物的刺激感应性,再到高等动物的感觉和心理,最终发展成人类的意识。意识不仅是自然界长期发展的产物,而且是社会历史发展的产物。劳动为意识的产生和发展提供了客观需要和可能;人们在劳动和交往中形成的语言促进了意识的发展。

        • ② 从意识的本质来看,意识是客观世界的主观映像。马克思指出:“观念的东西不外是移入人的头脑并在人的头脑中改造过的物质的东西而已。”

      • (2)意识对物质具有反作用
        物质决定意识,意识的能动作用是指意识对物质具有反作用。意识的能动作用主要表现在:

        • ① 意识活动具有目的性和计划性。马克思认为:“人在劳动过程结束时得到的结果,在这个过程开始时就已经在劳动者的表象中存在着,即已经观念地存在着”。人的整个实践过程,就是围绕意识活动所构建的目标和蓝图来进行的。

        • ② 意识活动具有创造性。人的意识可以对客观世界中的感性材料加工和建构,在思维中构造一个现实中没有的理想世界。

        • ③ 意识具有指导实践改造客观世界的作用。在实践中形成观念,以这些观念为指导,通过实践使之变成客观现实。④ 意识具有调控人的行为和生理活动的作用。现代科学证明,意识、心理因素对人的行为选择和健康状况能够产生重要影响。

      • (3)主观能动性和客观规律性的统一
        正确认识和把握物质与意识的辩证关系,需要处理好主观能动性与客观规律性的关系,原因在于:

        • ① 尊重客观规律是正确发挥主观能动性的前提。人们正确地认识世界,有效地改造世界的前提是认识和掌握客观规律。

        • ② 只有充分发挥主观能动性,才能正确认识和利用客观规律。承认规律的客观性,并不是说人在规律面前无能为力、无所作为。人类能够按照客观规律改造世界,以达到自己的目的。

      # 运用矛盾的普遍性和特殊性辩证关系原理,说明把马克思主义基本真理与中国具体实际相结合的重要性。答:

      • (1)矛盾普遍性与特殊性的辩证关系

        • ① 矛盾的普遍性即矛盾的共性,矛盾的特殊性即矛盾的个性。矛盾的共性是无条件的、绝对的;矛盾的个性是有条件的、相对的。

        • ② 任何现实存在的事物的矛盾都是共性和个性的有机统一,共性寓于个性之中,没有离开个性的共性,也没有离开共性的个性。矛盾的共性和个性相统一的关系,既是客观事物固有的辩证法,也是科学的认识方法。

      • (2)把马克思主义基本真理与中国具体实际相结合的重要性
        矛盾的普遍性和特殊性辩证关系的原理,是把马克思主义普遍真理同各国具体实际相结合的理论基础,也是建设中国特色社会主义的理论根据。

        • ① 矛盾的普遍性和特殊性辩证统一的原理,是把马克思主义普遍真理与中国的具体实际相结合,走建设有中国特色社会主义道路的重要理论依据。矛盾的普遍性和特殊性的关系就是共性与个性、绝对与相对的关系。我国走中国特色社会主义道路,是中国共产党把马克思主义普遍真理同中国的具体实际相结合的过程中实现的第二次飞跃。在这里,“中国特色” 是中国不同于其他社会主义国家的个性、特殊性。“社会主义” 则是中国和其他社会主义国家的共性、普遍性。

        • ② 根据共性与个性相统一的原理,我们坚持中国特色社会主义道路。

          • a.不管中国的情况如何特殊,都必须坚持马克思主义的普遍真理,坚持社会主义根本制度和基本原则,这是共性。

          • b.社会主义的一般只能在各国特色的个别中存在,我们又必须建设中国特色的社会主义,从中国的国情出发,注意把握中国的特点。只有坚持党的基本路线不动摇,走自己的路,我们才能在建设中国特色社会主义的道路上不断取得胜利,这是个性。

      # 不断增强思维能力:辩证思维能力、历史思维能力、战略思维能力、底线思维能力、创新思维能力。

      答:创新思维能力是对常规思维的突破,是破除迷信、超越陈规,善于因时制宜、知难而进、开拓创新的能力。

      • (1)培养和提高创新思维能力的重要性

        • ① 坚持创新思维,才能推动发展、取得进步。“发展的观点” 是唯物辩证法的基本观点,马克思主义关于人类社会不断进步的发展观,不仅揭示了人类社会历史是不断向前发展的,而且说明了正是人类的创新思维和创造智慧推动了社会更好地发展。

        • ② 创新是一个民族进步的灵魂,是一个国家兴旺发达的不竭动力,也是中华民族最深沉的民族禀赋。这些年中华民族进步和贡献的取得,正是中华民族勇于创新和善于创新的结果。失去了创新思维,就会失去前进的动力,导致封闭和落后。

        改革开放以来,中国共产党高度重视思想解放和理论创新,开辟了中国特色社会主义道路,形成了中国特色社会主义理论体系,确立了中国特色社会主义制度,发展了中国特色社会主义文化,实现了中国人民从站起来到富起来、强起来的伟大飞跃。从某种意义上说,这些成就正是我们党坚持创新思维、大力推进理论创新和实践创新的结果。

      • (2)提高自己的创新思维能力的做法

        • ① 提高创新思维能力,必须坚决反对各种形而上学的思维方式,做到不唯书、不唯上,只唯实。提高创新思维能力,需要坚持和运用唯物辩证法,坚决反对形而上学。

          • a.要破除对 “本本” 的迷信;

          • b.要破除对 “经验” 的迷信;

          • c.要破除对 “权威” 的迷信。

        • ② 问题意识是提高创新思维能力的起点和动力源。

        增强问题意识、坚持问题导向,就是承认矛盾的普遍性客观性,就是善于把认识和化解矛盾作为打开工作局面的突破口,善于具体问题具体分析,透过现象看本质,抓主要矛盾和矛盾的主要方面,科学分析问题,深入研究问题。

        • ③ 善于继承才能善于创新。

          • a.创新思维不是凭空产生的,善于继承,才能将过去、现在和未来联系起来;

          • b.善于创新,才会有现在超越过去、未来超越现在的前进运动。

          • c.中国特色社会主义是科学社会主义理论逻辑和中国社会发展历史逻辑的辩证统一,是中国共产党人运用创新思维,在继承和发展中形成的创新成果。

        • ④ 在解放思想中锻造创新思维。

          • a.提高创新思维能力,就是要有敢为人先的锐气,打破惯性思维,以思想认识的新飞跃打开工作的新局面;

          • b.提高创新思维的过程,就是思想解放的过程。没有思想的大解放,就不可能有创新思维的大突破。

      # 第二章 实践与认识及其发展规律

      # 实践与认识的辩证关系及其规律

      • (1)毛泽东《实践论》的主要观点:
        毛泽东强调:“一个正确的认识,往往需要经过由物质到精神,由精神到物质,即由实践到认识,由认识到实践这样多次的反复,才能够完成。” 如此 “实践、认识、再实践、再认识,循环往复以至无穷,而实践和认识之每一循环的内容,都比较地进到了高一级的程度”。这就是认识辩证运动发展的基本过程,也是认识运动的总规律。认识是一个反复循环和无限发展的过程,是一个波浪式前进和螺旋式上升的过程。认识在实践基础上不断深化发展,并推动实践在认识指导下不断深入推进。这个过程既不是封闭式的循环,也不是直线式的发展,而是波浪式前进和螺旋式上升的。

      • (2)实践与认识的辩证关系

        • ① 实践是认识的基础,实践在认识活动中起决定性作用。主要表现在以下四个方面:

          • a.实践是认识的来源。认识的内容是在实践活动的基础上产生和发展的。只有在实践中实际改造和变革对象,人们才能形成对认识对象属性、本质、规律更为准确的认识,并以这种认识指导实践活动。

          • b.实践是认识发展的动力。认识的产生和发展源于实践的需要,也正是这种需要推动人类的科学发现和技术发明,推动人类的思想进步和理论创新。实践的需要是推动认识在深度和广度上不断发展之根本。此外,实践是认识发展的动力,还表现为实践为认识的发展提供了如经验资料、实验仪器和工具等的手段和条件。另外,实践改造了人的主观世界,锻炼和提高了人的认识能力。人们正是在实践的推动下,不断突破旧认识、旧思想,引起认识上的新飞跃,从而不断有新发现、有所前进。

          • c.实践是认识的目的。通过实践获得认识,其最终目的是为实践服务,指导实践,以满足生活和生产的需要。

          • d.实践是检验认识真理性的唯一标准。真理不是自封的。判断认识的真理性,不是依主观感觉,而是依客观上社会实践的结果。

        • ② 认识反作用于实践。

          • a.人的实践活动是受人的意识支配的,实践的这种本质特性决定着它不能离开认识的指导。

          • b.认识活动及其成果有相对独立性,遵循其特有的活动方式和发展规律,它一经形成,便能反作用于实践。

          • c.认识对实践的指导作用表现在:正确的认识能够推动实践的发展,而错误的认识则会对实践起阻碍作用。

      # 真理、真理的绝对性和相对性及其辩证关系、真理与谬误(自学);

      • (1)真理是绝对的又是相对的原因
        真理是一个过程。就真理的发展过程以及人们对它的认识和掌握程度来说,真理既具有绝对性,又具有相对性,它们是同一客观真理的两
        种属性,这是真理问题上的辩证法。任何真理都是绝对性和相对性的统一,二者相互联系、不可分割。两者关系具体如下:

        • ①真理的绝对性

          真理的绝对性是指真理主客观统一的确定性和发展的无限性。它有两个方面的含义:

          • a.任何真理都标志着主观与客观之间的符合,都包含着不依赖于人和人的意识的客观内容,都同谬误有原则的界限。这一点是绝对的、无条件的。在这个意义上,承认了真理的客观性也就是承认了真理的绝对性。

          • b.人类认识按其本性来说,能够正确认识无限发展着的物质世界,认识每前进一步,都是对无限发展着的物质世界的接近,这一点也是绝对的、无条件的。在这个意义上,承认了世界的可知性,承认人能够获得关于无限发展着的物质世界的正确认识,也就是承认了真理的绝对性。

        • ②真理的相对性

          真理的相对性是指人们在一定条件下对客观事物及其本质和发展规律的正确认识总是有限度的、不完善的。它具有两个方面的含义:

          • a.从客观世界的整体来看,任何真理都只是对客观世界的某一阶段、某一部分的正确认识,人类已经达到的认识的广度总是有限度的,因而,认识有待扩展。

          • b.就特定事物而言,任何真理都只是对客观对象一定方面、一定层次和一定程度的正确认识,认识反映事物的深度是有限度的,或是近似性的。因而,认识有待深化。任何真理都只能是主观对客观事物近似正确即相对正确的反映。

        • ③真理的绝对性和相对性的关系

          真理的绝对性和相对性是辩证统一的,具体如下:

          • a.二者相互依存。即人们对于客观事物及其本质和规律的每一个正确认识,都是在一定范围内、一定程度上、一定条件下的认识,因而是相对的和有局限的;但是,在这一定范围内、一定程度上、一定条件下,它也是对客观对象的正确反映,因而它也是无条件的、绝对的。

          • b.二者相互包含。一是真理的绝对性寓于真理的相对性之中。任何真理所包含的客观内容都只能是人们在特定历史条件下所把握到的,都只是对客观世界及其事物的一定范围、一定程度的正确反映。二是真理的相对性包含并表现着真理的绝对性。任何真理都与谬误有本质的区别,标志着人们在一定范围内和一定层次上达到对于无限发展着的物质世界的正确认识,包含着确定的客观内容。毛泽东把真理的绝对性与相对性的关系比喻为长河与水滴的关系,“马克思主义者承认,在绝对的总的宇宙发展过程中,各个具体过程的发展都是相对的,因而在绝对真理的长河中,人们对于在各个一定发展阶段上的具体过程的认识只具有相对的真理性。无数相对的真理之总和,就是绝对的真理”。

          • c.相对性向绝对性转化。真理永远处在由相对向绝对的转化和发展中,是从真理的相对性走向绝对性、接近绝对性的过程。任何真理性的认识都是由真理的相对性向绝对性转化过程中的一个环节,这是真理发展的规律。真理的绝对性与相对性根源于人认识世界的能力的无限性与有限性、绝对性与相对性的矛盾。人类的思维按其本性、可能和历史的终极目的来说,是能够认识无限发展着的物质世界的,思维是无限的和绝对的。但是,具体到每一个人乃至每一代人,由于受到客观事物及其本质的显露程度、社会历史的实践水平、主观的条件以及生命的有限性等各方面的限制,其思维也是有限的和相对的。人的认识能力、思维能力是无限性与有限性、绝对性与相对性的对立统一,作为人的正确认识成果的真理,也必然是绝对性和相对性的对立统一。

      • (2)真理的绝对性和相对性相统一对马克思主义的重要意义

        • ① 割裂真理绝对性与相对性之间的辩证关系,就会走向形而上学的真理观,即绝对主义和相对主义。绝对主义在实际工作中表现为教条主义、思想僵化,把马克思主义当作一成不变的公式。相对主义否认真理内容的客观性,把真理的相对性歪曲成了主观随意性,由此陷入主观真理论,导致不可知论和诡辩论。

        • ② 马克思主义是客观真理,是绝对性和相对性的统一

          马克思主义正确地反映了人类社会发展的规律,是经过长期革命、建设和改革的实践所证明了的真理,因而具有绝对性的一面。但是,马克思主义并没有穷尽对一切事物及其规律的认识,仍然需要随着社会实践的发展而发展,因而又具有相对性的一面。正因为马克思主义具有绝对性,所以我们必须坚持以马克思主义为指导思想;也因为它具有相对性,所以我们必须在实践中丰富和发展马克思主义。既坚持又发展,才是对待马克思主义的正确态度。

      # 真理和价值的辩证关系。

      • (1)真理尺度和价值尺度的含义

        • ① 人们的实践活动总是受着真理尺度和价值尺度的制约。

        • ② 实践的真理尺度是指在实践中人们必须遵循正确反映客观事物本质和规律的真理。只有按照真理办事,才能在实践中取得成功。

        • ③ 实践的价值尺度是指在实践中人们都是按照自己的尺度和需要去认识世界和改造世界。这一尺度体现了人的活动的目的性。

      • (2)真理尺度与价值尺度的关系

        • ① 任何实践活动都要受到这两种尺度的共同制约,任何活动都是合规律性和合目的性的统一。

        • ② 真理与价值或真理尺度与价值尺度之间是紧密联系、不可分割的。一方面,价值尺度必须以真理为前提。脱离了真理尺度,价值尺度就偏离了正确的轨道。另一方面,人类满足自身需要的内在尺度,推动新的真理不断被发现。脱离了价值尺度,真理就缺失了主体意义。

      • (3)帮助和启示
        因为实践具有具体性和历史性,真理尺度与价值尺度的统一也是具体的和历史的,二者的统一会随着实践的发展而不断发展到更高级的程度,真理由相对走向绝对,人的需要和利益也日益呈现出多元化特征。真理尺度与价值尺度是否达到了具体的、历史的统一,必须通过实践来验证。新时代中国特色社会主义的实践充分体现了真理尺度与价值尺度的辩证统一。正如习近平所指出的:“中国共产党人的理想信念,建立在马克思主义科学真理的基础之上,建立在马克思主义揭示的人类社会发展规律的基础之上,建立在为最广大人民谋利益的崇高价值的基础之上。我们坚定,是因为我们追求的是真理。我们坚定,是因为我们遵循的是规律。我们坚定,是因为我们代表的是最广大人民的根本利益。”

      # 第三章 人类社会及其发展规律

      # 为什么说物质资料的生产方式是社会发展的决定性力量?

      答:物质资料的生产方式是社会发展的决定性力量,主要是基于以下原因:

      • (1)物质资料的生产方式是人类其他一切活动的首要前提,是人类社会赖以存在和发展的物质基础。人们为了能够创造历史,必须能够生活,为了生活,首先就需要衣、食、住及其他东西。因此,人类历史的第一个历史活动就是生产满足这些需要的物质资料本身。这是一个简单的事实和起码的真理。发现并承认这一真理,是历史观的一个伟大革命。

      • (2)物质资料的生产方式决定着社会的结构、性质和面貌。有什么样的生产方式便有什么样的社会形态。正如马克思所说:“手推磨产生的是封建主为首的社会,蒸汽磨产生的是工业资本家为首的社会。”

      • (3)生产方式的发展变化决定着社会历史的发展变化和形态更替。在物质资料的生产方式中,生产力是最活跃、最能动的因素,它总是要向前发展的,而生产关系则是相对稳定的。随着生产力的发展,原有的生产关系便由生产力发展的形式变成生产力发展的桎梏,由适合生产力的发展变成阻碍生产力的发展。只有变革生产关系,才能解放和发展生产力。随着生产关系(即经济基础)的变革,全部的、庞大的上层建筑也会或迟或早地发展变革,从而引起社会形态的更替。

      • 总之,人类社会的历史就是物质资料生产的历史,是劳动发展史。马克思正是从劳动发展史中找到了理解人类社会发展史的 “钥匙”。

      # 运用社会基本矛盾运动的原理分析深化改革的客观依据与重要意义。答:

      • 与深化改革最相近的是生产力与生产关系的矛盾运动。

        • 社会基本矛盾运动包括

          • 生产力与生产关系之间的矛盾

          • 经济基础与上层建筑之间的矛盾

        • 它们是贯穿社会发展过程始终,规定社会发展过程的基本性质和基本趋势,并对社会历史发展起根本推动作用的矛盾。

        • 因此,社会基本矛盾的解决对历史发展具有重要作用。

        • 而要解决社会基本矛盾,改革是一种重要的方式和途径。

      • (1)客观依据
        社会基本矛盾,特别是生产力与生产关系的矛盾在历史发展中起根本的推动作用,为了推动社会发展,必须解决好社会基本矛盾,改革就是其中一种重要方式。深化改革的客观依据就在于社会基本矛盾在历史发展过程中的重要作用,主要表现在:

        • ① 生产力是社会基本矛盾运动中最基本的动力因素,是人类社会发展和进步的最终决定力量。

        • ② 社会基本矛盾特别是生产力和生产关系的矛盾,是 “一切历史冲突的根源”,决定着社会中其他矛盾的存在和发展。

        • ③ 社会基本矛盾有不同的表现形式和解决方式,并从根本上影响和促进社会形态的变化和发展。

        • 因此,当两者不能够及时适应时,就需要改革来调整两者的关系,因而改革也是必不可少的。

      • (2)重要意义
        改革的成功,是对社会基本矛盾的某一方面或某种程度的解决,从而促进社会发展。社会生活的基础是物质生产,推动社会进步的最活跃、最革命的要素是生产力,社会主义的根本任务是解放和发展社会生产力。全面深化改革中,要把坚持发展作为解决我国所有问题的关键,推动我国社会生产力不断发展前进,进而推动人的全面发展和社会的全面进步。同时,还应通过改革,使生产关系适应生产力的发展、上层建筑适应经济基础的发展,从而顺利解决社会基本矛盾,促进社会的进一步发展。

      # 结合我国科学技术的重大成就,如高铁、大飞机以及 “天宫”“蛟龙”“天眼”“悟空”“墨子” 等,谈谈对科学技术在社会发展中的作用的认识。答:

      • (1)科学技术是先进生产力的重要标志,对于推动社会发展有非常重要的作用。科技革命是推动经济和社会发展的强大杠杆,近代以来,科技革命极大地推动了社会历史的进步,其主要是通过促进人们的生产方式、生活方式和思维方式的深刻变化来推动社会发展:

        • ① 对生产方式产生了深刻影响:

          • a.改变了社会生产力的构成要素。科技发展使生产自动化程度提高,大大地改变了体力劳动与脑力劳动的比例,使劳动力结构向着智能化趋势发展。

          • b.改变了人们的劳动形式。科技发展使人们的劳动方式经历了由机械自动化走向智能自动化、由局部自动化走向大系统管理和控制自动化的根本性变革。

          • c.改变了社会经济结构,特别是导致产业结构发生变革。科技的发展使第三产业在国民经济中所占的比重日益提高。

        • ② 对生活方式产生了巨大影响:

          • a.现代科技革命把人们带入了信息时代,要求人们不断更新和充实知识,以适应时代发展的需要。

          • b.现代信息技术为人们提供了处理、存储和传递信息的手段,给学习、工作带来了极大便利。

          • c.现代化的交通、通信等手段,为人们的交往提供了方便。

          • d.劳动生产率的提高,使人们自由支配的闲暇时间增多,为人的自由而全面的发展创造了更多条件。

        • ③促进了思维方式的变革。主要表现在新的科学理论和技术手段通过影响思维主体、思维客体和思维工具,引起了思维方式的变革正确把握科学技术的社会作用科学技术社会作用的两重性:

          • a.科学技术能够通过促进经济和社会发展造福于人类,科学技术的作用既受到一定客观条件的影响,也受到一定主观条件的影响。

          • b.科学技术的发展标志着人类改造自然能力的增强,意味着人们能够创造出更多的物质财富,对社会发展有巨大的推动作用。

      • (2)科学技术是社会发展的重要动力。近代中国落后于西方国家主要原因是科学技术水平低。习近平总书记提出 “科技兴则民族兴,科技强则国家强”。

      • (3)新时期我国的科学技术发展取得重大成就:2016 年 6 月 20 日,使用中国自主芯片制造的超级计算机 “神威 - 太湖之光” 登上全球超级计算机 500 强榜首。2016 年 8 月 16 日,长征二号运载火箭成功将世界首颗量子科学实验卫星 “墨子号” 发射升空。2016 年 8 月 25 日,我国研发的自主遥控水下机器人 “海斗” 号潜深达到 10767 米,首次进入万米时代。2016 年 9 月 15 日,“天宫二号” 顺利升空。2016 年 9 月 25 日,被誉为 “中国天眼” 的 FAST 射电望远镜落成启用。
        这些科学技术的发展不仅提高了我国的综合国力和国际地位,而且对我们的生产生活产生巨大影响。比如我国研制的全球超级计算机将对我们所进行的科学实验起到促进作用;“墨子号” 的发射升空将促进我国科研事业的发展,从而改善普通群众的生活。

      # 请结合人民群众是历史创造者的原理,谈谈对坚持以人民为中心重要性的认识。答:

      • (1)人民群众的含义
        人民群众是社会历史的主体,是历史的创造者,这是马克思主义最基本的观点之一。人民群众是一个历史范畴。从质上看,人民群众是指一切对社会历史发展起推动作用的人;从量上看,人民群众是指社会人口中的绝大多数。在不同的历史时期,人民群众有着不同的内容,包含着不同的阶级、阶层和集团,但其中最稳定的主体部分始终是从事物质资料生产的劳动群众。

      • (2)对坚持以人民为中心重要性的认识
        在实际生活中,我们必须坚持以人民为中心的思想,这是因为人民群众在创造历史过程中的决定作用。

        • ①人民群众是社会物质财富的创造者。人类社会赖以存在和发展的基础是物质资料的生产方式。人民群众创造的社会物质财富,是社会得以存在和发展的物质保障。人民群众的这一创造作用同生产力是社会发展的最终决定力量这一原理具有逻辑上的一致性,因为作为人民群众主体的劳动群众,乃是生产力的体现者。

        • ②人民群众是社会精神财富的创造者。首先,人民群众的社会实践活动是科学、文化、艺术的唯一源泉;其次,劳动群众为人们从事精神文化活动提供了一切物质手段和物质条件;再次,劳动知识分子在精神财富的创造过程中起着极其重要的作用。

        • ③人民群众是社会变革的决定力量。人民群众在创造社会财富的同时,也创造并改造着社会关系。人民群众既是社会革命的决定力量,又是社会改革的决定力量。社会变革、社会改革根源于社会基本矛盾,但生产关系一定要适合生产力发展状况的规律、上层建筑一定要适合经济基础发展状况的规律不可能自发地起作用,必须通过人民群众这一社会变革的主体才能实现其作用。

      # 习近平指出:“我们既要绿水青山,也要金山银山。宁要绿水青山,不要金山银山,而且绿水青山就是金山银山。” 请结合自然地理环境在社会生存和发展中的作用,谈谈应怎样认识和处理经济发展与环境保护的关系。答:

      • 自然地理环境是人类赖以存在和发展的必要前提,是社会存在的组成部分。没有自然界,没有感性的外部世界,工人什么也不能创造。没有地理环境,就不会有人和人类社会。可以看出,自然环境对人类的生存发展具有重要意义,因此,我们在发展经济的同时,不能忽略自然环境,不能以牺牲环境为代价来取得
        经济发展。我们必须坚持可持续的绿色发展理念,在发展经济的同时保护环境,“既要金山银山,也要绿水青山”。为此,我们必须做到以下四点:

      • (1)强化环境意识,树立生态理念要树立 “绿水青山就是金山银山” 的环境价值理念,实现以环境换取经济增长向以环境优化经济增长转变。绿水青山意味着优美的人居环境、清洁的水源和清新的空气,可以大大减少因环境污染和生态破坏造成的直接和间接损失,大大减轻因污染治理和生态恢复所需付出的巨大代价,大大缓解生态环境问题引发的各种社会矛盾,有利于维护社会稳定。

      • (2)把环境保护作为决策的重要环节,从源头落实环保基本国策
        环保从源头抓起,最重要的是各级政府、各级管理部门、各级领导要依法承担起改善环境质量和环境管理的责任,牢牢树立科学发展观念,转变把环境因素置于决策之外的决策模式,实行环境与发展综合决策。同时,必须树立正确的政绩观。

      • (3)把环境保护作为生产和消费过程中的重要环节,大力发展循环经济解决经济高速增长与生态环境日益恶化这一矛盾的根本出路是转变经济增长方式,用绿色核算体系来重新审视和把握经济发展的途径,走新型工业化道路,积极推动发展循环经济,实现经济与环境 “双赢”。

      • (4)把环境保护作为改善人居环境的重要环节,集中精力解决突出的环境问题
        改善人居环境不仅仅是改善市民的住房条件,要充分发挥环境保护的文明发展与协调稳定功能,以人为本,下决心解决老百姓广泛关注的影响环境质量和日常环境生活质量的突出问题。强化饮用水源的环保严管措施,保证饮用水安全。采取有效措施保护水源地,确保生态环境改善。大力改善区域环境,创建绿色环保文明社区,提高人民生活质量。

      • (5)正确认识和利用科学技术
        科学技术是把双刃剑,既能通过促进经济和社会发展造福于人类,也能在一定条件下对人类的生存和发展带来消极后果。

      # 第四章 资本主义的本质及规律

      # 为什么说 “资本来到世间,从头到脚,每个毛孔都滴着血和肮脏的东西”?答:

      • (1)资本主义的产生与发展
        资本主义于 14 世纪末 15 世纪初开始在地中海沿岸的一些城市出现,一是从小商品经济分化出来,二是从商人和高利贷者转化而来。资本主义生产关系产生之后,其成长是一个缓慢的过程。新兴资产阶级和资产阶级化的贵族用暴力剥夺小生产者从而加速形成资本主义生产方式。

      • (2)资本的原始积累
        资本原始积累,是生产者与生产资料相分离,货币资本迅速集中于少数人手中的历史过程。它主要是通过两个途径进行的:

        • ① 用暴力手段剥夺农民的土地,是资本原始积累过程的基础。资本家和封建贵族还通过 “掠夺教会地产,欺骗性地出让国有土地,盗窃公有地,用剥夺方法、用残暴的恐怖手段把封建财产和克兰财产转化为现代私有财产”,建立了资本主义的土地私有制,从而奠定了资本主义私有财产制度的基础。

        • ② 利用国家政权的力量进行残酷的殖民掠夺。新兴资产阶级在国外进行疯狂掠夺的同时,还通过国债制度、课税制度和保护关税制度等,加强对国内人民的剥削,在少数人手中积累起了大量的资本。这些极大地促进了资本主义的发展,缩短了封建生产方式转变为资本主义生产方式的历史过程。

      资本原始积累的事实表明,资产阶级的发家史就是一部罪恶的掠夺史。正如马克思所说:“资本来到世间,从头到脚,每个毛孔都滴着血和肮脏的东西。”

      # 如何理解商品二因素的矛盾来自劳动二重性的矛盾,归根结底来源于私人劳动和社会劳动之间的矛盾?答:

      • (1)商品经济存在着一系列的矛盾,其中私人劳动和社会劳动的矛盾是商品经济的基本矛盾,它决定着劳动二重性的矛盾和商品二因素的矛盾。
        商品经济存在的一系列的矛盾包括:

        • 商品的使用价值和价值的矛盾(即商品二因素的矛盾)

        • 具体劳动和抽象劳动的矛盾(即劳动二重性的矛盾)

        • 私人劳动和社会劳动的矛盾

      • (2)在私有制商品经济条件下,商品二因素的矛盾来源于生产商品的劳动二重性的矛盾。在商品交换过程中,生产商品使用价值的具体劳动不能直接进行量的比较,只有将具体劳动还原为抽象劳动,即从具体劳动中抽象出无差别的人类劳动,才可以进行量的比较。

      • (3)具体劳动能否还原为抽象劳动,取决于私人劳动和社会劳动能否实现一。一切商品,只有换成货币,商品生产者的私人劳动才会转化为社会劳动,具体劳动才会还原为抽象劳动,商品的使用价值和价值的矛盾才能得到解决。商品生产者的私人劳动生产的产品如果与社会的需求不相适应,该私人劳动就不被承认为社会劳动,其作为具体劳动的有用性质也就不被社会所承认,从而不能还原为抽象劳动,这意味着商品的价值不能实现,商品的使用价值和价值之间的矛盾没有解决。反过来,如果私人劳动生产的产品为社会所接受,则该私人劳动就被承认并转化为社会劳动,其作为具体劳动的有用性质就被社会所承认,从而可以还原为抽象劳动,这意味着商品的价值得到了实现,商品的使用价值和价值之间的矛盾得到了解决。

      # 如何理解 “资本是带来剩余价值的价值”?

      答:资本是带来剩余价值的价值,可以作以下理解:

      • (1)劳动力商品在使用价值上有一个很大的特点,其使用价值是价值的源泉,消费过程中能够创造新的价值,并且这个新的价值超过了劳动力本身的价值。由于该特点,货币所有者购买到劳动力以后,在消费过程中,不仅能够收回他在购买这种商品时支付的价值,还能得到增值的价值即剩余价值。

      • (2)资本是自行增殖的价值,是能够带来剩余价值的价值。在现实生活中,资本总是表现为一定的物,例如货币、机器设备、商品等,但这些物本身并不是资本,只有在一定的社会关系下,这些物被用来从事以获得剩余价值为目的的生产活动,也就是成为带来剩余价值的手段时,它才成为资本。所以马克思强调指出,资本的本质不是物,而是在物的外壳掩盖下的一种社会生产关系,即资本主义剥削关系。

      • (3)资本主义条件下,资本家剥削剩余价值具有隐蔽性。资本在运动过程中使用了例如货币、生产资料、商品等物质形态,资本家购买劳动力依照等价交换原则进行,于是在人们的观念上容易形成一种错觉,好像这些物天然就是资本,资本变成一种神秘的东西,似乎劳动的一切社会生产力并非劳动本身所有,而为资本所有,资本本身具有一种能使价值增殖的魔力,这就是资本拜物教。马克思指出:“资本家用货币购买的是雇佣工人的劳动力商品,劳动力商品的使用价值是劳动,劳动本身并不是商品,劳动力商品的使用价值具有成为价值源泉的特殊属性,它的实际使用本身就是劳动的物化,从而创造了剩余价值,使货币转化为资本。” 马克思的分析揭露了资本拜物教产生的实质,为科学认识资本主义经济制度的本质提供了理论武器。

      # 运用历史和现实的事实说明经济危机是资本主义基本矛盾的集中体现。答:

      • 资本主义发展到一定阶段,就会出现生产的相对过剩,这是经济危机的基本特征。经济危机发生时,大量商品积压,企业减产甚至停工,伴随着许多金融机构倒闭,整个社会经济生活一片混乱。对该论述理解如下:

      • (1)在资本主义经济的发展过程中,经济危机是周期性地重演的,危机与危机之间的间隔表现了一定的规律性。第二次世界大战后,各主要资本主义国家发生了次数不等的经济危机。在战后各国的历次危机中,有的是属于部分国家同期发生的,有的是普遍性的资本主义世界经济危机。属于世界性经济危机的有三次,即 1957—1958 年、1973—1975 年和 1980—1982 年的经济危机,因为这三次危机表现了明显的国际同期性。
        第二次世界大战结束以来,随着国家垄断资本主义的形成和发展,虽然市场机制依然在资源配置过程中发挥着基础性调节作用,但它已不是唯一的经济调节机制了。调节机制发生了一些明显的变化,其主要表现是资产阶级国家对经济的干预不断加强。国家已经承担起了提供财产保护、增强国家竞争力、实现经济增长和充分就业、保持经济稳定、提高社会福利水平以及维护竞争秩序等重要职能。它与市场机制相辅相成,共同推动着资本主义经济的运行和发展。

      • (2)生产过剩不是生产的商品绝对超过了人们的物质生活需要,而是一种相对过剩,即生产的商品相对于人民群众有支付能力的需求来说是过剩了。生产相对过剩是资本主义经济危机的实质。经济危机的抽象的一般的可能性,是由货币作为流通手段和支付手段引起的。以货币为媒介的商品买卖在时间上分为两个相互独立的行为。如果一些商品生产者在出卖自己的商品后不接着购买他人生产的商品,就会有另一些商品生产者的商品卖不出去。同时,在商品买卖有更多的部分采取赊购赊销的情况下,若某些债务人在债务到期时不能支付,就会使整个信用关系体系遭到破坏。但是,这仅仅是危机在形式上的可能性。

      • (3)资本主义经济危机是资本主义基本矛盾存在、激化和集中暴露的证明。这一基本矛盾具体表现在两个方面:①生产无限扩大的趋势与劳动人民现有支付能力和需求相对缩小的矛盾;②个别企业内部生产的有组织性和整个社会生产的无政府状态之间的矛盾。正如马克思所指出的:“一切现实的危机的最终原因始终是:群众贫穷和群众的消费受到限制,而与此相对立,资本主义生产却竭力发展生产力,好像只有社会的绝对的消费能力才是生产力发展的界限。”

      • (4)在经济调节机制变化的同时,经济危机形态也发生了变化,表现为:危机对社会经济运行的干扰减轻,破坏性减弱,生产下降的幅度减小,失业率有所降低,企业破产的数量减少;危机周期的长度缩短;经济危机的四个阶段(即危机阶段、萧条阶段、复苏阶段和高涨阶段)之间的差别有所减弱,各阶段的交替过程已不如过去那样明显;金融危机对整个经济危机的影响加强。随着调节机制的变化,资本主义经济危机的形态尽管发生了这样或那样的变化,但是由于资本主义的基本矛盾所决定,资产阶级不论采取什么样的调节措施和手段,经济危机是克服不了的。经济危机是资本主义基本矛盾的集中体现。

      # 有人认为,资本主义民主是囿于 “钱主” 的民主,迷于 “游戏” 的民主,止于 “选举” 的民主。你如何看待这种说法,为什么?

      • 答:资本主义民主存在着自身无法克服的 “软肋” 和 “硬伤”,这是因为资本主义政治制度为资产阶级专政服务,其本质上是资产阶级进行政治统治和社会管理的手段和方式,不可避免地有其阶级和历史的局限性。

      • (1)资本主义的民主是金钱操纵下的民主,是资产阶级精英统治下的民主。民主是具体的、相对的,而不是抽象的、绝对的。资本主义社会的主导逻辑是资本逻辑,不仅经济领域服从这一逻辑的统治,民主政治领域同样服从这一逻辑的主宰。西式民主的实质是 “钱主”,金钱是西式民主的 “母乳”,无论是政党还是政客都在母乳的滋养下成长,政客与财团之间结成生死与共的命运共同体,也常被金钱、媒体、黑势力、财团等影响和操纵。在实际的选举过程中,为得到选民的支持和认可,参选者往往需要支付巨额的竞选活动经费,这笔经费是普通公民根本没有能力支付的,只有依靠大财团才能支付得起。资本主义政治制度中的选举只能是有钱人的游戏,是资本玩弄民意的过程。号称民主典范的美国,其总统和参众两院议员的选举在现实中已经沦为烧钱的游戏,一人一票异化为 “一元一票”,筹集竞选经费的能力早已成为问鼎白宫的风向标,金钱是 “打开权力之门的金钥匙”。历史学家作过统计,从 1860 年以来的历次美国总统大选中,竞选经费占优的一方几乎都获得了胜利。“钱主” 的后果就是 “钱权联姻”。在西方,钱与权具有天然的近亲关系,“钱能生权,权又能生更多的钱”“政治献金” 与 “政治分赃” 总是如影随形。美国民主的实质就是 “1% 所有,1% 统治,1% 享用”。

      • (2)资本主义的民主是迷于 “游戏” 的民主。资本家和富人拥有特权,这对劳动者和穷人严重不平等,资产阶级法律将这种不平等合法化。民主的游戏化、娱乐化,这是西方的又一杰作。西方将民主变成了游戏,选民以娱乐的心态对待民主。西式民主在游戏中沉沦,选民在娱乐中迷茫。在这场游戏中,赢的永远是政客,输的始终是选民。

      • (3)资本主义的民主是止于 “选举” 的民主。民主不等于选举,民主和选举不能等量齐观、等同视之。真正的民主体制应该包括民主选举、民主决策、民主管理、民主监督等各个环节,覆盖起点、过程、结果等各个阶段。资本主义国家的多党制仍是资产阶级选择自己的国家管理者,以实现其内部利益平衡的政治机制。然而,现代资本主义民主却大都沉迷于 “选举” 这一初始环节,“人民主权” 被置换成 “人民的选举权”,民主被简化为选举,选举进一步简化为投票,而对于决策是否民主、管理是否民主、监督是否民主等方面却并不感兴趣。止于 “选
        举” 的民主只顾开头,不顾过程和结尾。这种民主即便有始却不一定有终,即便能善始却未必能善终。其实,民主是基于文化传统和现实国情的长期实践,采取何种民主形式必须与各个国家的历史文化传统、社会状况、人口结构、宗教信仰、民族构成、经济发展水平、法制意识、国民素质等因素相结合,否则很难有效运转。

      # 第五章 资本主义的发展及其趋势

      # 垄断是怎样产生的?为什么说垄断并没有消除竞争?答:

      • (1)垄断产生的原因

        • ① 当生产集中发展到相当高的程度,极少数企业就会联合起来,操纵和控制本部门的生产和销售,实行垄断,以获得高额利润。

        • ② 企业规模巨大,形成对竞争的限制,也会产生垄断。

        • ③ 激烈的竞争给竞争各方带来的损失越来越严重,为了避免两败俱伤,企业之间会达成妥协,联合起来,实行垄断垄断组织垄断是通过一定的垄断组织形式实现的。垄断组织是指在一个或几个经济部门中,占据垄断地位的大企业联合。垄断组织的形式多种多样,如初级的短期价格协定。但本质上都是通过联合达到独占和瓜分商品生产和销售市场,操纵垄断价格,以攫取高额垄断利润。

      • (2)垄断没有消除竞争的原因

        • ① 垄断没有消除产生竞争的经济根源。

        • ② 垄断必须通过竞争来维持。

        • ③ 社会生产是复杂多样的,任何垄断组织都不可能把包罗万象的社会生产都包下来。

      • 为什么说国家垄断资本主义体现了资本主义生产关系的部分质变?
        答:国家垄断资本主义是垄断资本和国家政权密切结合的垄断资本主义。国家垄断资本主义的产生,标志着资本主义发展进入了新的阶段。国家垄断资本主义体现了资本主义生产关系的部分质变的原因是:

        • (1)国家垄断资本主义是垄断资本主义的新发展,它对资本主义经济的发展产生了积极的作用。

          • ① 国家垄断资本主义的出现在一定程度上有利于社会生产力的发展,资本主义国家的政府通过公共投资和支出,开办大型新兴工业企业,部分克服了社会化大生产与私人垄断资本之间的矛盾。
          • ② 私人垄断统治扩大了资本主义生产与消费的矛盾,资产阶级国家采取一定手段干预国民经济,减轻经济危机的程度,缓和了社会各阶级的利益矛盾,有利于社会稳定,促进经济较为协调地发展。
          • ③ 宏观调控的发展,使国家对经济的干预和调节与市场机制日益有机结合起来,自由放任的市场经济逐渐演变成为由国家干预的现代市场经济,一定程度上弥补了自由市场经济的缺陷,对于国家的经济运行和社会发展产生了积极作用。
          • ④ 资产阶级国家通过税收和收入再分配手段,提高了劳动人民的生活水平。
        • (2)国家垄断资本主义的出现并没有根本改变垄断资本主义的性质。

          • ①国家垄断资本主义仍然是以资本主义私有制为基础,维护资产阶级利益和资本主义制度。
          • ②国家垄断资本主义没有从根本上消除资本主义的基本矛盾,它代表的是资产阶级的总利益。

      # 如何认识和把握经济全球化及其影响?

      • 答:经济全球化是指在生产不断发展、科技加速进步、社会分工和国际分工不断深化、生产的社会化和国际化程度不断提高的情况下,世界各国、各地区的经济活动越来越超出某一国家和地区的范围而相互联系、相互依赖的过程。

      • (1)经济全球化的表现

        • ① 国际分工进一步深化。

        • ② 贸易全球化。

        • ③ 金融全球化。

        • ④ 企业生产经营全球化。

      • (2)经济全球化的动因从本质上讲,经济全球化是生产力发展和社会化大生产的必然要求。导致经济全球化迅猛发展的因素主要有三点:

        • ① 科学技术的进步和生产力的发展提供了坚实的物质基础和根本的推动力。

        • ② 跨国公司的发展提供了适宜的企业组织形式。

        • ③ 各国经济体制的变革是经济全球化的体制保障。

      • (3)经济全球化的影响

        • ① 积极影响

          • a.社会分工得以在更大的范围内进行,资金、技术等生产要素可以在国际社会流动和优化配置,由此带来巨大的分工利益,推动世界生产力的发展。

          • b.体现了社会化生产的要求,不仅发达国家从中受益,一些发展中国家在参与经济全球化进程中也得到了快速发展。全球化为发展中国家提供先进技术和管理经验、就业机会,推动发展中国家国际贸易和跨国公司发展。

        • ② 消极影响

          • a.发达国家与发展中国家在经济全球化过程中的地位和收益不平等、不平衡。

          • b.加剧了发展中国家资源短缺和环境污染恶化。

          • c.一定程度上增加经济风险。

        • ③ 正确看待经济全球化

          • a.“把困扰世界的问题简单归咎于经济全球化,既不符合事实,也无助于问题解决。” 国际金融危机不是经济全球化发展的必然产物,而是金融资本过度逐利、金融监管严重缺失的结果。

          • b.经济全球化不是一部分国家的独角戏,而是世界各国、各民族共同实现发展的大舞台。

          • c.面对不同国家在生产方式、发展水平、文化背景等方面的差异,要以共同构建人类命运共同体的理念引领经济全球化。

      # 近年来资本主义社会发生了哪些新变化?试分析其原因及影响。答:

      • (1)资本主义社会的新变化

        • ① 生产资料所有制的变化:

          • a.国家资本所有制是指生产资料由国家占有并服务于垄断资本的所有制形式。国家资本所有制主要存在于基础设施和公共事业部门,所以对整个社会经济的发展有着重要的影响。但就其性质而言,仍然是资本主义形式,体现着总资本家剥削雇佣劳动者的关系。

          • b.法人资本所有制是资本主义生产资料所有制发展的新形式,是法人股东化的产物。法人资本所有制有两种形式:一种是企业法人资本所有制,另一种是机构法人资本所有制,但其在性质上是一种基于资本雇佣劳动的垄断资本。

        • ② 集体所有制劳资关系和分配关系的变化

          • a.职工参与决策。这一制度旨在协调劳资关系,缓和阶级矛盾。

          • b.终身雇佣。目的是增强工人对企业的归属意识,从而更加自觉地服从资本家的统治。

          • c.职工持股。旨在通过使职工持有一部分本公司的股份来调动工人的生产积极性,使工人产生归属感,在生产中努力提高劳动生产率,增加剩余价值生产。

          • d.普及化、全民化的社会福利制度。在一定程度上满足劳动者的安全和保障需求,保证劳动者维持最低生活水平,改善劳动者的社会状况。

        • ③ 社会阶层和阶级结构的变化

          • a.资本家的地位和作用已经发生很大变化。

          • b.高级职业经理成为大公司经营活动的实际控制者。

          • c.知识型和服务型劳动者的数量不断增加,劳动方式发生了新变化。

        • ④ 经济调节机制的变化 a.去工业化和产业空心化日趋严重,产业竞争力下降。

          • b.经济高度金融化,虚拟经济与实体经济严重脱节。

          • c.财政严重债务化,债务危机频繁爆发。

          • d.两极分化和社会对立加剧。

          • e.经济增长乏力,发展活力不足,周期性危机与结构性危机交织在一起。

          • f.金融危机频发,全球经济屡受打击。

        • ⑤ 政治制度的变化

          • a.政治制度出现多元化的趋势,公民权利有所扩大。

          • b.重视并加强法制建设。

          • c.改良主义政党在政治舞台上的影响日益扩大。

      • (2)资本主义社会的新变化的原因

        • ① 科学技术革命和生产力的发展,是当代资本主义发生新变化的根本推动力量。

        • ② 工人阶级争取自身权利和利益的斗争,是推动当代资本主义发生新变化的重要力量。

        • ③ 社会主义制度初步显示的优越性对当代资本主义产生了重要影响。

        • ④ 主张改良主义的政党对资本主义制度的改革,也对当代资本主义新变化发挥了重要作用。

      • (3)资本主义社会的新变化的影响

        • ① 当代资本主义发生的变化从根本上说是人类社会发展一般规律和资本主义经济规律作用的结果。

        • ② 当代资本主义发生的变化是在资本主义制度基本框架内的变化,并不意味着资本主义生产关系的根本性质发生了变化。

        • ③ 没有改变其为资产阶级利益服务,仍然是服从于资产阶级进行统治和压迫需要的政治工具的本质属性,没有改变马克思主义关于资本主义的基本论断的科学性。

      # 如何理解资本主义的历史地位及其为社会主义所代替的历史必然性?

      • 答:从人类社会发展的长河看,社会主义取代资本主义,即社会主义公有制取代资本主义私有制,这是历史发展的基本趋势。

      • (1)资本主义的内在矛盾决定了资本主义必然被社会主义所代替

        • ① 资本主义基本矛盾 “包含着现代的一切冲突的萌芽”。

          • a.资本主义基本矛盾表现在阶级关系上,是无产阶级和资产阶级的对立。

          • b.资本主义基本矛盾表现在经济关系上,是个别工厂中生产的组织性和整个社会中生产的无政府状态之间的对立。

          • c.资本主义经济危机的爆发正是这个基本矛盾发展的结果。

        • ② 资本积累推动资本主义基本矛盾不断激化并最终否定资本主义自身。

          • a.从资本主义积累过程来看,资本主义基本矛盾在资本积累过程中不断发展。

          • b.资本的不断积累必然提高生产的社会化程度,这在客观上势必导致生产的集中和资本的集中,使资本的社会化占有成为可能。

          • c.资本的不断积累使对生产过程的管理社会化,相应地派生出管理社会化大生产的管理人员和专业的管理机构,而这些都弱化甚至排斥资本家个人在管理中的地位和作用。

          当资本主义基本矛盾及其派生的各种矛盾在资本积累中不断发展、激化到资本主义制度自身无法使之释放时,社会主义取代资本主义就将成为不可避免的结果。这是资本主义积累过程所具有的客观历史趋势。

        • ③ 国家垄断资本主义中孕育着某些社会主义的因素,将成为社会主义的前奏。

        • ④ 资本主义社会中存在着资产阶级和无产阶级两大阶级之间的矛盾和斗争。无产阶级和资产阶级之间不可调和的矛盾、对立和斗争,必然导致资本主义政治危机。资产阶级的灭亡和无产阶级的胜利是不可避免的。通过无产阶级革命推翻资本主义制度,用社会主义公有制代替资本主义私有制,成为人类社会由低级向高级发展的客观规律的必然要求。

      • (2)社会主义代替资本主义是一个复杂的、长期的历史过程。其原因在于:

        • ① 社会主义自身的巩固、发展和完善是一个长期的历史过程。

          • a.经济上的强烈反差使社会主义国家面临严峻挑战。

          • b.西方敌对势力的颠覆、破坏与和平演变活动,加重了社会主义建设的曲折性、复杂性和长期性。

          • c.对社会主义建设规律的探索需要经过一个长期曲折的过程。

        • ② 社会主义在世界范围代替资本主义是一个长期的历史过程。

          • a.社会主义的本质决定了它在全世界取代资本主义的长期性、曲折性与艰巨性。

          • b.资本主义的暂时强大决定了它在全世界被社会主义所代替的长期性、曲折性与艰巨性。

          • c.20 世纪末世界社会主义运动遭受了重大挫折,导致社会主义顺利发展、再造辉煌需要较长的时间。

      # 第六章 社会主义的发展及其规律(本章仅供学习参考,不作考试要求)

      # 如何认识世界社会主义五百年的发展历程?

      • 答:世界社会主义五百年的发展过程实际上经历了四个阶段,分别是社会主义从空想到科学、社会主义从理论到实践、社会主义从一国到多国、在中国焕发强大生机活力。

      • (1)社会主义从空想到科学

        • ①空想社会主义

        空想社会主义产生于 16 世纪初期,到 19 世纪上半叶达到顶峰。这 300 多年正是欧洲从封建主义生产方式向资本主义生产方式转变的时期。其发展大致分为三个阶段:16 世纪和 17 世纪的早期空想社会主义,有理想社会制度的空想的描写,代表著作是英国人莫尔的《乌托邦》和意大利人康帕内拉的《太阳城》;18 世纪的空想平均共产主义;19 世纪初期出现了批判空想社会主义。主要代表是法国的圣西门、傅立叶和英国的欧文,以三大空想社会主义者为代表的空想社会主义学说,它对资本主义的揭露和批判,提供了启发工人觉悟的极为宝贵的材料。空想社会主义是早期无产阶级意识和利益的先声,反映了早期无产阶级迫切要求改造现存社会、建立理想的新社会的愿望。但其没有能够指出真正的出路。空想社会主义看不到无产阶级负有的历史使命,反对政治斗争,幻想依靠统治阶级的帮助,通过和平的方式来实现社会主义。

        • ② 科学社会主义

        19 世纪 40 年代,资本主义生产方式在西欧先进国家已占统治地位,随着资本主义的发展,资本主义内部矛盾日益尖锐,无产阶级反对资产阶级的斗争日益高涨。马克思和恩格斯参加了当时阶级斗争的实践。在此基础上,周密地研究了资本主义生产方式的矛盾,批判地继承了 19 世纪三大空想社会主义者法国的圣西门、傅立叶和英国的欧文的思想成果,创立了唯物史观和剩余价值论,为实现社会主义从空想到科学的飞跃奠定了坚实的理论基础。他们阐明了生产社会性和生产资料资本主义私人占有形式之间的矛盾的发展,必然导致社会主义取代资本主义,以生产资料的公有制取代生产资料私有制,科学地论述了资本主义必然灭亡、社会主义必然胜利的客观规律,从根本上超越了空想社会主义,实现了社会主义从空想到科学的伟大飞跃。

      • (2)社会主义从理论到现实

        • ① 第一国际与巴黎公社

        1848 年欧洲革命后,资本主义在各国飞速发展,无产阶级力量不断壮大。到 19 世纪 50 年代末 60 年代初,反压迫反剥削的斗争实践使各国无产阶级认识到,他们有着共同的利益和共同的敌人,而以往分散的斗争常常使他们遭到同样的失败,无产阶级必须在国际范围内联合起来。1864 年,国际工人协会(第一国际)应运而生。马克思是第一国际的真正领袖,在他指导下,第一国际把无产阶级先进分子团结在自己周围,率领各国工人群众向资产阶级和压迫者进行坚决斗争,促进了马克思主义的传播和与国际工人运动的结合,初步确立了马克思主义在工人运动中的指导地位。1871 年爆发的巴黎公社革命,深受第一国际精神的影响,是建立无产阶级专政的第一次伟大尝试。公社在经济方面采取了措施,对资本主义企业进行了一定程度的限制和剥夺;成立了管理经济工作的最高权力机构 —— 粮食委员会、财政委员会和劳动、就业及交换委员会;对工人群众的生活状况和劳动条件尽可能加以改善,提出了劳动者八小时工作制的原则。巴黎公社是世界上无产阶级武装暴力直接夺取城市政权的第一次尝试。它丰富和发展了马克思主义关于阶级斗争和社会主义的学说,在国际共产主义运动上写下了光辉、伟大而悲壮的一页。

        • ② 十月革命与第一个社会主义国家的建立

        1917 年 11 月 7 日(俄历 10 月 25 日)作为伟大的十月社会主义革命胜利日载入史册。俄国十月社会主义革命是人类历史上第一次获得胜利的社会主义革命,世界上第一个社会主义国家由此诞生。十月革命的胜利沉重打击了帝国主义的统治,推动了国际社会主义运动的发展,鼓舞了殖民地半殖民地人民的解放斗争。它改变了俄国历史的发展方向,用社会主义方式改造俄国的道路,对整个人类社会的发展都产生了巨大的影响。十月革命是二十世纪国际共产主义运动的序幕,触发了此后各国社会主义运动在全球范围的扩张,许多殖民地或半殖民地的解放运动也因此得到了更多支持,加速了世界范围内帝国主义殖民体系的整体瓦解,深刻改变了国际力量对比和世界格局。

      • (3)社会主义从一国到多国

        • ① 社会主义在苏联一国的实践

        苏维埃俄国是世界上第一个社会主义国家。年轻的苏维埃政权建立之后,既面临着巩固政权的任务,又面临着在经济文化相对落后的条件下建设社会主义的任务。列宁对苏维埃俄国社会主义的探索大体经历了巩固苏维埃政权时期、战时共产主义时期和新经济政策时期。

        • ② 社会主义发展到多个国家俄国十月革命的胜利后,第一个社会主义国家诞生,开辟了人类历史新纪元,极大地鼓舞了世界各国人民,促进了世界社会主义运动的发展。二战以后,社会主义在世界范围内获得大发展,在欧洲、亚洲、拉丁美洲,先后有 15 个国家建立社会主义制度,在国家数量上,占世界的 1/14,在领土上,占世界的 1/4,在人口上,占总人口的 1/3。社会主义国家相继开展了大规模的社会主义建设,推动了国家经济、政治、文化和社会各项事业的发展,世界形成了社会主义和资本主义两种制度共处的新格局。
      • (4)社会主义在中国焕发出强大生机活力
        俄国十月革命的胜利,给中国人民送来了马克思列宁主义。1921 年 7 月,中国共产党成立并成为中国社会主义运动的领导力量。中国共产党率领中国人民进行的社会主义事业经历了从新民主主义革命到社会主义革命、建设、改革的发展过程,中国共产党在近百年的奋斗中不断发展壮大,在 21 世纪焕发出强大的生机活力。习近平总书记在十九大报告中指出:“中国特色社会主义进入新时代,意味着近代以来久经磨难的中华民族迎来了从站起来、富起来到强起来的伟大飞跃,迎来了实现中华民族伟大复兴的光明前景;意味着科学社会主义在 21 世纪的中国焕发出强大生机活力,在世界上高高举起了中国特色社会主义伟大旗帜;意味着中国特色社会主义道路、理论、制度、文化不断发展,拓展了发展中国家走向现代化的途径,给世界上那些既希望加快发展又希望保持自身独立性的国家和民族提供了全新选择,为解决人类问题贡献了中国智慧和中国方案。” 总之,
        中国特色社会主义是科学社会主义 “中国化” 的伟大成果,是在当代中国的成功实践,充分表明了社会主义在世界上人口最多的国家成功开辟出了通向繁荣富强的正确道路,显著地展现了社会主义制度的优越性,标志着社会主义在世界范围内正在开拓新的历史征程。

      # 如何认识和把握科学社会主义一般原则?答:

      • (1)科学社会主义一般原则的主要内容
        科学社会主义一般原则是社会主义事业发展规律的集中体现,是马克思主义政党领导人民进行社会主义革命、建设、改革的基本遵循。

        • ① 人类社会发展规律和资本主义基本矛盾是 “资本主义必然灭亡、社会主义必然胜利” 的根本依据。

        • ② 无产阶级是最先进最革命的阶级,肩负着推翻资本主义旧世界、建立社会主义和共产主义新世界的历史使命。

        • ③ 无产阶级革命是无产阶级进行斗争的最高形式,以建立无产阶级专政的国家为目的。

        • ④ 社会主义社会要在生产资料公有制基础上组织生产,以满足全体社会成员的需要为生产的根本目的。

        • ⑤ 社会主义社会要对社会生产进行有计划的指导和调节,实行按劳分配原则。

        • ⑥ 社会主义社会要合乎自然规律地改造和利用自然,努力实现人与自然的和谐共生。

        • ⑦ 社会主义社会必须坚持科学的理论指导,大力发展社会主义先进文化。

        • ⑧ 无产阶级政党是无产阶级的先锋队,社会主义事业必须始终坚持无产阶级政党的领导。

        • ⑨ 社会主义社会要大力解放和发展生产力,逐步消灭剥削和消除两极分化,实现共同富裕和社会全面进步,并最终向共产主义社会过渡。

      • (2)正确对待科学社会主义一般原则的科学态度

        • ① 必须始终坚持社会主义一般原则,反对任何背离科学社会主义一般原则的错误倾向。

        • ② 要善于把科学社会主义一般原则与本国实际相结合,创造性地回答和解决革命、建设、改革中的重大问题。

        • ③ 紧跟时代和实践的发展,在不断总结新鲜经验中进一步丰富和发展科学社会主义一般原则。

      # 请结合科学社会主义一般原则,谈谈为什么说中国特色社会主义是科学社会主义,而不是其他什么主义。答:

      • (1)科学社会主义一般原则
        科学社会主义一般原则是社会主义事业发展规律的集中体现,是马克思主义政党领导人民进行社会主义革命、建设、改革的基本遵循。马克思、恩格斯在深刻揭示人类社会发展一般规律的基础上,深入阐发资本主义基本矛盾及其发展趋势,并在指导国际工人运动的过程中不断总结经验,逐步形成了科学社会主义一般原则。这些原则在后来的社会主义革命和建设中得到了证实、丰富和发展。这些原则具体如下:

        • ① 人类社会发展规律和资本主义基本矛盾是 “资本主义必然灭亡、社会主义必然胜利” 的根本依据。

        • ② 无产阶级是最先进最革命的阶级,肩负着推翻资本主义旧世界、建立社会主义和共产主义新世界的历史使命。

        • ③ 无产阶级革命是无产阶级进行斗争的最高形式,以建立无产阶级专政的国家为目的。

        • ④ 社会主义社会要在生产资料公有制基础上组织生产,以满足全体社会成员的需要为生产的根本目的。

        • ⑤ 社会主义社会要对社会生产进行有计划的指导和调节,实行按劳分配原则。

        • ⑥ 社会主义社会要合乎自然规律地改造和利用自然,努力实现人与自然的和谐共生。

        • ⑦ 社会主义社会必须坚持科学的理论指导,大力发展社会主义先进文化。

        • ⑧ 无产阶级政党是无产阶级的先锋队,社会主义事业必须始终坚持无产阶级政党的领导。

        • ⑨ 社会主义社会要大力解放和发展生产力,逐步消灭剥削和消除两极分化,实现共同富裕和社会全面进步,并最终向共产主义社会过渡。

      • (2)中国特色社会主义是科学的社会主义的原因
        中国特色社会主义,是科学社会主义理论逻辑和中国社会发展历史逻辑的辩证统一。中国特色社会主义既坚持了科学社会主义的基本原则,又根据时代条件赋予其鲜明的中国特色,是一百多年来科学社会主义理论与实践发展的结晶,是当代中国的科学社会主义。

        • ① 新中国成立后,中国共产党领导人民开始社会主义革命和建设的伟大实践。在只有苏联模式可学的情况下,在开始进行社会主义建设时我们走了照搬苏联经验的路子。但是,我们党很快就觉察到苏联模式的种种弊端,果断决定独立探索适合中国国情的社会主义建设道路。这一探索尽管曾出现过脱离实际的严重失误,却还是取得了巨大的成绩,形成了关于社会主义建设的许多独创性的理论成果和实践成果。在新的历史时期,我们党坚持解放思想、实事求是,深刻总结历史经验教训,正确判断时代主题和基本国情,经过 30 多年的努力,形成了中国特色社会主义道路、中国特色社会主义理论体系、中国特色社会主义制度三位一体的伟大成果,取得了中国特色社会主义建设的巨大成就。

        • ② 中国特色社会主义之所以是社会主义而不是别的什么主义,就在于它始终坚持以科学社会主义的基本原则为理论源泉和理论核心。科学社会主义创始人对社会主义的设想和他们提出的科学社会主义基本原则的最终实现,需要一个过程。我们党始终将其作为核心价值追求,始终将其作为进行改革开放和实践创新、理论创新、制度创新的 “魂”。这样一种追求,这样的 “魂”,鲜明地体现在改革开放新时期我们党所制定的路线、方针、政策中。

        • ③ 科学社会主义包含极其丰富的内容,集中到一点,就是科学地论证了社会主义必然代替资本主义的历史趋势,论证了无产阶级取代资本主义、建设社会主义和共产主义的伟大历史使命。科学社会主义理论创立以来的历史证明它的理论是正确的,社会主义具有强大的生命力。同时,它又不是一成不变的教条。它在指导实践的过程中,又要接受实践的检验,随着实践的发展而不断扩展、不断深化、不断丰富、不断完善。中国特色社会主义理论体系,就是科学社会主义在当代中国的新发展。

        • ④ 当前,资本主义现实和社会主义实践同马克思、恩格斯两位伟大思想家所处的历史环境相比,都发生了巨大的变化,但从世界社会主义发展的五百年大视野来看,目前依然处在马克思主义所指明的历史时代,处在资本主义向社会主义转变的历史进程之中,科学社会主义从没有过时,仍然有强大的生命力,必须始终坚持、不动摇。正如习近平指出:“中国特色社会主义是社会主义而不是其他什么主义,科学社会主义基本原则不能丢,丢了就不是社会主义。”

      # 请谈谈中国特色社会主义的成功实践对世界社会主义发展的贡献。答:

      • 党的十九大报告作出了 “中国特色社会主义进入新时代” 的重大政治论断。习近平总书记在报告中指出:“中国特色社会主义进入新时代,意味着近代以来久经磨难的中华民族迎来了从站起来、富起来到强起来的伟大飞跃,迎来了实现中华民族伟大复兴的光明前景;意味着科学社会主义在二十一世纪的中国焕发出强大生机活力,在世界上高高举起了中国特色社会主义伟大旗帜;意味着中国特色社会主义道路、理论、制度、文化不断发展,拓展了发展中国家走向现代化的途径,给世界上那些既希望加快发展又希望保持自身独立性的国家和民族提供了全新选择,为解决人类问题贡献了中国智慧和中国方案。” 这一重大政治论断给我们许多启示,增加了我们对中国特色社会主义的自信,也使我们充分认识到中国特色社会主义不仅在 21 世纪的中国充分显现出生机与活力,取得伟大成功,使科学社会主义理论在中国实践中获得巨大发展,也使得中国特色社会主义超越了国界,具有世界性的意义,为发展中国家走向现代化提供了新的路径选择,也为世界发展和人类问题的解决贡献了中国智慧和中国方案。

      • (1)中国特色社会主义为世界贡献了中国智慧
        中国走上中国特色社会主义道路,是几代中国共产党人带领全国人民在艰难曲折中艰辛探索、不断实践创新的结果,体现了中国共产党人的不屈不挠,也体现了中国共产党人的卓越智慧,其中最核心的就是党的实事求是的思想路线,一切从实际出发,把马克思主义基本原理与中国客观实际相结合,走适合中国国情的社会主义道路。改革开放以来,我们党坚持实事求是的思想路线,在实践中不断探索和回答了什么是社会主义、怎样建设社会主义,建设什么样的党、怎样建设党,实现什么样的发展、怎样发展,并继续探索和回答新时代坚持和发展什么样的中国特色社会主义、怎样坚持和发展中国特色社会主义这些基本问题。党的思想路线体现的是马克思主义的世界观、方法论。因此,中国特色社会主义的成功,是马克思主义世界观和方法论的成功,是马克思主义中国化、时代化的成功。中国特色社会主义贡献给世界的智慧,最为根本的是实事求是,国家建设一定要从自己的国情出发,探索适合自己国情的建设道路,任何脱离实际、不符合国情的道路、方法、模式都是不可能取得成功的。

      • (2)中国特色社会主义为世界贡献了中国方案
        中国特色社会主义不仅为世界贡献了指导国家建设的正确的思想方法,还为世界贡献了国家建设的具体方案和治国理政的基本方略。中国特色社会主义治国方案既包括总目标、总任务、总体布局、战略布局和发展方向、发展方式、发展动力、战略步骤、外部条件、政治保证等基本方面的总体设计,也包括经济、政治、科技、文化、教育、民生、民族、宗教、社会、生态、国家安全、国防和军队、国家统一、统一战线、外交、党的建设等各方面的基本规定。还有就是,坚持党对一切工作的领导,坚持以人民为中心,坚持全面深化改革,坚持新发展理念,坚持人民当家作主,坚持全面依法治国,坚持社会主义核心价值体系,坚持在发展中保障和改善民生,坚持人与自然和谐共生,坚持总体国家安全观,坚持党对人民军队的绝对领导,坚持 “一国两制” 和推进祖国统一,坚持推动构建人类命运共同体,坚持全面从严治党等基本方略。这些既是新时代坚持和发展中国特色社会主义的基本方略,也是中国特色社会主义为解决人类问题向世界贡献的中国方案,给世界上那些既希望加快发展又希望保持自身独立性的国家和民族提供了全新选择。

      # 如何正确认识和把握共产党执政规律?

      答:可以从以下几个方面正确认识和把握共产党执政规律:

      • (1)共产党执政规律,最根本的是人心向背定理。习近平总书记指出:“一个政党,一个政权,其前途和命运最终取决于人心向背。”“人心是最大的政治。” 要始终把人民放在心中最高位置。坚持一切为了人民、一切依靠人民。

      • (2)共产党执政首要的是坚持党中央权威和集中统一领导,党是最高政治领导力量,党的领导是全面领导。党的十九大报告指明 “坚持党中央权威和集中统一领导,是党的政治建设的首要任务”,揭示了保证党的团结和集中统一的根本性问题,阐明了进行伟大斗争、建设伟大工程、推进伟大事业、实现伟大梦想的根本保证,意义重大而深远。

      • (3)共产党在执政过程中,要把党的政治建设摆在首位。要坚持党要管党、全面从严治党,以应对各种考验,坚定不移地惩治和预防腐败,勇于自我革命。只有全面从严治党,才能顺利实现中华民族伟大复兴的中国梦。

      • (4)要始终抓住科学执政、民主执政、依法执政这个要律,为实现国家治理现代化指明方向路径。

      # 第七章 共产主义是人类最崇高的社会理想

      # 请谈谈在未来理想社会的认识上,马克思主义经典作家与空想社会主义者有何本质区别。

      • 答:在未来理想社会的认识上,马克思主义经典作家与空想社会主义者的本质区别是:是否坚持科学的立场、观点和方法来预见未来。预见未来社会的方法论原则主要包括:

      • (1)在揭示人类社会发展一般规律的基础上指明社会发展的方向。

      • (2)在剖析资本主义旧世界的过程中阐发未来新世界的特点。

      • (3)在社会主义社会发展中不断深化对未来共产主义社会的认识。

      • (4)立足于揭示未来社会的一般特征,而不作详尽的细节描绘。

      # 既然共产主义理想的实现是历史的必然,为什么又要人们去努力追求?既然共产主义的最终实现是一个漫长的过程,为什么又说 “共产主义渺茫论” 是错误的?请用马克思主义的辩证观点予以解答。答:

      • (1)实现共产主义的历史必然

        • ① 共产主义理想的实现是历史规律的必然要求

          • a.共产主义理想是能够实现的理想,它与一切空想和幻想有着本质区别。

          • b.共产主义理想一定会实现,是以人类社会发展规律以及资本主义社会的基本矛盾发展为依据的。

          • c.社会主义运动的实践,特别是社会主义国家的兴起和不断发展,已经且正在用事实证明共产主义理想实现的必然性。从一定意义上讲,社会主义革命的胜利本身就是对共产主义理想可以实现的证明。

        • ② 实现共产主义是人类最伟大的事业

          • a.实现共产主义理想是广大人民群众的共同愿望。

          • b.实现共产主义,必须找到现实的阶级力量,这就是现代工人阶级或无产阶级。

          • c.无产阶级的解放与全人类的解放是完全一致的。

      • (2)共产主义的实现是一个漫长的过程

        • ① 资本主义的灭亡和向社会主义的转变是一个长期的过程

          • a.资本主义作为一个社会形态,其走向灭亡是一个长期的历史过程。资本主义国家经历过严重的经济和社会危机,在与社会主义国家的竞争中也伴随着巨大的压力。但资本主义并没有退出历史舞台,而是仍然有一定发展空间。这些危机背后隐藏着资本主义衰败的必然趋势,但目前谁也无法准确判断资本主义何时走到尽头。

          • b.社会主义革命取得胜利后,从资本主义转变为社会主义也需要一段时期。这个重要的过渡期是不以人的意志为转移的,它不能省略,更不可随意缩短。

          • c.在完成转变以后,仍然需要经历一段社会主义的发展阶段,才能最终逐渐走向共产主义。在任何国家,实现共产主义都不能超越社会主义发展阶段。不管资本主义国家发达到何种程度,当发生根本性的制度变革时,也不可能直接达到共产主义社会,只能首先进入社会主义社会,也就是共产主义社会的低级阶段。

          • d 要真正迎来新社会,消除旧社会痕迹,也需要经过一个很长的时期。

        • ② 社会主义社会自身巩固、发展和完善并最终成为共产主义也是一个长期的过程。

          • a.想要在全世界范围内实现共产主义,必须取决于社会主义国家的巩固和发展,取决于这些国家所经历的社会主义社会的时间长短。因此,共产主义只有在社会主义社会充分发展和高度发达的基础上才能实现。

          • b.经济上的强烈反差使社会主义国家面临严峻挑战。社会主义革命没有像马克思和恩格斯所设想的那样,在发达的资本主义国家首先发生,而是在少数经济和文化比较落后的国家首先取得胜利。这些国家基础差、起点低,要在经济上赶上资本主义发达国家,提高社会化生产水平,建设和完善社会主义政治、经济、文化等各项制度,体现出社会主义优于资本主义,需要付出更大、更艰苦和更长期的努力,是一个漫长的历史过程。

          • c.对社会主义建设规律的探索需要经过一个长期曲折的过程。建设社会主义是前无古人的崭新事业,没有现成固定的模式可循,需要各个社会主义国家在实践中把马克思主义的基本原理与本国的具体实践相结合,探索适合本国发展的社会主义建设道路和模式。而探索的过程不会是一帆风顺的,难免会出现不同程度的失误,甚至发生曲折和暂时倒退现象。这种探索过程的曲折性,无疑会增加这些国家建设、巩固和发展社会主义的艰巨性与长期性。

          • d.社会主义是共产主义的低级阶段,也是实现共产主义的必由之路。作为同一社会形态发展进程中的两个阶段,社会主义是共产主义的必要准备,共产主义是社会主义发展的必然趋势。随着社会主义生产力和其他因素的不断发展,属于社会主义的一些因素将逐步消失,而共产主义的所有因素将逐步增长。社会主义社会不断发展和完善的过程,就是共产主义因素不断扩大的过程。一旦条件完全成熟,社会主义社会就自然过渡到共产主义社会。

      • (3)实现共产主义是历史发展规律的必然要求,“共产主义渺茫论” 是错误的

        • ① 共产主义渺茫论者不了解共产主义的含义。

        共产主义有两方面的含义:一方面指的是在共产主义思想体系指导下的共产主义运动;另一方面指的是共产主义的社会制度。当然,共产主义社会制度彻底实现,是需要经过若干代人的不懈努力的,是一个远大的奋斗目标。但是,作为在共产主义思想体系指导下的共产主义运动,作为一种亿万人民在共产党领导下改造社会的革命实践,则是一点也不 “渺茫”,而是实实在在地、每日每时地存在于我们的现实生活中。一个多世纪以来,各国无产阶级及其政党为了实现共产主义制度这一伟大理想,进行了艰苦卓绝的斗争,诸如巴黎公社、十月社会主义革命以及我国的社会主义革命和社会主义建设,每向前发展一步都意味着向共产主义靠拢一步。今天,我们的一切革命工作都是伟大的共产主义运动的具体体现和组成部分。

        • ② 共产主义渺茫论者割裂了共产主义与社会主义之间的联系。

        共产主义渺茫论者忽视了一个很重要的事实,即共产主义运动不仅在全世界,而且在中国也早已存在,而且已经取得了显著成果,这就是共产主义社会的过渡阶段 —— 社会主义社会,已经在中国和世界一些国家建立起来并取得重大发展,从而使共产主义运动发生了质的飞跃。我国社会主义制度的建立,不仅使人民从被压迫和被剥削的旧制度下解放出来,而且,随着社会主义改革和建设的不断深入,人们生活的不断改善,社会主义制度的不断完善以及社会道德水准和文化教育科学事业的向前推进,共产主义理想逐渐深入人心。

        • ③共产主义渺茫论者不能正确对待社会主义事业中的曲折和困难。

        马克思主义辩证法告诉我们,事物的发展不是直线上升,而是在曲折中前进的。社会主义事业也是如此,它有成功,也有失误,有前进,也有暂时的困难。中国的改革和经济建设取得了举世瞩目的伟大成就,但也存在不少问题。只有坚持中国特色社会主义道路,集中精力把经济建设搞上去,人民生活得到了不断改善,人们才能看到社会主义的前途和希望。只要把社会主义建设好,才能为将来的共产主义打下了坚实的基础。我们要继续坚定不移地沿着社会主义道路勇往直前,坚信共产主义必胜的信念。

      # 有人说:“在社会主义初级阶段只能讲树立中国特色社会主义共同理想,而不应提树立共产主义远大理想,否则就是脱离实际。” 请用共同理想和远大理想的关系来分析评论这一观点。

      • 答:共产主义理想是建立在科学基础上的社会理想,是人类最伟大的社会理想。在坚持和发展中国特色社会主义的实践中,我们不但要坚定中国特色社会主义共同理想,而且要进一步树立共产主义远大理想。

      • (1)正确认识和把握共产主义远大理想与中国特色社会主义共同理想的关系

        • ①从时间上看,远大理想与共同理想的关系是最终理想与阶段性理想的关系。

        • ②从层次上看,远大理想与共同理想的关系是最高纲领与最低纲领的关系。实现共产主义远大理想要坚持最高纲领和最低纲领的统一。

        • ③从范围来看,远大理想与共同理想的关系也是全人类理想与全体中国人民理想的关系。

      • (2)以辩证思维把握和处理远大理想和共同理想的关系
        必须以马克思主义的辩证思维和历史思维去把握远大理想和共同理想的关系。实现中国特色社会主义的共同理想,是为了实现共产主义远大理想而服务。中国特色社会主义共同理想在我国的成功实践,必然为实现共产主义远大理想奠定坚实的基础。

      # 中国特色社会主义进入了新时代。为了不辜负这个伟大的时代,当代大学生应该怎样确立和追求自己的人生理想?答:

      • (1)新时代的特征
        中国特色社会主义进入新时代。我们党对 “什么是社会主义、如何建设社会主义” 的认识又向前推进了一步,从理论和实践结合上系统回答了 “新时代坚持和发展什么样的中国特色社会主义、怎样坚持和发展中国特色社会主义” 这一重大历史课题,习近平新时代中国特色社会主义思想成为指引全国人民沿着中国特色社会主义道路继续前进的重要理论基础。

      • (2)对当代大学生的要求习近平指出:“青年是标志时代的最灵敏的晴雨表,时代的责任赋予青年,时代的光荣属于青年。” 青年是祖国的未来、民族的希望。青年兴则国兴,青年强则国强。当前,中国特色社会主义进入新时代,为当代青年特别是当代大学生提供了实现人生才华的极为有利的历史机遇。

        • ①要坚定理想信念。心中有信仰,脚下才有力量。为此,就要深入学习马克思主义基本原理及马克思主义中国化的理论成果,特别是学习习近平新时代中国特色社会主义思想。

        • ②要积极投身实现中华民族伟大复兴的中国梦,勇做担当中华民族伟大复兴大任的时代新人。

        • ③要投身新时代中国特色社会主义事业,当代大学生是祖国的未来、民族的希望,要以勇于担当的精神,做走在新时代前列的奋进者、开拓者、奉献者,投身于党和人民在中国特色社会主义新时代的伟大奋斗。

      \ No newline at end of file +马原课后习题 - 马克思主义基本原理 - 思政 | Balloon Party = 風船のパーティー = fuusen no party

      # 思维导图

      # 绪论部分

      绪论部分

      # 第一章 世界的物质性及发展规律

      第一章 世界的物质性及发展规律

      # 第二章 实践与认识及其发展规律

      第二章 实践与认识及其发展规律

      # 第三章 人类社会及其发展规律

      第三章 人类社会及其发展规律

      # 第四章 资本主义的本质及规律

      第四章 资本主义的本质及规律

      # 第五章 资本主义的发展及其趋势

      第五章 资本主义的发展及其趋势

      # 第六章社会主义的发展及其规律(本章仅供学习参考,不作考试要求)

      第六章 社会主义的发展及其规律(本章仅供学习参考,不作考试要求)

      # 第七章 共产主义是人类最崇高的社会理想

      第七章 共产主义是人类最崇高的社会理想

      # 大纲

      # 绪论部分

      # 什么是马克思主义?

      • a) 从创造者、继承者的认识成果讲,马克思主义是由马克思、恩格斯创立的,由其后继者不断丰富和发展的观点和学说的科学理论体系。

      • b) 从阶级属性讲,马克思主义是关于无产阶级解放、全人类解放和每个人自由而全面发展的学说,是指引人民创造美好生活的行动指南,具有鲜明的阶级性。

      • c) 从研究对象和主要内容讲,马克思主义是无产阶级的科学世界观和方法论,是关于自然、社会和人类思维发展的一般规律的学说,是关于社会主义必然代替资本主义、最终实现共产主义的学说。

      • d) 马克思主义哲学、马克思主义政治经济学和科学社会主义的有机统一并共同构成了马克思主义理论的主体内容。

      # 马克思主义的直接的理论来源?

      • a) 资本主义生产方式造成社会化大生产迅猛发展的同时也带来了严重的社会灾难(社会两极分化;周期性经济危机频发)

      • b) 无产阶级在反抗资产阶级剥削和压迫的斗争中,逐步走向自觉,并迫切渴望科学的理论指导

      • c) 19C 西欧三大先进思潮为马克思主义的创立提供直接的理论来源(德国古典哲学、英国古典政治经济学和英法两国的空想社会主义)

      • d) 19C 三大科学发现也为马克思主义的产生提供了自然科学前提(细胞学说、能量守恒和转化定律)

      • e) 还有主观条件,结合马恩二人的生平谈就行

      # 马克思主义的鲜明特征?

      • a) 科学性

        • a.马克思主义是对自然、社会和人类思维发展本质和规律的正确反映。它是在社会实践和科学发展的基础上产生的,并在自身发展过程中不断总结实践经验,吸取自然科学和社会科学发展的最新成就。

        • b.马克思主义具有科学的世界观和方法论基础,即辩证唯物主义和历史唯物主义,这是马克思主义的一个突出特征和理论优势,也是马克思主义科学性的重要体现。

        • c.马克思主义理论是一个逻辑严密的有机整体,它以事实为依据、以规律为对象,并以实践为检验标准。马克思主义的发展具有科学探索性,是一个不断探索和掌握客观规律的过程。

      • b) 人民性

        • a.人民至上是马克思主义的政治立场。马克思主义政党把人民放在心中最高位置,一切奋斗都致力于实现最广大人民的根本利益,这是马克思主义最鲜明的政治立场。

        • b.人民群众是历史的创造者,是社会主义事业的依靠力量,马克思主义的人民性是以阶级性为深刻基础的,是无产阶级先进性的体现。

        • c.马克思主义是关于无产阶级解放的学说。无产阶级解放和全人类解放是完全一致的。

      • c) 实践性

        • a.马克思主义具有突出的实践精神,它始终强调理论与实践的统一,始终坚持与社会主义实际运动紧密结合。马克思主义是从实践中来,到实践中去,在实践中接受检验,并随实践的发展而不断发展的学说。

        • b.从马克思主义的使命和作用来说,它不是一种纯粹解释世界的学说,而是直接服务于无产阶级和人民群众改造世界的实践活动的科学理论。

        • c.从马克思主义的内容来看,实践观点是马克思主义首要的和基本的观点,这一基本观点体现在马克思主义全部思想内容之中。

      • d) 发展性

        • a.马克思主义是不断发展的学说,具有与时俱进的理论品质。马克思主义是时代的产物,并随着时代、实践和科学的发展而不断发展。

        • b.马克思主义理论体系是开放的,它不断吸取人类最新的文明成果来充实和发展自己。

        • c.马克思主义在指导人们认识世界和改造世界的过程中,在指导社会主义事业发展的过程中,不断与时代特征和各国具体实际相结合,得到丰富和发展,并形成新的理论成果。

      # 结合当代世界所面临的课题和当代青年所肩负的使命,谈谈马克思主义的当代价值和指导意义?

      • (1)当代世界所面临的新课题和当代青年所肩负的新使命

        • a) 在经济全球化的背景下,资本主义内部矛盾越来越突出,经济政治发展的不平衡加剧了资本主义世界的两极分化,贫富差距日益扩大。20 世纪 90 年代末的东南亚金融危机以及由华盛顿开始波及全球的 2008 年全球金融危机,都暴露了资本主义的缺陷。当代世界的新课题是和平与发展,各国都希望在一个相对稳定的环境中谋求国内经济发展,提高人们的生活水平。因此,马克思主义思想对现代社会仍有指导意义。

        • b) 不同的时代有不同的历史责任与使命,当代青年是在中国改革开放新时期成长起来的,处在一个继往开来的历史时期,肩负着祖国人民更多的期望,也应肩负起民族复兴的重任。当代青年所处的时代正是社会主义现代化建设的关键时刻,中华民族的伟大复兴对当代青年提出了新的挑战,我们有责任也有义务来维护祖国的统一,保卫祖国,建设祖国。而大学生作为当代青年的主体和中坚力量,更应该发挥引领带头作用。

        • c) 总而言之,马克思主义作为具有科学性、真理性的学说,对当代青年的人生发展有重要的指引作用,有助于青年们树立正确的世界观、人生观和价值观,提高其应对和处理问题的能力。

      • (2)马克思主义的当代价值

        • ① 当代世界变化的认识工具

          • a.马克思主义给予我们观察当代世界的宏大视野。

          • b.马克思主义给予我们透视时代风云的锐利目光。

          • c.马克思主义给予我们展望未来世界的长远眼光和战略定力指引。

        • ② 当代中国发展的行动指南

          • a.马克思主义是指引当代中国发展的精神旗帜。

          • b.马克思主义是推动当代中国发展的精神动力。

          • c.马克思主义是引领当代中国实践的行动指南。

        • ③ 引领人类社会进步的科学真理

          • a.从人类历史发展的大视野来看,世界仍然处于马克思主义所指明的从资本主义走向社会主义的大时代。马克思主义所揭示的资本主义基本矛盾仍然存在,而且在近年来西方的金融危机和社会危机中呈现出某种激化的趋势。

          • b.人类的未来仍然需要马克思主义的启迪和指引。社会是在矛盾中进步的,每一个时代的社会进步总是伴随着相应的社会问题,面对当今社会的重大问题,还是需要从马克思主义中寻找智慧。

      • (3)对当代青年的指导意义

        • 青年是祖国的未来、事业的希望。青年强则国家强,青年一代有理想、有本领、有担当,国家就有前途,民族就有希望。学习马克思主义理论可以帮助青年提高分析和解决问题的能力,有助于其树立正确的世界观、人生观和价值观。当代青年在学习马克思主义的过程中,要有正确的态度和科学的方法:

          • ① 努力学习和掌握马克思主义的基本立场、观点、方法。
          • ② 坚持理论联系实际的马克思主义学风。
          • ③ 自觉将马克思主义内化于心、外化于行。

      # 阅读感受:

      • 《资本论》内容宏大,理论深奥,创造了一个崭新的思想体系。其研究世界的方法源于德国古典哲学、英法两国的空想社会主义和英国古典政治经济学。马克思吸收了黑格尔的辩证法思想,相信能够用一个辩证法公式概括人类的进化历程。他认为,所有哲学家所做的一切都在致力于解释世界,但他同时认为,问题的关键在于如何改造世界。马克思在黑格尔辩证法的基础之上,颠覆了传统的 “形而上学”,建立了一个现实中得以实践的最大的思想体系。《资本论》以唯物史观的基本思想为指导,通过深刻分析资本主义生产方式,揭示了资本主义社会发展的规律,同时也使唯物史观得到了科学的验证和进一步的丰富和发展。它运用唯物史观的观点和方法,将社会关系归结为生产关系,将生产关系归结于生产力水平,从而证明了社会形态的发展是一个不以人的意志为转移的自然历史过程。

      # 第一章 世界的物质性及发展规律

      # 马克思主义的物质范畴的理论意义

      • (1)马克思主义的物质观
        马克思主义认为,世界是物质的世界,物质是第一性,物质是不依赖于人类的意识而存在,并能为人类的意识所反映的客观存在。“物质” 范畴是唯物主义哲学关于世界本原和统一性的最高抽象,是唯物主义世界观的基石。马克思主义批判继承了以往唯物主义的传统,在总结现代自然科学重大成就的基础上,创立了辩证唯物主义的物质观。20 世纪初,列宁对物质概念做出了科学的概括:“物质是标志客观实在的哲学范畴,这种客观实在是人通过感觉感知的,它不依赖于我们的感觉而存在,为我们的感觉所复写、摄影、反映。”

      • (2)马克思主义的物质观具有深刻的理论意义

        • ① 坚持唯物主义一元论,同唯心主义一元论和二元论划清了界限。马克思主义指明了物质对于意识的独立性、根源性,以及意识对于物质的依赖性、派生性。因为意识不过是物质的反映,不能离开物质而独立存在,所以意识不可能成为世界的另一种本原。

        • ② 坚持了能动的反映论和可知论,批判了不可知论。目前世界上还有很多事物未被人类认识,但这并不意味着它们不可认识。人们已经认识到未知世界与已知世界都是客观存在的。世界上只有尚未认识之物,没有不可认识之物。

        • ③ 体现了唯物论和辩证法的统一,克服了形而上学唯物主义的缺陷。马克思主义的物质观认为,物质的唯一特性是客观实在性,既肯定了哲学物质范畴同自然科学物质结构理论的联系,又将它们相区别。从个性中看到共性,从暂时中发现永恒,从相对中找到绝对,这是马克思主义物质观体现的唯物辩证法。

        • ④ 体现了唯物主义自然观与唯物主义历史观的统一,为彻底的唯物主义奠定了理论基础。马克思主义的物质观建立了统一说明自然历史过程的唯物主义原则,揭示了自然和社会的物质性,实现了唯物主义自然观和历史观的辩证统一。

      # 物质与意识的辩证关系

      物质决定意识,意识对物质具有反作用,这种反作用就是意识的能动作用。

      • (1)物质决定意识
        意识是人脑的机能和属性,是客观世界的主观映像。物质对意识的决定作用表现在意识的起源、本质和作用上。

        • ① 从意识的起源来看,其形成和发展经历了三个阶段,即:由一切物质所具有的反应特性到低等生物的刺激感应性,再到高等动物的感觉和心理,最终发展成人类的意识。意识不仅是自然界长期发展的产物,而且是社会历史发展的产物。劳动为意识的产生和发展提供了客观需要和可能;人们在劳动和交往中形成的语言促进了意识的发展。

        • ② 从意识的本质来看,意识是客观世界的主观映像。马克思指出:“观念的东西不外是移入人的头脑并在人的头脑中改造过的物质的东西而已。”

      • (2)意识对物质具有反作用
        物质决定意识,意识的能动作用是指意识对物质具有反作用。意识的能动作用主要表现在:

        • ① 意识活动具有目的性和计划性。马克思认为:“人在劳动过程结束时得到的结果,在这个过程开始时就已经在劳动者的表象中存在着,即已经观念地存在着”。人的整个实践过程,就是围绕意识活动所构建的目标和蓝图来进行的。

        • ② 意识活动具有创造性。人的意识可以对客观世界中的感性材料加工和建构,在思维中构造一个现实中没有的理想世界。

        • ③ 意识具有指导实践改造客观世界的作用。在实践中形成观念,以这些观念为指导,通过实践使之变成客观现实。④ 意识具有调控人的行为和生理活动的作用。现代科学证明,意识、心理因素对人的行为选择和健康状况能够产生重要影响。

      • (3)主观能动性和客观规律性的统一
        正确认识和把握物质与意识的辩证关系,需要处理好主观能动性与客观规律性的关系,原因在于:

        • ① 尊重客观规律是正确发挥主观能动性的前提。人们正确地认识世界,有效地改造世界的前提是认识和掌握客观规律。

        • ② 只有充分发挥主观能动性,才能正确认识和利用客观规律。承认规律的客观性,并不是说人在规律面前无能为力、无所作为。人类能够按照客观规律改造世界,以达到自己的目的。

      # 运用矛盾的普遍性和特殊性辩证关系原理,说明把马克思主义基本真理与中国具体实际相结合的重要性。答:

      • (1)矛盾普遍性与特殊性的辩证关系

        • ① 矛盾的普遍性即矛盾的共性,矛盾的特殊性即矛盾的个性。矛盾的共性是无条件的、绝对的;矛盾的个性是有条件的、相对的。

        • ② 任何现实存在的事物的矛盾都是共性和个性的有机统一,共性寓于个性之中,没有离开个性的共性,也没有离开共性的个性。矛盾的共性和个性相统一的关系,既是客观事物固有的辩证法,也是科学的认识方法。

      • (2)把马克思主义基本真理与中国具体实际相结合的重要性
        矛盾的普遍性和特殊性辩证关系的原理,是把马克思主义普遍真理同各国具体实际相结合的理论基础,也是建设中国特色社会主义的理论根据。

        • ① 矛盾的普遍性和特殊性辩证统一的原理,是把马克思主义普遍真理与中国的具体实际相结合,走建设有中国特色社会主义道路的重要理论依据。矛盾的普遍性和特殊性的关系就是共性与个性、绝对与相对的关系。我国走中国特色社会主义道路,是中国共产党把马克思主义普遍真理同中国的具体实际相结合的过程中实现的第二次飞跃。在这里,“中国特色” 是中国不同于其他社会主义国家的个性、特殊性。“社会主义” 则是中国和其他社会主义国家的共性、普遍性。

        • ② 根据共性与个性相统一的原理,我们坚持中国特色社会主义道路。

          • a.不管中国的情况如何特殊,都必须坚持马克思主义的普遍真理,坚持社会主义根本制度和基本原则,这是共性。

          • b.社会主义的一般只能在各国特色的个别中存在,我们又必须建设中国特色的社会主义,从中国的国情出发,注意把握中国的特点。只有坚持党的基本路线不动摇,走自己的路,我们才能在建设中国特色社会主义的道路上不断取得胜利,这是个性。

      # 不断增强思维能力:辩证思维能力、历史思维能力、战略思维能力、底线思维能力、创新思维能力。

      答:创新思维能力是对常规思维的突破,是破除迷信、超越陈规,善于因时制宜、知难而进、开拓创新的能力。

      • (1)培养和提高创新思维能力的重要性

        • ① 坚持创新思维,才能推动发展、取得进步。“发展的观点” 是唯物辩证法的基本观点,马克思主义关于人类社会不断进步的发展观,不仅揭示了人类社会历史是不断向前发展的,而且说明了正是人类的创新思维和创造智慧推动了社会更好地发展。

        • ② 创新是一个民族进步的灵魂,是一个国家兴旺发达的不竭动力,也是中华民族最深沉的民族禀赋。这些年中华民族进步和贡献的取得,正是中华民族勇于创新和善于创新的结果。失去了创新思维,就会失去前进的动力,导致封闭和落后。

        改革开放以来,中国共产党高度重视思想解放和理论创新,开辟了中国特色社会主义道路,形成了中国特色社会主义理论体系,确立了中国特色社会主义制度,发展了中国特色社会主义文化,实现了中国人民从站起来到富起来、强起来的伟大飞跃。从某种意义上说,这些成就正是我们党坚持创新思维、大力推进理论创新和实践创新的结果。

      • (2)提高自己的创新思维能力的做法

        • ① 提高创新思维能力,必须坚决反对各种形而上学的思维方式,做到不唯书、不唯上,只唯实。提高创新思维能力,需要坚持和运用唯物辩证法,坚决反对形而上学。

          • a.要破除对 “本本” 的迷信;

          • b.要破除对 “经验” 的迷信;

          • c.要破除对 “权威” 的迷信。

        • ② 问题意识是提高创新思维能力的起点和动力源。

        增强问题意识、坚持问题导向,就是承认矛盾的普遍性客观性,就是善于把认识和化解矛盾作为打开工作局面的突破口,善于具体问题具体分析,透过现象看本质,抓主要矛盾和矛盾的主要方面,科学分析问题,深入研究问题。

        • ③ 善于继承才能善于创新。

          • a.创新思维不是凭空产生的,善于继承,才能将过去、现在和未来联系起来;

          • b.善于创新,才会有现在超越过去、未来超越现在的前进运动。

          • c.中国特色社会主义是科学社会主义理论逻辑和中国社会发展历史逻辑的辩证统一,是中国共产党人运用创新思维,在继承和发展中形成的创新成果。

        • ④ 在解放思想中锻造创新思维。

          • a.提高创新思维能力,就是要有敢为人先的锐气,打破惯性思维,以思想认识的新飞跃打开工作的新局面;

          • b.提高创新思维的过程,就是思想解放的过程。没有思想的大解放,就不可能有创新思维的大突破。

      # 第二章 实践与认识及其发展规律

      # 实践与认识的辩证关系及其规律

      • (1)毛泽东《实践论》的主要观点:
        毛泽东强调:“一个正确的认识,往往需要经过由物质到精神,由精神到物质,即由实践到认识,由认识到实践这样多次的反复,才能够完成。” 如此 “实践、认识、再实践、再认识,循环往复以至无穷,而实践和认识之每一循环的内容,都比较地进到了高一级的程度”。这就是认识辩证运动发展的基本过程,也是认识运动的总规律。认识是一个反复循环和无限发展的过程,是一个波浪式前进和螺旋式上升的过程。认识在实践基础上不断深化发展,并推动实践在认识指导下不断深入推进。这个过程既不是封闭式的循环,也不是直线式的发展,而是波浪式前进和螺旋式上升的。

      • (2)实践与认识的辩证关系

        • ① 实践是认识的基础,实践在认识活动中起决定性作用。主要表现在以下四个方面:

          • a.实践是认识的来源。认识的内容是在实践活动的基础上产生和发展的。只有在实践中实际改造和变革对象,人们才能形成对认识对象属性、本质、规律更为准确的认识,并以这种认识指导实践活动。

          • b.实践是认识发展的动力。认识的产生和发展源于实践的需要,也正是这种需要推动人类的科学发现和技术发明,推动人类的思想进步和理论创新。实践的需要是推动认识在深度和广度上不断发展之根本。此外,实践是认识发展的动力,还表现为实践为认识的发展提供了如经验资料、实验仪器和工具等的手段和条件。另外,实践改造了人的主观世界,锻炼和提高了人的认识能力。人们正是在实践的推动下,不断突破旧认识、旧思想,引起认识上的新飞跃,从而不断有新发现、有所前进。

          • c.实践是认识的目的。通过实践获得认识,其最终目的是为实践服务,指导实践,以满足生活和生产的需要。

          • d.实践是检验认识真理性的唯一标准。真理不是自封的。判断认识的真理性,不是依主观感觉,而是依客观上社会实践的结果。

        • ② 认识反作用于实践。

          • a.人的实践活动是受人的意识支配的,实践的这种本质特性决定着它不能离开认识的指导。

          • b.认识活动及其成果有相对独立性,遵循其特有的活动方式和发展规律,它一经形成,便能反作用于实践。

          • c.认识对实践的指导作用表现在:正确的认识能够推动实践的发展,而错误的认识则会对实践起阻碍作用。

      # 真理、真理的绝对性和相对性及其辩证关系、真理与谬误(自学);

      • (1)真理是绝对的又是相对的原因
        真理是一个过程。就真理的发展过程以及人们对它的认识和掌握程度来说,真理既具有绝对性,又具有相对性,它们是同一客观真理的两
        种属性,这是真理问题上的辩证法。任何真理都是绝对性和相对性的统一,二者相互联系、不可分割。两者关系具体如下:

        • ①真理的绝对性

          真理的绝对性是指真理主客观统一的确定性和发展的无限性。它有两个方面的含义:

          • a.任何真理都标志着主观与客观之间的符合,都包含着不依赖于人和人的意识的客观内容,都同谬误有原则的界限。这一点是绝对的、无条件的。在这个意义上,承认了真理的客观性也就是承认了真理的绝对性。

          • b.人类认识按其本性来说,能够正确认识无限发展着的物质世界,认识每前进一步,都是对无限发展着的物质世界的接近,这一点也是绝对的、无条件的。在这个意义上,承认了世界的可知性,承认人能够获得关于无限发展着的物质世界的正确认识,也就是承认了真理的绝对性。

        • ②真理的相对性

          真理的相对性是指人们在一定条件下对客观事物及其本质和发展规律的正确认识总是有限度的、不完善的。它具有两个方面的含义:

          • a.从客观世界的整体来看,任何真理都只是对客观世界的某一阶段、某一部分的正确认识,人类已经达到的认识的广度总是有限度的,因而,认识有待扩展。

          • b.就特定事物而言,任何真理都只是对客观对象一定方面、一定层次和一定程度的正确认识,认识反映事物的深度是有限度的,或是近似性的。因而,认识有待深化。任何真理都只能是主观对客观事物近似正确即相对正确的反映。

        • ③真理的绝对性和相对性的关系

          真理的绝对性和相对性是辩证统一的,具体如下:

          • a.二者相互依存。即人们对于客观事物及其本质和规律的每一个正确认识,都是在一定范围内、一定程度上、一定条件下的认识,因而是相对的和有局限的;但是,在这一定范围内、一定程度上、一定条件下,它也是对客观对象的正确反映,因而它也是无条件的、绝对的。

          • b.二者相互包含。一是真理的绝对性寓于真理的相对性之中。任何真理所包含的客观内容都只能是人们在特定历史条件下所把握到的,都只是对客观世界及其事物的一定范围、一定程度的正确反映。二是真理的相对性包含并表现着真理的绝对性。任何真理都与谬误有本质的区别,标志着人们在一定范围内和一定层次上达到对于无限发展着的物质世界的正确认识,包含着确定的客观内容。毛泽东把真理的绝对性与相对性的关系比喻为长河与水滴的关系,“马克思主义者承认,在绝对的总的宇宙发展过程中,各个具体过程的发展都是相对的,因而在绝对真理的长河中,人们对于在各个一定发展阶段上的具体过程的认识只具有相对的真理性。无数相对的真理之总和,就是绝对的真理”。

          • c.相对性向绝对性转化。真理永远处在由相对向绝对的转化和发展中,是从真理的相对性走向绝对性、接近绝对性的过程。任何真理性的认识都是由真理的相对性向绝对性转化过程中的一个环节,这是真理发展的规律。真理的绝对性与相对性根源于人认识世界的能力的无限性与有限性、绝对性与相对性的矛盾。人类的思维按其本性、可能和历史的终极目的来说,是能够认识无限发展着的物质世界的,思维是无限的和绝对的。但是,具体到每一个人乃至每一代人,由于受到客观事物及其本质的显露程度、社会历史的实践水平、主观的条件以及生命的有限性等各方面的限制,其思维也是有限的和相对的。人的认识能力、思维能力是无限性与有限性、绝对性与相对性的对立统一,作为人的正确认识成果的真理,也必然是绝对性和相对性的对立统一。

      • (2)真理的绝对性和相对性相统一对马克思主义的重要意义

        • ① 割裂真理绝对性与相对性之间的辩证关系,就会走向形而上学的真理观,即绝对主义和相对主义。绝对主义在实际工作中表现为教条主义、思想僵化,把马克思主义当作一成不变的公式。相对主义否认真理内容的客观性,把真理的相对性歪曲成了主观随意性,由此陷入主观真理论,导致不可知论和诡辩论。

        • ② 马克思主义是客观真理,是绝对性和相对性的统一

          马克思主义正确地反映了人类社会发展的规律,是经过长期革命、建设和改革的实践所证明了的真理,因而具有绝对性的一面。但是,马克思主义并没有穷尽对一切事物及其规律的认识,仍然需要随着社会实践的发展而发展,因而又具有相对性的一面。正因为马克思主义具有绝对性,所以我们必须坚持以马克思主义为指导思想;也因为它具有相对性,所以我们必须在实践中丰富和发展马克思主义。既坚持又发展,才是对待马克思主义的正确态度。

      # 真理和价值的辩证关系。

      • (1)真理尺度和价值尺度的含义

        • ① 人们的实践活动总是受着真理尺度和价值尺度的制约。

        • ② 实践的真理尺度是指在实践中人们必须遵循正确反映客观事物本质和规律的真理。只有按照真理办事,才能在实践中取得成功。

        • ③ 实践的价值尺度是指在实践中人们都是按照自己的尺度和需要去认识世界和改造世界。这一尺度体现了人的活动的目的性。

      • (2)真理尺度与价值尺度的关系

        • ① 任何实践活动都要受到这两种尺度的共同制约,任何活动都是合规律性和合目的性的统一。

        • ② 真理与价值或真理尺度与价值尺度之间是紧密联系、不可分割的。一方面,价值尺度必须以真理为前提。脱离了真理尺度,价值尺度就偏离了正确的轨道。另一方面,人类满足自身需要的内在尺度,推动新的真理不断被发现。脱离了价值尺度,真理就缺失了主体意义。

      • (3)帮助和启示
        因为实践具有具体性和历史性,真理尺度与价值尺度的统一也是具体的和历史的,二者的统一会随着实践的发展而不断发展到更高级的程度,真理由相对走向绝对,人的需要和利益也日益呈现出多元化特征。真理尺度与价值尺度是否达到了具体的、历史的统一,必须通过实践来验证。新时代中国特色社会主义的实践充分体现了真理尺度与价值尺度的辩证统一。正如习近平所指出的:“中国共产党人的理想信念,建立在马克思主义科学真理的基础之上,建立在马克思主义揭示的人类社会发展规律的基础之上,建立在为最广大人民谋利益的崇高价值的基础之上。我们坚定,是因为我们追求的是真理。我们坚定,是因为我们遵循的是规律。我们坚定,是因为我们代表的是最广大人民的根本利益。”

      # 第三章 人类社会及其发展规律

      # 为什么说物质资料的生产方式是社会发展的决定性力量?

      答:物质资料的生产方式是社会发展的决定性力量,主要是基于以下原因:

      • (1)物质资料的生产方式是人类其他一切活动的首要前提,是人类社会赖以存在和发展的物质基础。人们为了能够创造历史,必须能够生活,为了生活,首先就需要衣、食、住及其他东西。因此,人类历史的第一个历史活动就是生产满足这些需要的物质资料本身。这是一个简单的事实和起码的真理。发现并承认这一真理,是历史观的一个伟大革命。

      • (2)物质资料的生产方式决定着社会的结构、性质和面貌。有什么样的生产方式便有什么样的社会形态。正如马克思所说:“手推磨产生的是封建主为首的社会,蒸汽磨产生的是工业资本家为首的社会。”

      • (3)生产方式的发展变化决定着社会历史的发展变化和形态更替。在物质资料的生产方式中,生产力是最活跃、最能动的因素,它总是要向前发展的,而生产关系则是相对稳定的。随着生产力的发展,原有的生产关系便由生产力发展的形式变成生产力发展的桎梏,由适合生产力的发展变成阻碍生产力的发展。只有变革生产关系,才能解放和发展生产力。随着生产关系(即经济基础)的变革,全部的、庞大的上层建筑也会或迟或早地发展变革,从而引起社会形态的更替。

      • 总之,人类社会的历史就是物质资料生产的历史,是劳动发展史。马克思正是从劳动发展史中找到了理解人类社会发展史的 “钥匙”。

      # 运用社会基本矛盾运动的原理分析深化改革的客观依据与重要意义。答:

      • 与深化改革最相近的是生产力与生产关系的矛盾运动。

        • 社会基本矛盾运动包括

          • 生产力与生产关系之间的矛盾

          • 经济基础与上层建筑之间的矛盾

        • 它们是贯穿社会发展过程始终,规定社会发展过程的基本性质和基本趋势,并对社会历史发展起根本推动作用的矛盾。

        • 因此,社会基本矛盾的解决对历史发展具有重要作用。

        • 而要解决社会基本矛盾,改革是一种重要的方式和途径。

      • (1)客观依据
        社会基本矛盾,特别是生产力与生产关系的矛盾在历史发展中起根本的推动作用,为了推动社会发展,必须解决好社会基本矛盾,改革就是其中一种重要方式。深化改革的客观依据就在于社会基本矛盾在历史发展过程中的重要作用,主要表现在:

        • ① 生产力是社会基本矛盾运动中最基本的动力因素,是人类社会发展和进步的最终决定力量。

        • ② 社会基本矛盾特别是生产力和生产关系的矛盾,是 “一切历史冲突的根源”,决定着社会中其他矛盾的存在和发展。

        • ③ 社会基本矛盾有不同的表现形式和解决方式,并从根本上影响和促进社会形态的变化和发展。

        • 因此,当两者不能够及时适应时,就需要改革来调整两者的关系,因而改革也是必不可少的。

      • (2)重要意义
        改革的成功,是对社会基本矛盾的某一方面或某种程度的解决,从而促进社会发展。社会生活的基础是物质生产,推动社会进步的最活跃、最革命的要素是生产力,社会主义的根本任务是解放和发展社会生产力。全面深化改革中,要把坚持发展作为解决我国所有问题的关键,推动我国社会生产力不断发展前进,进而推动人的全面发展和社会的全面进步。同时,还应通过改革,使生产关系适应生产力的发展、上层建筑适应经济基础的发展,从而顺利解决社会基本矛盾,促进社会的进一步发展。

      # 结合我国科学技术的重大成就,如高铁、大飞机以及 “天宫”“蛟龙”“天眼”“悟空”“墨子” 等,谈谈对科学技术在社会发展中的作用的认识。答:

      • (1)科学技术是先进生产力的重要标志,对于推动社会发展有非常重要的作用。科技革命是推动经济和社会发展的强大杠杆,近代以来,科技革命极大地推动了社会历史的进步,其主要是通过促进人们的生产方式、生活方式和思维方式的深刻变化来推动社会发展:

        • ① 对生产方式产生了深刻影响:

          • a.改变了社会生产力的构成要素。科技发展使生产自动化程度提高,大大地改变了体力劳动与脑力劳动的比例,使劳动力结构向着智能化趋势发展。

          • b.改变了人们的劳动形式。科技发展使人们的劳动方式经历了由机械自动化走向智能自动化、由局部自动化走向大系统管理和控制自动化的根本性变革。

          • c.改变了社会经济结构,特别是导致产业结构发生变革。科技的发展使第三产业在国民经济中所占的比重日益提高。

        • ② 对生活方式产生了巨大影响:

          • a.现代科技革命把人们带入了信息时代,要求人们不断更新和充实知识,以适应时代发展的需要。

          • b.现代信息技术为人们提供了处理、存储和传递信息的手段,给学习、工作带来了极大便利。

          • c.现代化的交通、通信等手段,为人们的交往提供了方便。

          • d.劳动生产率的提高,使人们自由支配的闲暇时间增多,为人的自由而全面的发展创造了更多条件。

        • ③促进了思维方式的变革。主要表现在新的科学理论和技术手段通过影响思维主体、思维客体和思维工具,引起了思维方式的变革正确把握科学技术的社会作用科学技术社会作用的两重性:

          • a.科学技术能够通过促进经济和社会发展造福于人类,科学技术的作用既受到一定客观条件的影响,也受到一定主观条件的影响。

          • b.科学技术的发展标志着人类改造自然能力的增强,意味着人们能够创造出更多的物质财富,对社会发展有巨大的推动作用。

      • (2)科学技术是社会发展的重要动力。近代中国落后于西方国家主要原因是科学技术水平低。习近平总书记提出 “科技兴则民族兴,科技强则国家强”。

      • (3)新时期我国的科学技术发展取得重大成就:2016 年 6 月 20 日,使用中国自主芯片制造的超级计算机 “神威 - 太湖之光” 登上全球超级计算机 500 强榜首。2016 年 8 月 16 日,长征二号运载火箭成功将世界首颗量子科学实验卫星 “墨子号” 发射升空。2016 年 8 月 25 日,我国研发的自主遥控水下机器人 “海斗” 号潜深达到 10767 米,首次进入万米时代。2016 年 9 月 15 日,“天宫二号” 顺利升空。2016 年 9 月 25 日,被誉为 “中国天眼” 的 FAST 射电望远镜落成启用。
        这些科学技术的发展不仅提高了我国的综合国力和国际地位,而且对我们的生产生活产生巨大影响。比如我国研制的全球超级计算机将对我们所进行的科学实验起到促进作用;“墨子号” 的发射升空将促进我国科研事业的发展,从而改善普通群众的生活。

      # 请结合人民群众是历史创造者的原理,谈谈对坚持以人民为中心重要性的认识。答:

      • (1)人民群众的含义
        人民群众是社会历史的主体,是历史的创造者,这是马克思主义最基本的观点之一。人民群众是一个历史范畴。从质上看,人民群众是指一切对社会历史发展起推动作用的人;从量上看,人民群众是指社会人口中的绝大多数。在不同的历史时期,人民群众有着不同的内容,包含着不同的阶级、阶层和集团,但其中最稳定的主体部分始终是从事物质资料生产的劳动群众。

      • (2)对坚持以人民为中心重要性的认识
        在实际生活中,我们必须坚持以人民为中心的思想,这是因为人民群众在创造历史过程中的决定作用。

        • ①人民群众是社会物质财富的创造者。人类社会赖以存在和发展的基础是物质资料的生产方式。人民群众创造的社会物质财富,是社会得以存在和发展的物质保障。人民群众的这一创造作用同生产力是社会发展的最终决定力量这一原理具有逻辑上的一致性,因为作为人民群众主体的劳动群众,乃是生产力的体现者。

        • ②人民群众是社会精神财富的创造者。首先,人民群众的社会实践活动是科学、文化、艺术的唯一源泉;其次,劳动群众为人们从事精神文化活动提供了一切物质手段和物质条件;再次,劳动知识分子在精神财富的创造过程中起着极其重要的作用。

        • ③人民群众是社会变革的决定力量。人民群众在创造社会财富的同时,也创造并改造着社会关系。人民群众既是社会革命的决定力量,又是社会改革的决定力量。社会变革、社会改革根源于社会基本矛盾,但生产关系一定要适合生产力发展状况的规律、上层建筑一定要适合经济基础发展状况的规律不可能自发地起作用,必须通过人民群众这一社会变革的主体才能实现其作用。

      # 习近平指出:“我们既要绿水青山,也要金山银山。宁要绿水青山,不要金山银山,而且绿水青山就是金山银山。” 请结合自然地理环境在社会生存和发展中的作用,谈谈应怎样认识和处理经济发展与环境保护的关系。答:

      • 自然地理环境是人类赖以存在和发展的必要前提,是社会存在的组成部分。没有自然界,没有感性的外部世界,工人什么也不能创造。没有地理环境,就不会有人和人类社会。可以看出,自然环境对人类的生存发展具有重要意义,因此,我们在发展经济的同时,不能忽略自然环境,不能以牺牲环境为代价来取得
        经济发展。我们必须坚持可持续的绿色发展理念,在发展经济的同时保护环境,“既要金山银山,也要绿水青山”。为此,我们必须做到以下四点:

      • (1)强化环境意识,树立生态理念要树立 “绿水青山就是金山银山” 的环境价值理念,实现以环境换取经济增长向以环境优化经济增长转变。绿水青山意味着优美的人居环境、清洁的水源和清新的空气,可以大大减少因环境污染和生态破坏造成的直接和间接损失,大大减轻因污染治理和生态恢复所需付出的巨大代价,大大缓解生态环境问题引发的各种社会矛盾,有利于维护社会稳定。

      • (2)把环境保护作为决策的重要环节,从源头落实环保基本国策
        环保从源头抓起,最重要的是各级政府、各级管理部门、各级领导要依法承担起改善环境质量和环境管理的责任,牢牢树立科学发展观念,转变把环境因素置于决策之外的决策模式,实行环境与发展综合决策。同时,必须树立正确的政绩观。

      • (3)把环境保护作为生产和消费过程中的重要环节,大力发展循环经济解决经济高速增长与生态环境日益恶化这一矛盾的根本出路是转变经济增长方式,用绿色核算体系来重新审视和把握经济发展的途径,走新型工业化道路,积极推动发展循环经济,实现经济与环境 “双赢”。

      • (4)把环境保护作为改善人居环境的重要环节,集中精力解决突出的环境问题
        改善人居环境不仅仅是改善市民的住房条件,要充分发挥环境保护的文明发展与协调稳定功能,以人为本,下决心解决老百姓广泛关注的影响环境质量和日常环境生活质量的突出问题。强化饮用水源的环保严管措施,保证饮用水安全。采取有效措施保护水源地,确保生态环境改善。大力改善区域环境,创建绿色环保文明社区,提高人民生活质量。

      • (5)正确认识和利用科学技术
        科学技术是把双刃剑,既能通过促进经济和社会发展造福于人类,也能在一定条件下对人类的生存和发展带来消极后果。

      # 第四章 资本主义的本质及规律

      # 为什么说 “资本来到世间,从头到脚,每个毛孔都滴着血和肮脏的东西”?答:

      • (1)资本主义的产生与发展
        资本主义于 14 世纪末 15 世纪初开始在地中海沿岸的一些城市出现,一是从小商品经济分化出来,二是从商人和高利贷者转化而来。资本主义生产关系产生之后,其成长是一个缓慢的过程。新兴资产阶级和资产阶级化的贵族用暴力剥夺小生产者从而加速形成资本主义生产方式。

      • (2)资本的原始积累
        资本原始积累,是生产者与生产资料相分离,货币资本迅速集中于少数人手中的历史过程。它主要是通过两个途径进行的:

        • ① 用暴力手段剥夺农民的土地,是资本原始积累过程的基础。资本家和封建贵族还通过 “掠夺教会地产,欺骗性地出让国有土地,盗窃公有地,用剥夺方法、用残暴的恐怖手段把封建财产和克兰财产转化为现代私有财产”,建立了资本主义的土地私有制,从而奠定了资本主义私有财产制度的基础。

        • ② 利用国家政权的力量进行残酷的殖民掠夺。新兴资产阶级在国外进行疯狂掠夺的同时,还通过国债制度、课税制度和保护关税制度等,加强对国内人民的剥削,在少数人手中积累起了大量的资本。这些极大地促进了资本主义的发展,缩短了封建生产方式转变为资本主义生产方式的历史过程。

      资本原始积累的事实表明,资产阶级的发家史就是一部罪恶的掠夺史。正如马克思所说:“资本来到世间,从头到脚,每个毛孔都滴着血和肮脏的东西。”

      # 如何理解商品二因素的矛盾来自劳动二重性的矛盾,归根结底来源于私人劳动和社会劳动之间的矛盾?答:

      • (1)商品经济存在着一系列的矛盾,其中私人劳动和社会劳动的矛盾是商品经济的基本矛盾,它决定着劳动二重性的矛盾和商品二因素的矛盾。
        商品经济存在的一系列的矛盾包括:

        • 商品的使用价值和价值的矛盾(即商品二因素的矛盾)

        • 具体劳动和抽象劳动的矛盾(即劳动二重性的矛盾)

        • 私人劳动和社会劳动的矛盾

      • (2)在私有制商品经济条件下,商品二因素的矛盾来源于生产商品的劳动二重性的矛盾。在商品交换过程中,生产商品使用价值的具体劳动不能直接进行量的比较,只有将具体劳动还原为抽象劳动,即从具体劳动中抽象出无差别的人类劳动,才可以进行量的比较。

      • (3)具体劳动能否还原为抽象劳动,取决于私人劳动和社会劳动能否实现一。一切商品,只有换成货币,商品生产者的私人劳动才会转化为社会劳动,具体劳动才会还原为抽象劳动,商品的使用价值和价值的矛盾才能得到解决。商品生产者的私人劳动生产的产品如果与社会的需求不相适应,该私人劳动就不被承认为社会劳动,其作为具体劳动的有用性质也就不被社会所承认,从而不能还原为抽象劳动,这意味着商品的价值不能实现,商品的使用价值和价值之间的矛盾没有解决。反过来,如果私人劳动生产的产品为社会所接受,则该私人劳动就被承认并转化为社会劳动,其作为具体劳动的有用性质就被社会所承认,从而可以还原为抽象劳动,这意味着商品的价值得到了实现,商品的使用价值和价值之间的矛盾得到了解决。

      # 如何理解 “资本是带来剩余价值的价值”?

      答:资本是带来剩余价值的价值,可以作以下理解:

      • (1)劳动力商品在使用价值上有一个很大的特点,其使用价值是价值的源泉,消费过程中能够创造新的价值,并且这个新的价值超过了劳动力本身的价值。由于该特点,货币所有者购买到劳动力以后,在消费过程中,不仅能够收回他在购买这种商品时支付的价值,还能得到增值的价值即剩余价值。

      • (2)资本是自行增殖的价值,是能够带来剩余价值的价值。在现实生活中,资本总是表现为一定的物,例如货币、机器设备、商品等,但这些物本身并不是资本,只有在一定的社会关系下,这些物被用来从事以获得剩余价值为目的的生产活动,也就是成为带来剩余价值的手段时,它才成为资本。所以马克思强调指出,资本的本质不是物,而是在物的外壳掩盖下的一种社会生产关系,即资本主义剥削关系。

      • (3)资本主义条件下,资本家剥削剩余价值具有隐蔽性。资本在运动过程中使用了例如货币、生产资料、商品等物质形态,资本家购买劳动力依照等价交换原则进行,于是在人们的观念上容易形成一种错觉,好像这些物天然就是资本,资本变成一种神秘的东西,似乎劳动的一切社会生产力并非劳动本身所有,而为资本所有,资本本身具有一种能使价值增殖的魔力,这就是资本拜物教。马克思指出:“资本家用货币购买的是雇佣工人的劳动力商品,劳动力商品的使用价值是劳动,劳动本身并不是商品,劳动力商品的使用价值具有成为价值源泉的特殊属性,它的实际使用本身就是劳动的物化,从而创造了剩余价值,使货币转化为资本。” 马克思的分析揭露了资本拜物教产生的实质,为科学认识资本主义经济制度的本质提供了理论武器。

      # 运用历史和现实的事实说明经济危机是资本主义基本矛盾的集中体现。答:

      • 资本主义发展到一定阶段,就会出现生产的相对过剩,这是经济危机的基本特征。经济危机发生时,大量商品积压,企业减产甚至停工,伴随着许多金融机构倒闭,整个社会经济生活一片混乱。对该论述理解如下:

      • (1)在资本主义经济的发展过程中,经济危机是周期性地重演的,危机与危机之间的间隔表现了一定的规律性。第二次世界大战后,各主要资本主义国家发生了次数不等的经济危机。在战后各国的历次危机中,有的是属于部分国家同期发生的,有的是普遍性的资本主义世界经济危机。属于世界性经济危机的有三次,即 1957—1958 年、1973—1975 年和 1980—1982 年的经济危机,因为这三次危机表现了明显的国际同期性。
        第二次世界大战结束以来,随着国家垄断资本主义的形成和发展,虽然市场机制依然在资源配置过程中发挥着基础性调节作用,但它已不是唯一的经济调节机制了。调节机制发生了一些明显的变化,其主要表现是资产阶级国家对经济的干预不断加强。国家已经承担起了提供财产保护、增强国家竞争力、实现经济增长和充分就业、保持经济稳定、提高社会福利水平以及维护竞争秩序等重要职能。它与市场机制相辅相成,共同推动着资本主义经济的运行和发展。

      • (2)生产过剩不是生产的商品绝对超过了人们的物质生活需要,而是一种相对过剩,即生产的商品相对于人民群众有支付能力的需求来说是过剩了。生产相对过剩是资本主义经济危机的实质。经济危机的抽象的一般的可能性,是由货币作为流通手段和支付手段引起的。以货币为媒介的商品买卖在时间上分为两个相互独立的行为。如果一些商品生产者在出卖自己的商品后不接着购买他人生产的商品,就会有另一些商品生产者的商品卖不出去。同时,在商品买卖有更多的部分采取赊购赊销的情况下,若某些债务人在债务到期时不能支付,就会使整个信用关系体系遭到破坏。但是,这仅仅是危机在形式上的可能性。

      • (3)资本主义经济危机是资本主义基本矛盾存在、激化和集中暴露的证明。这一基本矛盾具体表现在两个方面:①生产无限扩大的趋势与劳动人民现有支付能力和需求相对缩小的矛盾;②个别企业内部生产的有组织性和整个社会生产的无政府状态之间的矛盾。正如马克思所指出的:“一切现实的危机的最终原因始终是:群众贫穷和群众的消费受到限制,而与此相对立,资本主义生产却竭力发展生产力,好像只有社会的绝对的消费能力才是生产力发展的界限。”

      • (4)在经济调节机制变化的同时,经济危机形态也发生了变化,表现为:危机对社会经济运行的干扰减轻,破坏性减弱,生产下降的幅度减小,失业率有所降低,企业破产的数量减少;危机周期的长度缩短;经济危机的四个阶段(即危机阶段、萧条阶段、复苏阶段和高涨阶段)之间的差别有所减弱,各阶段的交替过程已不如过去那样明显;金融危机对整个经济危机的影响加强。随着调节机制的变化,资本主义经济危机的形态尽管发生了这样或那样的变化,但是由于资本主义的基本矛盾所决定,资产阶级不论采取什么样的调节措施和手段,经济危机是克服不了的。经济危机是资本主义基本矛盾的集中体现。

      # 有人认为,资本主义民主是囿于 “钱主” 的民主,迷于 “游戏” 的民主,止于 “选举” 的民主。你如何看待这种说法,为什么?

      • 答:资本主义民主存在着自身无法克服的 “软肋” 和 “硬伤”,这是因为资本主义政治制度为资产阶级专政服务,其本质上是资产阶级进行政治统治和社会管理的手段和方式,不可避免地有其阶级和历史的局限性。

      • (1)资本主义的民主是金钱操纵下的民主,是资产阶级精英统治下的民主。民主是具体的、相对的,而不是抽象的、绝对的。资本主义社会的主导逻辑是资本逻辑,不仅经济领域服从这一逻辑的统治,民主政治领域同样服从这一逻辑的主宰。西式民主的实质是 “钱主”,金钱是西式民主的 “母乳”,无论是政党还是政客都在母乳的滋养下成长,政客与财团之间结成生死与共的命运共同体,也常被金钱、媒体、黑势力、财团等影响和操纵。在实际的选举过程中,为得到选民的支持和认可,参选者往往需要支付巨额的竞选活动经费,这笔经费是普通公民根本没有能力支付的,只有依靠大财团才能支付得起。资本主义政治制度中的选举只能是有钱人的游戏,是资本玩弄民意的过程。号称民主典范的美国,其总统和参众两院议员的选举在现实中已经沦为烧钱的游戏,一人一票异化为 “一元一票”,筹集竞选经费的能力早已成为问鼎白宫的风向标,金钱是 “打开权力之门的金钥匙”。历史学家作过统计,从 1860 年以来的历次美国总统大选中,竞选经费占优的一方几乎都获得了胜利。“钱主” 的后果就是 “钱权联姻”。在西方,钱与权具有天然的近亲关系,“钱能生权,权又能生更多的钱”“政治献金” 与 “政治分赃” 总是如影随形。美国民主的实质就是 “1% 所有,1% 统治,1% 享用”。

      • (2)资本主义的民主是迷于 “游戏” 的民主。资本家和富人拥有特权,这对劳动者和穷人严重不平等,资产阶级法律将这种不平等合法化。民主的游戏化、娱乐化,这是西方的又一杰作。西方将民主变成了游戏,选民以娱乐的心态对待民主。西式民主在游戏中沉沦,选民在娱乐中迷茫。在这场游戏中,赢的永远是政客,输的始终是选民。

      • (3)资本主义的民主是止于 “选举” 的民主。民主不等于选举,民主和选举不能等量齐观、等同视之。真正的民主体制应该包括民主选举、民主决策、民主管理、民主监督等各个环节,覆盖起点、过程、结果等各个阶段。资本主义国家的多党制仍是资产阶级选择自己的国家管理者,以实现其内部利益平衡的政治机制。然而,现代资本主义民主却大都沉迷于 “选举” 这一初始环节,“人民主权” 被置换成 “人民的选举权”,民主被简化为选举,选举进一步简化为投票,而对于决策是否民主、管理是否民主、监督是否民主等方面却并不感兴趣。止于 “选
        举” 的民主只顾开头,不顾过程和结尾。这种民主即便有始却不一定有终,即便能善始却未必能善终。其实,民主是基于文化传统和现实国情的长期实践,采取何种民主形式必须与各个国家的历史文化传统、社会状况、人口结构、宗教信仰、民族构成、经济发展水平、法制意识、国民素质等因素相结合,否则很难有效运转。

      # 第五章 资本主义的发展及其趋势

      # 垄断是怎样产生的?为什么说垄断并没有消除竞争?答:

      • (1)垄断产生的原因

        • ① 当生产集中发展到相当高的程度,极少数企业就会联合起来,操纵和控制本部门的生产和销售,实行垄断,以获得高额利润。

        • ② 企业规模巨大,形成对竞争的限制,也会产生垄断。

        • ③ 激烈的竞争给竞争各方带来的损失越来越严重,为了避免两败俱伤,企业之间会达成妥协,联合起来,实行垄断垄断组织垄断是通过一定的垄断组织形式实现的。垄断组织是指在一个或几个经济部门中,占据垄断地位的大企业联合。垄断组织的形式多种多样,如初级的短期价格协定。但本质上都是通过联合达到独占和瓜分商品生产和销售市场,操纵垄断价格,以攫取高额垄断利润。

      • (2)垄断没有消除竞争的原因

        • ① 垄断没有消除产生竞争的经济根源。

        • ② 垄断必须通过竞争来维持。

        • ③ 社会生产是复杂多样的,任何垄断组织都不可能把包罗万象的社会生产都包下来。

      • 为什么说国家垄断资本主义体现了资本主义生产关系的部分质变?
        答:国家垄断资本主义是垄断资本和国家政权密切结合的垄断资本主义。国家垄断资本主义的产生,标志着资本主义发展进入了新的阶段。国家垄断资本主义体现了资本主义生产关系的部分质变的原因是:

        • (1)国家垄断资本主义是垄断资本主义的新发展,它对资本主义经济的发展产生了积极的作用。

          • ① 国家垄断资本主义的出现在一定程度上有利于社会生产力的发展,资本主义国家的政府通过公共投资和支出,开办大型新兴工业企业,部分克服了社会化大生产与私人垄断资本之间的矛盾。
          • ② 私人垄断统治扩大了资本主义生产与消费的矛盾,资产阶级国家采取一定手段干预国民经济,减轻经济危机的程度,缓和了社会各阶级的利益矛盾,有利于社会稳定,促进经济较为协调地发展。
          • ③ 宏观调控的发展,使国家对经济的干预和调节与市场机制日益有机结合起来,自由放任的市场经济逐渐演变成为由国家干预的现代市场经济,一定程度上弥补了自由市场经济的缺陷,对于国家的经济运行和社会发展产生了积极作用。
          • ④ 资产阶级国家通过税收和收入再分配手段,提高了劳动人民的生活水平。
        • (2)国家垄断资本主义的出现并没有根本改变垄断资本主义的性质。

          • ①国家垄断资本主义仍然是以资本主义私有制为基础,维护资产阶级利益和资本主义制度。
          • ②国家垄断资本主义没有从根本上消除资本主义的基本矛盾,它代表的是资产阶级的总利益。

      # 如何认识和把握经济全球化及其影响?

      • 答:经济全球化是指在生产不断发展、科技加速进步、社会分工和国际分工不断深化、生产的社会化和国际化程度不断提高的情况下,世界各国、各地区的经济活动越来越超出某一国家和地区的范围而相互联系、相互依赖的过程。

      • (1)经济全球化的表现

        • ① 国际分工进一步深化。

        • ② 贸易全球化。

        • ③ 金融全球化。

        • ④ 企业生产经营全球化。

      • (2)经济全球化的动因从本质上讲,经济全球化是生产力发展和社会化大生产的必然要求。导致经济全球化迅猛发展的因素主要有三点:

        • ① 科学技术的进步和生产力的发展提供了坚实的物质基础和根本的推动力。

        • ② 跨国公司的发展提供了适宜的企业组织形式。

        • ③ 各国经济体制的变革是经济全球化的体制保障。

      • (3)经济全球化的影响

        • ① 积极影响

          • a.社会分工得以在更大的范围内进行,资金、技术等生产要素可以在国际社会流动和优化配置,由此带来巨大的分工利益,推动世界生产力的发展。

          • b.体现了社会化生产的要求,不仅发达国家从中受益,一些发展中国家在参与经济全球化进程中也得到了快速发展。全球化为发展中国家提供先进技术和管理经验、就业机会,推动发展中国家国际贸易和跨国公司发展。

        • ② 消极影响

          • a.发达国家与发展中国家在经济全球化过程中的地位和收益不平等、不平衡。

          • b.加剧了发展中国家资源短缺和环境污染恶化。

          • c.一定程度上增加经济风险。

        • ③ 正确看待经济全球化

          • a.“把困扰世界的问题简单归咎于经济全球化,既不符合事实,也无助于问题解决。” 国际金融危机不是经济全球化发展的必然产物,而是金融资本过度逐利、金融监管严重缺失的结果。

          • b.经济全球化不是一部分国家的独角戏,而是世界各国、各民族共同实现发展的大舞台。

          • c.面对不同国家在生产方式、发展水平、文化背景等方面的差异,要以共同构建人类命运共同体的理念引领经济全球化。

      # 近年来资本主义社会发生了哪些新变化?试分析其原因及影响。答:

      • (1)资本主义社会的新变化

        • ① 生产资料所有制的变化:

          • a.国家资本所有制是指生产资料由国家占有并服务于垄断资本的所有制形式。国家资本所有制主要存在于基础设施和公共事业部门,所以对整个社会经济的发展有着重要的影响。但就其性质而言,仍然是资本主义形式,体现着总资本家剥削雇佣劳动者的关系。

          • b.法人资本所有制是资本主义生产资料所有制发展的新形式,是法人股东化的产物。法人资本所有制有两种形式:一种是企业法人资本所有制,另一种是机构法人资本所有制,但其在性质上是一种基于资本雇佣劳动的垄断资本。

        • ② 集体所有制劳资关系和分配关系的变化

          • a.职工参与决策。这一制度旨在协调劳资关系,缓和阶级矛盾。

          • b.终身雇佣。目的是增强工人对企业的归属意识,从而更加自觉地服从资本家的统治。

          • c.职工持股。旨在通过使职工持有一部分本公司的股份来调动工人的生产积极性,使工人产生归属感,在生产中努力提高劳动生产率,增加剩余价值生产。

          • d.普及化、全民化的社会福利制度。在一定程度上满足劳动者的安全和保障需求,保证劳动者维持最低生活水平,改善劳动者的社会状况。

        • ③ 社会阶层和阶级结构的变化

          • a.资本家的地位和作用已经发生很大变化。

          • b.高级职业经理成为大公司经营活动的实际控制者。

          • c.知识型和服务型劳动者的数量不断增加,劳动方式发生了新变化。

        • ④ 经济调节机制的变化 a.去工业化和产业空心化日趋严重,产业竞争力下降。

          • b.经济高度金融化,虚拟经济与实体经济严重脱节。

          • c.财政严重债务化,债务危机频繁爆发。

          • d.两极分化和社会对立加剧。

          • e.经济增长乏力,发展活力不足,周期性危机与结构性危机交织在一起。

          • f.金融危机频发,全球经济屡受打击。

        • ⑤ 政治制度的变化

          • a.政治制度出现多元化的趋势,公民权利有所扩大。

          • b.重视并加强法制建设。

          • c.改良主义政党在政治舞台上的影响日益扩大。

      • (2)资本主义社会的新变化的原因

        • ① 科学技术革命和生产力的发展,是当代资本主义发生新变化的根本推动力量。

        • ② 工人阶级争取自身权利和利益的斗争,是推动当代资本主义发生新变化的重要力量。

        • ③ 社会主义制度初步显示的优越性对当代资本主义产生了重要影响。

        • ④ 主张改良主义的政党对资本主义制度的改革,也对当代资本主义新变化发挥了重要作用。

      • (3)资本主义社会的新变化的影响

        • ① 当代资本主义发生的变化从根本上说是人类社会发展一般规律和资本主义经济规律作用的结果。

        • ② 当代资本主义发生的变化是在资本主义制度基本框架内的变化,并不意味着资本主义生产关系的根本性质发生了变化。

        • ③ 没有改变其为资产阶级利益服务,仍然是服从于资产阶级进行统治和压迫需要的政治工具的本质属性,没有改变马克思主义关于资本主义的基本论断的科学性。

      # 如何理解资本主义的历史地位及其为社会主义所代替的历史必然性?

      • 答:从人类社会发展的长河看,社会主义取代资本主义,即社会主义公有制取代资本主义私有制,这是历史发展的基本趋势。

      • (1)资本主义的内在矛盾决定了资本主义必然被社会主义所代替

        • ① 资本主义基本矛盾 “包含着现代的一切冲突的萌芽”。

          • a.资本主义基本矛盾表现在阶级关系上,是无产阶级和资产阶级的对立。

          • b.资本主义基本矛盾表现在经济关系上,是个别工厂中生产的组织性和整个社会中生产的无政府状态之间的对立。

          • c.资本主义经济危机的爆发正是这个基本矛盾发展的结果。

        • ② 资本积累推动资本主义基本矛盾不断激化并最终否定资本主义自身。

          • a.从资本主义积累过程来看,资本主义基本矛盾在资本积累过程中不断发展。

          • b.资本的不断积累必然提高生产的社会化程度,这在客观上势必导致生产的集中和资本的集中,使资本的社会化占有成为可能。

          • c.资本的不断积累使对生产过程的管理社会化,相应地派生出管理社会化大生产的管理人员和专业的管理机构,而这些都弱化甚至排斥资本家个人在管理中的地位和作用。

          当资本主义基本矛盾及其派生的各种矛盾在资本积累中不断发展、激化到资本主义制度自身无法使之释放时,社会主义取代资本主义就将成为不可避免的结果。这是资本主义积累过程所具有的客观历史趋势。

        • ③ 国家垄断资本主义中孕育着某些社会主义的因素,将成为社会主义的前奏。

        • ④ 资本主义社会中存在着资产阶级和无产阶级两大阶级之间的矛盾和斗争。无产阶级和资产阶级之间不可调和的矛盾、对立和斗争,必然导致资本主义政治危机。资产阶级的灭亡和无产阶级的胜利是不可避免的。通过无产阶级革命推翻资本主义制度,用社会主义公有制代替资本主义私有制,成为人类社会由低级向高级发展的客观规律的必然要求。

      • (2)社会主义代替资本主义是一个复杂的、长期的历史过程。其原因在于:

        • ① 社会主义自身的巩固、发展和完善是一个长期的历史过程。

          • a.经济上的强烈反差使社会主义国家面临严峻挑战。

          • b.西方敌对势力的颠覆、破坏与和平演变活动,加重了社会主义建设的曲折性、复杂性和长期性。

          • c.对社会主义建设规律的探索需要经过一个长期曲折的过程。

        • ② 社会主义在世界范围代替资本主义是一个长期的历史过程。

          • a.社会主义的本质决定了它在全世界取代资本主义的长期性、曲折性与艰巨性。

          • b.资本主义的暂时强大决定了它在全世界被社会主义所代替的长期性、曲折性与艰巨性。

          • c.20 世纪末世界社会主义运动遭受了重大挫折,导致社会主义顺利发展、再造辉煌需要较长的时间。

      # 第六章 社会主义的发展及其规律(本章仅供学习参考,不作考试要求)

      # 如何认识世界社会主义五百年的发展历程?

      • 答:世界社会主义五百年的发展过程实际上经历了四个阶段,分别是社会主义从空想到科学、社会主义从理论到实践、社会主义从一国到多国、在中国焕发强大生机活力。

      • (1)社会主义从空想到科学

        • ①空想社会主义

        空想社会主义产生于 16 世纪初期,到 19 世纪上半叶达到顶峰。这 300 多年正是欧洲从封建主义生产方式向资本主义生产方式转变的时期。其发展大致分为三个阶段:16 世纪和 17 世纪的早期空想社会主义,有理想社会制度的空想的描写,代表著作是英国人莫尔的《乌托邦》和意大利人康帕内拉的《太阳城》;18 世纪的空想平均共产主义;19 世纪初期出现了批判空想社会主义。主要代表是法国的圣西门、傅立叶和英国的欧文,以三大空想社会主义者为代表的空想社会主义学说,它对资本主义的揭露和批判,提供了启发工人觉悟的极为宝贵的材料。空想社会主义是早期无产阶级意识和利益的先声,反映了早期无产阶级迫切要求改造现存社会、建立理想的新社会的愿望。但其没有能够指出真正的出路。空想社会主义看不到无产阶级负有的历史使命,反对政治斗争,幻想依靠统治阶级的帮助,通过和平的方式来实现社会主义。

        • ② 科学社会主义

        19 世纪 40 年代,资本主义生产方式在西欧先进国家已占统治地位,随着资本主义的发展,资本主义内部矛盾日益尖锐,无产阶级反对资产阶级的斗争日益高涨。马克思和恩格斯参加了当时阶级斗争的实践。在此基础上,周密地研究了资本主义生产方式的矛盾,批判地继承了 19 世纪三大空想社会主义者法国的圣西门、傅立叶和英国的欧文的思想成果,创立了唯物史观和剩余价值论,为实现社会主义从空想到科学的飞跃奠定了坚实的理论基础。他们阐明了生产社会性和生产资料资本主义私人占有形式之间的矛盾的发展,必然导致社会主义取代资本主义,以生产资料的公有制取代生产资料私有制,科学地论述了资本主义必然灭亡、社会主义必然胜利的客观规律,从根本上超越了空想社会主义,实现了社会主义从空想到科学的伟大飞跃。

      • (2)社会主义从理论到现实

        • ① 第一国际与巴黎公社

        1848 年欧洲革命后,资本主义在各国飞速发展,无产阶级力量不断壮大。到 19 世纪 50 年代末 60 年代初,反压迫反剥削的斗争实践使各国无产阶级认识到,他们有着共同的利益和共同的敌人,而以往分散的斗争常常使他们遭到同样的失败,无产阶级必须在国际范围内联合起来。1864 年,国际工人协会(第一国际)应运而生。马克思是第一国际的真正领袖,在他指导下,第一国际把无产阶级先进分子团结在自己周围,率领各国工人群众向资产阶级和压迫者进行坚决斗争,促进了马克思主义的传播和与国际工人运动的结合,初步确立了马克思主义在工人运动中的指导地位。1871 年爆发的巴黎公社革命,深受第一国际精神的影响,是建立无产阶级专政的第一次伟大尝试。公社在经济方面采取了措施,对资本主义企业进行了一定程度的限制和剥夺;成立了管理经济工作的最高权力机构 —— 粮食委员会、财政委员会和劳动、就业及交换委员会;对工人群众的生活状况和劳动条件尽可能加以改善,提出了劳动者八小时工作制的原则。巴黎公社是世界上无产阶级武装暴力直接夺取城市政权的第一次尝试。它丰富和发展了马克思主义关于阶级斗争和社会主义的学说,在国际共产主义运动上写下了光辉、伟大而悲壮的一页。

        • ② 十月革命与第一个社会主义国家的建立

        1917 年 11 月 7 日(俄历 10 月 25 日)作为伟大的十月社会主义革命胜利日载入史册。俄国十月社会主义革命是人类历史上第一次获得胜利的社会主义革命,世界上第一个社会主义国家由此诞生。十月革命的胜利沉重打击了帝国主义的统治,推动了国际社会主义运动的发展,鼓舞了殖民地半殖民地人民的解放斗争。它改变了俄国历史的发展方向,用社会主义方式改造俄国的道路,对整个人类社会的发展都产生了巨大的影响。十月革命是二十世纪国际共产主义运动的序幕,触发了此后各国社会主义运动在全球范围的扩张,许多殖民地或半殖民地的解放运动也因此得到了更多支持,加速了世界范围内帝国主义殖民体系的整体瓦解,深刻改变了国际力量对比和世界格局。

      • (3)社会主义从一国到多国

        • ① 社会主义在苏联一国的实践

        苏维埃俄国是世界上第一个社会主义国家。年轻的苏维埃政权建立之后,既面临着巩固政权的任务,又面临着在经济文化相对落后的条件下建设社会主义的任务。列宁对苏维埃俄国社会主义的探索大体经历了巩固苏维埃政权时期、战时共产主义时期和新经济政策时期。

        • ② 社会主义发展到多个国家俄国十月革命的胜利后,第一个社会主义国家诞生,开辟了人类历史新纪元,极大地鼓舞了世界各国人民,促进了世界社会主义运动的发展。二战以后,社会主义在世界范围内获得大发展,在欧洲、亚洲、拉丁美洲,先后有 15 个国家建立社会主义制度,在国家数量上,占世界的 1/14,在领土上,占世界的 1/4,在人口上,占总人口的 1/3。社会主义国家相继开展了大规模的社会主义建设,推动了国家经济、政治、文化和社会各项事业的发展,世界形成了社会主义和资本主义两种制度共处的新格局。
      • (4)社会主义在中国焕发出强大生机活力
        俄国十月革命的胜利,给中国人民送来了马克思列宁主义。1921 年 7 月,中国共产党成立并成为中国社会主义运动的领导力量。中国共产党率领中国人民进行的社会主义事业经历了从新民主主义革命到社会主义革命、建设、改革的发展过程,中国共产党在近百年的奋斗中不断发展壮大,在 21 世纪焕发出强大的生机活力。习近平总书记在十九大报告中指出:“中国特色社会主义进入新时代,意味着近代以来久经磨难的中华民族迎来了从站起来、富起来到强起来的伟大飞跃,迎来了实现中华民族伟大复兴的光明前景;意味着科学社会主义在 21 世纪的中国焕发出强大生机活力,在世界上高高举起了中国特色社会主义伟大旗帜;意味着中国特色社会主义道路、理论、制度、文化不断发展,拓展了发展中国家走向现代化的途径,给世界上那些既希望加快发展又希望保持自身独立性的国家和民族提供了全新选择,为解决人类问题贡献了中国智慧和中国方案。” 总之,
        中国特色社会主义是科学社会主义 “中国化” 的伟大成果,是在当代中国的成功实践,充分表明了社会主义在世界上人口最多的国家成功开辟出了通向繁荣富强的正确道路,显著地展现了社会主义制度的优越性,标志着社会主义在世界范围内正在开拓新的历史征程。

      # 如何认识和把握科学社会主义一般原则?答:

      • (1)科学社会主义一般原则的主要内容
        科学社会主义一般原则是社会主义事业发展规律的集中体现,是马克思主义政党领导人民进行社会主义革命、建设、改革的基本遵循。

        • ① 人类社会发展规律和资本主义基本矛盾是 “资本主义必然灭亡、社会主义必然胜利” 的根本依据。

        • ② 无产阶级是最先进最革命的阶级,肩负着推翻资本主义旧世界、建立社会主义和共产主义新世界的历史使命。

        • ③ 无产阶级革命是无产阶级进行斗争的最高形式,以建立无产阶级专政的国家为目的。

        • ④ 社会主义社会要在生产资料公有制基础上组织生产,以满足全体社会成员的需要为生产的根本目的。

        • ⑤ 社会主义社会要对社会生产进行有计划的指导和调节,实行按劳分配原则。

        • ⑥ 社会主义社会要合乎自然规律地改造和利用自然,努力实现人与自然的和谐共生。

        • ⑦ 社会主义社会必须坚持科学的理论指导,大力发展社会主义先进文化。

        • ⑧ 无产阶级政党是无产阶级的先锋队,社会主义事业必须始终坚持无产阶级政党的领导。

        • ⑨ 社会主义社会要大力解放和发展生产力,逐步消灭剥削和消除两极分化,实现共同富裕和社会全面进步,并最终向共产主义社会过渡。

      • (2)正确对待科学社会主义一般原则的科学态度

        • ① 必须始终坚持社会主义一般原则,反对任何背离科学社会主义一般原则的错误倾向。

        • ② 要善于把科学社会主义一般原则与本国实际相结合,创造性地回答和解决革命、建设、改革中的重大问题。

        • ③ 紧跟时代和实践的发展,在不断总结新鲜经验中进一步丰富和发展科学社会主义一般原则。

      # 请结合科学社会主义一般原则,谈谈为什么说中国特色社会主义是科学社会主义,而不是其他什么主义。答:

      • (1)科学社会主义一般原则
        科学社会主义一般原则是社会主义事业发展规律的集中体现,是马克思主义政党领导人民进行社会主义革命、建设、改革的基本遵循。马克思、恩格斯在深刻揭示人类社会发展一般规律的基础上,深入阐发资本主义基本矛盾及其发展趋势,并在指导国际工人运动的过程中不断总结经验,逐步形成了科学社会主义一般原则。这些原则在后来的社会主义革命和建设中得到了证实、丰富和发展。这些原则具体如下:

        • ① 人类社会发展规律和资本主义基本矛盾是 “资本主义必然灭亡、社会主义必然胜利” 的根本依据。

        • ② 无产阶级是最先进最革命的阶级,肩负着推翻资本主义旧世界、建立社会主义和共产主义新世界的历史使命。

        • ③ 无产阶级革命是无产阶级进行斗争的最高形式,以建立无产阶级专政的国家为目的。

        • ④ 社会主义社会要在生产资料公有制基础上组织生产,以满足全体社会成员的需要为生产的根本目的。

        • ⑤ 社会主义社会要对社会生产进行有计划的指导和调节,实行按劳分配原则。

        • ⑥ 社会主义社会要合乎自然规律地改造和利用自然,努力实现人与自然的和谐共生。

        • ⑦ 社会主义社会必须坚持科学的理论指导,大力发展社会主义先进文化。

        • ⑧ 无产阶级政党是无产阶级的先锋队,社会主义事业必须始终坚持无产阶级政党的领导。

        • ⑨ 社会主义社会要大力解放和发展生产力,逐步消灭剥削和消除两极分化,实现共同富裕和社会全面进步,并最终向共产主义社会过渡。

      • (2)中国特色社会主义是科学的社会主义的原因
        中国特色社会主义,是科学社会主义理论逻辑和中国社会发展历史逻辑的辩证统一。中国特色社会主义既坚持了科学社会主义的基本原则,又根据时代条件赋予其鲜明的中国特色,是一百多年来科学社会主义理论与实践发展的结晶,是当代中国的科学社会主义。

        • ① 新中国成立后,中国共产党领导人民开始社会主义革命和建设的伟大实践。在只有苏联模式可学的情况下,在开始进行社会主义建设时我们走了照搬苏联经验的路子。但是,我们党很快就觉察到苏联模式的种种弊端,果断决定独立探索适合中国国情的社会主义建设道路。这一探索尽管曾出现过脱离实际的严重失误,却还是取得了巨大的成绩,形成了关于社会主义建设的许多独创性的理论成果和实践成果。在新的历史时期,我们党坚持解放思想、实事求是,深刻总结历史经验教训,正确判断时代主题和基本国情,经过 30 多年的努力,形成了中国特色社会主义道路、中国特色社会主义理论体系、中国特色社会主义制度三位一体的伟大成果,取得了中国特色社会主义建设的巨大成就。

        • ② 中国特色社会主义之所以是社会主义而不是别的什么主义,就在于它始终坚持以科学社会主义的基本原则为理论源泉和理论核心。科学社会主义创始人对社会主义的设想和他们提出的科学社会主义基本原则的最终实现,需要一个过程。我们党始终将其作为核心价值追求,始终将其作为进行改革开放和实践创新、理论创新、制度创新的 “魂”。这样一种追求,这样的 “魂”,鲜明地体现在改革开放新时期我们党所制定的路线、方针、政策中。

        • ③ 科学社会主义包含极其丰富的内容,集中到一点,就是科学地论证了社会主义必然代替资本主义的历史趋势,论证了无产阶级取代资本主义、建设社会主义和共产主义的伟大历史使命。科学社会主义理论创立以来的历史证明它的理论是正确的,社会主义具有强大的生命力。同时,它又不是一成不变的教条。它在指导实践的过程中,又要接受实践的检验,随着实践的发展而不断扩展、不断深化、不断丰富、不断完善。中国特色社会主义理论体系,就是科学社会主义在当代中国的新发展。

        • ④ 当前,资本主义现实和社会主义实践同马克思、恩格斯两位伟大思想家所处的历史环境相比,都发生了巨大的变化,但从世界社会主义发展的五百年大视野来看,目前依然处在马克思主义所指明的历史时代,处在资本主义向社会主义转变的历史进程之中,科学社会主义从没有过时,仍然有强大的生命力,必须始终坚持、不动摇。正如习近平指出:“中国特色社会主义是社会主义而不是其他什么主义,科学社会主义基本原则不能丢,丢了就不是社会主义。”

      # 请谈谈中国特色社会主义的成功实践对世界社会主义发展的贡献。答:

      • 党的十九大报告作出了 “中国特色社会主义进入新时代” 的重大政治论断。习近平总书记在报告中指出:“中国特色社会主义进入新时代,意味着近代以来久经磨难的中华民族迎来了从站起来、富起来到强起来的伟大飞跃,迎来了实现中华民族伟大复兴的光明前景;意味着科学社会主义在二十一世纪的中国焕发出强大生机活力,在世界上高高举起了中国特色社会主义伟大旗帜;意味着中国特色社会主义道路、理论、制度、文化不断发展,拓展了发展中国家走向现代化的途径,给世界上那些既希望加快发展又希望保持自身独立性的国家和民族提供了全新选择,为解决人类问题贡献了中国智慧和中国方案。” 这一重大政治论断给我们许多启示,增加了我们对中国特色社会主义的自信,也使我们充分认识到中国特色社会主义不仅在 21 世纪的中国充分显现出生机与活力,取得伟大成功,使科学社会主义理论在中国实践中获得巨大发展,也使得中国特色社会主义超越了国界,具有世界性的意义,为发展中国家走向现代化提供了新的路径选择,也为世界发展和人类问题的解决贡献了中国智慧和中国方案。

      • (1)中国特色社会主义为世界贡献了中国智慧
        中国走上中国特色社会主义道路,是几代中国共产党人带领全国人民在艰难曲折中艰辛探索、不断实践创新的结果,体现了中国共产党人的不屈不挠,也体现了中国共产党人的卓越智慧,其中最核心的就是党的实事求是的思想路线,一切从实际出发,把马克思主义基本原理与中国客观实际相结合,走适合中国国情的社会主义道路。改革开放以来,我们党坚持实事求是的思想路线,在实践中不断探索和回答了什么是社会主义、怎样建设社会主义,建设什么样的党、怎样建设党,实现什么样的发展、怎样发展,并继续探索和回答新时代坚持和发展什么样的中国特色社会主义、怎样坚持和发展中国特色社会主义这些基本问题。党的思想路线体现的是马克思主义的世界观、方法论。因此,中国特色社会主义的成功,是马克思主义世界观和方法论的成功,是马克思主义中国化、时代化的成功。中国特色社会主义贡献给世界的智慧,最为根本的是实事求是,国家建设一定要从自己的国情出发,探索适合自己国情的建设道路,任何脱离实际、不符合国情的道路、方法、模式都是不可能取得成功的。

      • (2)中国特色社会主义为世界贡献了中国方案
        中国特色社会主义不仅为世界贡献了指导国家建设的正确的思想方法,还为世界贡献了国家建设的具体方案和治国理政的基本方略。中国特色社会主义治国方案既包括总目标、总任务、总体布局、战略布局和发展方向、发展方式、发展动力、战略步骤、外部条件、政治保证等基本方面的总体设计,也包括经济、政治、科技、文化、教育、民生、民族、宗教、社会、生态、国家安全、国防和军队、国家统一、统一战线、外交、党的建设等各方面的基本规定。还有就是,坚持党对一切工作的领导,坚持以人民为中心,坚持全面深化改革,坚持新发展理念,坚持人民当家作主,坚持全面依法治国,坚持社会主义核心价值体系,坚持在发展中保障和改善民生,坚持人与自然和谐共生,坚持总体国家安全观,坚持党对人民军队的绝对领导,坚持 “一国两制” 和推进祖国统一,坚持推动构建人类命运共同体,坚持全面从严治党等基本方略。这些既是新时代坚持和发展中国特色社会主义的基本方略,也是中国特色社会主义为解决人类问题向世界贡献的中国方案,给世界上那些既希望加快发展又希望保持自身独立性的国家和民族提供了全新选择。

      # 如何正确认识和把握共产党执政规律?

      答:可以从以下几个方面正确认识和把握共产党执政规律:

      • (1)共产党执政规律,最根本的是人心向背定理。习近平总书记指出:“一个政党,一个政权,其前途和命运最终取决于人心向背。”“人心是最大的政治。” 要始终把人民放在心中最高位置。坚持一切为了人民、一切依靠人民。

      • (2)共产党执政首要的是坚持党中央权威和集中统一领导,党是最高政治领导力量,党的领导是全面领导。党的十九大报告指明 “坚持党中央权威和集中统一领导,是党的政治建设的首要任务”,揭示了保证党的团结和集中统一的根本性问题,阐明了进行伟大斗争、建设伟大工程、推进伟大事业、实现伟大梦想的根本保证,意义重大而深远。

      • (3)共产党在执政过程中,要把党的政治建设摆在首位。要坚持党要管党、全面从严治党,以应对各种考验,坚定不移地惩治和预防腐败,勇于自我革命。只有全面从严治党,才能顺利实现中华民族伟大复兴的中国梦。

      • (4)要始终抓住科学执政、民主执政、依法执政这个要律,为实现国家治理现代化指明方向路径。

      # 第七章 共产主义是人类最崇高的社会理想

      # 请谈谈在未来理想社会的认识上,马克思主义经典作家与空想社会主义者有何本质区别。

      • 答:在未来理想社会的认识上,马克思主义经典作家与空想社会主义者的本质区别是:是否坚持科学的立场、观点和方法来预见未来。预见未来社会的方法论原则主要包括:

      • (1)在揭示人类社会发展一般规律的基础上指明社会发展的方向。

      • (2)在剖析资本主义旧世界的过程中阐发未来新世界的特点。

      • (3)在社会主义社会发展中不断深化对未来共产主义社会的认识。

      • (4)立足于揭示未来社会的一般特征,而不作详尽的细节描绘。

      # 既然共产主义理想的实现是历史的必然,为什么又要人们去努力追求?既然共产主义的最终实现是一个漫长的过程,为什么又说 “共产主义渺茫论” 是错误的?请用马克思主义的辩证观点予以解答。答:

      • (1)实现共产主义的历史必然

        • ① 共产主义理想的实现是历史规律的必然要求

          • a.共产主义理想是能够实现的理想,它与一切空想和幻想有着本质区别。

          • b.共产主义理想一定会实现,是以人类社会发展规律以及资本主义社会的基本矛盾发展为依据的。

          • c.社会主义运动的实践,特别是社会主义国家的兴起和不断发展,已经且正在用事实证明共产主义理想实现的必然性。从一定意义上讲,社会主义革命的胜利本身就是对共产主义理想可以实现的证明。

        • ② 实现共产主义是人类最伟大的事业

          • a.实现共产主义理想是广大人民群众的共同愿望。

          • b.实现共产主义,必须找到现实的阶级力量,这就是现代工人阶级或无产阶级。

          • c.无产阶级的解放与全人类的解放是完全一致的。

      • (2)共产主义的实现是一个漫长的过程

        • ① 资本主义的灭亡和向社会主义的转变是一个长期的过程

          • a.资本主义作为一个社会形态,其走向灭亡是一个长期的历史过程。资本主义国家经历过严重的经济和社会危机,在与社会主义国家的竞争中也伴随着巨大的压力。但资本主义并没有退出历史舞台,而是仍然有一定发展空间。这些危机背后隐藏着资本主义衰败的必然趋势,但目前谁也无法准确判断资本主义何时走到尽头。

          • b.社会主义革命取得胜利后,从资本主义转变为社会主义也需要一段时期。这个重要的过渡期是不以人的意志为转移的,它不能省略,更不可随意缩短。

          • c.在完成转变以后,仍然需要经历一段社会主义的发展阶段,才能最终逐渐走向共产主义。在任何国家,实现共产主义都不能超越社会主义发展阶段。不管资本主义国家发达到何种程度,当发生根本性的制度变革时,也不可能直接达到共产主义社会,只能首先进入社会主义社会,也就是共产主义社会的低级阶段。

          • d 要真正迎来新社会,消除旧社会痕迹,也需要经过一个很长的时期。

        • ② 社会主义社会自身巩固、发展和完善并最终成为共产主义也是一个长期的过程。

          • a.想要在全世界范围内实现共产主义,必须取决于社会主义国家的巩固和发展,取决于这些国家所经历的社会主义社会的时间长短。因此,共产主义只有在社会主义社会充分发展和高度发达的基础上才能实现。

          • b.经济上的强烈反差使社会主义国家面临严峻挑战。社会主义革命没有像马克思和恩格斯所设想的那样,在发达的资本主义国家首先发生,而是在少数经济和文化比较落后的国家首先取得胜利。这些国家基础差、起点低,要在经济上赶上资本主义发达国家,提高社会化生产水平,建设和完善社会主义政治、经济、文化等各项制度,体现出社会主义优于资本主义,需要付出更大、更艰苦和更长期的努力,是一个漫长的历史过程。

          • c.对社会主义建设规律的探索需要经过一个长期曲折的过程。建设社会主义是前无古人的崭新事业,没有现成固定的模式可循,需要各个社会主义国家在实践中把马克思主义的基本原理与本国的具体实践相结合,探索适合本国发展的社会主义建设道路和模式。而探索的过程不会是一帆风顺的,难免会出现不同程度的失误,甚至发生曲折和暂时倒退现象。这种探索过程的曲折性,无疑会增加这些国家建设、巩固和发展社会主义的艰巨性与长期性。

          • d.社会主义是共产主义的低级阶段,也是实现共产主义的必由之路。作为同一社会形态发展进程中的两个阶段,社会主义是共产主义的必要准备,共产主义是社会主义发展的必然趋势。随着社会主义生产力和其他因素的不断发展,属于社会主义的一些因素将逐步消失,而共产主义的所有因素将逐步增长。社会主义社会不断发展和完善的过程,就是共产主义因素不断扩大的过程。一旦条件完全成熟,社会主义社会就自然过渡到共产主义社会。

      • (3)实现共产主义是历史发展规律的必然要求,“共产主义渺茫论” 是错误的

        • ① 共产主义渺茫论者不了解共产主义的含义。

        共产主义有两方面的含义:一方面指的是在共产主义思想体系指导下的共产主义运动;另一方面指的是共产主义的社会制度。当然,共产主义社会制度彻底实现,是需要经过若干代人的不懈努力的,是一个远大的奋斗目标。但是,作为在共产主义思想体系指导下的共产主义运动,作为一种亿万人民在共产党领导下改造社会的革命实践,则是一点也不 “渺茫”,而是实实在在地、每日每时地存在于我们的现实生活中。一个多世纪以来,各国无产阶级及其政党为了实现共产主义制度这一伟大理想,进行了艰苦卓绝的斗争,诸如巴黎公社、十月社会主义革命以及我国的社会主义革命和社会主义建设,每向前发展一步都意味着向共产主义靠拢一步。今天,我们的一切革命工作都是伟大的共产主义运动的具体体现和组成部分。

        • ② 共产主义渺茫论者割裂了共产主义与社会主义之间的联系。

        共产主义渺茫论者忽视了一个很重要的事实,即共产主义运动不仅在全世界,而且在中国也早已存在,而且已经取得了显著成果,这就是共产主义社会的过渡阶段 —— 社会主义社会,已经在中国和世界一些国家建立起来并取得重大发展,从而使共产主义运动发生了质的飞跃。我国社会主义制度的建立,不仅使人民从被压迫和被剥削的旧制度下解放出来,而且,随着社会主义改革和建设的不断深入,人们生活的不断改善,社会主义制度的不断完善以及社会道德水准和文化教育科学事业的向前推进,共产主义理想逐渐深入人心。

        • ③共产主义渺茫论者不能正确对待社会主义事业中的曲折和困难。

        马克思主义辩证法告诉我们,事物的发展不是直线上升,而是在曲折中前进的。社会主义事业也是如此,它有成功,也有失误,有前进,也有暂时的困难。中国的改革和经济建设取得了举世瞩目的伟大成就,但也存在不少问题。只有坚持中国特色社会主义道路,集中精力把经济建设搞上去,人民生活得到了不断改善,人们才能看到社会主义的前途和希望。只要把社会主义建设好,才能为将来的共产主义打下了坚实的基础。我们要继续坚定不移地沿着社会主义道路勇往直前,坚信共产主义必胜的信念。

      # 有人说:“在社会主义初级阶段只能讲树立中国特色社会主义共同理想,而不应提树立共产主义远大理想,否则就是脱离实际。” 请用共同理想和远大理想的关系来分析评论这一观点。

      • 答:共产主义理想是建立在科学基础上的社会理想,是人类最伟大的社会理想。在坚持和发展中国特色社会主义的实践中,我们不但要坚定中国特色社会主义共同理想,而且要进一步树立共产主义远大理想。

      • (1)正确认识和把握共产主义远大理想与中国特色社会主义共同理想的关系

        • ①从时间上看,远大理想与共同理想的关系是最终理想与阶段性理想的关系。

        • ②从层次上看,远大理想与共同理想的关系是最高纲领与最低纲领的关系。实现共产主义远大理想要坚持最高纲领和最低纲领的统一。

        • ③从范围来看,远大理想与共同理想的关系也是全人类理想与全体中国人民理想的关系。

      • (2)以辩证思维把握和处理远大理想和共同理想的关系
        必须以马克思主义的辩证思维和历史思维去把握远大理想和共同理想的关系。实现中国特色社会主义的共同理想,是为了实现共产主义远大理想而服务。中国特色社会主义共同理想在我国的成功实践,必然为实现共产主义远大理想奠定坚实的基础。

      # 中国特色社会主义进入了新时代。为了不辜负这个伟大的时代,当代大学生应该怎样确立和追求自己的人生理想?答:

      • (1)新时代的特征
        中国特色社会主义进入新时代。我们党对 “什么是社会主义、如何建设社会主义” 的认识又向前推进了一步,从理论和实践结合上系统回答了 “新时代坚持和发展什么样的中国特色社会主义、怎样坚持和发展中国特色社会主义” 这一重大历史课题,习近平新时代中国特色社会主义思想成为指引全国人民沿着中国特色社会主义道路继续前进的重要理论基础。

      • (2)对当代大学生的要求习近平指出:“青年是标志时代的最灵敏的晴雨表,时代的责任赋予青年,时代的光荣属于青年。” 青年是祖国的未来、民族的希望。青年兴则国兴,青年强则国强。当前,中国特色社会主义进入新时代,为当代青年特别是当代大学生提供了实现人生才华的极为有利的历史机遇。

        • ①要坚定理想信念。心中有信仰,脚下才有力量。为此,就要深入学习马克思主义基本原理及马克思主义中国化的理论成果,特别是学习习近平新时代中国特色社会主义思想。

        • ②要积极投身实现中华民族伟大复兴的中国梦,勇做担当中华民族伟大复兴大任的时代新人。

        • ③要投身新时代中国特色社会主义事业,当代大学生是祖国的未来、民族的希望,要以勇于担当的精神,做走在新时代前列的奋进者、开拓者、奉献者,投身于党和人民在中国特色社会主义新时代的伟大奋斗。

      \ No newline at end of file diff --git a/si-zheng/ma-yuan/ti-gang/index.html b/si-zheng/ma-yuan/ti-gang/index.html index 93120d4e..36ac2137 100644 --- a/si-zheng/ma-yuan/ti-gang/index.html +++ b/si-zheng/ma-yuan/ti-gang/index.html @@ -1 +1 @@ -马原题纲 - 马克思主义基本原理 - 思政 | Balloon Party = 風船のパーティー = fuusen no party

      # 思维导图

      # 绪论部分

      绪论部分

      # 第一章 世界的物质性及发展规律

      第一章 世界的物质性及发展规律

      # 第二章 实践与认识及其发展规律

      第二章 实践与认识及其发展规律

      # 第三章 人类社会及其发展规律

      第三章 人类社会及其发展规律

      # 第四章 资本主义的本质及规律

      第四章 资本主义的本质及规律

      # 第六章社会主义的发展及其规律(本章仅供学习参考,不作考试要求)

      第六章 社会主义的发展及其规律(本章仅供学习参考,不作考试要求)

      # 第七章 共产主义是人类最崇高的社会理想

      第七章 共产主义是人类最崇高的社会理想

      # 大纲

      # 绪论部分

      # 马克思主义的含义、理论来源、经典著作、鲜明特征;马克思主义基本原理的含义(马克思主义的基本立场、基本观点、基本方法);

      • 含义:马克思主义是由马克思和恩格斯创立的,为他们的后继承者所发展的,以反对资本主义、建设社会主义和实现共产主义为目标的科学理论体系,是关于无产阶级和人类解放的科学。

      • 理论来源: 德国古典哲学、英国古典政治经济学、英法两国的空想社会主义。

      • 经典著作:

        • 两人《神圣家族》 《德意志意识形态》 《共产党宣言》 《新莱茵报》

          • 马《资本论》 《法兰西内战》 《哥达纲领批判》

          • 恩《反杜林论》 《家庭、私有制和国家的起源》 《路德维希・费尔巴哈和德国古典哲学的终结》

      整理出版《资本论》二三卷

      • 鲜明特征:

        • (1)科学性,它是对客观世界特别是人类社会本质和规律的正确反应。(表现在坚持世界的物质性和真理的客观性)

        • (2)革命性, 它是无产阶级和广大人民群众推翻旧世界,建设新世界的理论,按本质来说,它是批判的和革命的,它具有鲜明的无产阶级政治立场(表现在坚持唯物辩证法)。

        • (3)实践性,马克思主义的科学性和革命性是统一的,以社会主义运动的实践为基础,致力于实现无产阶级和广大人民群众的根本利益。

      • 马克思主义基本原理的含义

        • (1)基本立场:是马克思主义观察、分析和解决问题的根本立足点和出发点

        • (2)基本观点:是关于自然、社会和人类思维发展一般规律的科学认识,是对人类思想成果和社会实践经验的科学总结

        • (3)基本方法:是建立在辩证唯物主义和历史唯物主义世界观和方法论基础上的指导我们正确认识世界和改造世界的思想方法和工作方法。

      # 第一章 世界的物质性及发展规律

      # 哲学的基本问题、哲学派别的划分及各派别的基本思想和代表人物(唯物主义 VS 唯心主义;可知论 VS 不可知论;唯物史观 VS 唯心史观;辩证法 VS 形而上学)

      • 哲学的基本问题:存在和思维、物质和精神的关系问题

        • 存在和思维、物质和精神何者是第一性

        • 存在和思维、物质和精神是否具有同一性

      • 哲学派别的划分及各派别的基本思想和代表人物

        • 存在和思维究竟谁是世界的本原,即物质和精神何者是第一性、何者是第二性的问题

          • 唯物主义

          存在决定思维

          • 唯心主义

          思维决定存在

        • 存在和思维是否具有同一性?我们关于我们周围世界的思想对这个世界本身的关系是怎样的?我们的思维能不能认识现实世界?我们能不能在我们关于现实世界的表象和概念中正确的反映现实?

          • 可知论

          认为思维和存在有同一性,人的意识能够认识客观世界及其规律

          • 不可知论

          认为思维和存在没有同一性,人的意识不能或不能彻底认识客观世界及其规律
          古希腊怀疑论者 皮浪,

        • 社会意识和社会存在的关系

          • 唯物史观

          社会存在决定社会意识

          • 唯心史观

          社会意识决定社会存在

        • 是否承认事物的内部矛盾是事物发展的根本动力

          • 辩证法

          承认事物的内部矛盾是事物发展的根本动力

          • 形而上学

          否认事物的内部矛盾是事物发展的根本动力

      # 物质观(物质的含义、意识的含义;物质与意识的辩证关系;主观能动性与客观规律性的统一)、运动观(运动的含义、运动与静止、运动与物质的关系)、时空观(时间的含义及其特点、空间的含义及其特点、时空与物质运动的关系)

      • (一)物质观

        • 物质的含义:物质就是不依赖于人类意识而存在并能为人类的意识所反映的客观存在

        • 意识的含义:意识是人脑的机能和属性,是客观世界的主观映像

        • 物质与意识的辩证关系:

          • (一) 物质决定意识。物质对意识的决定作用表现在意识的起源、本质和作用上。

          • (二) 意识对物质具有反作用。

            • 1. 意识活动具有目的性和计划性;

            • 2. 意识活动具有创造性;

            • 3. 意识具有指导实践改造客观世界的作用;

            • 4. 意识具有控制人的行为和生理活动的作用。

          • (三) 主观能动性和客观规律性的统一

        • 主观能动性与客观规律性的统一:

          • 首先,尊重客观规律是正确发挥主观能动性的前提

          • 其次,只有充分发挥主观能动性,才能正确认识和利用客观规律。

          • 要正确发挥主观能动性,应注意:

            • 一,从实际出发,努力认识和把握事物的发展规律。

            • 二,实践是发挥人的主观能动性的途径。

            • 三,主观能动性的发挥还依赖于一定的物质条件和物质手段

      • (二)运动观

        • 运动的含义:运动是标志一切事物和现象的变化及其过程的哲学范畴

        • 运动与静止:物质世界的运动是绝对的,而物质在运动的过程中又有某种相对的静止。相对静止是物质运动在一定条件下的稳定状态,包括空间的相对位置和事物的根本性质暂时未变这样两种运动的特殊状态。

          • 运动的绝对性体现了物质运动的变动性、无条件性,静止的相对性体现了物质运动的稳定性,有条件性。

          • 运动和静止相互依赖、相互渗透、相互包含,“静中有动,动中有静”。

          • 无条件的绝对运动和有条件的相对静止构成对立统一关系

        • 运动与物质的关系:物质和运动是不可分割的,运动是物质的运动,物质是运动着的物质,离开物质的运动和离开运动的物质都是不可想象的。

      • (三)时空观

        • 时间的含义:是指物质运动的持续性、顺序性

        特点:一维性,即一去不复返

        • 空间的含义:是指物质运动的广延性、伸张性

        特点:三维性

        • 时空与物质运动的关系:

      物质运动总是在一定的时间和空间中进行的,没有离开物质运动的 “纯粹” 时间和空间,也没有离开时间和空间的物质运动。

      # 世界的物质统一性原理

      • (一)意识统一于物质。

      • (二)人类社会也统一于物质。

        • 1. 人类社会依赖于自然界,是整个物质世界的组成部分。

        • 2. 人类谋取物资生活资料的实践活动虽然有意识作指导,但仍然是以物质力量改造物质力量的活动,仍然是物质活动。

        • 3. 物质资料的生产方式是人类社会存在和发展的基础,集中体现着人类社会的物质性。

      # 唯物辩证法的总特征:联系与发展的观点(联系的含义、特点;发展的含义、实质等)

      • 联系的含义:作为一个普遍的哲学范畴,联系是指事物内部各要素之间和事物之间相互影响、相互制约、相互作用的关系。

      • 联系的特点:客观性、普遍性、多样性、条件性

      • 发展的含义:变化的基本趋势是发展,发展是前进的上升的运动

      • 发展的实质:

        • 新事物的产生和旧事物的灭亡。

          • 新事物是指合乎历史前进方向,具有远大前途的东西

          • 旧事物是指丧失历史必然性、日趋灭亡的东西

      # 唯物辩证法的五对范畴(原因与结果、现象与本质、内容与形式、必然性与偶然性、现实性与可能性)

      • 原因与结果:这是揭示事物引起和被引起的一对范畴。

        原因是引起某种现象的现象,结果是被某种现象引起的现象。

        因果关系就是包括时间先后顺序在内的一种现象必然引起另一种现象的普遍联系

      • 现象与本质:这是揭示事物外在联系和内在联系的一对范畴。

        现象是事物的外部联系和表面特征,本质是事物的根本性质和构成要素的内在联系。

        本质是现象的根据,现象是本质的表现

      • 内容与形式:这是从构成要素和表现方式两个方面反映事物的一对范畴。

        内容是指构成事物的一切要素总和,形式是指把内容诸要素统一起来的结构或表现内容的方式

      • 必然性与偶然性:这是揭示事物发生、发展和灭亡的不同趋势的一对范畴。

        必然性是事物联系和发展过程中合乎规律的确定不移的趋势,

        偶然性是联系和发展过程中并非必定如此的、不确定的趋势。

      • 现实性与可能性:这是反映事物过去、现在和将来关系的一对范畴。

        现实性包括内在根据的、合乎必然性的存在,

        可能性是指包含在现实事物中、预示着事物发展前途的种种趋势。

      # 唯物辩证法的三大规律:对立统一规律(矛盾的同一性与斗争性的辩证关系;矛盾的普遍性与特殊性的辩证关系)、质量互变规律(质、量、度等范畴的含义;量变与质变的辩证关系)、否定之否定规律;对立统一规律是唯物辩证法的实质与核心

      • 一、对立统一规律:是事物发展的根本规律,是唯物辩证法的实质与核心。

        ①矛盾是反应事物内部和事物之间对立统一关系的哲学范畴。

        矛盾的同一性和斗争性是相互联结,相辅相成的,没有斗争性就没有同一性,没有同一性也没有斗争性,斗争性寓于同一性之中。

        ②矛盾的普遍性与特殊性是辩证统一的关系,任何现实存在的事物的矛盾都是共性和个性的有机统一,共性寓于个性之中,没有离开个性的共性,也没有离开共性的个性。

      • 二、质量互变规律:

        • ① 事物的联系和发展都采取量变和质变两种状态和形式。

        • ② 质是一事物区别于其他事物的内在规定,量是事物的规模、程度、速度等可以用数量关系表示的规定性。

        度是保持事物质的稳定性的数量界限,即事物的限度、幅度和范围。

        度的两端叫关节点或临界点,超出度的范围,此物就转化为他物。

        “度” 启示我们,在认识和处理问题时要掌握适度的原则。

        • ③ 辩证关系:

          • (1)量变是质变的必要准备

          • (2)质变是量变的必然结果

          • (3)量变和质变是相互渗透的。

      • 三、否定之否定规律:

        • ① 辩证否定观

          • (1)否定是事物的自我否定,是事物内部矛盾运动的结果

          • (2)否定是事物发展的环节,是新事物向旧事物的转变,是旧质到新质的飞跃

          • (3)否定是新旧事物联系的环节

          • (4)辩证否定的实质是 “扬弃” 即新事物对旧事物既批判又继承,既克服其消极因素又保留其积极因素。

        • ② 否定之否定规律揭示了事物发展的前进性与曲折性的统一。

        • ③ 按照否定之否定规律办事,要求我们对待一切事物都要采取科学分析的态度,反对肯定一切和否定一切的形而上学否定观。

      # 如何理解 “以唯物辩证法为指导,不断增强思维能力”P53(五大思维)

      • 一、思维能力包括:战略思维能力、历史思维能力、辩证思维能力、创新思维能力、底线思维能力

      // 战历辩创底

      • 二、战略思维能力,就是高瞻远瞩、统揽全局,善于把握事物发展总体趋势和方向的能力。(树立大局意识,放眼未来。善于观大势,把握工作主权。开阔视野,紧跟时代步伐。)

      • 三、历史思维能力就是以史为鉴、知古鉴今,善于运用历史眼光认识发展规律、把握前进方向、知道现实工作的能力。(善于运用历史智慧推进 ** 的思想观点。加强对中国历史,世界历史的学习,总结历史经验,把握认清规律,更好的走向未来。)

      • 四、辩证思维能力就是承认矛盾,分析矛盾、解决矛盾,善于抓住关键,找准重点,洞察事物发展规律的能力。(坚持 “两点论”, 一分为二的看问题。要勇于进取,稳扎稳打。发展的眼光,全面,普遍联系)

      • 五、创新思维能力就是破除迷信、超越过时的陈规,善于因时制宜、知难而进、开拓创新的能力。(勇于创新,不因循守旧,满足现状。有探索真知、求真务实的态度。百折不挠、勇往直前,不断积累经验。)

      • 六、底线思维能力就是客观地设定最低目标,立足最低点,争取最大期望值的一种积极的思维能力.(基点放在出现较大的锋线上,做好对策,争取最好结果。要居安思危,增强忧患意识。)

      # 第二章 实践与认识及其发展规律

      # 实践观(实践的含义、特点、类型、实践在认识中的决定性作用、实践是检验真理的唯一标准)

      • 一、实践的本质含义:实践是人类能动地改造世界的感性物质活动。

      • 二、实践的基本特征:

        • 第一,实践是改造世界的客观物质活动,具有直接现实性。

        • 第二,实践是人类有意识的活动,体现了自觉能动性。

        • 第三,实践是社会的、历史的活动,具有社会历史性。

      • 三、实践的类型:

        • (1)物质生产实践(最基本的):人类最基本的实践活动,决定着社会的基本性质和面貌。

          • (2)社会政治实践:是改造社会关系的实践活动,形成了复杂的社会政治关系

          • (3)科学文化实践:是创造精神文化产品的实践活动。

      • 四、实践在认识中的决定作用:

        • (1)辩证唯物主义认识论认为,实践决定认识,实践是认识的基础。

        • (2)实践是认识的来源

        • (3)实践是认识发展的动力

        • (4)实践是认识的目的

        • (5)实践是检验认识真理性的唯一标准。

      # 辩证唯物主义和旧唯物主义对认识本质的不同回答;感性认识和理性认识及其辩证关系、非理性因素;认识运动的基本规律

      • Ⅰ. 辩证唯物主义和旧唯物主义对认识本质的不同回答:

        • ② 辩证唯物主义和旧唯物主义都坚持反映论,但是两者之间又有着本质的区别

        • ② 旧唯物主义认识论以感性直观为基础,把人的认识看成是消极地、被动地反映和接受外界对象,不能把认识看作一个不断发展的过程,认为认识是一次性完成的。这种直观的,消极被动的反映论是不科学的

        • ③ 辩证唯物主义认识论继承了旧唯物主义反映论的合理前提,同时又克服了它的严重缺陷。它把实践的观点引入认识论,把辩证法应用于反映论,把认识看成是一个由不知到知、由浅入深的充满矛盾的能动的认识过程,是能动的反映论。

      • Ⅱ. 感性认识和理性认识及其辩证关系、非理性因素:

        • ① 感性认识:是认识的低级阶段,是人在实践中通过感官对事物外部形态的直接的、具体的反映。它包括感觉、知觉、表象三种形式。它的突出特点是直接现实性。它只是对事物表面现象的反映,没有反映事物的本质,因而具体局限性。

        • ② 理性认识:人们通过抽象思维得到的对事物本质、内在联系和规律性的认识,是认识的高级阶段,包括概念、判断和推理三种形式。其特点是间接性和抽象性。

        • ③ 感性认识和理性认识的辩证关系:

          • (1)感性认识是理性认识的基础,理性认识依赖于感性认识。

          • (2)感性认识有待于发展和深化为理性认识。

          • (3)感性认识和感性认识相互渗透、相互包含。

          • ④ 从感性认识上升到理性认识需要具备的条件:

            • (1)勇于实践、深入调查,获取丰富的感性材料,这是基础。

            • (2)必须经过理性思考,将感性材料加以去粗取精、去伪存真、由此及彼、由表及里加工,才能将感性认识上升为理性认识。

          • ⑤ 非理性因素:主要是指认识主体的情感和意志。也包括不自觉、非逻辑等特点的认识形式(如:联想、想象、猜测、直觉、顿悟、灵感等)

            • (1)人的认识过程是理性因素和非理性因素协同作用的结果。

            • (2)非理性因素对于人的认识能力和人是活动具有激活,驱动和控制作用我们应当在理性认识的指导下,充分发挥非理性因素的积极作用)

      • Ⅲ. 认识运动的基本规律:

        • (1)认识运动的辩证过程,是从实践到认识的过程,即在实践基础上由感性认识能动的飞跃到理性认识的过程。

        • (2)认识过程的第二个阶段是从认识到实践,即由 “精神到物质的阶段,由思想到存在的阶段”。

        • (3)认识运动是不断反复和无限发展的,是一个波浪式前进和螺旋式上升的过程。

      # 真理的含义及其属性;价值评价的含义

      • 真理的定义

      真理是人们对于客观事物及其规律的正确认识。

      • 真理的属性

        • (1) 真理的客观性

          真理具有客观性,凡真理都是客观真理。真理的客观性或客观真理有两层含义:一是指真理的内容是客观的,是不以人的意志为转移的客观世界;二是指检验真理的标准是客观的。检验真理的唯一标准是实践,而实践是物质性的活动。

          • (2) 真理的绝对性

          真理的绝对性或者绝对真理是指真理的内容具有正确性,真理的发展具有无限性。其具体含义有:其一,就真理的内容而言,任何真理都必然包含着同客观对象相符合的客观内容,都同谬误有原则的界限。因此,承认了客观真理就是承认了绝对真理。其二,就真理的发展而言,其前景是无限的。由于人类依其认识本性来说,能够正确认识无限发展着的物质世界。所以,承认世界的可知性,也就是承认了绝对真理。其三,就真理发展的最终结果而言,无数相对真理的总和构成为绝对真理。所以,承认认识发展的无限性,就必然承认绝对真理。

          • (3) 真理的相对性

          真理的相对性是指真理的有限性、有条件性,是指人们在一定条件下对世界的正确把握具有近似性。其含义有三层:其一,从认识的广度上看,任何真理只能是对无限的物质世界的某一阶段、某一方面、某一领域的认识。其二,从认识的深度上看,任何真理对特定事物的一定程度、一定层次的近似正确的反映。其三,从认识的进程看,任何真理只是对事物的一定发展阶段的正确认识。

      • 价值评价的定义:价值评价即对主体和客体的价值关系进行评判,是一种关于价值现象的评价性的认识活动。

      # 第三章 人类社会及其发展规律

      # 社会存在与社会意识的含义及其辩证关系(社会存在的含义,社会存在的要素及其对人类社会发展的作用;社会意识的含义及分类;社会存在与社会意识的辩证关系、社会意识相对独立性的表现)

      • 社会存在的含义:

      社会存在是指社会生活的物质方面,是社会实践和物质生活条件的总和。

      • 社会存在的要素:物质生产方式、自然地理环境和人口因素。

        • Ⅰ. 生产方式是社会历史发展的决定力量。

          • 其一,物质生产活动及生产方式是人类社会赖以存在和发展的基础,是人类其他一切活动的首要前提。

          • 其二,物质生产活动及生产方式决定着社会的结构、性质和面貌,制约着人们的经济生活、政治生活和精神生活等全部社会生活。

          • 其三,物质生产活动及生产方式的变化发展决定整个社会历史的变化发展,决定社会形态从低级向高级的更替和发展。

        • Ⅱ. 自然地理环境是人类社会生存和发展的必要和永恒的条件。是人们生活和生产的自然基础。自然地理环境提供了社会生活和生产资料的来源。

        • Ⅲ. 人口因素也是重要的社会物质生活条件,对社会发展起着制约和影响的作用。人是从事物质生产活动和其他一切社会活动的主体,是一切社会关系的承担者。

      • 社会意识的含义:社会意识是社会生活的精神方面,是社会存在的反映。

      • 社会意识的构成
        社会意识具有复杂的结构,可以按照不同的标准进行划分。

        • 根据社会意识的主体,可以分为个体意识、群体意识;

        • 根据其发展水平,可以分为

          • 低级的自发的社会心理

          • 高级的社会意识形式

            • 作为上层建筑的意识形式,又称为社会意识形态、观念上层建筑
              主要包括政治法律思想、道德、艺术、宗教、哲学等。
              在阶级社会中,社会意识形态本质上是占统治阶级的思想文化,反映经济基础,具有鲜明的阶级性。

            • 非上层建筑的意识形式
              包括语言学、逻辑学以及自然科学等。
              它不具有阶级性。

      • 社会存在和社会意识的关系

        社会存在和社会意识是辩证统一的关系。社会存在决定社会意识,社会意识是社会存在的反映,并反作用于社会存在。

        • (1) 社会存在对社会意识的决定作用表现在:

          • 其一,社会存在是社会意识内容的客观来源,社会意识是社会物质生活过程及其条件的主观反映。这是社会意识对社会存在的依赖性。

          • 其二,社会存在决定社会意识的性质。

          • 其三,随着社会存在的发展,社会意识也相应地或迟或早地发生变化和发展。

        • (2) 社会意识有其相对独立性,对社会存在具有反作用。其具体表现有:

          • 其一,社会意识具有相对独立性,它与社会存在之间存在发展的不平衡性、不同步性。

          • 其二,社会意识内部各种形式之间的相互影响及各自具有的历史继承性。

          • 其三,社会意识对社会存在的能动的反作用。这是社会意识相对独立性的突出表现。先进的社会意识,反映了社会发展的客观规律,可以对社会发展起积极的促进作用;而落后的社会意识,对社会发展起着阻碍的作用。

        • (3) 社会意识起作用的形式

      社会意识的能动作用是通过指导人们的实践活动实现的。思想本身并不能实现什么,要实现思想就要诉诸实践。而社会实践的主体是人民群众。因此,一种社会意识发挥作用的程度及范围大小、时间久暂,同它实际掌握群众的深度和广度密切联系在一起。

      # 生产力与生产关系的含义及其辩证关系;经济基础与上层建筑的含义及其辩证关系

      • 生产力的含义:是人类在生产事件中形成的改造和影响自然以使其适合社会需要的物质力量。

      • 生产关系的含义:生产关系是人们在物质生产过程中形成的不以人的意志为转移的经济关系。

      • 生产力与生产关系的关系

        生产力和生产关系是社会生产不可分割的两个方面。在社会生产中,生产力是生产的物质内容,生产关系是生产的社会形式,二者的有机结合和统一,构成社会的生产方式。

        • Ⅰ. 生产力决定生产关系:

          • (1) 生产力状况决定生产关系的性质。

          • (2) 生产力的发展决定生产关系的变化。

        • Ⅱ. 生产关系对生产力具有能动的反作用。其主要表现为:当生产关系适合生产力发展的客观要求时,它对生产力的发展起推动作用;当生产关系不适合生产力发展的客观要求时,它就会阻碍生产力的发展。

      • 经济基础的含义:经济基础是指由社会一定发展阶段的生产力所决定的生产关系的总和。其实质是社会一定发展阶段上的基本经济制度,是制度化的物质社会关系。其表现形式是经济体制,即社会基本经济制度所采取的组织形式和管理方式。

      • 上层建筑的含义:上层建筑是建立在一定经济基础之上的意识形态以及相应的制度、组织和设施。

      • 经济基础与上层建筑的关系 辩证统一

        • (1) 经济基础决定上层建筑。具体表现有:

          • 第一,经济基础的需要决定了上层建筑的产生;

          • 第二,经济基础的性质决定上层建筑的性质,有什么样的经济基础就有什么样的上层建筑;

          • 第三,经济基础的变更必然引起上层建筑的变革,并决定着其变革的方向。

        • (2) 上层建筑对经济基础具有反作用。

      这种反作用集中表现在,上层建筑保护和促进自己的经济基础的形成巩固和发展;同时反对和排除与自己性质不一致的生产关系。

      # 社会基本矛盾是人类社会发展的根本动力;人类社会发展动力学说

      • Ⅰ. 社会基本矛盾是人类社会发展的根本动力

        • 含义:社会基本矛盾就是指贯穿社会发展始终,规定社会发展过程的基本性质和基本趋势,并对社会历史发展起根本推动作用的矛盾。生产力和生产关系、经济基础和上层建筑的矛盾是社会的基本矛盾。

        • 作用:

          • (1)生产力是社会基本矛盾运动中最基本的动力因素,是人类社会发展和进步的最终决定力量。生产力是社会存在和发展的物质基础,是不能任意选择的物质力量和历史活动的前提。

          • (2)生产力是社会进步的根本内容,是衡量社会进步的根本尺度。人类社会是在生产力与生产关系的矛盾运动中前进的。

          • (3)社会基本矛盾特别是生产力和生产关系的矛盾,决定着社会中其他矛盾的存在和发展。

          • (4)经济基础和上层建筑的矛盾也会影响和制约生产力和生产关系的矛盾。

          • (5)社会基本矛盾具有不同的表现形式,并从根本上影响和促进社会形态的变化和发展。

      • Ⅱ. 人类社会发展动力学

        • (1)阶级斗争是社会基本矛盾在阶级社会中表现,是阶级社会发展的直接动力。离开了阶级斗争,就无法理解阶级社会发展。“没有对抗就没有进步。这是文明直到今天所遵循的规律。”

        • (2)社会革命是阶级斗争发展到一定阶级的产物,是推动社会发展的重要动力。

      # 第四章 资本主义的本质及规律

      # 商品经济的含义、产生条件、特点

      • 含义:是以交换为目的而进行生产的经济形式,它是一定社会历史条件产物。

      • 产生条件:

        • (1)存在社会分工

        • (2)生产资料和劳动产品属于不同的所有者。

      • 特点

        • (1)商品经济本质上是交换经济,在商品经济条件下,生产要素和消费资料的全部或大部分都要通过市场交换来获得,商品生产者以追求价值为目的,并通过市场交换来实现。

        • (2)商品经济是开放型经济,商品经济以社会分工为基础,强调生产过程中的分工与协作,人与人之间,商品生产者之间以及生产单位之间的经济联系随着商品经济的发展而日益紧密,范围也日益扩大。

        • (3)商品经济是开拓进取型经济。

        • (4)商品经济以扩大再生产为特征。商品生产者为获得更多的价值实现和在竞争中处于有利地位,必然不断增加投入,改进技术和改善经营管理,从而使生产规模不断扩大。

      # 商品的含义、商品二因素及其辩证关系、商品的价值量

      • 含义:是用来交换,能满足人们某种需要的劳动产品,具有使用价值和价值两种因素或者两种属性,是使用价值和价值的统一体。

      • 商品的二因素及其辩证关系

        • 1. 商品的二因素:使用价值和价值。

          • 关于使用价值:

            • (1)使用价值反映的是人与自然之间的物质关系,是商品的自然属性,是一切劳动产品所共有的属性,使用价值由商品本身的自然属性决定,离开了商品它就不复存在。

            • (2)使用价值是交换价值的物质承担者。

          • 关于价值:

            • (1)价值是凝结在商品中无差别的一般人类劳动,即人类脑力和体力的耗费。

            • (2)价值是商品所特有地位社会属性。

            • (3)价值是交换价值的基础,交换价值是价值的表现形式。

        • 2. 辩证关系

          • (1)商品的价值和使用价值之间是对立统一的关系。

          • (2)其对立表现在:商品的使用价值和价值是相互排斥的,二者不可兼得。要获得商品的价值,就必须放弃商品的使用价值;要得到商品的使用价值,就不能得到商品的价值。

          • (3)其统一性表现在:作为商品,必须同时具有使用价值和价值两个因素。使用价值是价值的物质承担者,价值寓于使用价值之中。一种物品尽管具有使用价值,但如果不是劳动产品,也没有价值。

      • 商品的价值量

        • (1)首先,价值量是由劳动者生产商品所耗费的劳动量决定的,而劳动量则是按照劳动时间来计量。决定商品价值量的不是生产商品的个别劳动时间,而只能是社会必要劳动时间。生产商品所需要的社会必要劳动时间随着劳动生产力的变化而变化。

        • (2)商品价值量与生产商所耗费的劳动时间成正比,与劳动生产力成反比。

        • (3)商品的价值量同简单劳动与复杂劳动有密切饿关系。简单劳动书指不需要经过专门训练和培养的一般劳动者能从事的劳动。复杂劳动是指需要经过专门的训练和培养,具有一定的文化知识和技术专长的劳动者所从事的劳动。

      # 劳动二重性

      • 生产商品的劳动可以区分为具体劳动和抽象劳动

        • 具体劳动是指生产一定使用价值的具体形式的劳动;

        • 抽象劳动是指撇开一切具有形式的、无差别的一般人类劳动,即人的体力和脑力消耗。

        • 具体劳动形成商品的使用价值,抽象劳动形成商品的价值实体。

      • 劳动的二重性决定了商品的二因素。具体劳动和抽象劳动是对立统一的:

        • 一方面,具体劳动和抽象劳动在时间上和空间上是统一的,是商品生产者的同一劳动过程的不可分割的两方面;

        • 另一方面,具体劳动所反映的是人与自然的关系,是劳动的自然属性,抽象劳动所反映的是商品生产者的社会关系,是劳动的社会属性。

      # 价值规律的内容、表现形式、作用

      • 价值规律的基本内容:

      • ①商品的价值量是由生产这种商品的社会必要劳动时间决定的。

      • ②商品交换要以价值量为基础,按照等价交换的原则进行。

      • 价值规律的表现形式:
        商品的价格围绕商品的价值上下波动。

      • 价值规律的作用:

        • ①自发地调节生产资料和劳动力在社会各生产部门之间的分配比例。

        • ②自发地刺激社会生产力的发展。

        • ③自发地调节社会收入的分配。

      # 劳动力商品的特点

      • 劳动力商品的使用价值是价值的源泉

      • 劳动力成为商品的基本条件:

        • 第一、劳动者是自由人,能够把自己的劳动力当做自己的商品来支配;

        • 第二、劳动者自由的一无所有,没有任何实现自己的劳动力所必需的物质条件。

      • 劳动力的价值,是由生产、发展、维持和延续劳动力所必需的生活必需品的价值决定的。
        它包括三个部分:

        • ① 是维持劳动者自身生存所必需的生活资料的价值,用以再生产他的劳动力。

        • ② 是劳动者家属的生存必需的生活资料的价值,用以延续劳动力的供给。

        • ③ 劳动者接受教育和训练所支出的费用,用以培训适合资本主义再生产所需要的劳动力。

      # 资本主义生产的直接目的;绝对剩余价值、相对剩余价值

      • 资本主义生产的直接目的是获取更多剩余价值。

      • 资本主义生产是以雇佣劳动为基础,以获取剩余价值为目的的生产。

      • 其生产过程具有二重性:一方面是生产使用价值的劳动过程;另一方面又是生产剩余价值的价值增殖过程。

      • 绝对剩余价值是指在必要劳动时间不变的条件下,由于延长工作日的长度和提高劳动强度而生产的剩余价值。

      • 相对剩余价值是指在工作日长度不变的条件下,通过缩短必要劳动时间而相对延长剩余劳动时间所生产的剩余价值

      # 资本主义扩大再生产的途径

      • 第一,第 Ⅰ 部类原有可变资本加上追加的可变资本,再加上本部类资本家用于个人消费的剩余价值之和,必须等于第 Ⅱ 部类的不变资本加上追加的不变资本,即
        Ⅰ(v+△v+m/x)=Ⅱ(c+△c)

      • 第二,第 Ⅰ 部类全部产品的价值必须等于两大部类原有的不变资本加上追加的不变资本,即
        Ⅰ(c+v+m)=Ⅰ(c+△c)+Ⅱ(c+△c)

      • 第三,第 Ⅱ 部类全部产品的价值必须等于两大部类原有的可变资本加上追加的可变资本,再加上资本家用于个人消费的剩余价值之和,即
        Ⅱ(c+v+m)=Ⅰ(v+△v+m/x)+Ⅱ(v+△v+m/x)

      # 资本主义基本矛盾、资本主义经济危机的实质

      • 基本矛盾:生产社会化和生产资料资本主义私人占有之间的矛盾。

      • 资本主义经济危机的实质:相对过剩的危机,即生产和销售矛盾造成的相对过剩。

      # 资本主义选举制度

      • 是资产阶级制定某种原则和程序,通过竞选产生议会和国家元首的一种政治机制。

      • 在资本主义国家中,选举已经成为国家政治制度运行中对社会发展和稳定产生举足轻重影响的一个不可或缺的政治机制。

      # 第五章 资本主义的发展及其趋势

      # 第六章 社会主义的发展及其规律(本章仅供学习参考,不作考试要求)

      # 科学社会主义的基本原则

      • 第一,在生产资料公有制基础上组织生产,满足全体社会成员的需要是社会主义生产的根本目的。

      • 第二,对社会生产进行有计划的指导和调节,实行等量劳动领取等量产品的按劳分配原则。

      • 第三,合乎自然规律地改造和利用自然。

      • 第四,无产阶级革命是无产阶级进行斗争的最高形式,必须以建立无产阶级专政的国家为目的。

      • 第五,社会主义事业必须坚持无产阶级政党的领导。

      • 第六,通过无产阶级专政和社会主义高度发展,最终实现向消灭阶级、消灭剥削,实现人的全面而自由发展的共产主义的过渡。

      • 一方面,科学社会主义基本原则任何时候都不能违背;另一方面,科学社会主义基本原则在实践中不能僵化地教条地对待它。

      # 经济文化相对落后国社会主义革命理论

      经济文化相对落后的国家社会主义建设的艰巨性和长期性

      • 第一、生产力发展状态的约束。社会主义国家在经济上落后于发达的资本主义国家,有的甚至落后很远,社会主义制度下必须把大力发展生产力作为根本任务,努力完成生产社会化、商品化、现代化的艰巨任务。

      • 第二、经济基础和上层建筑发展状况的制约。发展公有经济,改造小农经济,建立、巩固和完善社会主义的经济基础,就成为无产阶级政权的一项十分巨大的任务。社会主义民主政治建设受到这些国家的经济、政治、文化条件的严重制约,在这一过程中,还要进一步消灭阶级和阶级差别,改变几千年形成的传统观念,建设社会主义的先进文化,实现真正的社会公正的平等。

      • 第三,国际环境的严峻挑战。如果说在社会主义国家成立之初,国际资本主义对资本主义的进攻主要是武力方式,那么在社会主义建设取得重大成就后,进攻方式则往往转变为一和平演变为主。一是通过军事、政治压力盒有限的经济、科技的合作和援助,迫使社会主义国家屈从其经济政治。二是通过文化渗透,在社会主义国家内部制造经济、政治、思想等种种混乱,阻挠和破坏社会主义国家的发展。

      • 第四,马克思主义执政党和对社会主义发展的道路的探索和对社会主义建设规律的认识,需要一个长期的艰苦的

      # 第七章 共产主义是人类最崇高的社会理想

      # 实现共产主义是一个长期的历史过程(辨析题)p286

      • (1)理论上,马克思主义所揭示的社会形态发展与更替的规律是一般的历史规律,是只有在漫长的历史过程中才能体现出来的规律。

      • (2)每一个社会形态的产生发展,都会经历一个很长的历史时期,而旧的社会形态走向没落并为新的社会形态所代替也是一个长期的历史过程。

      • (3)从资本主义到共产主义的转变是一种根本的转变,它不是具体制度的更新,而是整个社会的根本改造,因而必然是个长期而艰难的过程。

      # 共产主义的基本特征 p275

      • (1)物质财富极大丰富,消费资料按需分配。

      • (2)社会关系高度和谐,人们精神境界极大提高。

      • (3)每个人自由而全面的发展,人类从必然王国向自由王国飞跃。

      \ No newline at end of file +马原题纲 - 马克思主义基本原理 - 思政 | Balloon Party = 風船のパーティー = fuusen no party

      # 思维导图

      # 绪论部分

      绪论部分

      # 第一章 世界的物质性及发展规律

      第一章 世界的物质性及发展规律

      # 第二章 实践与认识及其发展规律

      第二章 实践与认识及其发展规律

      # 第三章 人类社会及其发展规律

      第三章 人类社会及其发展规律

      # 第四章 资本主义的本质及规律

      第四章 资本主义的本质及规律

      # 第六章社会主义的发展及其规律(本章仅供学习参考,不作考试要求)

      第六章 社会主义的发展及其规律(本章仅供学习参考,不作考试要求)

      # 第七章 共产主义是人类最崇高的社会理想

      第七章 共产主义是人类最崇高的社会理想

      # 大纲

      # 绪论部分

      # 马克思主义的含义、理论来源、经典著作、鲜明特征;马克思主义基本原理的含义(马克思主义的基本立场、基本观点、基本方法);

      • 含义:马克思主义是由马克思和恩格斯创立的,为他们的后继承者所发展的,以反对资本主义、建设社会主义和实现共产主义为目标的科学理论体系,是关于无产阶级和人类解放的科学。

      • 理论来源: 德国古典哲学、英国古典政治经济学、英法两国的空想社会主义。

      • 经典著作:

        • 两人《神圣家族》 《德意志意识形态》 《共产党宣言》 《新莱茵报》

          • 马《资本论》 《法兰西内战》 《哥达纲领批判》

          • 恩《反杜林论》 《家庭、私有制和国家的起源》 《路德维希・费尔巴哈和德国古典哲学的终结》

      整理出版《资本论》二三卷

      • 鲜明特征:

        • (1)科学性,它是对客观世界特别是人类社会本质和规律的正确反应。(表现在坚持世界的物质性和真理的客观性)

        • (2)革命性, 它是无产阶级和广大人民群众推翻旧世界,建设新世界的理论,按本质来说,它是批判的和革命的,它具有鲜明的无产阶级政治立场(表现在坚持唯物辩证法)。

        • (3)实践性,马克思主义的科学性和革命性是统一的,以社会主义运动的实践为基础,致力于实现无产阶级和广大人民群众的根本利益。

      • 马克思主义基本原理的含义

        • (1)基本立场:是马克思主义观察、分析和解决问题的根本立足点和出发点

        • (2)基本观点:是关于自然、社会和人类思维发展一般规律的科学认识,是对人类思想成果和社会实践经验的科学总结

        • (3)基本方法:是建立在辩证唯物主义和历史唯物主义世界观和方法论基础上的指导我们正确认识世界和改造世界的思想方法和工作方法。

      # 第一章 世界的物质性及发展规律

      # 哲学的基本问题、哲学派别的划分及各派别的基本思想和代表人物(唯物主义 VS 唯心主义;可知论 VS 不可知论;唯物史观 VS 唯心史观;辩证法 VS 形而上学)

      • 哲学的基本问题:存在和思维、物质和精神的关系问题

        • 存在和思维、物质和精神何者是第一性

        • 存在和思维、物质和精神是否具有同一性

      • 哲学派别的划分及各派别的基本思想和代表人物

        • 存在和思维究竟谁是世界的本原,即物质和精神何者是第一性、何者是第二性的问题

          • 唯物主义

          存在决定思维

          • 唯心主义

          思维决定存在

        • 存在和思维是否具有同一性?我们关于我们周围世界的思想对这个世界本身的关系是怎样的?我们的思维能不能认识现实世界?我们能不能在我们关于现实世界的表象和概念中正确的反映现实?

          • 可知论

          认为思维和存在有同一性,人的意识能够认识客观世界及其规律

          • 不可知论

          认为思维和存在没有同一性,人的意识不能或不能彻底认识客观世界及其规律
          古希腊怀疑论者 皮浪,

        • 社会意识和社会存在的关系

          • 唯物史观

          社会存在决定社会意识

          • 唯心史观

          社会意识决定社会存在

        • 是否承认事物的内部矛盾是事物发展的根本动力

          • 辩证法

          承认事物的内部矛盾是事物发展的根本动力

          • 形而上学

          否认事物的内部矛盾是事物发展的根本动力

      # 物质观(物质的含义、意识的含义;物质与意识的辩证关系;主观能动性与客观规律性的统一)、运动观(运动的含义、运动与静止、运动与物质的关系)、时空观(时间的含义及其特点、空间的含义及其特点、时空与物质运动的关系)

      • (一)物质观

        • 物质的含义:物质就是不依赖于人类意识而存在并能为人类的意识所反映的客观存在

        • 意识的含义:意识是人脑的机能和属性,是客观世界的主观映像

        • 物质与意识的辩证关系:

          • (一) 物质决定意识。物质对意识的决定作用表现在意识的起源、本质和作用上。

          • (二) 意识对物质具有反作用。

            • 1. 意识活动具有目的性和计划性;

            • 2. 意识活动具有创造性;

            • 3. 意识具有指导实践改造客观世界的作用;

            • 4. 意识具有控制人的行为和生理活动的作用。

          • (三) 主观能动性和客观规律性的统一

        • 主观能动性与客观规律性的统一:

          • 首先,尊重客观规律是正确发挥主观能动性的前提

          • 其次,只有充分发挥主观能动性,才能正确认识和利用客观规律。

          • 要正确发挥主观能动性,应注意:

            • 一,从实际出发,努力认识和把握事物的发展规律。

            • 二,实践是发挥人的主观能动性的途径。

            • 三,主观能动性的发挥还依赖于一定的物质条件和物质手段

      • (二)运动观

        • 运动的含义:运动是标志一切事物和现象的变化及其过程的哲学范畴

        • 运动与静止:物质世界的运动是绝对的,而物质在运动的过程中又有某种相对的静止。相对静止是物质运动在一定条件下的稳定状态,包括空间的相对位置和事物的根本性质暂时未变这样两种运动的特殊状态。

          • 运动的绝对性体现了物质运动的变动性、无条件性,静止的相对性体现了物质运动的稳定性,有条件性。

          • 运动和静止相互依赖、相互渗透、相互包含,“静中有动,动中有静”。

          • 无条件的绝对运动和有条件的相对静止构成对立统一关系

        • 运动与物质的关系:物质和运动是不可分割的,运动是物质的运动,物质是运动着的物质,离开物质的运动和离开运动的物质都是不可想象的。

      • (三)时空观

        • 时间的含义:是指物质运动的持续性、顺序性

        特点:一维性,即一去不复返

        • 空间的含义:是指物质运动的广延性、伸张性

        特点:三维性

        • 时空与物质运动的关系:

      物质运动总是在一定的时间和空间中进行的,没有离开物质运动的 “纯粹” 时间和空间,也没有离开时间和空间的物质运动。

      # 世界的物质统一性原理

      • (一)意识统一于物质。

      • (二)人类社会也统一于物质。

        • 1. 人类社会依赖于自然界,是整个物质世界的组成部分。

        • 2. 人类谋取物资生活资料的实践活动虽然有意识作指导,但仍然是以物质力量改造物质力量的活动,仍然是物质活动。

        • 3. 物质资料的生产方式是人类社会存在和发展的基础,集中体现着人类社会的物质性。

      # 唯物辩证法的总特征:联系与发展的观点(联系的含义、特点;发展的含义、实质等)

      • 联系的含义:作为一个普遍的哲学范畴,联系是指事物内部各要素之间和事物之间相互影响、相互制约、相互作用的关系。

      • 联系的特点:客观性、普遍性、多样性、条件性

      • 发展的含义:变化的基本趋势是发展,发展是前进的上升的运动

      • 发展的实质:

        • 新事物的产生和旧事物的灭亡。

          • 新事物是指合乎历史前进方向,具有远大前途的东西

          • 旧事物是指丧失历史必然性、日趋灭亡的东西

      # 唯物辩证法的五对范畴(原因与结果、现象与本质、内容与形式、必然性与偶然性、现实性与可能性)

      • 原因与结果:这是揭示事物引起和被引起的一对范畴。

        原因是引起某种现象的现象,结果是被某种现象引起的现象。

        因果关系就是包括时间先后顺序在内的一种现象必然引起另一种现象的普遍联系

      • 现象与本质:这是揭示事物外在联系和内在联系的一对范畴。

        现象是事物的外部联系和表面特征,本质是事物的根本性质和构成要素的内在联系。

        本质是现象的根据,现象是本质的表现

      • 内容与形式:这是从构成要素和表现方式两个方面反映事物的一对范畴。

        内容是指构成事物的一切要素总和,形式是指把内容诸要素统一起来的结构或表现内容的方式

      • 必然性与偶然性:这是揭示事物发生、发展和灭亡的不同趋势的一对范畴。

        必然性是事物联系和发展过程中合乎规律的确定不移的趋势,

        偶然性是联系和发展过程中并非必定如此的、不确定的趋势。

      • 现实性与可能性:这是反映事物过去、现在和将来关系的一对范畴。

        现实性包括内在根据的、合乎必然性的存在,

        可能性是指包含在现实事物中、预示着事物发展前途的种种趋势。

      # 唯物辩证法的三大规律:对立统一规律(矛盾的同一性与斗争性的辩证关系;矛盾的普遍性与特殊性的辩证关系)、质量互变规律(质、量、度等范畴的含义;量变与质变的辩证关系)、否定之否定规律;对立统一规律是唯物辩证法的实质与核心

      • 一、对立统一规律:是事物发展的根本规律,是唯物辩证法的实质与核心。

        ①矛盾是反应事物内部和事物之间对立统一关系的哲学范畴。

        矛盾的同一性和斗争性是相互联结,相辅相成的,没有斗争性就没有同一性,没有同一性也没有斗争性,斗争性寓于同一性之中。

        ②矛盾的普遍性与特殊性是辩证统一的关系,任何现实存在的事物的矛盾都是共性和个性的有机统一,共性寓于个性之中,没有离开个性的共性,也没有离开共性的个性。

      • 二、质量互变规律:

        • ① 事物的联系和发展都采取量变和质变两种状态和形式。

        • ② 质是一事物区别于其他事物的内在规定,量是事物的规模、程度、速度等可以用数量关系表示的规定性。

        度是保持事物质的稳定性的数量界限,即事物的限度、幅度和范围。

        度的两端叫关节点或临界点,超出度的范围,此物就转化为他物。

        “度” 启示我们,在认识和处理问题时要掌握适度的原则。

        • ③ 辩证关系:

          • (1)量变是质变的必要准备

          • (2)质变是量变的必然结果

          • (3)量变和质变是相互渗透的。

      • 三、否定之否定规律:

        • ① 辩证否定观

          • (1)否定是事物的自我否定,是事物内部矛盾运动的结果

          • (2)否定是事物发展的环节,是新事物向旧事物的转变,是旧质到新质的飞跃

          • (3)否定是新旧事物联系的环节

          • (4)辩证否定的实质是 “扬弃” 即新事物对旧事物既批判又继承,既克服其消极因素又保留其积极因素。

        • ② 否定之否定规律揭示了事物发展的前进性与曲折性的统一。

        • ③ 按照否定之否定规律办事,要求我们对待一切事物都要采取科学分析的态度,反对肯定一切和否定一切的形而上学否定观。

      # 如何理解 “以唯物辩证法为指导,不断增强思维能力”P53(五大思维)

      • 一、思维能力包括:战略思维能力、历史思维能力、辩证思维能力、创新思维能力、底线思维能力

      // 战历辩创底

      • 二、战略思维能力,就是高瞻远瞩、统揽全局,善于把握事物发展总体趋势和方向的能力。(树立大局意识,放眼未来。善于观大势,把握工作主权。开阔视野,紧跟时代步伐。)

      • 三、历史思维能力就是以史为鉴、知古鉴今,善于运用历史眼光认识发展规律、把握前进方向、知道现实工作的能力。(善于运用历史智慧推进 ** 的思想观点。加强对中国历史,世界历史的学习,总结历史经验,把握认清规律,更好的走向未来。)

      • 四、辩证思维能力就是承认矛盾,分析矛盾、解决矛盾,善于抓住关键,找准重点,洞察事物发展规律的能力。(坚持 “两点论”, 一分为二的看问题。要勇于进取,稳扎稳打。发展的眼光,全面,普遍联系)

      • 五、创新思维能力就是破除迷信、超越过时的陈规,善于因时制宜、知难而进、开拓创新的能力。(勇于创新,不因循守旧,满足现状。有探索真知、求真务实的态度。百折不挠、勇往直前,不断积累经验。)

      • 六、底线思维能力就是客观地设定最低目标,立足最低点,争取最大期望值的一种积极的思维能力.(基点放在出现较大的锋线上,做好对策,争取最好结果。要居安思危,增强忧患意识。)

      # 第二章 实践与认识及其发展规律

      # 实践观(实践的含义、特点、类型、实践在认识中的决定性作用、实践是检验真理的唯一标准)

      • 一、实践的本质含义:实践是人类能动地改造世界的感性物质活动。

      • 二、实践的基本特征:

        • 第一,实践是改造世界的客观物质活动,具有直接现实性。

        • 第二,实践是人类有意识的活动,体现了自觉能动性。

        • 第三,实践是社会的、历史的活动,具有社会历史性。

      • 三、实践的类型:

        • (1)物质生产实践(最基本的):人类最基本的实践活动,决定着社会的基本性质和面貌。

          • (2)社会政治实践:是改造社会关系的实践活动,形成了复杂的社会政治关系

          • (3)科学文化实践:是创造精神文化产品的实践活动。

      • 四、实践在认识中的决定作用:

        • (1)辩证唯物主义认识论认为,实践决定认识,实践是认识的基础。

        • (2)实践是认识的来源

        • (3)实践是认识发展的动力

        • (4)实践是认识的目的

        • (5)实践是检验认识真理性的唯一标准。

      # 辩证唯物主义和旧唯物主义对认识本质的不同回答;感性认识和理性认识及其辩证关系、非理性因素;认识运动的基本规律

      • Ⅰ. 辩证唯物主义和旧唯物主义对认识本质的不同回答:

        • ② 辩证唯物主义和旧唯物主义都坚持反映论,但是两者之间又有着本质的区别

        • ② 旧唯物主义认识论以感性直观为基础,把人的认识看成是消极地、被动地反映和接受外界对象,不能把认识看作一个不断发展的过程,认为认识是一次性完成的。这种直观的,消极被动的反映论是不科学的

        • ③ 辩证唯物主义认识论继承了旧唯物主义反映论的合理前提,同时又克服了它的严重缺陷。它把实践的观点引入认识论,把辩证法应用于反映论,把认识看成是一个由不知到知、由浅入深的充满矛盾的能动的认识过程,是能动的反映论。

      • Ⅱ. 感性认识和理性认识及其辩证关系、非理性因素:

        • ① 感性认识:是认识的低级阶段,是人在实践中通过感官对事物外部形态的直接的、具体的反映。它包括感觉、知觉、表象三种形式。它的突出特点是直接现实性。它只是对事物表面现象的反映,没有反映事物的本质,因而具体局限性。

        • ② 理性认识:人们通过抽象思维得到的对事物本质、内在联系和规律性的认识,是认识的高级阶段,包括概念、判断和推理三种形式。其特点是间接性和抽象性。

        • ③ 感性认识和理性认识的辩证关系:

          • (1)感性认识是理性认识的基础,理性认识依赖于感性认识。

          • (2)感性认识有待于发展和深化为理性认识。

          • (3)感性认识和感性认识相互渗透、相互包含。

          • ④ 从感性认识上升到理性认识需要具备的条件:

            • (1)勇于实践、深入调查,获取丰富的感性材料,这是基础。

            • (2)必须经过理性思考,将感性材料加以去粗取精、去伪存真、由此及彼、由表及里加工,才能将感性认识上升为理性认识。

          • ⑤ 非理性因素:主要是指认识主体的情感和意志。也包括不自觉、非逻辑等特点的认识形式(如:联想、想象、猜测、直觉、顿悟、灵感等)

            • (1)人的认识过程是理性因素和非理性因素协同作用的结果。

            • (2)非理性因素对于人的认识能力和人是活动具有激活,驱动和控制作用我们应当在理性认识的指导下,充分发挥非理性因素的积极作用)

      • Ⅲ. 认识运动的基本规律:

        • (1)认识运动的辩证过程,是从实践到认识的过程,即在实践基础上由感性认识能动的飞跃到理性认识的过程。

        • (2)认识过程的第二个阶段是从认识到实践,即由 “精神到物质的阶段,由思想到存在的阶段”。

        • (3)认识运动是不断反复和无限发展的,是一个波浪式前进和螺旋式上升的过程。

      # 真理的含义及其属性;价值评价的含义

      • 真理的定义

      真理是人们对于客观事物及其规律的正确认识。

      • 真理的属性

        • (1) 真理的客观性

          真理具有客观性,凡真理都是客观真理。真理的客观性或客观真理有两层含义:一是指真理的内容是客观的,是不以人的意志为转移的客观世界;二是指检验真理的标准是客观的。检验真理的唯一标准是实践,而实践是物质性的活动。

          • (2) 真理的绝对性

          真理的绝对性或者绝对真理是指真理的内容具有正确性,真理的发展具有无限性。其具体含义有:其一,就真理的内容而言,任何真理都必然包含着同客观对象相符合的客观内容,都同谬误有原则的界限。因此,承认了客观真理就是承认了绝对真理。其二,就真理的发展而言,其前景是无限的。由于人类依其认识本性来说,能够正确认识无限发展着的物质世界。所以,承认世界的可知性,也就是承认了绝对真理。其三,就真理发展的最终结果而言,无数相对真理的总和构成为绝对真理。所以,承认认识发展的无限性,就必然承认绝对真理。

          • (3) 真理的相对性

          真理的相对性是指真理的有限性、有条件性,是指人们在一定条件下对世界的正确把握具有近似性。其含义有三层:其一,从认识的广度上看,任何真理只能是对无限的物质世界的某一阶段、某一方面、某一领域的认识。其二,从认识的深度上看,任何真理对特定事物的一定程度、一定层次的近似正确的反映。其三,从认识的进程看,任何真理只是对事物的一定发展阶段的正确认识。

      • 价值评价的定义:价值评价即对主体和客体的价值关系进行评判,是一种关于价值现象的评价性的认识活动。

      # 第三章 人类社会及其发展规律

      # 社会存在与社会意识的含义及其辩证关系(社会存在的含义,社会存在的要素及其对人类社会发展的作用;社会意识的含义及分类;社会存在与社会意识的辩证关系、社会意识相对独立性的表现)

      • 社会存在的含义:

      社会存在是指社会生活的物质方面,是社会实践和物质生活条件的总和。

      • 社会存在的要素:物质生产方式、自然地理环境和人口因素。

        • Ⅰ. 生产方式是社会历史发展的决定力量。

          • 其一,物质生产活动及生产方式是人类社会赖以存在和发展的基础,是人类其他一切活动的首要前提。

          • 其二,物质生产活动及生产方式决定着社会的结构、性质和面貌,制约着人们的经济生活、政治生活和精神生活等全部社会生活。

          • 其三,物质生产活动及生产方式的变化发展决定整个社会历史的变化发展,决定社会形态从低级向高级的更替和发展。

        • Ⅱ. 自然地理环境是人类社会生存和发展的必要和永恒的条件。是人们生活和生产的自然基础。自然地理环境提供了社会生活和生产资料的来源。

        • Ⅲ. 人口因素也是重要的社会物质生活条件,对社会发展起着制约和影响的作用。人是从事物质生产活动和其他一切社会活动的主体,是一切社会关系的承担者。

      • 社会意识的含义:社会意识是社会生活的精神方面,是社会存在的反映。

      • 社会意识的构成
        社会意识具有复杂的结构,可以按照不同的标准进行划分。

        • 根据社会意识的主体,可以分为个体意识、群体意识;

        • 根据其发展水平,可以分为

          • 低级的自发的社会心理

          • 高级的社会意识形式

            • 作为上层建筑的意识形式,又称为社会意识形态、观念上层建筑
              主要包括政治法律思想、道德、艺术、宗教、哲学等。
              在阶级社会中,社会意识形态本质上是占统治阶级的思想文化,反映经济基础,具有鲜明的阶级性。

            • 非上层建筑的意识形式
              包括语言学、逻辑学以及自然科学等。
              它不具有阶级性。

      • 社会存在和社会意识的关系

        社会存在和社会意识是辩证统一的关系。社会存在决定社会意识,社会意识是社会存在的反映,并反作用于社会存在。

        • (1) 社会存在对社会意识的决定作用表现在:

          • 其一,社会存在是社会意识内容的客观来源,社会意识是社会物质生活过程及其条件的主观反映。这是社会意识对社会存在的依赖性。

          • 其二,社会存在决定社会意识的性质。

          • 其三,随着社会存在的发展,社会意识也相应地或迟或早地发生变化和发展。

        • (2) 社会意识有其相对独立性,对社会存在具有反作用。其具体表现有:

          • 其一,社会意识具有相对独立性,它与社会存在之间存在发展的不平衡性、不同步性。

          • 其二,社会意识内部各种形式之间的相互影响及各自具有的历史继承性。

          • 其三,社会意识对社会存在的能动的反作用。这是社会意识相对独立性的突出表现。先进的社会意识,反映了社会发展的客观规律,可以对社会发展起积极的促进作用;而落后的社会意识,对社会发展起着阻碍的作用。

        • (3) 社会意识起作用的形式

      社会意识的能动作用是通过指导人们的实践活动实现的。思想本身并不能实现什么,要实现思想就要诉诸实践。而社会实践的主体是人民群众。因此,一种社会意识发挥作用的程度及范围大小、时间久暂,同它实际掌握群众的深度和广度密切联系在一起。

      # 生产力与生产关系的含义及其辩证关系;经济基础与上层建筑的含义及其辩证关系

      • 生产力的含义:是人类在生产事件中形成的改造和影响自然以使其适合社会需要的物质力量。

      • 生产关系的含义:生产关系是人们在物质生产过程中形成的不以人的意志为转移的经济关系。

      • 生产力与生产关系的关系

        生产力和生产关系是社会生产不可分割的两个方面。在社会生产中,生产力是生产的物质内容,生产关系是生产的社会形式,二者的有机结合和统一,构成社会的生产方式。

        • Ⅰ. 生产力决定生产关系:

          • (1) 生产力状况决定生产关系的性质。

          • (2) 生产力的发展决定生产关系的变化。

        • Ⅱ. 生产关系对生产力具有能动的反作用。其主要表现为:当生产关系适合生产力发展的客观要求时,它对生产力的发展起推动作用;当生产关系不适合生产力发展的客观要求时,它就会阻碍生产力的发展。

      • 经济基础的含义:经济基础是指由社会一定发展阶段的生产力所决定的生产关系的总和。其实质是社会一定发展阶段上的基本经济制度,是制度化的物质社会关系。其表现形式是经济体制,即社会基本经济制度所采取的组织形式和管理方式。

      • 上层建筑的含义:上层建筑是建立在一定经济基础之上的意识形态以及相应的制度、组织和设施。

      • 经济基础与上层建筑的关系 辩证统一

        • (1) 经济基础决定上层建筑。具体表现有:

          • 第一,经济基础的需要决定了上层建筑的产生;

          • 第二,经济基础的性质决定上层建筑的性质,有什么样的经济基础就有什么样的上层建筑;

          • 第三,经济基础的变更必然引起上层建筑的变革,并决定着其变革的方向。

        • (2) 上层建筑对经济基础具有反作用。

      这种反作用集中表现在,上层建筑保护和促进自己的经济基础的形成巩固和发展;同时反对和排除与自己性质不一致的生产关系。

      # 社会基本矛盾是人类社会发展的根本动力;人类社会发展动力学说

      • Ⅰ. 社会基本矛盾是人类社会发展的根本动力

        • 含义:社会基本矛盾就是指贯穿社会发展始终,规定社会发展过程的基本性质和基本趋势,并对社会历史发展起根本推动作用的矛盾。生产力和生产关系、经济基础和上层建筑的矛盾是社会的基本矛盾。

        • 作用:

          • (1)生产力是社会基本矛盾运动中最基本的动力因素,是人类社会发展和进步的最终决定力量。生产力是社会存在和发展的物质基础,是不能任意选择的物质力量和历史活动的前提。

          • (2)生产力是社会进步的根本内容,是衡量社会进步的根本尺度。人类社会是在生产力与生产关系的矛盾运动中前进的。

          • (3)社会基本矛盾特别是生产力和生产关系的矛盾,决定着社会中其他矛盾的存在和发展。

          • (4)经济基础和上层建筑的矛盾也会影响和制约生产力和生产关系的矛盾。

          • (5)社会基本矛盾具有不同的表现形式,并从根本上影响和促进社会形态的变化和发展。

      • Ⅱ. 人类社会发展动力学

        • (1)阶级斗争是社会基本矛盾在阶级社会中表现,是阶级社会发展的直接动力。离开了阶级斗争,就无法理解阶级社会发展。“没有对抗就没有进步。这是文明直到今天所遵循的规律。”

        • (2)社会革命是阶级斗争发展到一定阶级的产物,是推动社会发展的重要动力。

      # 第四章 资本主义的本质及规律

      # 商品经济的含义、产生条件、特点

      • 含义:是以交换为目的而进行生产的经济形式,它是一定社会历史条件产物。

      • 产生条件:

        • (1)存在社会分工

        • (2)生产资料和劳动产品属于不同的所有者。

      • 特点

        • (1)商品经济本质上是交换经济,在商品经济条件下,生产要素和消费资料的全部或大部分都要通过市场交换来获得,商品生产者以追求价值为目的,并通过市场交换来实现。

        • (2)商品经济是开放型经济,商品经济以社会分工为基础,强调生产过程中的分工与协作,人与人之间,商品生产者之间以及生产单位之间的经济联系随着商品经济的发展而日益紧密,范围也日益扩大。

        • (3)商品经济是开拓进取型经济。

        • (4)商品经济以扩大再生产为特征。商品生产者为获得更多的价值实现和在竞争中处于有利地位,必然不断增加投入,改进技术和改善经营管理,从而使生产规模不断扩大。

      # 商品的含义、商品二因素及其辩证关系、商品的价值量

      • 含义:是用来交换,能满足人们某种需要的劳动产品,具有使用价值和价值两种因素或者两种属性,是使用价值和价值的统一体。

      • 商品的二因素及其辩证关系

        • 1. 商品的二因素:使用价值和价值。

          • 关于使用价值:

            • (1)使用价值反映的是人与自然之间的物质关系,是商品的自然属性,是一切劳动产品所共有的属性,使用价值由商品本身的自然属性决定,离开了商品它就不复存在。

            • (2)使用价值是交换价值的物质承担者。

          • 关于价值:

            • (1)价值是凝结在商品中无差别的一般人类劳动,即人类脑力和体力的耗费。

            • (2)价值是商品所特有地位社会属性。

            • (3)价值是交换价值的基础,交换价值是价值的表现形式。

        • 2. 辩证关系

          • (1)商品的价值和使用价值之间是对立统一的关系。

          • (2)其对立表现在:商品的使用价值和价值是相互排斥的,二者不可兼得。要获得商品的价值,就必须放弃商品的使用价值;要得到商品的使用价值,就不能得到商品的价值。

          • (3)其统一性表现在:作为商品,必须同时具有使用价值和价值两个因素。使用价值是价值的物质承担者,价值寓于使用价值之中。一种物品尽管具有使用价值,但如果不是劳动产品,也没有价值。

      • 商品的价值量

        • (1)首先,价值量是由劳动者生产商品所耗费的劳动量决定的,而劳动量则是按照劳动时间来计量。决定商品价值量的不是生产商品的个别劳动时间,而只能是社会必要劳动时间。生产商品所需要的社会必要劳动时间随着劳动生产力的变化而变化。

        • (2)商品价值量与生产商所耗费的劳动时间成正比,与劳动生产力成反比。

        • (3)商品的价值量同简单劳动与复杂劳动有密切饿关系。简单劳动书指不需要经过专门训练和培养的一般劳动者能从事的劳动。复杂劳动是指需要经过专门的训练和培养,具有一定的文化知识和技术专长的劳动者所从事的劳动。

      # 劳动二重性

      • 生产商品的劳动可以区分为具体劳动和抽象劳动

        • 具体劳动是指生产一定使用价值的具体形式的劳动;

        • 抽象劳动是指撇开一切具有形式的、无差别的一般人类劳动,即人的体力和脑力消耗。

        • 具体劳动形成商品的使用价值,抽象劳动形成商品的价值实体。

      • 劳动的二重性决定了商品的二因素。具体劳动和抽象劳动是对立统一的:

        • 一方面,具体劳动和抽象劳动在时间上和空间上是统一的,是商品生产者的同一劳动过程的不可分割的两方面;

        • 另一方面,具体劳动所反映的是人与自然的关系,是劳动的自然属性,抽象劳动所反映的是商品生产者的社会关系,是劳动的社会属性。

      # 价值规律的内容、表现形式、作用

      • 价值规律的基本内容:

      • ①商品的价值量是由生产这种商品的社会必要劳动时间决定的。

      • ②商品交换要以价值量为基础,按照等价交换的原则进行。

      • 价值规律的表现形式:
        商品的价格围绕商品的价值上下波动。

      • 价值规律的作用:

        • ①自发地调节生产资料和劳动力在社会各生产部门之间的分配比例。

        • ②自发地刺激社会生产力的发展。

        • ③自发地调节社会收入的分配。

      # 劳动力商品的特点

      • 劳动力商品的使用价值是价值的源泉

      • 劳动力成为商品的基本条件:

        • 第一、劳动者是自由人,能够把自己的劳动力当做自己的商品来支配;

        • 第二、劳动者自由的一无所有,没有任何实现自己的劳动力所必需的物质条件。

      • 劳动力的价值,是由生产、发展、维持和延续劳动力所必需的生活必需品的价值决定的。
        它包括三个部分:

        • ① 是维持劳动者自身生存所必需的生活资料的价值,用以再生产他的劳动力。

        • ② 是劳动者家属的生存必需的生活资料的价值,用以延续劳动力的供给。

        • ③ 劳动者接受教育和训练所支出的费用,用以培训适合资本主义再生产所需要的劳动力。

      # 资本主义生产的直接目的;绝对剩余价值、相对剩余价值

      • 资本主义生产的直接目的是获取更多剩余价值。

      • 资本主义生产是以雇佣劳动为基础,以获取剩余价值为目的的生产。

      • 其生产过程具有二重性:一方面是生产使用价值的劳动过程;另一方面又是生产剩余价值的价值增殖过程。

      • 绝对剩余价值是指在必要劳动时间不变的条件下,由于延长工作日的长度和提高劳动强度而生产的剩余价值。

      • 相对剩余价值是指在工作日长度不变的条件下,通过缩短必要劳动时间而相对延长剩余劳动时间所生产的剩余价值

      # 资本主义扩大再生产的途径

      • 第一,第 Ⅰ 部类原有可变资本加上追加的可变资本,再加上本部类资本家用于个人消费的剩余价值之和,必须等于第 Ⅱ 部类的不变资本加上追加的不变资本,即
        Ⅰ(v+△v+m/x)=Ⅱ(c+△c)

      • 第二,第 Ⅰ 部类全部产品的价值必须等于两大部类原有的不变资本加上追加的不变资本,即
        Ⅰ(c+v+m)=Ⅰ(c+△c)+Ⅱ(c+△c)

      • 第三,第 Ⅱ 部类全部产品的价值必须等于两大部类原有的可变资本加上追加的可变资本,再加上资本家用于个人消费的剩余价值之和,即
        Ⅱ(c+v+m)=Ⅰ(v+△v+m/x)+Ⅱ(v+△v+m/x)

      # 资本主义基本矛盾、资本主义经济危机的实质

      • 基本矛盾:生产社会化和生产资料资本主义私人占有之间的矛盾。

      • 资本主义经济危机的实质:相对过剩的危机,即生产和销售矛盾造成的相对过剩。

      # 资本主义选举制度

      • 是资产阶级制定某种原则和程序,通过竞选产生议会和国家元首的一种政治机制。

      • 在资本主义国家中,选举已经成为国家政治制度运行中对社会发展和稳定产生举足轻重影响的一个不可或缺的政治机制。

      # 第五章 资本主义的发展及其趋势

      # 第六章 社会主义的发展及其规律(本章仅供学习参考,不作考试要求)

      # 科学社会主义的基本原则

      • 第一,在生产资料公有制基础上组织生产,满足全体社会成员的需要是社会主义生产的根本目的。

      • 第二,对社会生产进行有计划的指导和调节,实行等量劳动领取等量产品的按劳分配原则。

      • 第三,合乎自然规律地改造和利用自然。

      • 第四,无产阶级革命是无产阶级进行斗争的最高形式,必须以建立无产阶级专政的国家为目的。

      • 第五,社会主义事业必须坚持无产阶级政党的领导。

      • 第六,通过无产阶级专政和社会主义高度发展,最终实现向消灭阶级、消灭剥削,实现人的全面而自由发展的共产主义的过渡。

      • 一方面,科学社会主义基本原则任何时候都不能违背;另一方面,科学社会主义基本原则在实践中不能僵化地教条地对待它。

      # 经济文化相对落后国社会主义革命理论

      经济文化相对落后的国家社会主义建设的艰巨性和长期性

      • 第一、生产力发展状态的约束。社会主义国家在经济上落后于发达的资本主义国家,有的甚至落后很远,社会主义制度下必须把大力发展生产力作为根本任务,努力完成生产社会化、商品化、现代化的艰巨任务。

      • 第二、经济基础和上层建筑发展状况的制约。发展公有经济,改造小农经济,建立、巩固和完善社会主义的经济基础,就成为无产阶级政权的一项十分巨大的任务。社会主义民主政治建设受到这些国家的经济、政治、文化条件的严重制约,在这一过程中,还要进一步消灭阶级和阶级差别,改变几千年形成的传统观念,建设社会主义的先进文化,实现真正的社会公正的平等。

      • 第三,国际环境的严峻挑战。如果说在社会主义国家成立之初,国际资本主义对资本主义的进攻主要是武力方式,那么在社会主义建设取得重大成就后,进攻方式则往往转变为一和平演变为主。一是通过军事、政治压力盒有限的经济、科技的合作和援助,迫使社会主义国家屈从其经济政治。二是通过文化渗透,在社会主义国家内部制造经济、政治、思想等种种混乱,阻挠和破坏社会主义国家的发展。

      • 第四,马克思主义执政党和对社会主义发展的道路的探索和对社会主义建设规律的认识,需要一个长期的艰苦的

      # 第七章 共产主义是人类最崇高的社会理想

      # 实现共产主义是一个长期的历史过程(辨析题)p286

      • (1)理论上,马克思主义所揭示的社会形态发展与更替的规律是一般的历史规律,是只有在漫长的历史过程中才能体现出来的规律。

      • (2)每一个社会形态的产生发展,都会经历一个很长的历史时期,而旧的社会形态走向没落并为新的社会形态所代替也是一个长期的历史过程。

      • (3)从资本主义到共产主义的转变是一种根本的转变,它不是具体制度的更新,而是整个社会的根本改造,因而必然是个长期而艰难的过程。

      # 共产主义的基本特征 p275

      • (1)物质财富极大丰富,消费资料按需分配。

      • (2)社会关系高度和谐,人们精神境界极大提高。

      • (3)每个人自由而全面的发展,人类从必然王国向自由王国飞跃。

      \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 00000000..e330988b --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,1647 @@ + + + + + https://fuuzen.github.io/cs/ai/search/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/devops/haproxy-ssh/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/principles-of-computer-composition/yatcpu/chisel/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/languages/rust/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/raspberrypi/static-ip/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/devops/sync-pve-cluster/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/acgn/anime-log/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/ie/signals-and-systems/communication/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/algebra/coset-of-subgroup/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/algebra/group-basics/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/algebra/permutation-group/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/algebra/homomorphism/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/algebra/normal-subgroup/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/algebra/prime-max-ideal/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/algebra/ring/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/discrete-math-basics/dmbs/algebra-system/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/discrete-math-basics/dmbs/counting/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/discrete-math-basics/dmbs/functions/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/discrete-math-basics/dmbs/operations-of-sets-and-relations/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/discrete-math-basics/dmbs/permutaion-and-combination/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/discrete-math-basics/dmbs/difference-equations/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/discrete-math-basics/dmbs/principles-of-counting/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/discrete-math-basics/problem1/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/discrete-math-basics/dmbs/relations/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/discrete-math-basics/set/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/graph/algebra-graph/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/graph/coloring/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/graph/connectivity/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/graph/match/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/graph/shortest-path-algorithms/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/graph/graph-basics/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/graph/spectral-clustering/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/graph/tree/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/graph/euler_hamilton/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/graph/planar-graph/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/acgn/epiao/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/cryptography/lattice-attack/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/ai/rl/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/ctf/w4terctf2024/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/data-structure-and-algorithm/b-tree/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/data-structure-and-algorithm/binary-tree/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/data-structure-and-algorithm/critical-path/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/data-structure-and-algorithm/graph/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/data-structure-and-algorithm/hash/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/data-structure-and-algorithm/heap-sort/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/data-structure-and-algorithm/shortest-path/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/data-structure-and-algorithm/stack-queue/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/data-structure-and-algorithm/minimum-spanning-tree/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/data-structure-and-algorithm/pre-in-post-index/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/fronet-end/hexo/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/data-structure-and-algorithm/radix-sort/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/fronet-end/nodejs/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/os/ysosv2/lab0/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/os/ysosv2/lab2/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/os/ysosv2/lab1/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/os/ysosv2/lab3/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/os/ysosv2/lab4/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/os/ysosv2/lab6/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/os/ysosv2/lab5/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/os/scheduling/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/os/thread/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/devops/acme/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/devops/nat-traversal/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/devops/overleaf/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/devops/nginx/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/parallel-programing/pthread/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/devops/pve-passthrough-gpu/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/devops/sql/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/devops/pve/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/devops/pve-switch-sysdisk/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/friends/index.html + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/assets/yatcpu/lab1/SingleCycle.html + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/si-zheng/ma-yuan/ke-hou-xi-ti/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/si-zheng/ma-yuan/ti-gang/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/math/discrete-math/discrete-math-basics/dmb/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/tools/vscode-remote-ssh-login-shell/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/tools/cmake/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/ie/signals-and-systems/CTFT/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/ie/signals-and-systems/DTFT/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/ie/signals-and-systems/LT/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/ie/signals-and-systems/FS/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/ie/signals-and-systems/duality/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/ie/signals-and-systems/lti/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/ie/signals-and-systems/signals-concepts/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/ie/signals-and-systems/systems-concepts/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/ie/signals-and-systems/zT/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/ie/de/bool-algebra/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/ie/de/coding/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/ie/de/combinatorial-logic/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/ie/de/gate-circuit/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/ie/de/digital-process/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/ie/de/integrated-circuit/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/ie/de/memory-storage/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/ie/de/shift-register/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/ie/de/numerical-system/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/ie/de/sequential-circuit/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/principles-of-computer-composition/yatcpu/yatcpu-report/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/principles-of-computer-composition/yatcpu/lab-reports/lab4/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/principles-of-computer-composition/yatcpu/lab-reports/lab3/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/os/concepts/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/os/deadlock/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/os/fs/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/os/linux-customized-syscall/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/os/io/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/os/memory-management/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/os/process/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/os/sync/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/principles-of-computer-composition/basic-indicators-of-computer-performance/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/principles-of-computer-composition/cache/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/principles-of-computer-composition/cpu/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/principles-of-computer-composition/data-path/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/principles-of-computer-composition/dram-refresh/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/principles-of-computer-composition/exception-and-interruption/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/principles-of-computer-composition/memory/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/principles-of-computer-composition/instruction-system/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/principles-of-computer-composition/operation/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/principles-of-computer-composition/virtual-memory/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/principles-of-computer-composition/von-neumann-architecture/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/principles-of-computer-composition/yatcpu/lab-reports/lab1/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/principles-of-computer-composition/yatcpu/lab-reports/lab2/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/devops/bash/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/devops/clone-vm/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/languages/js/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/about/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/THANK-YOU/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/ai/agent/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/ai/concepts/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/ai/knowledge-presentation-and-resolution/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/ai/ml/ + + 2024-08-14 + + monthly + 0.6 + + + + https://fuuzen.github.io/cs/ai/uncentain-knowledge-presentation-and-resolution/ + + 2024-08-14 + + monthly + 0.6 + + + + + https://fuuzen.github.io/ + 2024-08-14 + daily + 1.0 + + + + + https://fuuzen.github.io/tags/AI/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/discrete-math/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/%E9%80%BB%E8%BE%91/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/graph/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/ctf/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/%E6%90%9C%E7%B4%A2/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/cs/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/%E7%AE%97%E6%B3%95/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/%E6%A6%82%E7%8E%87%E8%AE%BA/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/Node-js/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/%E5%89%8D%E7%AB%AF/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/Linux/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/DevOps/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/JS/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/Rust/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/os/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/principles-of-computer-composition/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/%E5%B9%B6%E8%A1%8C/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/%E6%A0%91%E8%8E%93%E6%B4%BE/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/%E7%B3%BB%E7%BB%9F/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/%E4%BF%A1%E5%8F%B7/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/FT/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/%E5%A4%8D%E5%8F%98%E5%87%BD%E6%95%B0/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/algebra/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/%E7%BE%A4%E8%AE%BA/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/%E5%AF%86%E7%A0%81%E5%AD%A6/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/%E6%A0%BC/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/%E6%80%9D%E6%94%BF/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/%E5%82%85%E9%87%8C%E5%8F%B6%E5%8F%98%E6%8D%A2/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/%E5%8D%B7%E7%A7%AF/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/%E6%95%B0%E7%94%B5/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/coursework/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/scala/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/chisel/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/%E9%9B%86%E5%90%88%E8%AE%BA/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/combinatorics/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/%E7%8E%AF/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/tags/number/ + 2024-08-14 + weekly + 0.2 + + + + + + https://fuuzen.github.io/categories/ACGN/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/cs/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/cs/ctf/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/cs/ai/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/cs/data-structure-and-algorithm/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/cs/front-end/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/cs/devops/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/cs/languages/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/cs/os/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/cs/principles-of-computer-composition/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/cs/%E5%B9%B6%E8%A1%8C%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/cs/raspberrypi/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/cs/tools/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/ie/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/math/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/si-zheng/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/cs/os/ysosv2/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/cs/principles-of-computer-composition/yatcpu/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/ie/signals-and-systems/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/math/cryptography/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/si-zheng/ma-yuan/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/ie/de/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/math/discrete-math/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/math/discrete-math/%E4%BB%A3%E6%95%B0%E7%BB%93%E6%9E%84/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/math/discrete-math/%E7%A6%BB%E6%95%A3%E6%95%B0%E5%AD%A6%E5%9F%BA%E7%A1%80/ + 2024-08-14 + weekly + 0.2 + + + + https://fuuzen.github.io/categories/math/discrete-math/graph/ + 2024-08-14 + weekly + 0.2 + + + diff --git a/tags/AI/index.html b/tags/AI/index.html index 8729730a..f3c35461 100644 --- a/tags/AI/index.html +++ b/tags/AI/index.html @@ -1 +1 @@ -Tag: AI | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: AI | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/DevOps/index.html b/tags/DevOps/index.html index 98993af7..daf1239d 100644 --- a/tags/DevOps/index.html +++ b/tags/DevOps/index.html @@ -1 +1 @@ -Tag: DevOps | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: DevOps | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/DevOps/page/2/index.html b/tags/DevOps/page/2/index.html index f8d5916b..5fc96594 100644 --- a/tags/DevOps/page/2/index.html +++ b/tags/DevOps/page/2/index.html @@ -1 +1 @@ -Tag: DevOps | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: DevOps | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/FT/index.html b/tags/FT/index.html index d1ce90d9..21c52994 100644 --- a/tags/FT/index.html +++ b/tags/FT/index.html @@ -1 +1 @@ -Tag: FT | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: FT | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/JS/index.html b/tags/JS/index.html index aaff99f1..adb96d3a 100644 --- a/tags/JS/index.html +++ b/tags/JS/index.html @@ -1 +1 @@ -Tag: JS | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: JS | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/Linux/index.html b/tags/Linux/index.html index 6bd4c7c1..1cee1830 100644 --- a/tags/Linux/index.html +++ b/tags/Linux/index.html @@ -1 +1 @@ -Tag: Linux | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: Linux | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/Node-js/index.html b/tags/Node-js/index.html index 7caffb4d..ca5d8819 100644 --- a/tags/Node-js/index.html +++ b/tags/Node-js/index.html @@ -1 +1 @@ -Tag: Node.js | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: Node.js | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/Rust/index.html b/tags/Rust/index.html index f4ccf4cc..3e7b4e9a 100644 --- a/tags/Rust/index.html +++ b/tags/Rust/index.html @@ -1 +1 @@ -Tag: Rust | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: Rust | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/algebra/index.html b/tags/algebra/index.html index 1f661ef3..fb8f2bc5 100644 --- a/tags/algebra/index.html +++ b/tags/algebra/index.html @@ -1 +1 @@ -Tag: 代数 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 代数 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/algebra/page/2/index.html b/tags/algebra/page/2/index.html index b852d04a..81e29552 100644 --- a/tags/algebra/page/2/index.html +++ b/tags/algebra/page/2/index.html @@ -1 +1 @@ -Tag: 代数 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 代数 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/chisel/index.html b/tags/chisel/index.html index dbdd2154..a89f3d36 100644 --- a/tags/chisel/index.html +++ b/tags/chisel/index.html @@ -1 +1 @@ -Tag: Chisel | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: Chisel | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/combinatorics/index.html b/tags/combinatorics/index.html index a6202762..1069db34 100644 --- a/tags/combinatorics/index.html +++ b/tags/combinatorics/index.html @@ -1 +1 @@ -Tag: 组合数学 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 组合数学 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/coursework/index.html b/tags/coursework/index.html index 4e83cd35..d786d11c 100644 --- a/tags/coursework/index.html +++ b/tags/coursework/index.html @@ -1 +1 @@ -Tag: 大作业 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 大作业 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/coursework/page/2/index.html b/tags/coursework/page/2/index.html index 290fbcc6..63923785 100644 --- a/tags/coursework/page/2/index.html +++ b/tags/coursework/page/2/index.html @@ -1 +1 @@ -Tag: 大作业 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 大作业 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/cs/index.html b/tags/cs/index.html index ef14c17a..2ecf8ee0 100644 --- a/tags/cs/index.html +++ b/tags/cs/index.html @@ -1 +1 @@ -Tag: CS | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: CS | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/cs/page/2/index.html b/tags/cs/page/2/index.html index fe7d547c..1a075684 100644 --- a/tags/cs/page/2/index.html +++ b/tags/cs/page/2/index.html @@ -1 +1 @@ -Tag: CS | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: CS | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/ctf/index.html b/tags/ctf/index.html index 12f7afa6..74c5d53b 100644 --- a/tags/ctf/index.html +++ b/tags/ctf/index.html @@ -1 +1 @@ -Tag: ctf | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: ctf | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/discrete-math/index.html b/tags/discrete-math/index.html index ebf534a1..e9f9a2a5 100644 --- a/tags/discrete-math/index.html +++ b/tags/discrete-math/index.html @@ -1 +1 @@ -Tag: 离散数学 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 离散数学 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/discrete-math/page/2/index.html b/tags/discrete-math/page/2/index.html index 5dd4360b..043d73bf 100644 --- a/tags/discrete-math/page/2/index.html +++ b/tags/discrete-math/page/2/index.html @@ -1 +1 @@ -Tag: 离散数学 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 离散数学 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/discrete-math/page/3/index.html b/tags/discrete-math/page/3/index.html index d5c135a9..ece227f8 100644 --- a/tags/discrete-math/page/3/index.html +++ b/tags/discrete-math/page/3/index.html @@ -1 +1 @@ -Tag: 离散数学 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 离散数学 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/graph/index.html b/tags/graph/index.html index 37e0e210..4464f757 100644 --- a/tags/graph/index.html +++ b/tags/graph/index.html @@ -1 +1 @@ -Tag: 图论 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 图论 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/graph/page/2/index.html b/tags/graph/page/2/index.html index a15e84d0..f89c9c46 100644 --- a/tags/graph/page/2/index.html +++ b/tags/graph/page/2/index.html @@ -1 +1 @@ -Tag: 图论 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 图论 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/index.html b/tags/index.html index e0f1b917..0c0a43d3 100644 --- a/tags/index.html +++ b/tags/index.html @@ -1 +1 @@ -AllTag | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +AllTag | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/number/index.html b/tags/number/index.html index 08a128bd..fc65207c 100644 --- a/tags/number/index.html +++ b/tags/number/index.html @@ -1 +1 @@ -Tag: 数论 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 数论 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/os/index.html b/tags/os/index.html index b2755fe1..2427f729 100644 --- a/tags/os/index.html +++ b/tags/os/index.html @@ -1 +1 @@ -Tag: OS | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: OS | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/os/page/2/index.html b/tags/os/page/2/index.html index 66392c3b..d2fc96b1 100644 --- a/tags/os/page/2/index.html +++ b/tags/os/page/2/index.html @@ -1 +1 @@ -Tag: OS | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: OS | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/principles-of-computer-composition/index.html b/tags/principles-of-computer-composition/index.html index 103378e7..2e58474b 100644 --- a/tags/principles-of-computer-composition/index.html +++ b/tags/principles-of-computer-composition/index.html @@ -1 +1 @@ -Tag: 计组 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 计组 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/principles-of-computer-composition/page/2/index.html b/tags/principles-of-computer-composition/page/2/index.html index 202ecc02..3ccf8cb6 100644 --- a/tags/principles-of-computer-composition/page/2/index.html +++ b/tags/principles-of-computer-composition/page/2/index.html @@ -1 +1 @@ -Tag: 计组 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 计组 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git a/tags/scala/index.html b/tags/scala/index.html index 6d887397..8a1480e8 100644 --- a/tags/scala/index.html +++ b/tags/scala/index.html @@ -1 +1 @@ -Tag: Scala | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: Scala | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git "a/tags/\344\277\241\345\217\267/index.html" "b/tags/\344\277\241\345\217\267/index.html" index b33633d5..3c1cbf6b 100644 --- "a/tags/\344\277\241\345\217\267/index.html" +++ "b/tags/\344\277\241\345\217\267/index.html" @@ -1 +1 @@ -Tag: 信号 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 信号 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git "a/tags/\345\202\205\351\207\214\345\217\266\345\217\230\346\215\242/index.html" "b/tags/\345\202\205\351\207\214\345\217\266\345\217\230\346\215\242/index.html" index 0ca16106..5f314117 100644 --- "a/tags/\345\202\205\351\207\214\345\217\266\345\217\230\346\215\242/index.html" +++ "b/tags/\345\202\205\351\207\214\345\217\266\345\217\230\346\215\242/index.html" @@ -1 +1 @@ -Tag: 傅里叶变换 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 傅里叶变换 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git "a/tags/\345\211\215\347\253\257/index.html" "b/tags/\345\211\215\347\253\257/index.html" index 427ce11c..4f94b763 100644 --- "a/tags/\345\211\215\347\253\257/index.html" +++ "b/tags/\345\211\215\347\253\257/index.html" @@ -1 +1 @@ -Tag: 前端 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 前端 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git "a/tags/\345\215\267\347\247\257/index.html" "b/tags/\345\215\267\347\247\257/index.html" index bcb70066..f60ed6f3 100644 --- "a/tags/\345\215\267\347\247\257/index.html" +++ "b/tags/\345\215\267\347\247\257/index.html" @@ -1 +1 @@ -Tag: 卷积 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 卷积 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git "a/tags/\345\244\215\345\217\230\345\207\275\346\225\260/index.html" "b/tags/\345\244\215\345\217\230\345\207\275\346\225\260/index.html" index 1ea6afc1..60d5912f 100644 --- "a/tags/\345\244\215\345\217\230\345\207\275\346\225\260/index.html" +++ "b/tags/\345\244\215\345\217\230\345\207\275\346\225\260/index.html" @@ -1 +1 @@ -Tag: 复变函数 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 复变函数 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git "a/tags/\345\257\206\347\240\201\345\255\246/index.html" "b/tags/\345\257\206\347\240\201\345\255\246/index.html" index 5175cedb..d77ef160 100644 --- "a/tags/\345\257\206\347\240\201\345\255\246/index.html" +++ "b/tags/\345\257\206\347\240\201\345\255\246/index.html" @@ -1 +1 @@ -Tag: 密码学 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 密码学 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git "a/tags/\345\271\266\350\241\214/index.html" "b/tags/\345\271\266\350\241\214/index.html" index 596a2071..080b7db5 100644 --- "a/tags/\345\271\266\350\241\214/index.html" +++ "b/tags/\345\271\266\350\241\214/index.html" @@ -1 +1 @@ -Tag: 并行 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 并行 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git "a/tags/\345\274\272\345\214\226\345\255\246\344\271\240/index.html" "b/tags/\345\274\272\345\214\226\345\255\246\344\271\240/index.html" index 170e8955..d4886e14 100644 --- "a/tags/\345\274\272\345\214\226\345\255\246\344\271\240/index.html" +++ "b/tags/\345\274\272\345\214\226\345\255\246\344\271\240/index.html" @@ -1 +1 @@ -Tag: 强化学习 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 强化学习 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git "a/tags/\346\200\235\346\224\277/index.html" "b/tags/\346\200\235\346\224\277/index.html" index 812a7faf..2ab0a1d4 100644 --- "a/tags/\346\200\235\346\224\277/index.html" +++ "b/tags/\346\200\235\346\224\277/index.html" @@ -1 +1 @@ -Tag: 思政 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 思政 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git "a/tags/\346\220\234\347\264\242/index.html" "b/tags/\346\220\234\347\264\242/index.html" index 7e403da8..04c2a824 100644 --- "a/tags/\346\220\234\347\264\242/index.html" +++ "b/tags/\346\220\234\347\264\242/index.html" @@ -1 +1 @@ -Tag: 搜索 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 搜索 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git "a/tags/\346\225\260\346\215\256\347\273\223\346\236\204/index.html" "b/tags/\346\225\260\346\215\256\347\273\223\346\236\204/index.html" index c55eefcf..25259c6c 100644 --- "a/tags/\346\225\260\346\215\256\347\273\223\346\236\204/index.html" +++ "b/tags/\346\225\260\346\215\256\347\273\223\346\236\204/index.html" @@ -1 +1 @@ -Tag: 数据结构 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 数据结构 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git "a/tags/\346\225\260\347\224\265/index.html" "b/tags/\346\225\260\347\224\265/index.html" index 4861df2c..8397d844 100644 --- "a/tags/\346\225\260\347\224\265/index.html" +++ "b/tags/\346\225\260\347\224\265/index.html" @@ -1 +1 @@ -Tag: 数电 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 数电 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git "a/tags/\346\240\221\350\216\223\346\264\276/index.html" "b/tags/\346\240\221\350\216\223\346\264\276/index.html" index 7a943793..1f0e9519 100644 --- "a/tags/\346\240\221\350\216\223\346\264\276/index.html" +++ "b/tags/\346\240\221\350\216\223\346\264\276/index.html" @@ -1 +1 @@ -Tag: 树莓派 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 树莓派 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git "a/tags/\346\240\274/index.html" "b/tags/\346\240\274/index.html" index 4dbacf83..11296146 100644 --- "a/tags/\346\240\274/index.html" +++ "b/tags/\346\240\274/index.html" @@ -1 +1 @@ -Tag: 格 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 格 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git "a/tags/\346\246\202\347\216\207\350\256\272/index.html" "b/tags/\346\246\202\347\216\207\350\256\272/index.html" index a9d9c02e..02b36174 100644 --- "a/tags/\346\246\202\347\216\207\350\256\272/index.html" +++ "b/tags/\346\246\202\347\216\207\350\256\272/index.html" @@ -1 +1 @@ -Tag: 概率论 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 概率论 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git "a/tags/\347\216\257/index.html" "b/tags/\347\216\257/index.html" index 88cc9a08..79498966 100644 --- "a/tags/\347\216\257/index.html" +++ "b/tags/\347\216\257/index.html" @@ -1 +1 @@ -Tag: 环 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 环 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git "a/tags/\347\256\227\346\263\225/index.html" "b/tags/\347\256\227\346\263\225/index.html" index a654dc3a..b7026c57 100644 --- "a/tags/\347\256\227\346\263\225/index.html" +++ "b/tags/\347\256\227\346\263\225/index.html" @@ -1 +1 @@ -Tag: 算法 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 算法 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git "a/tags/\347\263\273\347\273\237/index.html" "b/tags/\347\263\273\347\273\237/index.html" index d2f8fa34..7aa6fe13 100644 --- "a/tags/\347\263\273\347\273\237/index.html" +++ "b/tags/\347\263\273\347\273\237/index.html" @@ -1 +1 @@ -Tag: 系统 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 系统 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git "a/tags/\347\276\244\350\256\272/index.html" "b/tags/\347\276\244\350\256\272/index.html" index b13bf6b2..a49904b5 100644 --- "a/tags/\347\276\244\350\256\272/index.html" +++ "b/tags/\347\276\244\350\256\272/index.html" @@ -1 +1 @@ -Tag: 群论 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 群论 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git "a/tags/\351\200\273\350\276\221/index.html" "b/tags/\351\200\273\350\276\221/index.html" index 1e8b9aa6..54aa55d6 100644 --- "a/tags/\351\200\273\350\276\221/index.html" +++ "b/tags/\351\200\273\350\276\221/index.html" @@ -1 +1 @@ -Tag: 逻辑 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 逻辑 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file diff --git "a/tags/\351\233\206\345\220\210\350\256\272/index.html" "b/tags/\351\233\206\345\220\210\350\256\272/index.html" index 17742a44..815c6119 100644 --- "a/tags/\351\233\206\345\220\210\350\256\272/index.html" +++ "b/tags/\351\233\206\345\220\210\350\256\272/index.html" @@ -1 +1 @@ -Tag: 集合论 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file +Tag: 集合论 | Balloon Party = 風船のパーティー = fuusen no party
      \ No newline at end of file