<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Maxwell&#39;s Blog</title>
  
  <subtitle>Think &amp; Write</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="https://Maxwell-lyu.github.io/"/>
  <updated>2021-03-03T15:16:33.968Z</updated>
  <id>https://Maxwell-lyu.github.io/</id>
  
  <author>
    <name>Maxwell Lyu</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>SSH+Proxy案例</title>
    <link href="https://Maxwell-lyu.github.io/2021/03/03/Tech-20210303-SSH-Proxy%E6%A1%88%E4%BE%8B/"/>
    <id>https://Maxwell-lyu.github.io/2021/03/03/Tech-20210303-SSH-Proxy案例/</id>
    <published>2021-03-03T14:31:56.000Z</published>
    <updated>2021-03-03T15:16:33.968Z</updated>
    
    <content type="html"><![CDATA[<p>教育网内无外网的服务器，使用校园内网客户机上的代理服务器，连接外网(骚断腿的操作)<br><a id="more"></a></p><h2 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h2><h3 id="您遇到的情况"><a href="#您遇到的情况" class="headerlink" title="您遇到的情况"></a>您遇到的情况</h3><ul><li>设备<ul><li>S(Server): 114.x.x.x 服务器, 位于教育网内, 有公网IP, 无法访问外网, 科研用途</li><li>C(Client): 172.x.x.x 服务器, 位于校园内网的一个子网, 无公网IP, 可以访问外网</li></ul></li><li>需求<ul><li>让S能够通过C提供的代理服务器, 使用C的外网连接, 完成指定操作</li></ul></li><li>关键约束<ul><li>ICMPing<ul><li>C -&gt; S: 通</li><li>S -&gt; C: 断</li><li>原因未知, 应该可以认为路由表配置存在问题, 或链路上有NAT, 或防火墙限制</li></ul></li><li>服务器不能在无人在线时, 存在与外网的连接, 安全限制</li></ul></li></ul><h3 id="解决思路"><a href="#解决思路" class="headerlink" title="解决思路"></a>解决思路</h3><ul><li>某一外网请求的路径<ul><li>S上某程序发出请求Q</li><li>S上配置代理服务器<code>export ALL_PROXY=http://localhost:abcd</code>, Q到达<code>S:abcd</code></li><li>C在连接SSH到S时, 设置SSH端口转发, 从<code>S:abcd</code>到<code>C:efgh</code>, Q到达<code>C:efgh</code></li><li>C上安装代理服务器, 监听于<code>C:efgh</code>, Q到达代理服务器</li><li>代理服务器从设定的出站NIC将Q递入外网</li></ul></li><li>软件准备<ul><li>C端<ul><li>代理服务器软件, 按需选用</li><li>SSH客户端</li></ul></li><li>S端<ul><li>SSH服务端</li><li>默认该服务器使用bash作为终端, 其配置文件为<code>.bashrc</code>, 其他终端按需调整</li></ul></li></ul></li></ul><h3 id="配置步骤"><a href="#配置步骤" class="headerlink" title="配置步骤"></a>配置步骤</h3><ul><li>S端配置<ul><li>通过SSH连接到S</li><li>添加<code>export ALL_PROXY=http://localhost:abcd</code>至<code>.bashrc</code><ul><li>这里假设您选用的是http代理, 如果其他, 请修改协议, 例如改为<code>sock5://localhost:abcd</code></li><li>这里<code>abcd</code>为您选定的端口号, 尽量选择大一些但不超上限的值, 端口冲突将引发匪夷所思的故障查找</li><li>您也可以暂时不添加到<code>.bashrc</code>, 但我强烈推荐这么做</li></ul></li></ul></li><li>C端配置<ul><li>修改ssh配置文件<ul><li>在您的<code>~/.ssh/config</code>文件中, 添加S的信息, 必须包括别名(Host), 主机名(HostName), 用户(User), 端口(Port)</li><li>测试该连接选项, 确认能够成功连接, 之后将所有使用您的User连接的ssh会话关闭</li><li>在该选项下, 与主机名(HostName)同级, 添加端口转发<code>RemoteForward abcd localhost:efgh</code><ul><li>该命令的含义为, 监听S端的<code>abcd</code>, 转发至C端的<code>efgh</code></li><li>如果您不想使用<code>~/.ssh/config</code>, 而是直接使用命令行工具ssh连接, 相应的参数为<code>-R abcd:localhost:efgh</code></li></ul></li><li>测试该连接选项, 确认能够成功连接, 并能够成功访问外网</li></ul></li></ul></li></ul><h3 id="这有什么好处"><a href="#这有什么好处" class="headerlink" title="这有什么好处"></a>这有什么好处</h3><ul><li>方便: 无需因C端DHCP问题而修改任何东西, 包括远端的代理配置和本地的任何配置</li><li>安全: 代理服务器随SSH同时连通和断开, 保证没有合法人员使用时, 服务器不存在外网连接</li><li>安全: C端代理服务器无需对局域网开放, 只需监听localhost即可</li><li>安全: SSH将加密和保护该转发端口的数据, 即使本地代理服务器不设置授权或使用不加密通信, 也能够保证安全</li></ul>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;教育网内无外网的服务器，使用校园内网客户机上的代理服务器，连接外网(骚断腿的操作)&lt;br&gt;
    
    </summary>
    
      <category term="Technique" scheme="https://Maxwell-lyu.github.io/categories/Technique/"/>
    
    
      <category term="Utility" scheme="https://Maxwell-lyu.github.io/tags/Utility/"/>
    
  </entry>
  
  <entry>
    <title>BIOS/UEFI双引导U盘安装Ubuntu</title>
    <link href="https://Maxwell-lyu.github.io/2021/02/13/Tech-20210213-Ubuntu%E5%8F%8C%E5%90%AF%E5%8A%A8/"/>
    <id>https://Maxwell-lyu.github.io/2021/02/13/Tech-20210213-Ubuntu双启动/</id>
    <published>2021-02-13T02:23:21.000Z</published>
    <updated>2021-02-13T03:47:53.000Z</updated>
    
    <content type="html"><![CDATA[<p>在U盘中安装Ubuntu并支持在BIOS/UEFI 2种引导方式下启动<br><a id="more"></a></p><h2 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h2><h3 id="目标"><a href="#目标" class="headerlink" title="目标"></a>目标</h3><ul><li>向目标U盘中安装Ubuntu系统</li><li>该安装能够在BIOS或UEFI引导下进入系统</li><li>无需制作另外的LiveCD安装介质</li></ul><h3 id="方法"><a href="#方法" class="headerlink" title="方法"></a>方法</h3><ul><li>使用虚拟机(VMWare为例)作为安装环境, 安全无污染, 不必担心宿主机环境被损毁</li><li>使用GPT分区表, 预留bios_grub分区, 先进行UEFI引导下的安装, 之后添加BIOS引导</li><li>使用虚拟机(VMWare为例)作为测试环境, 无需开关宿主机就可以验证安装是否成功</li></ul><h3 id="需求"><a href="#需求" class="headerlink" title="需求"></a>需求</h3><ul><li>Ubuntu镜像, iso格式, 本教程使用20.04.1, 对于其他linux发行版有待验证</li><li>VMWare Workstation Pro或其替代品, 能够支持:<ul><li>创建并管理虚拟机, 需要提供虚拟光驱, USB</li><li>(安装用)UEFI模式引导虚拟机系统</li><li>(安装用)挂载USB设备, 或将宿主机UAS设备挂载为虚拟机SCSI磁盘</li><li>(测试用)BIOS模式引导虚拟机系统</li><li>(测试用)将宿主机UAS设备挂载为虚拟机SCSI磁盘</li></ul></li><li>U盘<ul><li>16GB或更高, USB3.1或更高</li><li>(推荐)使用固态硬盘+转换盒组成的固态U盘</li></ul></li></ul><h3 id="警告"><a href="#警告" class="headerlink" title="警告"></a>警告</h3><ul><li>升级内核时或者大版本时, 请务必谨慎</li><li>如果出现升级后无法引导的情况, 请查阅下文当中的<code>维护U盘中的Ubuntu</code></li></ul><h2 id="向U盘安装Ubuntu"><a href="#向U盘安装Ubuntu" class="headerlink" title="向U盘安装Ubuntu"></a>向U盘安装Ubuntu</h2><h3 id="准备U盘"><a href="#准备U盘" class="headerlink" title="准备U盘"></a>准备U盘</h3><ul><li>备份U盘中的任何数据, 如果有必要</li><li><strong>必须确认U盘中的数据可以全部被删除</strong></li><li>删除所有已经存在的分区, 并将U盘分区表转换为GPT类型</li></ul><h3 id="创建虚拟机"><a href="#创建虚拟机" class="headerlink" title="创建虚拟机"></a>创建虚拟机</h3><ul><li>虚拟机名称: 随意</li><li>虚拟机版本: 默认</li><li>客户机操作系统: Ubuntu 64位</li><li>硬件: 全部默认</li></ul><h3 id="更改虚拟机属性"><a href="#更改虚拟机属性" class="headerlink" title="更改虚拟机属性"></a>更改虚拟机属性</h3><ul><li>移除-虚拟网络控制器</li><li>移除-虚拟硬盘</li><li>修改-USB控制器版本, 匹配宿主机目标U盘的实际协议</li><li>修改-虚拟光驱, 挂载Ubuntu镜像iso, 勾选<code>启动时连接</code></li><li>修改-<code>虚拟机设置&gt;选项&gt;高级&gt;固件类型</code>, 设置为<code>UEFI</code></li></ul><h3 id="启动虚拟机-准备安装"><a href="#启动虚拟机-准备安装" class="headerlink" title="启动虚拟机, 准备安装"></a>启动虚拟机, 准备安装</h3><ul><li>开机-虚拟机应当引导进入Ubuntu LiveCD, 直到出现<code>Try Ubuntu</code>和<code>Install Ubuntu</code>字样</li><li>选择-<code>Try Ubuntu</code>, 直到进入LiveCD桌面</li><li>挂载-右下角托盘, 将目标U盘作为USB设备挂载到虚拟机</li><li>选择-检测到USB设备后, <code>Install Ubuntu xxxx</code>, 启动安装程序</li></ul><h3 id="开始安装"><a href="#开始安装" class="headerlink" title="开始安装"></a>开始安装</h3><ul><li>选择-按需选择语言, 安装规模等, 直到<code>Installation Type</code>页面</li><li>选择-<code>Something Else</code>, 即手动进行分区并安装</li></ul><h3 id="对U盘进行分区"><a href="#对U盘进行分区" class="headerlink" title="对U盘进行分区"></a>对U盘进行分区</h3><ul><li>新建分区表-右键U盘设备, 应当为<code>/dev/sda</code>, 选择<code>New partition table</code></li><li>添加分区-添加如下的分区, 分区大小仅供参考<ul><li>(<strong>必须</strong>)大小1MB, 类型为<code>Reserved BIOS boot area</code><ul><li>添加该分区后, 您可能会注意到, 磁盘头部出现33MB的未分配空间, 而该分区大小变为33MB, 这是完全正常的</li></ul></li><li>(<strong>必须</strong>)大小500MB, 类型为<code>EFI System Partition</code></li><li>(可选)大小500MB, 类型为<code>Ext4 journaling file system</code>, 挂载点<code>/boot</code><ul><li>该操作不推荐, 99%的情况下不必要</li><li>某些老旧的BIOS无法识别存在于8GB或64GB之后的可引导分区, 因此该操作曾经有意义</li><li>使用raid等方式安装系统时, 该操作是必须的, 很明显我们没有这样做</li></ul></li><li>(<strong>必须</strong>)大小10GB+, 类型为<code>Ext4 journaling file system</code>, 挂载点<code>/</code><ul><li>若有单独为<code>/home</code>分区, 该大小推荐设置为20GB左右</li><li>若无单独<code>/home</code>, 占满磁盘剩余空间即可, 若有需要可以保留一些未分配空间</li></ul></li><li>(可选)大小10GB+, 类型为<code>Ext4 journaling file system</code>, 挂载点<code>/home</code><ul><li>看个人情况, 占满剩余磁盘空间或保留一些未分配空间</li></ul></li></ul></li><li>确认分区-必须包括如下分区<ul><li>(<strong>必须</strong>)大小50MB, 类型为<code>Reserved BIOS boot area</code></li><li>(<strong>必须</strong>)大小500MB, 类型为<code>EFI System Partition</code></li><li>(<strong>必须</strong>)大小10GB+, 类型为<code>Ext4 journaling file system</code>, 挂载点<code>/</code></li></ul></li></ul><h3 id="完成安装"><a href="#完成安装" class="headerlink" title="完成安装"></a>完成安装</h3><ul><li>地区, 账户按需要填写, 等待安装完成, 不要退出安装程序</li><li>选择-<code>Continue trying</code></li></ul><h3 id="为BIOS添加引导"><a href="#为BIOS添加引导" class="headerlink" title="为BIOS添加引导"></a>为BIOS添加引导</h3><ul><li><p>切换到root用户</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo su</span><br></pre></td></tr></table></figure></li><li><p>确定挂载各个位置, 以您创建分区的顺序为依据</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">fdisk -l</span><br><span class="line"><span class="comment"># 教程假定挂载点为'/boot'的分区(若存在)为/dev/sda3, 请根据需要修改</span></span><br><span class="line"><span class="comment"># 教程假定挂载点为'/'的分区为/dev/sda3, 请根据需要修改</span></span><br></pre></td></tr></table></figure></li><li><p>挂载<code>/</code>的分区到当前系统 或 挂载<code>/boot</code>的分区到当前系统</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mkdir /mnt/sda3</span><br><span class="line">mount /dev/sda3 /mnt/sda3</span><br></pre></td></tr></table></figure></li><li><p>安装grub, 根据挂载的是否为<code>/boot</code>挂载点的分区选择您待执行的命令</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 如果您挂载的是'/'分区, 其为/dev/sda3, 则</span></span><br><span class="line">grub-install --target=i386-pc --boot-directory=/mnt/sda3/boot /dev/sda</span><br><span class="line"><span class="comment"># 如果您挂载的是'/boot'分区, 其为/dev/sda3, 则</span></span><br><span class="line">grub-install --target=i386-pc --boot-directory=/mnt/sda3 /dev/sda</span><br></pre></td></tr></table></figure></li><li><p>检查分区情况</p><ul><li>启动gparted</li><li>如果您发现添加时设置为1MB的分区, 此时拥有文件系统<code>grub core.img</code>, 说明grub-pc安装完毕</li></ul></li></ul><h3 id="关闭虚拟机"><a href="#关闭虚拟机" class="headerlink" title="关闭虚拟机"></a>关闭虚拟机</h3><h2 id="测试U盘中的Ubuntu"><a href="#测试U盘中的Ubuntu" class="headerlink" title="测试U盘中的Ubuntu"></a>测试U盘中的Ubuntu</h2><h3 id="更改虚拟机属性-1"><a href="#更改虚拟机属性-1" class="headerlink" title="更改虚拟机属性"></a>更改虚拟机属性</h3><ul><li>添加-虚拟硬盘, 磁盘类型设置为<code>使用物理驱动器</code>, 选择目标U盘, 一般为最后一个</li><li>修改-虚拟光驱, 取消勾选<code>启动时连接</code></li></ul><h3 id="启动虚拟机-UEFI"><a href="#启动虚拟机-UEFI" class="headerlink" title="启动虚拟机(UEFI)"></a>启动虚拟机(UEFI)</h3><ul><li>虚拟机应当成功引导进入Ubuntu桌面, 执行下面的命令, 以验证当前的引导类型<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">ls /sys/firmware/efi</span><br><span class="line"><span class="comment"># 若成功执行, 说明为UEFI引导; 若提示找不到文件, 则为BIOS引导</span></span><br></pre></td></tr></table></figure></li></ul><h3 id="更改虚拟机属性-2"><a href="#更改虚拟机属性-2" class="headerlink" title="更改虚拟机属性"></a>更改虚拟机属性</h3><ul><li>修改-<code>虚拟机设置&gt;选项&gt;高级&gt;固件类型</code>, 设置为<code>BIOS</code></li></ul><h3 id="启动虚拟机-BIOS"><a href="#启动虚拟机-BIOS" class="headerlink" title="启动虚拟机(BIOS)"></a>启动虚拟机(BIOS)</h3><ul><li>虚拟机应当成功引导进入Ubuntu桌面, 执行上文的命令, 以验证当前的引导类型</li></ul><h3 id="关闭虚拟机-1"><a href="#关闭虚拟机-1" class="headerlink" title="关闭虚拟机"></a>关闭虚拟机</h3><h2 id="维护U盘中的Ubuntu"><a href="#维护U盘中的Ubuntu" class="headerlink" title="维护U盘中的Ubuntu"></a>维护U盘中的Ubuntu</h2><ul><li>如果发生无法引导的状况, 可以参考该节进行维护, 仍使用虚拟机方法</li></ul><h3 id="创建虚拟机-1"><a href="#创建虚拟机-1" class="headerlink" title="创建虚拟机"></a>创建虚拟机</h3><ul><li>与前文用于安装的虚拟机配置相同</li></ul><h3 id="启动至LiveCD"><a href="#启动至LiveCD" class="headerlink" title="启动至LiveCD"></a>启动至LiveCD</h3><ul><li>选择-<code>Try Ubuntu</code></li><li>进入-终端</li></ul><h3 id="开始修复"><a href="#开始修复" class="headerlink" title="开始修复"></a>开始修复</h3><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># root</span></span><br><span class="line">sudo su</span><br><span class="line"></span><br><span class="line"><span class="comment"># 定位分区</span></span><br><span class="line">fdisk -l</span><br><span class="line"><span class="comment"># 假设 /dev/sda2 为 efi 分区</span></span><br><span class="line"><span class="comment"># 假设 /dev/sda3 为 / 分区</span></span><br><span class="line"><span class="comment"># 假设 /dev/sda3 为 /boot 分区, 如果有</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 挂载分区</span></span><br><span class="line">mkdir /mnt/sda2</span><br><span class="line">mkdir /mnt/sda3</span><br><span class="line">mount /dev/sda2 /mnt/sda2</span><br><span class="line">mount /dev/sda3 /mnt/sda3</span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装efi需要的依赖</span></span><br><span class="line">apt install grub-efi-amd64</span><br><span class="line"></span><br><span class="line"><span class="comment"># 以下命令针对没有单独/boot分区的用户</span></span><br><span class="line"><span class="comment">## 修复UEFI引导</span></span><br><span class="line">grub-install --target=x86_64-efi --boot-directory=/mnt/sda3/boot --efi-directory=/mnt/sda2 --removable /dev/sda</span><br><span class="line"><span class="comment">## 修复BIOS引导</span></span><br><span class="line">grub-install --target=i386-pc --boot-directory=/mnt/sda3/boot /dev/sda</span><br><span class="line"></span><br><span class="line"><span class="comment"># 以下命令针对单独/boot分区的用户</span></span><br><span class="line"><span class="comment">## 修复UEFI引导</span></span><br><span class="line">grub-install --target=x86_64-efi --boot-directory=/mnt/sda3 --efi-directory=/mnt/sda2 --removable /dev/sda</span><br><span class="line"><span class="comment">## 修复BIOS引导</span></span><br><span class="line">grub-install --target=i386-pc --boot-directory=/mnt/sda3 /dev/sda</span><br></pre></td></tr></table></figure><h3 id="测试修复结果"><a href="#测试修复结果" class="headerlink" title="测试修复结果"></a>测试修复结果</h3><ul><li>与前文安装后进行的测试相同</li></ul><h2 id="发生甚么事了"><a href="#发生甚么事了" class="headerlink" title="发生甚么事了"></a>发生甚么事了</h2><ul><li>这一部分将解释为什么上文的操作能行, 核心的概念:<ul><li>UEFI与BIOS引导</li><li>MBR与GPT分区表</li></ul></li><li>我不是BIOS或者UEFI或者MBR或者GPT专家, 这里的介绍仅供参考<ul><li>只介绍了用的上的部分</li></ul></li></ul><h3 id="MBR分区表"><a href="#MBR分区表" class="headerlink" title="MBR分区表"></a>MBR分区表</h3><ul><li>MBR: 主引导记录, 在磁盘扇区0, 包括一段引导代码和分区表之类的</li><li>神秘的空间: 扇区1~扇区62<ul><li>参阅<a href="https://stackoverflow.com/questions/36800786/why-is-the-first-partition-of-an-mbr-set-up-on-sector-63" target="_blank" rel="noopener">Why is the first partition of an MBR set up on sector 63</a></li><li>简而言之, 这个神秘的空间是历史遗留问题, 但恰好可以放东西; 当然, 这里也是病毒的快乐老家</li><li>还有VBR之类的balabala</li></ul></li></ul><h3 id="GPT分区表"><a href="#GPT分区表" class="headerlink" title="GPT分区表"></a>GPT分区表</h3><ul><li>GPT: 在磁盘扇区1</li><li>protective MBR: 在磁盘扇区0<ul><li>主要为了防止不认识GPT的程序, 将磁盘误认为未分区, 因此添加该部分, 假装自己是MBR</li><li>尽管具有正常MBR的结构, 但是这里把整个磁盘分为一个区, 意思就是”别瞎搞”</li><li>正因此结构, BIOS+GPT的组合才能成功</li></ul></li><li>bios_grub分区<ul><li>代替”神秘的空间”, 专门为grub-pc在GPT上运行</li></ul></li></ul><h3 id="BIOS引导"><a href="#BIOS引导" class="headerlink" title="BIOS引导"></a>BIOS引导</h3><ul><li>流程概述<ul><li>加载主板rom当中的BIOS固件</li><li>磁盘扇区0为MBR, 加载其中的代码段</li><li>代码段执行, 直接加载操作系统, 或者加载更多代码直到加载操作系统</li></ul></li><li>grub-pc<ul><li>MBR扇区代码段, 被grub-install替代为<code>boot.img</code>的内容, 该代码将加载一个硬编码地址的<code>core.img</code><ul><li>由于GPT存在<code>protective MBR</code>, 在GPT分区下依然可以安放这段代码, 而BIOS固件根本不在乎分区表类型, 因此可以启动</li></ul></li><li><code>core.img</code>存放在:<ul><li>MBR下: 扇区1~扇区62的这个部分里, “神秘的空间”, 和bootkit类病毒肩并肩</li><li>GPT下: 带有<code>bios_grub</code>的分区内</li></ul></li><li><code>core.img</code>执行时, 将根据配置文件加载操作系统</li></ul></li></ul><h3 id="UEFI引导"><a href="#UEFI引导" class="headerlink" title="UEFI引导"></a>UEFI引导</h3><ul><li>流程概述<ul><li>加载主板nvram当中的UEFI固件</li><li>磁盘带<code>esp</code> flag的分区, 加载其中的<code>.efi</code>文件</li><li>加载操作系统</li></ul></li><li>grub-efi<ul><li>没什么特别的, 本体就是一个<code>.efi</code>文件</li></ul></li></ul><h3 id="UEFI-GPT"><a href="#UEFI-GPT" class="headerlink" title="UEFI+GPT"></a>UEFI+GPT</h3><ul><li>美滋滋, 最新最好的引导和分区方式, 一种标准范式</li><li>windows使用UEFI引导强制要求GPT, 这是windows的错误</li></ul><h3 id="UEFI-MBR"><a href="#UEFI-MBR" class="headerlink" title="UEFI+MBR"></a>UEFI+MBR</h3><ul><li>可以配合BIOS+MBR实现双启动</li><li>我也尝试过了, 但是不优雅, 等我心情好在写在这里</li><li>MBR面临主分区最大4个或3个, 外带拓展分区和逻辑分区的问题, 不影响使用, 但不够优雅</li></ul><h3 id="BIOS-GPT"><a href="#BIOS-GPT" class="headerlink" title="BIOS+GPT"></a>BIOS+GPT</h3><ul><li>本文方法, 配合UEFI+GPT实现双启动</li><li>BIOS只查看第一个扇区, 加载里面的代码, 然后跳转走人, 因此只要第一个扇区是一个有效的MBR即可, 而GPT恰好可以</li><li>UEFI只看一个esp分区, 也是同样</li></ul><h3 id="BIOS-MBR"><a href="#BIOS-MBR" class="headerlink" title="BIOS+MBR"></a>BIOS+MBR</h3><ul><li>另一个标准范式</li></ul><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><ul><li>本文操作能成功的关键<ul><li>GPT的protective MBR, 允许一个GPT分区兼容MBR的代码段</li><li>grub-pc针对GPT提供的bios_grub解决方法</li></ul></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;在U盘中安装Ubuntu并支持在BIOS/UEFI 2种引导方式下启动&lt;br&gt;
    
    </summary>
    
      <category term="Technique" scheme="https://Maxwell-lyu.github.io/categories/Technique/"/>
    
    
      <category term="Utility" scheme="https://Maxwell-lyu.github.io/tags/Utility/"/>
    
  </entry>
  
  <entry>
    <title>编译原理 9</title>
    <link href="https://Maxwell-lyu.github.io/2020/05/13/Learn-PTC-20200513-PTC-09/"/>
    <id>https://Maxwell-lyu.github.io/2020/05/13/Learn-PTC-20200513-PTC-09/</id>
    <published>2020-05-13T10:25:22.000Z</published>
    <updated>2020-05-29T10:11:49.583Z</updated>
    
    <content type="html"><![CDATA[<h1 id="机器无关的优化"><a href="#机器无关的优化" class="headerlink" title="机器无关的优化"></a>机器无关的优化</h1><h2 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h2><ul><li>代码优化或代码改进<ul><li>消除不必要</li><li>替换为更快的同功能指令</li></ul></li><li>全局优化<ul><li>具体的优化实现基于数据流分析计数</li><li>用以收集程序相关信息的算法</li></ul></li></ul><h2 id="优化的来源"><a href="#优化的来源" class="headerlink" title="优化的来源"></a>优化的来源</h2><ul><li>编译器只能通过一些相对底层的语义等价转换来优化代码<ul><li>冗余的原因<ul><li>源程序中的冗余</li><li>高级语言的副产品</li></ul></li><li>语义不变的优化<ul><li>公共子表达式的消除0</li><li>复制传播</li><li>死代码消除</li><li>常量折叠</li></ul></li><li>全局公共子表达式<ul><li>表达式E<ul><li>如果某次出现之前必然被计算过</li><li>且E的运算分量在该计算之后没有被改变</li><li>那么E的本次出现就是一个公共子表达式</li></ul></li><li>如果上次E赋值给了x, 且x的值没有被修改过, 则可以使用x而不是计算E</li></ul></li><li>复制传播<ul><li>形如u=v的复制语句, 使得之后的程序点上, u的值等于v的值<ul><li>如果某点一定相等, 则u课替换为v</li><li>有时可以彻底消除对u的引用</li></ul></li><li>尽可能用v替代u, 可能就用不着这个</li></ul></li><li>死代码消除<ul><li>如果某个变量的值算出来后, 有被使用, 则是活跃的, 反之是死的</li><li>死代码多半是因为先前的优化产生的</li></ul></li><li>代码移动<ul><li>循环中的代码会被执行很多次<ul><li>循环不变表达式: 循环的同一次运行的不哦她那个迭代中, 表达式的值不改变</li><li>移到入口计算, 能提高效率</li></ul></li></ul></li><li>归纳变量和强度消减<ul><li>归纳变量<ul><li>每次对x赋值都使x增加c, 则把赋值改成增量操作, 可以减少开销</li><li>两个变量步调一致, 可删除一个<h2 id="数据流分析"><a href="#数据流分析" class="headerlink" title="数据流分析"></a>数据流分析</h2></li></ul></li></ul></li></ul></li><li>数据流分析<ul><li>用于获取数据沿着程序执行路径, 流动信息的相关技术</li><li>是优化的基础</li></ul></li><li>数据流抽象<ul><li>程序点: 三地址语句之前或之后的位置<ul><li>基本块内部: 一个语句之后的程序点, 等于下一个语句之前的程序点</li><li>如果流图中有B1到B2的边, 那么B2的第一个语句执行之前的点, 可能紧跟在B1的最后语句之后的点后面执行</li></ul></li><li>从p1到pn的执行路径<ul><li>要么pi是一个语句之前的点, pi+1是该语句之后的点</li><li>要么pi是某个基本块的结尾, 且pi+1是基本块某个后继的开头</li></ul></li><li>出现在某个点的程序状态<ul><li>某个运行时刻, 当指令指针指向这个程序点时, 各个变量和动态内存中存放的值</li><li>指令指针可能多次指向同一个程序点, 因此一个程序点可能对应多个程序状态</li></ul></li><li>数据流分析把可能出现在同一个程序点上的状态集合, 总结为一些特性<ul><li>不管程序怎么运行, 到达该点, 程序状态总是满足分析得到的特性</li><li>不同的分析技术关心不同的信息</li></ul></li><li>性质和算法<ul><li>根据不同的需要来设置不同的性质集合, 然后设计分析算法<ul><li>程序点上的性质被表示成为数据流值, 求解这些数据流值实际上就是推导这些性质的过程</li></ul></li><li>到达定值<ul><li>如果要求出变量在某个点上的值可能在哪里定制, 可以使用到达定值<ul><li>性质形式: x由d1定值</li></ul></li><li>如果希望实现常量折叠优化, 关心的是某个点上x的值是否总是由某个常量赋值语句给予<ul><li>性质形式: x=c, x = NAC</li></ul></li></ul></li></ul></li><li>数据流分析模式<ul><li>数据流分析中, 程序点和数据流值关联在一起<ul><li>数据流值表示了程序点的性质</li><li>和某个程序点相关的数据流值: 程序运行中经过这个点时必然具有的性质(安全)</li></ul></li><li>域<ul><li>某个数据流所有可能值的集合</li><li>不容的应用选不同的域, 例如到达定值, 数据流值是定值(三地址语句)的集合</li></ul></li></ul></li><li>数据流分析<ul><li>对一组数据约束求解, 得到各个点上的数据流值<ul><li>两类约束: 语义约束和控制流</li></ul></li><li>基于语义的约束<ul><li>一个语句之前和之后的数据流值, 受到其语义的约束</li><li>语句语义通常用传递函数表示, 它把一个数据流值映射为另一个数据流值</li></ul></li><li>基于控制流的约束<ul><li>在基本块内部, 一个语句的输出=下一个语句的输入</li><li>流图的控制流边也对应新的约束</li></ul></li></ul></li><li>基本块内的数据流模式<ul><li>非常简单<ul><li>从头到尾不会中断</li><li>没有分支</li></ul></li><li>基本块的效果, 就是各个语句效果的复合</li><li>可以预先处理基本块内部数据流关系, 给出基本块对应的传递函数</li></ul></li><li>基本块之间的控制流约束<ul><li>前向数据流问题<ul><li>B的传递函数根据IN计算OUT</li><li>IN和B的各个前驱基本块之间的OUT值具有约束关系</li></ul></li><li>逆向数据流问题<ul><li>B的传递函数根据OUT计算得到IN</li><li>OUT和B的各个后继基本块之间具有约束关系</li></ul></li></ul></li><li>数据流方程解的精确性和安全性<ul><li>数据流方程通常没有唯一解</li><li>目标是寻找一个最精确且满足约束的解<ul><li>精确: 进行最多的改进</li><li>满足约束: 根据分析结果来改进代码是安全的</li></ul></li></ul></li><li>到达定值<ul><li>到达定值<ul><li>假定x有定值d, 如果存在一个路径, 从紧随d的点到达某点p, 并且此路径上没有x的其他定值点, 则称x的定值d到达p</li><li>如果路径上有对x的其他定值, 我们说变量x的这个定值d被杀死了</li></ul></li><li>如果某个变量x的一个定值d到达了点p, 在p点使用x的时候, x的值是由d最后定值的</li><li>到达定值的解允许不精确, 但必须是安全的<ul><li>分析得到的到达定值可能实际上不会到达</li><li>但是实际到达的一定被分析出来, 否则不安全</li></ul></li><li>比如确定x在p是否为常量<ul><li>忽略变化, 可能被误认为常量, 不安全</li><li>过多估计则相反</li></ul></li><li>语句/基本块的传递方程<ul><li>定值d: u = v + w<ul><li>生成了对变量u的新定值, 杀死其他对u的定值</li><li>生成-杀死形式: $f_d(x) = gen_d\cup (x-kill_d)$</li><li>$gen_d = {d}, kill_d = \{程序中其他对u的定值\}$</li></ul></li><li>生成-杀死形式的函数复合仍具有该形式<ul><li>(直接函数复合就好)</li><li>生成的定值: 第二部分生成, 第一部分生成且没被第二部分杀死</li><li>杀死的定值: 第一部分, 第二部分杀死的定值</li></ul></li><li>设B有n个语句, 第i个语句的传递函数为fi<ul><li>$f_B(x)=gen_b\cup(x-kill_B)$</li><li>$gen_B$是所有i, 被第i个句子生成, 且未被其后的句子杀死的定值集合</li><li>$kill_B$</li></ul></li><li>到达定值的控制流方程<ul><li>只要一个定值能够沿某条路径到达一个程序点, 那么他就是到达定值</li><li>$IN[B]=\cup_{P是B的前驱基本块}OUT[P]$<ul><li>如果从P到B有一条控制流边, 则$OUT[P]$在$IN[B]$中</li><li>一个定值必然先出现在前驱, 才能出现在B</li></ul></li><li>$\cup$交汇运算符: 不一定是并集</li></ul></li><li>控制流方程的迭代解法<ul><li>ENTRY基本块的传递函数是常函数: $OUT[ENTRY] = \emptyset$</li><li>其他基本块<ul><li>$OUT[B] = gen_B\cup(IN[B] - kill_B)$</li><li>$IN[B]=\cup_{P是B的前驱基本块}OUT[P]$</li></ul></li><li>迭代解法<ul><li>先求出各个基本块的$gen$和$kill$</li><li>令所有的$OUT[B]$为空集, 然后不停迭代, 得到最小不动点的解</li></ul></li><li>解法的正确性: 不断传递定值, 直到被杀死</li><li>为什么不出现死循环<ul><li>各个OUT不会变小</li><li>各个OUT有穷的上界</li><li>只有增加了某个OUT的值, 算法才会继续迭代</li></ul></li><li>最大迭代次数: 流图的结点数n, 任意定值经过n步必然到达所有可能的结点</li><li>结束时, 各个IN/OUT必然满足数据流方程</li></ul></li></ul></li></ul></li></ul></li><li>活跃变量分析<ul><li>活跃变量分析<ul><li>x在p上的值是否会在某条从p出发的路径中使用</li><li>变量x在p上活跃, 当且仅当存在一条从p开始的路径, 其末端使用了x, 且路径上没有对x进行覆盖</li></ul></li><li>用途: 寄存器分配/死代码删除</li><li>数据流值: (活跃)变量的集合</li><li>基本块内的数据流方程<ul><li>基本块内的传递函数依然是生成-杀死形式, 但是从OUT算IN(逆向)<ul><li>$use_B$: 在B中先于定值被使用</li><li>$def_B$: 在B中先于使用被定值</li></ul></li><li>语句的传递函数<ul><li>s: x = y + z</li><li>$use_s = \{y,z\}$</li><li>$def_s = \{x\} - \{y,z\}$</li></ul></li><li>多个语句<ul><li>每一个语句的use需减去其前所有def, 然后cup得到整个块的use</li><li>每一个语句的def需减去其前所有use, 然后cup得到整个块的def</li></ul></li></ul></li><li>活跃变量数据流方程<ul><li>任何变量在程序出口不再活跃: $IN[EXIT] = 空集$</li><li>对于所有不等于EXIT的基本块<ul><li>$IN[B] = use_B\cup(OUT[B]-def_B)$</li><li>$OUT[B] = \bigcup_{S是B的后继基本块}IN[S]$</li></ul></li><li>与到达定值比较<ul><li>都使用并运算; 数据流向不同(逆向)</li></ul></li></ul></li><li>活跃变量分析的迭代方法<ul><li>首先所有IN都是空集</li><li>对除了EXIT的所有基本块<ul><li>计算新OUT</li><li>计算新IN</li></ul></li><li>直到各个IN无变化</li><li>IN越来越大, 且有上界, 因此必然停机</li></ul></li></ul></li><li><p>可用表达式分析</p><ul><li>x+y在p点可用<ul><li>从流图入口结点到达p的每条路径都对x+y求值, 且在最后一次求值之后再也没有对x或y赋值</li></ul></li><li>主要用途<ul><li>寻找全局公共子表达式</li></ul></li><li>生成-杀死<ul><li>生成: 基本块求值x+y, 且之后没有对x或y赋值, 那么它生成了x+y</li><li>杀死: 基本块对x或y赋值, 且没有重新计算x+y, 那么它杀死了x+y</li></ul></li><li>计算基本块生成的表达式<ul><li>初始化S={}</li><li>从头到尾处理每个指令x=y+z<ul><li>y+z添加到S中, 从S中删除任何涉及变量x的表达式</li></ul></li><li>遍历结束得到基本块生成的表达式集合</li></ul></li><li>计算基本块杀死的表达式: 表达式的某个分量被定值, 且没有被再次生成</li><li>可用表达式的数据流方程<ul><li>ENTRY结点的出口处没有可用表达式: $OUT[ENTRY]=空集$</li></ul></li><li>其他基本块的方程<ul><li>OUT: 跟到达定值一样</li><li>IN: 求交集而不是并集</li></ul></li><li><p>算法</p><ul><li>$OUT[ENTRY]$为空集, 而其余的OUT初始化为全集</li></ul><p>||到达定值|活跃变量|可用表达式|<br>|-|-|-|-|<br>|方向|正向|反向|正向|<br>|传递函数|$gen_B\cup(x-kill_B)$|$use_B\cup(x-def_B)$|$e_gen_B\cup(x-e_kill_B)$|<br>|边界条件|$OUT[ENTRY]=\emptyset$|$IN[EXIT]=\emptyset$|$OUT[ENTRY]=\emptyset$|<br>|交汇运算$\wedge$|$\cup$|$\cup$|$\cap$|<br>|方程组|$OUT[B]=f_B(IN[B])\quad IN[B]=\bigwedge_{P,pred(B)}OUT[P]$|$IN[B]=f_B(OUT[B])\quad OUT[B]=\bigvee_{S,succ(B)}IN[S]$|$OUT[B] = f_B(IN[B])\quad IN[B]=\bigvee_{P,pred(B)}OUT[P]$|<br>|初始值|$OUT[B]=\emptyset$|$IN[B]=\emptyset$|$OUT[B]=U$|</p></li></ul></li></ul><h2 id="部分冗余消除"><a href="#部分冗余消除" class="headerlink" title="部分冗余消除"></a>部分冗余消除</h2><ul><li>部分冗余消除<ul><li>目标: 尽量减少表达式求值的次数</li><li>对于表达式x+y<ul><li>全局公共子表达式: 如果x+y求值前的程序点上x+y可用, 那么不需要再对x+y求值</li><li>循环不变表达式: 循环中表达式x+y的值不变, 可以只计算一次</li><li>部分冗余: 在程序按照某些路径到达这个点的时候x+y已经计算过, 但另一些尚未计算过</li></ul></li><li>需要更复杂的数据流分析技术</li><li>需要添加基本块来消除的冗余<ul><li>进行两种操作<ul><li>在关键边上增加基本块</li><li>进行代码复制</li></ul></li><li>关键边<ul><li>从具有多个后继的结点, 到达具有多个前驱的结点</li></ul></li></ul></li><li>懒惰代码移动<ul><li>目标<ul><li>所有不复制代码就可消除的冗余计算都被消除</li><li>优化后的代码不会执行源程序中不执行的任何计算</li><li>表达式的计算应该尽量靠后, 利于寄存器分配</li></ul></li><li>冗余消除<ul><li>完全冗余</li><li>部分冗余: 在流图中放置表达式x+y的拷贝, 使得某处的x+y成为完全冗余从而删除</li></ul></li><li>基本步骤<ul><li>找出各个程序点上预期执行的所有表达式<ul><li>被预期执行: 如果从p出发的所有路径都会计算b+c的值, 并且b和c在那时的值就是p的值, 那么b+c在p预期执行</li><li>数据流分析框架<ul><li>逆向分析</li><li>基本块内部: 当表达式在B出口处被预期执行, 且它没有被B杀死, 那么它在B入口处也被预期执行</li><li>基本块之间: 当在B的所有后继基本块的入口处都被预期执行, 那么表达式在B出口处被预期执行</li><li>在整个程序的出口处, 没有表达式被预期执行</li></ul></li><li>求出预期执行点之后, 表达式被放置到首次被预期执行的程序点上: 一些表达式因此变成完全冗余</li></ul></li><li>在表达式被预期执行但是不可用的程序点上, 放置表达式的计算<ul><li>可用表达式: 和前面的可用表达式类似, 但假设代码已经被复制到的预期执行点上</li><li>表达式在基本块的出口处可用的条件<ul><li>在基本块的入口处可用, 或在基本块的入口处的预期执行表达式中</li><li>且没有被这个基本块杀死</li></ul></li></ul></li><li>把表达式尽量后延到某个程序点, 在到达这个程序点的所有路径上, 这个表达式在这个程序点之前被预期执行, 但还没有使用这个值<ul><li>可后延表达式<ul><li>在保持程序语义的情况下， 尽可能延后计算表达式</li><li>x + y可后延到p的条件: 所有从程序入口到达p的路径 中都会碰到一个位置较前的x + y，且在最后一个这样的位 置到p之间没有使用x + y</li><li>粗略地说，一个表达式将被放置在边界上，即一 个表达式从可后延变成不可后延的地方</li></ul></li></ul></li><li>消除只使用一次的临时变量<ul><li>确定一个被引入的临时变量是否在它所在基本块 之外的其它地方使用+<ul><li>对表达式的活跃性分析</li><li>如果从程序点p出发的一条路径在表达式被重新求值之 前使用了该表达式，那么该表达式在点p上被使用</li></ul></li></ul></li></ul></li></ul></li></ul></li></ul><h2 id="循环的识别分析和优化"><a href="#循环的识别分析和优化" class="headerlink" title="循环的识别分析和优化"></a>循环的识别分析和优化</h2><ul><li>循环的重要性+ 程序的大部分执行时间都花在循环上<ul><li>也是数据流分析需要经过若干次迭代的原因</li></ul></li><li>相关概念<ul><li>支配结点<ul><li>支配 (Dominate): 如果每条从入口结点到达n的路径都经过d，那么d支配n，记为d dom n</li><li>支配结点树可以表示支配关系<ul><li>根结点：入口结点</li><li>每个结点d支配且只支配树中的后代结点</li></ul></li><li>直接支配结点<ul><li>从入口结点到达n的任何路径 (不含n) 中，它是路径中 最后一个支配n的结点</li><li>n的直接支配结点m具有如下性质：如果d ≠ n且d dom n，那么d dom m</li></ul></li><li>寻找支配结点算法<br>+ </li></ul></li><li>深度优先排序</li><li>回边</li><li>图的深度</li><li>可归约性</li></ul></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;机器无关的优化&quot;&gt;&lt;a href=&quot;#机器无关的优化&quot; class=&quot;headerlink&quot; title=&quot;机器无关的优化&quot;&gt;&lt;/a&gt;机器无关的优化&lt;/h1&gt;&lt;h2 id=&quot;引言&quot;&gt;&lt;a href=&quot;#引言&quot; class=&quot;headerlink&quot; title=&quot;引
      
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Principles and Techniques of Compilers" scheme="https://Maxwell-lyu.github.io/tags/Principles-and-Techniques-of-Compilers/"/>
    
  </entry>
  
  <entry>
    <title>编译原理 8</title>
    <link href="https://Maxwell-lyu.github.io/2020/04/30/Learn-PTC-20200430-PTC-08/"/>
    <id>https://Maxwell-lyu.github.io/2020/04/30/Learn-PTC-20200430-PTC-08/</id>
    <published>2020-04-30T06:45:51.000Z</published>
    <updated>2020-05-13T10:24:59.542Z</updated>
    
    <content type="html"><![CDATA[<h1 id="代码生成"><a href="#代码生成" class="headerlink" title="代码生成"></a>代码生成</h1><ul><li>要解决的问题<ul><li>正确性</li><li>易于实现, 测试和维护</li></ul></li><li>输入IR的选择: 四元式, 三元式, 字节代码, 堆栈机代码, 后缀表示, 抽象语法树, DAG</li><li>输出: RISC, CISC, 可重定向代码, 汇编语言<h2 id="目标语言"><a href="#目标语言" class="headerlink" title="目标语言"></a>目标语言</h2></li><li>目标机模型<ul><li>使用三地址机器的模型</li><li>指令<ul><li>加载: LD dst,addr addr内存的内容加载到dst寄存器</li><li>保存: ST x,r 寄存器r到x</li><li>计算: OP dst,src1,src2 两个值运算后到dst</li><li>无条件跳转: BR L 控制流转到标号L的指令</li><li>条件跳转: Bcond r,L 对r种的值进行测试, 为真转向L</li></ul></li><li>寻址模式<ul><li>变量x: 指向分配x的内存位置</li><li>a(r): 地址是a的左值加上寄存器r中的值</li><li>constant(r): 寄存器中内容加上前面的常数即地址</li><li>*r: 寄存器的内容所表示的位置上, 存放的内容位置</li><li>*constant(r): 寄存器中内容加上前面的常数所代表的位置, 上的内容所表示的位置</li><li>#constant: 常量</li></ul></li><li>程序及指令的代价<ul><li>不同的目的有不同的度量</li><li>不可判定一个目标程序是否最优<h2 id="目标语言中的地址"><a href="#目标语言中的地址" class="headerlink" title="目标语言中的地址"></a>目标语言中的地址</h2></li></ul></li></ul></li><li>目标代码中的地址<ul><li>如何为过程调用和返回生成代码<ul><li>静态分配: 活动记录</li><li>栈式分配: 活动记录</li></ul></li><li>如何将变量名和函数名转换为地址? 不同区域的名字采用不同寻址方式</li></ul></li><li>活动记录的静态分配<ul><li>每个过程静态地分配一个数据区域, 用staticArea表示</li><li>call callee<ul><li>ST callee.staticArea, #here+20</li><li>BR callee.codeArea</li></ul></li><li>callee中的return<ul><li>BR *callee.staticArea: 跳转到静态区起始, 指向的地方(返回地址) </li></ul></li></ul></li><li>活动记录的栈式分配<ul><li>寄存器SP指向栈顶</li><li>第一个过程main初始化栈区</li><li>过程调用指令序列<ul><li>ADD SP, SP, #caller.recordSize</li><li>ST 0(SP), #here + 16</li><li>BR callee.codeArea</li></ul></li><li>返回指令序列<ul><li>BR *0(SP)</li><li>SUB SP, SP, $caller.recordSize</li></ul></li></ul></li><li>名字的运行时刻地址<ul><li>在三地址语句中使用名字: 实际上是指向符号表条目来引用变量</li><li>语句x = 0<ul><li>x在静态区, 且静态区开始位置为static, 则直接访问即可<ul><li>LD 112, #0     (112是在编译时刻确定)</li></ul></li><li>x在栈区, 且相对地址为12<ul><li>LD 12(SP), #0<h2 id="基本块和流图"><a href="#基本块和流图" class="headerlink" title="基本块和流图"></a>基本块和流图</h2></li></ul></li></ul></li></ul></li><li>基本块和流图<ul><li>中间代码的流图表示法<ul><li>中间代码划分为基本块<ul><li>控制流只能从基本块的第一条指令进入</li><li>除基本块的最后一条指令外, 控制流不会跳转/停机</li></ul></li><li>流图的结点是基本块, 边指明了哪些基本块可以在当前基本块后运行</li></ul></li><li>流图可以作为优化的基础<ul><li>指出了基本块之间的控制流</li><li>根据流图了解到一个值是否会被使用等信息</li></ul></li><li>划分基本块的算法<ul><li>方法<ul><li>确定首指令leader<ul><li>第一个三地址指令</li><li>任意一个转移指令的目标指令</li><li>紧跟在一个转移指令之后的指令</li></ul></li><li>确定基本块: 每个首指令对应一个基本块, 从一个首指令到下一个首指令</li></ul></li></ul></li><li>后续使用信息<ul><li>变量值的使用<ul><li>三地址语句i向x赋值, 如果另一个语句j的运算分量为x, 且从i开始有一条路径到j, 且路径上没有对x赋值, 那么j就使用了i处计算得到的x值</li><li>我们说变量x在语句i后的程序点上活跃<ul><li>程序执行完i, x中存放的值将被后面的语句使用</li><li>不活跃是指值不会被使用, 而不是变量不被只用</li></ul></li><li>用于代码生成: 如果不活跃, 且x占用了一个寄存器, 则可以将这个寄存器用于其他目的</li></ul></li></ul></li><li>确定基本块中的活跃性<ul><li>方法  <ul><li>从B的最后一个语句开始反向扫描</li><li>对于每个语句i: x = y + z<ul><li>令语句i和x, y, z的当前活跃性信息/使用信息关联</li><li>设置x为不活跃和无后续使用</li><li>设置y和z为活跃, 并指明他们下一次使用设置为语句i</li></ul></li></ul></li></ul></li></ul></li><li>流图的构造<ul><li>流图的结点是基本块<ul><li>两个结点B和C之间有一条有向边iff基本块C的第一个指令可能在B的最后一个指令之后执行</li></ul></li><li>存在边的原因<ul><li>B的结尾指令是跳转到C的开头的条件/无条件语句</li><li>C紧跟在B之后, 且B的结尾不是无条件跳转语句</li><li>B是C的前驱, C是B的后继</li></ul></li><li>入口/出口结点<ul><li>不和任何中间指令对应; 入口到第一条指令有一条边, 任何可能最后执行的基本块到出口有一条边</li></ul></li></ul></li><li>循环<ul><li>程序中的大部分时间都花在循环上</li><li>循环的定义<ul><li>循环L是一个结点集合</li><li>存在一个循环入口, 是唯一的, 前驱可以在这个循环之外, 到达循环的其余结点的路径必然经过这个入口</li><li>其余结点都存在到达入口的非空路径, 即路径在L中<h2 id="基本块优化"><a href="#基本块优化" class="headerlink" title="基本块优化"></a>基本块优化</h2></li></ul></li></ul></li><li>基本块的优化<ul><li>针对基本块的优化(局部优化)</li><li>DAG图可以反应变量及其值对其他变量的依赖关系</li><li>构造方法<ul><li>每个变量都有一DAG结点表示其初始值</li><li>每个语句s有一个相关的结点N, 代表此计算得到的值<ul><li>N的子节点对应于(得到其运算分量当前值的)其他语句</li><li>N的标号是s中的运算符, 同时还有一组变量被关联到N, 表示s是最晚对这些变量进行定值的语句\</li></ul></li></ul></li><li>DAG构造<ul><li>为基本块中出现的每个变量建立结点(表示初始值)</li><li>顺序扫描各个三地址指令<ul><li>指令x = y op z<ul><li>为该指令建立结点N, 标号op, 令x和N关联</li><li>N的子节点为y,z当前关联的结点</li></ul></li><li>指令x=y<ul><li>假设y关联到N, 那么x现在也关联到N</li></ul></li><li>扫描结束后, 出口处活跃的变量x, 其关联的结点设置为输出结点</li></ul></li></ul></li><li>DAG的作用<ul><li>描述了各变量的值之间的关系</li></ul></li><li>以DAG为基础, 对代码进行转换<ul><li>寻找局部公共子表达式<ul><li>局部公共子表达式的发现<ul><li>建立某个结点M之前, 检查是否存在一个结点N, 它和M具有相同的运算符和子节点(顺序也相同)</li><li>如果存在, 则不需要生成新结点, N代替M</li></ul></li></ul></li><li>消除死代码<ul><li>DAG图上, 消除没有附加活跃变量的根节点, 即消除死代码</li></ul></li><li>代数恒等式的使用<ul><li>消除计算步骤(加减乘除, 01的特殊)</li><li>降低强度: 例如乘2变为加</li><li>常量合并: 常量计算变赋值</li></ul></li><li>数组引用的表示<ul><li>从数组取值的运算, 对应于=[]的结点<ul><li>这个结点的子节点是数组对应初始值a和下标i</li><li>变量x是这个结点的标号之一</li></ul></li><li>对数组赋值的运算对应于[]=的结点<ul><li>这个结点的三个子节点分别表示a, 下标i和值y</li><li>杀死所有依赖于a的变量</li></ul></li></ul></li><li>指针赋值和过程调用<ul><li>通过指针进行取值/赋值: x=*p, q*=y<ul><li>x使用了任意变量, 因此无法消除死代码</li><li>*q=y对任意变量赋值, 因此杀死了全部其他节点</li></ul></li><li>可通过(全局/局部)指针分析, 部分解决该问题</li><li>过程调用类似<ul><li>使用了可访问范围内的所有变量</li><li>修改了课访问范围内的所有变量</li></ul></li></ul></li></ul></li><li>从DAG到基本块<ul><li>重构的方法<ul><li>每个结点构造一个三地址语句, 计算对应的值</li><li>结果尽量赋值给一个活跃的变量</li><li>如果结点有多个关联的变量, 则需要用赋值语句进行赋值</li><li>多个变量可选作为参数时, 尽量使用已经活跃的变量, 尽量少地将不活跃的变量变成活跃</li></ul></li><li>重组的规则<ul><li>注意求值顺序<ul><li>指令必须遵守DAG中结点的顺序</li><li>对数组赋值要跟在原来之前的赋值/求值之后</li><li>对数组求值要跟在原来的赋值指令之后</li><li>对变量的使用必须跟在所有原来在他之前的过程调用和指针间接复制之后</li><li>任何过程调用或指针间接赋值必须跟在原来它之前的变量求值之后</li></ul></li><li>即保证<ul><li>如果两个指令相互影响, 他们的顺序就不该改变</li></ul></li></ul></li></ul></li></ul></li></ul><h2 id="代码生成器"><a href="#代码生成器" class="headerlink" title="代码生成器"></a>代码生成器</h2><ul><li>根据三地址指令序列生成机器指令<ul><li>假设每个三地址指令只有一个对应的机器指令<ul><li>有一组寄存器, 用于计算基本块内部的值</li></ul></li><li>主要目标是减少加载LD和保存ST指令, 即最大限度地利用寄存器</li><li>寄存器的使用方法<ul><li>执行运算时, 运算分量必须放在寄存器中</li><li>存放临时变量</li><li>存放全局的值</li><li>进行运行时刻管理(比如栈顶指针)</li></ul></li></ul></li><li>算法的基本思想和数据结构<ul><li>依次考虑各个三地址指令, 尽可能把值保留在寄存器中, 以减少寄存器/内存之间的数据交换</li><li>为一个三地址指令生成机器指令时<ul><li>只有当运算分量不在寄存器中时, 才从内存载入</li><li>尽量保证只有当寄存器中的值不被使用时, 才覆盖掉</li></ul></li><li>数据结构<ul><li>寄存器描述符: 跟踪各个寄存器存放了哪些变量的当前值</li><li>地址描述符: 各个变量当前值存放在哪些位置上(内存/寄存器位置)</li></ul></li></ul></li><li>代码生成算法<ul><li>重要子函数getReg(I)<ul><li>根据寄存器描述符和地址描述符等数据流信息, 为三地址指令I选择最佳的寄存器</li><li>得到的机器指令的指令依赖于getReg函数选取寄存器的算法</li></ul></li><li>代码生成算法逐个处理三地址指令</li><li>运算语句: x = y + z<ul><li>getReg(x = y + z)为xyz选择寄存器Rx Ry Rz<ul><li>检查Ry的描述符, 如果y不在Ry中, 则生成指令LD Ry,y’, y’为当前位置</li><li>Rz类似</li></ul></li><li>生成指令ADD Rx,Ry,Rz</li></ul></li><li>复制语句: x = y<ul><li>getReg(x = y)为xy选择相同的寄存器</li><li>如果y不在Ry中, 则生成指令LD Ry, y</li></ul></li><li>基本块的收尾<ul><li>如果x活跃, 且不在内存中, 则生成指令ST x,Rx</li></ul></li><li>代码生成的同时, 更新寄存器和地址描述符</li><li>处理指令时生成的LD R, x<ul><li>R的寄存器描述符: 只包含x</li><li>x的地址描述符: R作为新位置加入到x的位置集合中, 从任何不同于x的变量描述符中删除R</li></ul></li><li>生成的ST x,R<ul><li>x的地址描述符L包含自己的内存位置: 新增</li></ul></li><li>ADD Rx,Ry,Rz<ul><li>Rx的寄存器描述符: 只包含x</li><li>x的地址描述符: 只包干Rx</li><li>从任何不同于x的变量的地址描述符中删除Rx</li></ul></li><li>处理x=y时<ul><li>如果生成LD Ry,y, 按照第一个规则处理</li><li>把x加入到Ry的寄存器描述符中</li><li>x的地址描述符: 只包含Ry</li></ul></li></ul></li><li>getReg函数<ul><li>目标: 减少LD/ST指令</li><li>任务: 为运算分量和结果分配寄存器</li><li>为x= y op z的运算分量yz分配寄存器<ul><li>如果y已经在某一个寄存器中, 不需要进行处理, 选择这个寄存器Ry</li><li>如果不在, 且有空闲寄存器, 选择一个空闲寄存器</li><li>如果不在且无空闲, 寻找一个寄存器R, 其寄存器描述符表示v在R中<ul><li>如果v的地址描述符表明, 还可以在别的地方找到v, DONE</li><li>如果v就是x, 且x不是运算分量z, DONE</li><li>如果v在此之后不会被使用(不活跃), DONE</li><li>生成保存指令ST v,R, 并修改v的地址描述符, 如果R中存放了多个变量的值, 那么需要生成多条ST指令</li></ul></li><li>为x = y op z结果选择寄存器Rx的方法和上面要把y从内存LD一样, 但是<ul><li>只存放x值的寄存器总是可以接受的</li><li>如果y在指令之后不再使用, 且Ry仅仅保存了y值, 那么Ry同时也可作为Rx</li></ul></li></ul></li><li>处理x=y时, 先选择Ry, 然后让Rx = Ry</li></ul></li><li>窥孔优化<ul><li>使用一个滑动窗口, 来检查目标指令, 在窥孔内实现优化<ul><li>冗余指令消除</li><li>控制流优化</li><li>代数化简, 强度消减</li><li>机器特有指令的使用</li></ul></li><li>冗余指令的消除<ul><li>多余的LD, ST指令: LD R0,a; ST a,R0; 且后者无标号</li><li>级联跳转代码<ul><li>IF GOTO反转条件优化</li><li>如果条件已知是0或1, 那么替换为一个跳转即可</li><li>(if x op y) goto L1; … L1:goto L2: 优化为goto L2; … L1:goto L2</li></ul></li><li>代数化简/强度消减.机器特有指令<ul><li>代数恒等式: +0 *1</li><li>机器特有指令: INC, DEC<h2 id="寄存器分配"><a href="#寄存器分配" class="headerlink" title="寄存器分配"></a>寄存器分配</h2></li></ul></li></ul></li></ul></li><li>寄存器分配和指派<ul><li>寄存器分配: 确定程序的每个点上, 哪个值应该存放在寄存器中</li><li>寄存器指派: 各个值应该给存放在哪个寄存器</li><li>简单方法: 特定类型的值分配给特定的寄存器(专存专用)<ul><li>缺点: 寄存器的使用效率低</li></ul></li><li>全局寄存器分配<ul><li>循环中频繁使用的值存放在固定寄存器<ul><li>分配固定多个寄存器来存放内部循环中最活跃的值</li></ul></li><li>可以通过计数的方法, 估算把一个值放到寄存器里面会带来多大好处</li></ul></li></ul></li><li>树重写实现指令选择<ul><li>某些机器上, 某一个三地址指令可以使用多种机器指令实现, 有时多个三地址指令可以使用一个机器指令实现</li><li>指令选择<ul><li>实现中间表示形式中出现的运算符, 选择适当的机器指令</li><li>用树来表示中间代码, 按照特定的规则不断覆盖这颗树, 生成机器指令</li></ul></li><li>目标指令选择<ul><li>重写规则 replacement &lt;- template [ action ]: 替换结点: 是一个结点, 模板是一颗子树, 动作类似语法制导翻译的代码片段</li><li>一组树重写规则被称作一个翻译方案</li><li>只剩一个结点则重写结束</li></ul></li></ul></li><li>树翻译方案的工作模式<ul><li>给定一颗输入树, 树重写规则中的模板被用来匹配输入树的子树</li><li>如果匹配到, 则将这个子树替换为替换节点, 执行相应动作(生成机器指令)</li><li>不断匹配, 直到变成单一节点, 或者找不到可以匹配的模板为止</li><li>此方案中得到的指令代码序列就是树翻译方案对于给定输入树的输出</li></ul></li><li>如何完成树匹配<ul><li>把树重写规则替换成相应的上下文无关文法的产生式</li><li>右部是其指令模板的前缀表示</li></ul></li><li>如果在某个时刻有多个模板匹配, 则大树优先</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;代码生成&quot;&gt;&lt;a href=&quot;#代码生成&quot; class=&quot;headerlink&quot; title=&quot;代码生成&quot;&gt;&lt;/a&gt;代码生成&lt;/h1&gt;&lt;ul&gt;
&lt;li&gt;要解决的问题&lt;ul&gt;
&lt;li&gt;正确性&lt;/li&gt;
&lt;li&gt;易于实现, 测试和维护&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
      
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Principles and Techniques of Compilers" scheme="https://Maxwell-lyu.github.io/tags/Principles-and-Techniques-of-Compilers/"/>
    
  </entry>
  
  <entry>
    <title>编译原理 7</title>
    <link href="https://Maxwell-lyu.github.io/2020/04/21/Learn-PTC-20200421-PTC-07/"/>
    <id>https://Maxwell-lyu.github.io/2020/04/21/Learn-PTC-20200421-PTC-07/</id>
    <published>2020-04-21T03:37:46.000Z</published>
    <updated>2020-04-30T06:45:25.038Z</updated>
    
    <content type="html"><![CDATA[<h1 id="运行时刻环境"><a href="#运行时刻环境" class="headerlink" title="运行时刻环境"></a>运行时刻环境</h1><ul><li>存储管理: 栈分配, 堆管理, 垃圾回收</li><li>对变量, 数据的访问</li></ul><h2 id="存储分配的典型方式"><a href="#存储分配的典型方式" class="headerlink" title="存储分配的典型方式"></a>存储分配的典型方式</h2><ul><li>代码, 静态区, 堆区, 空闲内存, 栈区</li><li>静态分配<ul><li>全局常量, 全局变量</li></ul></li><li>动态分配<ul><li>栈式存储: 和过程调用/返回同步, 值的声明周期与过程生命周期相同</li><li>堆存储: 数据对象比创建它的过程更加长寿<ul><li>手工回收/垃圾回收机制<h3 id="栈式分配"><a href="#栈式分配" class="headerlink" title="栈式分配"></a>栈式分配</h3></li></ul></li></ul></li><li>活动树<ul><li>在时间上是嵌套的: 后调用的先返回, 栈数据结构</li><li>程序运行的所有过程活动可以用树表示<ul><li>结点: 过程活动</li><li>根节点: main过程活动</li><li>过程p的某次活动对应的结点的所有子节点<ul><li>表示p调用的各个过程活动, 左到右表示先后顺序</li></ul></li><li>调用序列-&gt;前序遍历; 返回序列-&gt;后序遍历</li></ul></li></ul></li><li>活动记录<ul><li>过程调用和返回由控制栈进行管理</li><li>每个活跃的活动对应于栈中的一个活动记录</li><li>活动记录按照活动的开始时间, 从栈底到栈顶排列</li><li>实在参数-&gt;返回值-&gt;控制链-&gt;访问链-&gt;保存的机器状态-&gt;局部数据-&gt;临时变量<ul><li>调用者和被调用者之间传递的值被放在活动记录的开始位置</li><li>固定长度的项(控制链, 访问链, 机器状态): 放在中间位置</li><li>早期不知道大小的栈在活动记录尾部</li><li>栈顶指针指向固定长度字段的末端</li></ul></li></ul></li><li>调用代码序列<ul><li>调用代码序列: 为活动记录分配空间, 填写记录中的信息</li><li>返回代码序列: 恢复机器状态, 使调用者继续运行</li><li>调用代码序列会被分隔到调用者和被调用者中<ul><li>分割方式因系统不同, 尽可能放在被调用者中</li></ul></li><li>调用代码序列的例子<ul><li>调用者计算实在参数的值</li><li>将返回地址和原top_sp存放到被调用者的活动记录<ul><li>调用者增加top_sp, 越过调用者的局部数据和临时变量, 以及参数和机器状态</li></ul></li><li>被调用者保存机器状态</li><li>被调用者初始化局部数据, 开始运行</li></ul></li><li>返回序列<ul><li>被调用者将返回值放到与参数相邻的位置</li><li>恢复top_sp和寄存器, 跳转到返回地址</li></ul></li></ul></li><li>栈中的变长数据<ul><li>活动记录中, 存储指针</li></ul></li><li>非局部数据的访问<ul><li>没有嵌套过程的数据访问<ul><li>所有的函数都是全局的<ul><li>函数的局部变量: 相对地址已知, 存放在当前活动记录内, 直接访问</li><li>全局变量: 在静态区, 地址编译时可知</li></ul></li><li>函数很容易地作为参数传递: 首地址</li></ul></li><li>有嵌套过程<ul><li>A中定义了过程B, 当他使用A中变量时, 必须通过访问链访问</li></ul></li><li>嵌套深度<ul><li>根据源程序静态确定: 全局为1, 嵌套于i的深度为i+1</li></ul></li><li>访问链和访问链的使用<ul><li>访问链被用于访问非局部的数据<ul><li>如果过程p声明时, (直接)嵌套在过程q中, 那么p活动记录中的访问链指向上层最近的q的活动记录</li><li>从栈顶的活动记录开始, 访问链形成了一个链路, 嵌套深度随链路递减</li></ul></li><li>设深度为np的过程p访问x, 而x在深度为nq的过程q中声明<ul><li>差值np-nq在编译时已知; 从当前记录出发, 沿访问链前进这么多次, 找到活动记录</li><li>x相对于这个记录的偏移量在编译时已知</li></ul></li></ul></li><li>访问链的维护: 过程q调用p时<ul><li>p深度大于q, 根据作用域规则, p必然在q中直接定义, p的访问链指向当前记录</li><li>p = q, 新访问链等于当前活动记录的访问链</li><li>p深度小于q, 必然过程r, p直接在r中定义, 而q嵌套在r中, p的访问链指向栈中r的活动记录</li></ul></li><li>支持访问链的语言<ul><li>传函数指针时, 也需要传递访问链</li></ul></li><li>显示表<ul><li>用访问链访问数据, 访问开销和嵌套深度差有关</li><li>显示表: 数组d为每个嵌套深度保留一个指针<ul><li>指针$d[i]$指向栈中最近的, 嵌套深度为i的活动记录</li><li>如果过程p访问嵌套深度为i的过程q中声明的变量x, 那么$d[i]$直接指向相应的活动记录</li></ul></li><li>维护<ul><li>调用p时, 在p的活动记录中保存$d[n_p]$的值, 并将$d[n_p]$设置为当前活动记录, 即p</li><li>从p返回时, 恢复$d[n_p]$的值</li></ul></li></ul></li></ul></li><li>堆管理<ul><li>堆空间<ul><li>用于存放生命周期不确定, 或生存到被明确删除为止的对象</li></ul></li><li>存储管理器<ul><li>分配/回收堆区空间的子系统</li><li>根据语言而定: C/C++手动, JAVA自动</li><li>基本功能<ul><li>分配: 为内存请求分配一段连续适当大小的堆空间, 首先从空闲空间取, 不行则从系统获取更多</li><li>回收: 把被回收的空间返回空闲空间缓冲池, 以满足其他需求</li></ul></li><li>评价存储管理器的特性<ul><li>空间效率: 使程序需要的堆空间最小</li><li>程序效率: 运用内存系统的层次, 使程序运行更快</li><li>低开小: 分配回收的操纵尽可能高效</li></ul></li></ul></li></ul></li><li>计算机的存储层次结构<ul><li>寄存器-&gt;一级缓存-&gt;二级缓存-&gt;物理内存-&gt;虚拟内存(磁盘)</li></ul></li><li>程序执行的局部性<ul><li>时间局部性: 一个被访问的存储位置, 很可能在一个很短的时间段内被再次访问</li><li>空间局部性: 一个被访问的存储位置, 其临近位置很可能在一个很短的时间段内被再次访问</li><li>90%时间被用来执行10%的代码</li><li>局部性可以充分利用层次存储结构</li></ul></li><li>堆空间的碎片问题<ul><li>每次分配通常只能用到一个窗口的部分空间, 留下更小的碎片</li><li>分配方法<ul><li>best-fit: 分配能够满足请求的最小的窗口, 留下大窗口, 容易产生碎片</li><li>first-fit: 空闲的内存第一个能用的, 放置对象效率高, 总体性能差, 数据局部性好</li></ul></li><li>使用容器的堆管理方法<ul><li>设定不同大小的块规格, 相同的块放入同一容器</li><li>较小的尺寸设设置较多容器<ul><li>空闲块大小: 16, 24, …, 512</li><li>大于512的按照对数划分, 每一尺寸是前一个的2倍</li><li>荒野块: 可以拓展的内存块</li></ul></li><li>小尺寸的直接在容器中找, 大尺寸的在适当容器中寻找适当的空闲块, 可能需要分割, 可能需要从荒野块分割</li><li>管理和结合空闲空间<ul><li>回收一个块时, 可以把这个块和相邻的块接合构成更大的块</li><li>支持邻接块结合的数据结构<ul><li>边界标记</li><li>双向链表</li></ul></li></ul></li><li>手工存储管理<ul><li>内存泄漏: 未能删除不可能再被引用的数据</li><li>悬空指针引用: 引用已被删除的数据</li><li>其他问题: 空指针, 数组越界</li></ul></li></ul></li><li>垃圾回收<ul><li>垃圾<ul><li>广义: 不需要再被引用的数据</li><li>狭义: 不能被引用(不可达)的数据</li></ul></li><li>垃圾回收<ul><li>自动回收不可达的数据, 解除程序员的负担</li></ul></li></ul></li><li>垃圾回收器的设计目标<ul><li>语言必须是类型按权的, 保证回收器能够知道数据元素是否为一个指向某内存块的指针</li><li>c/c++类型不安全</li></ul></li><li>性能目标<ul><li>总体运行时间: 不显著增加应用程序的总运行时间</li><li>空间使用: 最大限度地利用可用内存</li><li>停顿时间: 当垃圾回收机制启动时, 可能引起应用程序的停顿</li><li>程序局部性: 改善空间局部性和时间局部性</li></ul></li><li>可达性<ul><li>指一个存储块可以被程序访问到</li><li>根集: 不需要指针解引用就可以直接访问到的数据<ul><li>Java: 静态(全局)变量, 栈中变量</li></ul></li><li>可达性: 根集可达; 任意对象, 如果指针保存在可达对象中, 那么这个对象也是可达的</li><li>性质: 一旦一个对象变成不可达, 它就不会再变成可达</li></ul></li><li>改变可达对象集合的操作<ul><li>对象分配: 返回一个新对象的引用</li><li>参数传递/返回值: 对象引用从实参传到形参, 从返回值传给调用者</li><li>引用赋值: u=v, v被赋值到u, u中原有的引用丢失, 使得其原来指向的对象不可达</li><li>过程返回: 活动记录出栈, 局部变量消失, 根集变小</li></ul></li><li>垃圾回收方法<ul><li>关注不可达: 捕获对象变成不可达的时刻, 回收占用空间</li><li>关注可达: 在需要时标出所有可达对象, 回收其他对象</li></ul></li><li>基于引用计数的垃圾回收器<ul><li>每个对象有引用计数字段<ul><li>对象分配: 设为1</li><li>参数传递: 加1</li><li>引用赋值: u=v, u指向的-1, v指向的+1</li><li>过程返回: 局部变量指向对象的引用-1</li></ul></li><li>一个对象的计数为0, 删除其之前, 其成员指针指向的对象引用计数-1</li><li>开销较大, 但不会引起停顿</li></ul></li><li>循环垃圾的例子<ul><li>对象相互引用, 没有来自外部的指针, 又不是根集成员, 都是垃圾, 但是引用计数大于0</li></ul></li><li>基于跟踪的垃圾回收<ul><li>标记-清扫式垃圾回收<ul><li>直接的, 全面停顿的算法, 图遍历</li><li>分成2阶段<ul><li>标记: 根集开始, 跟踪并标记出所有可达对象</li><li>清扫: 遍历整个堆区, 释放不可达对象</li></ul></li><li>基本抽象分类: 每个存储块处于4种状态之一, 空闲, 未被访问, 待扫描, 已扫描</li></ul></li><li>标记并压缩垃圾回收<ul><li>重定位可达对象, 消除内存碎片<ul><li>把可达对象移动到堆区的一端, 另一端则是空闲空间</li><li>空闲空间合并成单一块</li></ul></li><li>整个过程分成3个步骤<ul><li>标记</li><li>计算新位置</li><li>移动并设置新的引用</li></ul></li></ul></li><li>拷贝垃圾回收<ul><li>堆空间分为2个半空间<ul><li>充满某个半空间时, 开始打击回收</li><li>回收时, 可达对象拷贝到另一个半空间</li><li>回收完成后, 两个空间角色对调</li></ul></li></ul></li></ul></li></ul></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;运行时刻环境&quot;&gt;&lt;a href=&quot;#运行时刻环境&quot; class=&quot;headerlink&quot; title=&quot;运行时刻环境&quot;&gt;&lt;/a&gt;运行时刻环境&lt;/h1&gt;&lt;ul&gt;
&lt;li&gt;存储管理: 栈分配, 堆管理, 垃圾回收&lt;/li&gt;
&lt;li&gt;对变量, 数据的访问&lt;/li&gt;
&lt;/
      
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Principles and Techniques of Compilers" scheme="https://Maxwell-lyu.github.io/tags/Principles-and-Techniques-of-Compilers/"/>
    
  </entry>
  
  <entry>
    <title>编译原理 6</title>
    <link href="https://Maxwell-lyu.github.io/2020/04/02/Learn-PTC-20200402-PTC-06/"/>
    <id>https://Maxwell-lyu.github.io/2020/04/02/Learn-PTC-20200402-PTC-06/</id>
    <published>2020-04-02T04:25:15.000Z</published>
    <updated>2020-04-16T08:29:48.058Z</updated>
    
    <content type="html"><![CDATA[<h1 id="第六章-中间代码生成"><a href="#第六章-中间代码生成" class="headerlink" title="第六章: 中间代码生成"></a>第六章: 中间代码生成</h1><ul><li>中间代码表示<ul><li>有向无环图DAG</li><li>三地址代码: x = y op z</li></ul></li><li>类型检查: 类型, 类型检查, 表达式的翻译</li><li>中间代码生成: 控制流, 回填</li><li>编译器前端<ul><li>与后端在中间代码分开</li><li>前端是机器无关的</li><li>词法语法-&gt;语义检查-&gt;中间代码生成</li></ul></li><li>中间代码表示及其好处<ul><li>形式: 抽象语法树, 三地址代码</li><li>重定位: 新的机器, 只需新的后端(中间代码到目标代码翻译器)</li><li>高层次的优化: 中间代码的优化与源代码和目标代码无关</li></ul></li><li>中间代码的实现<ul><li>静态类型检查和中间代码生成, 都可以用语法制导翻译实现</li></ul></li></ul><h2 id="表达式的有向无环图"><a href="#表达式的有向无环图" class="headerlink" title="表达式的有向无环图"></a>表达式的有向无环图</h2><ul><li>公共子表达式每出现一次, 就有一棵对应的子树</li><li>表达式的有向无环图, 能够指出表达式中的公共子表达式, 更简洁</li><li>寻找重复<ul><li>值编码: op, l, r, 其中l, r为子节点编号</li><li>根据值编码去重, 新结点与某个已有结点, 值编码相同, 则重用</li></ul></li></ul><h2 id="三地址代码"><a href="#三地址代码" class="headerlink" title="三地址代码"></a>三地址代码</h2><ul><li>每条指令右侧最多有1个运算符</li><li>允许的运算分量<ul><li>名字: 源程序的中的名字</li><li>常量: 源程序中出现或生成的常量</li><li>临时变量: 分析过程中生成的名字</li></ul></li><li>指令集合<ul><li>运算赋值: x = y op z; x = op y</li><li>复制指令: x = y</li><li>无条件转移指令: goto L</li><li>条件转移指令: if x goto L; if False x goto L</li><li>条件转移指令: if x relop y goto L</li><li>过程调用: param $x_1$, …, param $x_n$ call p,n</li><li>下标复制指令: x = y[i]; x[i] = y</li><li>地址, 指针赋值指令: x = \&y; x = <em>y, </em>x = y</li></ul></li><li>表示方式<ul><li>四元式: 3个地址, 一个运算符: op arg1 arg2 result<ul><li>单目运算符不使用arg2</li><li>param运算不使用arg2和result</li><li>条件转移/非条件转移, 目标标号在result</li><li>一些情况<ul><li>引用: x = y[i]; =[] y i x</li><li>引用: x[i] = y; []= i y x</li></ul></li></ul></li><li>三元式: 没有result的四元式, 使用某行的结果, 直接用左侧标号(0起始)<ul><li>一些情况<ul><li>引用: x[i] = y; 先计算x[i]的地址, 之后才能赋值, 需要2行</li></ul></li></ul></li></ul></li></ul><h2 id="类型和声明"><a href="#类型和声明" class="headerlink" title="类型和声明"></a>类型和声明</h2><ul><li>类型检查: 利用一组规则, 检查运算分量的类型和运算符的预期类型是否匹配</li><li>类型信息的用途: 差错, 确定内存空间, 计算地址, 类型转换, 选择正确的运算符<h3 id="类型表达式"><a href="#类型表达式" class="headerlink" title="类型表达式"></a>类型表达式</h3></li><li>表示类型的结构<ul><li>基本类型<ul><li>boolean, char, integer, float, void</li></ul></li><li>类型构造算子, 作用于类型表达式<ul><li>array(数字, 类型表达式)</li><li>record(字段名 × 类型表达式)</li><li>-&gt; 函数类型的类型表达式</li></ul></li></ul></li><li>类型等价<ul><li>相同的基本类型</li><li>由相同的构造算子, 作用于结构等价的类型而得到</li><li>一个类型是另一个类型表达式的名字</li></ul></li><li>名等价: 类型名仅代表自身(仅有前两个条件)</li><li>类型的声明<ul><li>应用文法和对应的语法制导定义, 可得类型表达式和内存布局<h3 id="局部变量存储布局"><a href="#局部变量存储布局" class="headerlink" title="局部变量存储布局"></a>局部变量存储布局</h3></li><li>类型确定需要的内存大小, 可变大小的只需考虑指针</li><li>局部变量总是分配在连续区间, 给出相对地址</li><li>变量类型信息存在符号表中</li></ul></li><li>声明序列的SDT<ul><li>局部变量放入单独的符号表</li><li>变量内存布局是独立的<ul><li>相对地址从0开始, 变量放置顺序与声明相同</li></ul></li><li>SDT处理方法<ul><li>offset记录当前可用的相对地址</li><li>每分配一个, offset增加其宽度</li></ul></li><li>top.put(id.lexeme, T.type, offset)<ul><li>放入符号表, 记录标识符的类型和偏移量 </li></ul></li><li>offset看作继承属性</li></ul></li><li>记录和类中的字段<ul><li>约定<ul><li>记录字段名各不相同</li><li>相对地址是相对于该记录的数据区字段而言的</li></ul></li><li>记录类型使用专门的符号表</li><li>对其各个字段的类型和相对地址进行单独编码</li><li>记录类型record(t), t为符号表对象, 保存该记录类型各个字段的信息 <h3 id="表达式代码的SDD"><a href="#表达式代码的SDD" class="headerlink" title="表达式代码的SDD"></a>表达式代码的SDD</h3></li><li>表达式翻译成三地址代码的SDD<ul><li>code表示代码</li><li>addr表示存放结果的地址</li><li>new Temp()表示生成临时变量</li><li>gen()生成指令<h3 id="数组元素的寻址"><a href="#数组元素的寻址" class="headerlink" title="数组元素的寻址"></a>数组元素的寻址</h3></li></ul></li><li>数组连续存放, 0开始编号, 第i个元素的地址为 <code>base + i * w</code></li><li>k维数组的寻址: <code>A[i1][i2]...[ik]</code>, 则<code>base+i1*w1+...+ik*wk</code>, <code>wi</code>是一个当前层级元素的宽度, 相当于其后的维度取值范围, 连乘的积</li></ul></li><li>数组的翻译方案<ul><li>非终结符L: $L\to L[E]|\mathbf{id}[E]$ 三个综合属性<ul><li>L.array: 指向数组名字对应的符号表条目的指针, L.array.base是数组基地址</li><li>L.addr: 指示一个临时变量, 计算数组引用的偏移量</li><li>L.type: 是L生成的子数组的类型<ul><li>L.type.width给出其宽度</li><li>L.type.elem给出其数组元素</li></ul></li></ul></li><li>L的代码计算偏移量, 据此进一步计算加上base, 使用三地址指令<code>x=a[i]</code><h3 id="类型的检查和转换"><a href="#类型的检查和转换" class="headerlink" title="类型的检查和转换"></a>类型的检查和转换</h3></li><li>类型系统<ul><li>每个组成部分赋予类型表达式</li><li>一组规则来表达类型表达式必须满足的条件</li><li>可以: 发现错误, 提高代码效率, 确定临时变量的大小</li></ul></li><li>类型检查可以分为动态和静态两种</li><li>强类型: 编译器中的类型系统能够保证其接受的程序在运行时刻不会发生类型错误</li></ul></li><li>类型系统分类<ul><li>类型综合: 子表达式的类型-&gt;表达式的类型</li><li>类型推导: 语言结构的使用方式, 确定该结构的类型(函数重载)</li></ul></li><li>类型转换<ul><li>隐式转换: 编译器自动</li><li>显式转换: 程序员用代码指定的转换</li><li>拓宽类型转换/窄化类型转换 <ul><li>函数max: 寻找两个类型在拓宽层次结构中的LCA最小公共祖先</li><li>函数widen: 生成必要的类型转换代码<h3 id="控制流的翻译"><a href="#控制流的翻译" class="headerlink" title="控制流的翻译"></a>控制流的翻译</h3></li></ul></li><li>通过跳转指令实现控制流, 逻辑运算符本身不出现</li><li>短路: 逻辑或, 靠前的为真就不计算后面的; 逻辑与, 靠前的为假就不计算后面的</li></ul></li><li>自顶向下翻译控制流语句<ul><li>继承属性<ul><li>B.true B为真时跳转目标</li><li>B.false B为假时跳转目标</li><li>S.next S 执行完毕的跳转目标</li></ul></li><li>增量生成: gen(content)<h3 id="布尔表达式"><a href="#布尔表达式" class="headerlink" title="布尔表达式"></a>布尔表达式</h3></li></ul></li><li>没有与或非, 而是通过跳转目标设定实现<ul><li>或: Bi.true = B.true, Bi.false = (下一语句的开头)</li><li>与: Bi.false = B.false, Bi.true = (下一语句的开头)</li><li>非: 交换false 和 true</li></ul></li><li>子语句<ul><li>B -&gt; E1 rel E2: E1.code || E2.code || if ….. goto B.true || goto B.false</li><li>B -&gt; true: goto B.true</li><li>B -&gt; false: goto B.false</li></ul></li><li>布尔值和跳转代码<ul><li>布尔表达式也有可能是求值: 构建语法树, 根据表达式的不同角色来处理<ul><li>对于来自if和while, 生成跳转的代码</li><li>对于赋值语句, 生成计算右值的代码</li></ul></li></ul></li></ul><h3 id="回填"><a href="#回填" class="headerlink" title="回填"></a>回填</h3><ul><li>布尔表达式和控制流语句生成: 某些跳转指令应该跳转到哪里</li><li>生成跳转需要S.next, 但S没有生成, 需要第二趟处理; 一趟处理完毕: 使用综合属性</li><li>基本思想<ul><li>跳转语句的目标不确定时, 记录该跳转指令的标号, 但不生成跳转目标, 标号被记录到B的综合属性B.falselist/B.truelist中</li><li>当值已知时, 把falselist中的所有指令的目标都填上这个值</li></ul></li><li>回填翻译<ul><li>综合属性: 包含跳转指令的标号<ul><li>truelist: 取值true时执行的指令标号列表</li><li>falselist: 取值false时执行的指令标号列表</li></ul></li><li>辅助函数<ul><li>makelist(i): 创建一个包含指令标号i的列表</li><li>merge(p1, p2): p1p2指向的标号列表合并并返回</li><li>backpatch(p, i): 将i作为跳转目标, 插入p的所有指令中</li></ul></li><li>产生式的改动: 添加$M\to\epsilon$, M.instr = nextinstr, 添加于待跳转目标的开头,添加跳转目标, 用于backpatch</li></ul></li><li>控制流转移语句N<ul><li>综合属性<ul><li>nextlist: 包含该语句执行完毕后, 紧接着执行的下一条指令的标号</li></ul></li><li>产生式的改动: 添加$N\to\epsilon$在某S后<ul><li>将会产生goto语句, 表示S执行后跳转到哪里</li><li>N.nextlist = makelist(nextinstr), 直到交给顶层, 进行backpatch  </li></ul></li></ul></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;第六章-中间代码生成&quot;&gt;&lt;a href=&quot;#第六章-中间代码生成&quot; class=&quot;headerlink&quot; title=&quot;第六章: 中间代码生成&quot;&gt;&lt;/a&gt;第六章: 中间代码生成&lt;/h1&gt;&lt;ul&gt;
&lt;li&gt;中间代码表示&lt;ul&gt;
&lt;li&gt;有向无环图DAG&lt;/li&gt;
&lt;
      
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Principles and Techniques of Compilers" scheme="https://Maxwell-lyu.github.io/tags/Principles-and-Techniques-of-Compilers/"/>
    
  </entry>
  
  <entry>
    <title>Advanced Programming</title>
    <link href="https://Maxwell-lyu.github.io/2020/03/26/Learn-AP-AP-ALL/"/>
    <id>https://Maxwell-lyu.github.io/2020/03/26/Learn-AP-AP-ALL/</id>
    <published>2020-03-26T06:18:33.000Z</published>
    <updated>2020-05-09T07:25:06.988Z</updated>
    
    <content type="html"><![CDATA[<p>高级程序设计 课程的重点知识<br><a id="more"></a>  </p><h1 id="15-继承的基本概念和单继承"><a href="#15-继承的基本概念和单继承" class="headerlink" title="15.继承的基本概念和单继承"></a>15.继承的基本概念和单继承</h1><h2 id="继承的基本概念"><a href="#继承的基本概念" class="headerlink" title="继承的基本概念"></a>继承的基本概念</h2><ul><li><strong>继承机制</strong>: 对一个<strong>面向对象的程序</strong>，在定义一个<strong>新的类</strong>时，先把已有程序中的一个或多个类的<strong>功能全部包含</strong>进来，然后在新的类中<strong>再给出新功能</strong>的定义或对已有类的某些功能<strong>重新定义</strong><blockquote><p>新类 &lt;== 已有类的功能 + 新功能/已有功能重定义</p></blockquote></li></ul><h2 id="单继承"><a href="#单继承" class="headerlink" title="单继承"></a>单继承</h2><h2 id="继承中的访问控制"><a href="#继承中的访问控制" class="headerlink" title="继承中的访问控制"></a>继承中的访问控制</h2><h3 id="在派生类中访问基类成员"><a href="#在派生类中访问基类成员" class="headerlink" title="在派生类中访问基类成员"></a>在派生类中访问基类成员</h3><ul><li>C++中, 派生类不能直接访问基类的私有成员</li><li>继承与封装的矛盾: 派生类可能访问private, 但不允许c’c</li><li>实际上，有了继承机制以后，一个类的成员有两种被外界使用的场合：<ul><li>通过类的对象（实例）使用</li><li>在派生类中使用<h3 id="protected访问控制"><a href="#protected访问控制" class="headerlink" title="protected访问控制"></a>protected访问控制</h3></li></ul></li><li>用protected说明的成员不能通过对象使用，但可以在派生类中使用。</li><li>C++类向外界提供两种接口：<ul><li>public：对象的使用者（类的实例用户）</li><li>public+protected：派生类<h3 id="派生类成员标识符的作用域"><a href="#派生类成员标识符的作用域" class="headerlink" title="派生类成员标识符的作用域"></a>派生类成员标识符的作用域</h3></li></ul></li><li>派生类对基类成员的访问除了受到基类的访问控制的限制以外，还要受到标识符作用域的限制。<ul><li>在类中定义的标识符局部于类定义</li><li>在类中任何地方都可以访问</li><li>在类外使用类中定义的标识符时，需要通过对象名受限或者类名受限</li><li>在类中使用与成员标识符同名的全局标识符时，需要在全局标识符前面加上全局域解析符“::”</li></ul></li><li><strong>作用域嵌套</strong>: 对基类而言，派生类成员标识符的作用域是嵌套在基类作用域中的<ul><li>派生类可使用基类的标识符</li><li>基类不能用基类的标识符</li></ul></li><li><strong>同名成员</strong>: 如果派生类中定义了与基类同名的成员，则基类的成员名在派生类的作用域内不直接可见（被隐藏，Hidden）。<ul><li>访问基类同名成员时要用基类名受限</li><li>即使派生类中定义了与基类同名但参数不同的成员函数，基类的同名函数在派生类的作用域中也是不直接可见的，可以用基类名受限方式来使用之</li><li>也可以在派生类中使用using声明把基类中某个的函数名对派生类开放<h3 id="继承方式"><a href="#继承方式" class="headerlink" title="继承方式"></a>继承方式</h3>|继承方式\基类成员|public|protected|private|<br>|-|-|-|-|<br>|public|public|protected|不能访问|<br>|protected|protected|protected|不能访问|<br>|private|private|private|不能访问|</li></ul></li></ul><blockquote><p>原private都不可访问, 其余收紧(选继承方式和基类成员中, 修饰符严格的那个)</p></blockquote><h1 id="16-派生类的初始化和消亡处理"><a href="#16-派生类的初始化和消亡处理" class="headerlink" title="16.派生类的初始化和消亡处理"></a>16.派生类的初始化和消亡处理</h1><h2 id="派生类对象的初始化"><a href="#派生类对象的初始化" class="headerlink" title="派生类对象的初始化"></a>派生类对象的初始化</h2><ul><li><strong>共同完成</strong><ul><li>基类继承的成员由基类的构造函数初始化</li><li>派生类的数据成员由派生类的构造函数初始化<ul><li>派生类构造函数体前, 将调用基类构造函数</li></ul></li></ul></li><li><p>当<strong>创建派生类的对象</strong>时</p><ul><li>默认情况下，调用基类的默认构造函数</li><li>如果要调用基类的非默认构造函数，则必须在派生类构造函数的成员初始化表中指出<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span><span class="keyword">int</span> x;</span><br><span class="line">  <span class="keyword">public</span>:</span><br><span class="line">    A() &#123; x = <span class="number">0</span>; &#125;</span><br><span class="line">    A(<span class="keyword">int</span> i) &#123; x = i; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">B</span>:</span> <span class="keyword">public</span> A</span><br><span class="line">&#123;<span class="keyword">int</span> y;</span><br><span class="line">  <span class="keyword">public</span>:</span><br><span class="line">    B() &#123; y = <span class="number">0</span>; &#125;</span><br><span class="line">    B(<span class="keyword">int</span> i) &#123; y = i; &#125;</span><br><span class="line">    B(<span class="keyword">int</span> i, <span class="keyword">int</span> j):A(i) &#123; y = j; &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></li></ul></li><li><p>当<strong>析构派生类的对象</strong>时</p><ul><li>先执行派生类的析构, 再执行基类的析构</li></ul></li><li>类D同时有基类B和成员类M时:<ul><li>构造: D -&gt; M -&gt; A</li><li>析构: A -&gt; M -&gt; D<h2 id="派生类拷贝构造函数"><a href="#派生类拷贝构造函数" class="headerlink" title="派生类拷贝构造函数"></a>派生类拷贝构造函数</h2></li></ul></li><li>派生类的隐式拷贝构造函数: 调用基类的<strong>拷贝构造函数</strong></li><li>派生类的自定义拷贝构造函数, 自动调用基类的<strong>默认构造函数</strong>, 可在初始化表中指定调用哪个构造函数<h2 id="派生类对象的赋值操作"><a href="#派生类对象的赋值操作" class="headerlink" title="派生类对象的赋值操作"></a>派生类对象的赋值操作</h2></li><li>派生类隐式的赋值操作除了对派生类成员进行赋值外，还将调用基类的赋值操作对基类成员进行赋值</li><li>派生类自定义的赋值操作符重载函数<strong>不会</strong>自动调用基类的赋值操作，需要在自定义的赋值操作符重载函数中<strong>显式地指出</strong><h2 id="转移构造函数"><a href="#转移构造函数" class="headerlink" title="转移构造函数"></a>转移构造函数</h2></li><li>在创建一个对象用另一个同类型的对象对其初始化时，将会调用拷贝构造函数</li><li>当用一个临时或即将消亡的对象去初始化另一个同类的对象时，目前的拷贝构造函数的实现效率有时是不高的</li><li><strong>转移构造函数</strong>: <code>A(A&amp;&amp; x)</code> 右值引用类型: 不能作为赋值操作符的左操作符</li><li>当用一个临时对象或即将消亡的对象去初始化另一个对象时<ul><li>如果对象类中有<strong>转移构造函数</strong>，则会去调用转移构造函数来对对象初始化。</li><li>否则去调用<strong>拷贝构造函数</strong>进行对象初始化。（注意：系统<strong>不会提供隐式转移</strong>构造函数！）<h2 id="赋值操作符的重载"><a href="#赋值操作符的重载" class="headerlink" title="赋值操作符的重载"></a>赋值操作符的重载</h2></li></ul></li><li>用于赋值的对象是一个临时或即将消亡的对象时，目前的赋值操作符重载函数的实现效率有时是不高的</li><li><strong>转移赋值操作符</strong>: <code>A&amp; operator=(A&amp;&amp; x)</code></li><li>类似转移构造函数, 并且也需要检测自身赋值</li></ul><h1 id="17-消息的多态与动态绑定（虚函数）"><a href="#17-消息的多态与动态绑定（虚函数）" class="headerlink" title="17.消息的多态与动态绑定（虚函数）"></a>17.消息的多态与动态绑定（虚函数）</h1><h2 id="多态"><a href="#多态" class="headerlink" title="多态"></a>多态</h2><ul><li>某个论域中的一个元素存在多种解释<ul><li>体现<ul><li>函数名重载</li><li>操作符重载</li></ul></li><li>类属性(泛型)</li></ul></li><li>子类型<ul><li>用类型S替换所有程序P中的类型T, 程序P功能不变, 则S是T的子类型</li><li>C++中, 以public方式继承的派生类, 可以看作是基类的子类型</li></ul></li><li>面向对象程序设计的多态性<ul><li>对于public继承关系的2个类, c++中存在下面的多态<ul><li>一个对象, 多种类型: 派生类的对象的类型, 既可以是派生类, 也可以是基类</li><li>一个对象标识, 多种对象: 基类对象的指针, 可以指向派生类对象</li><li>消息多态: 可以发送到基类的消息, 也可以发送到派生类<h2 id="消息的动态绑定"><a href="#消息的动态绑定" class="headerlink" title="消息的动态绑定"></a>消息的动态绑定</h2></li></ul></li><li>虚函数: virtual关键字</li><li>根据运行时, 实际指向的对象来决定调用哪一个消息</li></ul></li><li>派生类中重定义基类的成员函数<ul><li>对于基类中的虚函数, 在派生类中定义的, 与之具有相同型构的函数成员, 是对基类该成员的重定义</li><li>型构: 名字, 参数个数和类型, 返回值类型要么相同, 要么是派生类</li></ul></li><li>动态绑定的条件<ul><li>基类的指针或引用</li><li>访问的是虚函数</li><li>基类构造函数和析构函数中, 对虚函数的调用, 不进行动态绑定</li></ul></li><li>几点说明<ul><li>只有类的成员函数才能是虚函数, 静态成员函数不能是虚函数</li><li>构造函数可以是虚函数, 析构函数可以并且往往是虚函数</li><li>只要在基类中说明了虚函数, 派生类的派生类…当中的同型构函数, 也是虚函数, 可不写virtual</li></ul></li><li>运行时刻类型信息: RTTI<ul><li>使用<code>dynamic_cast&lt;B *&gt;</code>, 进行类型转换, 之后检查转换是否成功<h2 id="虚函数与动态绑定的实现-不考"><a href="#虚函数与动态绑定的实现-不考" class="headerlink" title="虚函数与动态绑定的实现(不考)"></a>虚函数与动态绑定的实现(不考)</h2></li></ul></li><li>基类对象和派生类对象成员的空间分配<ul><li>内存布局: 基类成员低地址, 派生类新成员高地址</li><li>内存布局决定, 基类指针可以指向派生类对象</li></ul></li><li>多态的实现<ul><li>虚函数表: A, B两类, 分别生成虚函数表</li><li>虚函数表指针: 类的对象的指针位置(空间头部), 有指向虚函数表的指针, 据此进行动态绑定</li><li>虚函数表项类型: <code>typedef void (*FuncPtr)(void *)</code></li><li>虚函数表类型: <code>typedef FuncPtr *VtblPtr</code></li></ul></li><li>纯虚函数: 没有给出实现的虚函数<ul><li>函数体: <code>vitrual int f()=0;</code></li><li>派生类中, 所有同型构的函数, 都是虚函数</li></ul></li><li>抽象类: 包含纯虚函数的类<ul><li>抽象类的作用, 是为派生类提供一个基本框架和公共的对外接口</li></ul></li></ul><h1 id="18-抽象类（纯虚函数）"><a href="#18-抽象类（纯虚函数）" class="headerlink" title="18.抽象类（纯虚函数）"></a>18.抽象类（纯虚函数）</h1><h2 id="纯虚函数"><a href="#纯虚函数" class="headerlink" title="纯虚函数"></a>纯虚函数</h2><ul><li>纯虚函数是没给出实现的虚函数，函数体用“=0”表示<h2 id="抽象类"><a href="#抽象类" class="headerlink" title="抽象类"></a>抽象类</h2></li><li>包含纯虚函数的类称为抽象类</li><li>抽象类不能创建对象</li></ul><h1 id="19-多继承"><a href="#19-多继承" class="headerlink" title="19.多继承"></a>19.多继承</h1><ul><li>多继承是指派生类可以有一个以上的直接基类<ul><li>继承方式及访问控制的规定同单继承</li><li>派生类拥有所有基类的所有成员</li><li>基类的声明次序决定<ul><li>对基类构造函数/析构函数的调用次序</li><li>对基类数据成员的存储安排</li></ul></li></ul></li><li>可以把以public继承方式定义的多继承派生类的对象的地址赋给任何一个基类的指针<ul><li>这时将会自动进行地址调整: 不同基类指针指向的时候, 指针的值不一样, 指向对应基类数据成员的基地址</li></ul></li><li>名冲突<ul><li>使用基类名受限: <code>C c; c.A::f(); c.B::f();</code></li></ul></li><li>重复继承问题(虚基类)<ul><li>例如: B-&gt;A, C-&gt;A, D-&gt;(B,C), D从A继承了2次</li><li>如果要求D中仅有一个A, 则可以在B, C中, 将A继承为虚基类: <code>class B: virtual public A {};</code></li></ul></li><li>虚基类<ul><li>间接包含虚基类的类<ul><li>虚基类的构造函数, 由该类的构造函数直接调用(上例为D); 即由最新构造的类调用</li></ul></li></ul></li><li>虚基类的实现<ul><li>一般基类: 内存空间直接连接</li><li>虚基类: 虚基类成员移到直接基类最后,原位头留指针指向最后; 简洁派生类同理, 多个指针指向同一个地方<h1 id="20-继承和代码复用"><a href="#20-继承和代码复用" class="headerlink" title="20.继承和代码复用"></a>20.继承和代码复用</h1></li></ul></li><li>C++中, 把类看作类型，把以public方式继承的派生类看作是基类的子类型</li><li>具有继承关系的两个类之间通常属于一般与特殊的关系（is-a-kind-of）</li><li>聚集<ul><li>代码复用的另一种方式是通过聚集（aggregation，也称聚合）来实现，即把一个类作为另一个类（新类）的成员对象类</li><li>在基于对象的程序设计中，一般采用聚集来实现代码复用的</li></ul></li><li>继承与封装存在矛盾，聚集则否。<ul><li>在继承方式的代码复用中，一个类通过protected访问控制，向外界提供两种接口：<ul><li>public：对象（实例）用户</li><li>public+protected：派生类用户</li></ul></li><li>在聚集方式的代码复用中，一个类对外只需一个接口：public。</li></ul></li><li>具有聚集关系的两个类不具有子类型关系<h1 id="21-泛型-类属-程序设计-模板"><a href="#21-泛型-类属-程序设计-模板" class="headerlink" title="21.泛型(类属)程序设计 模板"></a>21.泛型(类属)程序设计 模板</h1><h2 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h2></li><li>泛型: <strong>一个程序实体</strong>能对<strong>多种类型的数据</strong>进行<strong>操作或描述</strong>的特性称为类属或泛型（Generics）。</li><li>具有类属特性的程序实体通常有：<ul><li>类属函数：一个能对<strong>不同类型的数据</strong>完成<strong>相同操作</strong>的函数。</li><li>类属类：一个<strong>成员类型可变</strong>、但<strong>功能不变</strong>的类。</li></ul></li><li>基于具有类属性的程序实体进行程序设计的技术称为：<strong>c泛型程序设计</strong>（或类属程序设计，Generic Programming）。<h2 id="类属函数"><a href="#类属函数" class="headerlink" title="类属函数"></a>类属函数</h2></li><li>一个函数能对不同类型的参数完成相同的操作</li><li><p>实现机制</p><ul><li><p>通用指针的参数(C做法): 用通用指针实现类属函数面临的问题</p><ul><li><p>排序函数为例</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">sort</span><span class="params">(<span class="keyword">void</span> *base, <span class="comment">//需排序的数据（数组）内存首地址</span></span></span></span><br><span class="line"><span class="function"><span class="params">  <span class="keyword">unsigned</span> <span class="keyword">int</span> count, <span class="comment">//数据元素的个数</span></span></span></span><br><span class="line"><span class="function"><span class="params">  <span class="keyword">unsigned</span> <span class="keyword">int</span> element_size, <span class="comment">//一个数据元素所占内存大小（字节数）</span></span></span></span><br><span class="line"><span class="function"><span class="params">  <span class="keyword">int</span> (*cmp)(<span class="keyword">const</span> <span class="keyword">void</span> *, <span class="keyword">const</span> <span class="keyword">void</span> *) )</span> <span class="comment">//比较两个元素的函数</span></span></span><br></pre></td></tr></table></figure></li><li><p>比较麻烦，需要大量的指针操作。</p></li><li>容易出错！编译程序无法进行类型检查。</li></ul></li><li>函数模板<h3 id="函数模板"><a href="#函数模板" class="headerlink" title="函数模板"></a>函数模板</h3></li></ul></li><li>函数模板是指带有类型参数的函数定义</li><li><p>一般格式</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span> &lt;<span class="class"><span class="keyword">class</span> <span class="title">T</span>&gt; </span></span><br><span class="line"><span class="class"><span class="title">void</span> <span class="title">sort</span>(<span class="title">T</span> <span class="title">elements</span>[], <span class="title">unsigned</span> <span class="title">int</span> <span class="title">count</span>)</span></span><br></pre></td></tr></table></figure><ul><li>T1、T2等是函数模板的参数, 函数的&lt;返回值类型&gt; 、&lt;参数表&gt;中的参数类型以及函数体中的局部变量的类型可以是：T1、T2等</li></ul></li><li><p>实例化</p><ul><li>实际上，函数模板定义了一系列重载的函数。<ul><li>要使用函数模板所定义的函数，首先必须要对函数模板进行实例化：<ul><li>给模板参数提供一个具体的类型，从而生成具体的函数。</li></ul></li><li>函数模板的实例化通常是<strong>隐式的</strong>：<ul><li>由<strong>编译程序</strong>根据函数调用的实参类型自动地把函数模板实例化为具体的函数。</li></ul></li><li>这种确定函数模板实例的过程叫做模板实参推导（template argument deduction）。</li></ul></li><li><p>显式地实例化</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span> &lt;<span class="class"><span class="keyword">class</span> <span class="title">T</span>&gt; </span></span><br><span class="line"><span class="class"><span class="title">T</span> <span class="title">max</span>(<span class="title">T</span> <span class="title">a</span>, <span class="title">T</span> <span class="title">b</span>) &#123;</span> <span class="keyword">return</span> a &gt; b ? a : b; &#125;</span><br><span class="line"></span><br><span class="line">max&lt;<span class="keyword">double</span>&gt;(x,m);</span><br></pre></td></tr></table></figure><ul><li>也可以进行显式类型转换以交由编译程序推导</li></ul></li></ul></li><li><p>带非类型参数的函数模板</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span> &lt;<span class="class"><span class="keyword">class</span> <span class="title">T</span>, <span class="title">int</span> <span class="title">size</span>&gt; //<span class="title">size</span>为一个<span class="title">int</span>型的普通参数</span></span><br><span class="line"><span class="class"><span class="title">void</span> <span class="title">f</span>(<span class="title">T</span> <span class="title">a</span>)</span></span><br><span class="line"><span class="class">&#123;</span>T temp[size];</span><br><span class="line">  ......  </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">f&lt;<span class="keyword">int</span>,<span class="number">10</span>&gt;(<span class="number">1</span>);</span><br></pre></td></tr></table></figure><ul><li>这样的函数模板在使用时需要显式实例化</li></ul></li></ul><h3 id="类模板"><a href="#类模板" class="headerlink" title="类模板"></a>类模板</h3><ul><li>如果一个类的成员类型可变、但功能不变，则该类称为类属类</li><li><p>类模板的格式为：</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span> &lt;<span class="class"><span class="keyword">class</span> <span class="title">T1</span>,<span class="title">class</span> <span class="title">T2</span>,...&gt; </span></span><br><span class="line"><span class="class"><span class="title">class</span> &lt;类名&gt;</span></span><br><span class="line"><span class="class">&#123;</span>&lt;类成员说明&gt;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>其中，T1、T2等为类模板的类型参数，在类成员的说明中可以用T1、T2等来作为它们的类型。 </li></ul></li><li><p>实例化</p><ul><li><p>类模板的实例化需要在程序中显式地指出</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">Stack&lt;<span class="keyword">int</span>&gt; st1; <span class="comment">//实例化int型栈类并创建一个相应类的对象</span></span><br><span class="line"><span class="keyword">int</span> x;</span><br><span class="line">st1.push(<span class="number">10</span>); st1.pop(x);</span><br><span class="line"></span><br><span class="line">Stack&lt;<span class="keyword">double</span>&gt; st2; <span class="comment">//实例化double型栈类并创建一个相应类的对象</span></span><br><span class="line"><span class="keyword">double</span> y;</span><br><span class="line">st2.push(<span class="number">1.2</span>); st2.pop(y); </span><br><span class="line"></span><br><span class="line">Stack&lt;A&gt; st3; <span class="comment">//实例化A类型栈类并创建一个相应类的对象</span></span><br><span class="line">A a,b;</span><br><span class="line">st3.push(a); st3.pop(b); <span class="comment">//A中可能要重载赋值操作符！为什么？</span></span><br></pre></td></tr></table></figure></li><li><p>不同类模板实例之间不共享类模板中的静态成员</p></li></ul></li><li>带非类型参数的类模板: 与函数类似<h3 id="模板的复用"><a href="#模板的复用" class="headerlink" title="模板的复用"></a>模板的复用</h3></li><li>用模板实现的类属也属于一种多态，称为参数化多态</li><li>模板属于源代码复用</li><li>模板的定义和实现都放在头文件中, 把模板的源代码全包含进来，以备实例化所需</li><li>重复实例的处理<ul><li>由开发环境来解决：编译第二个模块的时候不生成这个实例。（代价大！）</li><li>由连接程序来解决：舍弃一个相同的实例。</li></ul></li><li>类模板的友元函数<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span> &lt;<span class="class"><span class="keyword">class</span> <span class="title">T</span>&gt; <span class="title">class</span> <span class="title">A</span>;</span></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="class"><span class="keyword">class</span> <span class="title">T</span>&gt; <span class="title">void</span> <span class="title">f3</span>(<span class="title">A</span>&lt;T&gt;&amp; <span class="title">a</span>) &#123;</span> ...... &#125;</span><br><span class="line"><span class="keyword">template</span> &lt;<span class="class"><span class="keyword">class</span> <span class="title">T</span>&gt;</span></span><br><span class="line"><span class="class"><span class="title">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class">&#123;</span> T x,y;</span><br><span class="line">  ......</span><br><span class="line">  <span class="function"><span class="keyword">friend</span> <span class="keyword">void</span> <span class="title">f1</span><span class="params">(A&lt;T&gt;&amp; a)</span></span>; <span class="comment">//f1不是模板！</span></span><br><span class="line">  <span class="keyword">template</span> &lt;<span class="class"><span class="keyword">class</span> <span class="title">T</span>&gt; <span class="title">friend</span> <span class="title">void</span> <span class="title">f2</span>(<span class="title">A</span>&lt;T&gt;&amp; <span class="title">a</span>);</span> <span class="comment">//f2的实例与A的实例多对多友元</span></span><br><span class="line">  <span class="keyword">friend</span> <span class="keyword">void</span> f3&lt;T&gt;(A&lt;T&gt;&amp; a); <span class="comment">//f3的实例与A的实例一对一友元</span></span><br><span class="line">&#125;;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">f1</span><span class="params">(A&lt;<span class="keyword">int</span>&gt;&amp; a)</span> </span>&#123; ...... &#125; <span class="comment">//是A&lt;int&gt;的友元，但不是A&lt;double&gt;的友元！</span></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="class"><span class="keyword">class</span> <span class="title">T</span>&gt; <span class="title">void</span> <span class="title">f2</span>(<span class="title">A</span>&lt;T&gt;&amp; <span class="title">a</span>) &#123;</span>......&#125;</span><br><span class="line">......</span><br><span class="line">A&lt;<span class="keyword">int</span>&gt; a1; <span class="comment">//实例化A&lt;int&gt;</span></span><br><span class="line">A&lt;<span class="keyword">double</span>&gt; a2; <span class="comment">//实例化A&lt;double&gt;</span></span><br><span class="line">f1(a1); <span class="comment">//OK，调用f1(A&lt;int&gt;&amp;)</span></span><br><span class="line">f1(a2); <span class="comment">//链接错误! 调用f1(A&lt;double&gt;&amp;)，但它不存在！</span></span><br><span class="line">f2(a1); <span class="comment">//实例化f2&lt;int&gt;，它是A&lt;int&gt;和A&lt;double&gt;的友元</span></span><br><span class="line">f2(a2); <span class="comment">//实例化f2&lt;double&gt;，它是A&lt;int&gt;和A&lt;double&gt;的友元</span></span><br><span class="line">f3(a1); <span class="comment">//实例化f3&lt;int&gt;，它是A&lt;int&gt;的友元，但不是A&lt;double&gt;的友元！</span></span><br><span class="line">f3(a2); <span class="comment">//实例化f3&lt;double&gt;，它是A&lt;double&gt;的友元，但不是A&lt;int&gt;的友元！</span></span><br></pre></td></tr></table></figure></li></ul><h1 id="22-基于STL的编程"><a href="#22-基于STL的编程" class="headerlink" title="22.基于STL的编程"></a>22.基于STL的编程</h1><h2 id="STL"><a href="#STL" class="headerlink" title="STL"></a>STL</h2><ul><li>C++提供了一个基于模板实现的标准模板库（Standard Template Library，简称STL）<ul><li>STL基于模板实现了一些面向序列数据的表示及常用的操作。</li><li>STL支持了一种抽象的编程模式: 隐藏了一些低级的程序元素，如数组、链表、循环等</li></ul></li><li>容器类模板<ul><li>容器用于存储序列化的数据，如：向量、队列、栈、集合等。</li></ul></li><li>算法函数模板<ul><li>算法用于对容器中的数据元素进行一些常用操作，如：排序、统计等。</li></ul></li><li>迭代器类模板<ul><li>迭代器实现了抽象的指针功能，它们指向容器中的数据元素，用于对容器中的数据元素进行遍历和访问。</li><li>迭代器是容器和算法之间的桥梁：传给算法的不是容器，而是指向容器中元素的迭代器，算法通过迭代器实现对容器中数据元素的访问。这样使得算法与容器保持独立，从而提高算法的通用性。<h2 id="容器"><a href="#容器" class="headerlink" title="容器"></a>容器</h2></li></ul></li><li>容器用于表示由<strong>同类型元素</strong>构成的、<strong>长度可变</strong>的元素序列。</li><li>容器是由<strong>类模板</strong>来实现的，模板的<strong>参数是容器中元素</strong>的类型。</li><li>主要容器<ul><li>vector&lt;类型&gt;: 随机访问, 尾部增减, 动态数组实现</li><li>list&lt;类型&gt;: 任意位置增减, 双向链表实现</li><li>deque&lt;类型&gt;: 随机访问, 头尾增减, 分段的连续空间实现</li><li>stack&lt;类型&gt;: 尾部增减, 可基于前三者实现</li><li>queue&lt;类型&gt;: 尾增头减, 基于deque或list</li><li>priority_queue&lt;类型&gt;: 与queue的操作类似, 带排序功能, 基于deque或vector</li><li>map/multimap&lt;关键字类型, 值类型&gt;<ul><li>每个元素是一个pair, first是关键字, second是值, 元素根据关键字排序</li><li>map: 关键字各不相同; multimap: 关键字可以相同</li><li>常常用某种二叉树实现(例如红黑树)</li></ul></li><li>set/multiset&lt;类型&gt;: map/multimap的特例, 有关键字没值</li><li>basic_string&lt;字符类型&gt;: 类似vector, 但提供字符串相关的操作</li></ul></li><li><p>基本操作</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">push_front</span><span class="params">(<span class="keyword">const</span> T&amp; x)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">pop_front</span><span class="params">()</span></span>;</span><br><span class="line"><span class="comment">// * 分别在容器的头部增加和删除一个元素。适用于list和deque。</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">push_back</span><span class="params">(<span class="keyword">const</span> T&amp; x)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">pop_back</span><span class="params">()</span></span>;</span><br><span class="line"><span class="comment">// * 分别在容器的尾部增加和删除一个元素。适用于vector、list和deque。</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">push</span><span class="params">(<span class="keyword">const</span> T&amp; x)</span></span>;</span><br><span class="line"><span class="comment">// * 在容器的尾部增加一个元素。适用于stack、queue和priority_queue。</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">pop</span><span class="params">()</span></span>;</span><br><span class="line"><span class="comment">// * 在容器的尾部（适用于stack）或头部（适用于queue和priority_queue）删除一个元素。</span></span><br><span class="line"><span class="function">T&amp; <span class="title">front</span><span class="params">()</span></span>;和<span class="function"><span class="keyword">const</span> T&amp; <span class="title">front</span><span class="params">()</span> <span class="keyword">const</span></span>;</span><br><span class="line"><span class="comment">// * 获取容器中第一个元素。适用于vector、list、deque和queue。</span></span><br><span class="line"><span class="function">T&amp; <span class="title">back</span><span class="params">()</span></span>;和<span class="function"><span class="keyword">const</span> T&amp; <span class="title">back</span><span class="params">()</span> <span class="keyword">const</span></span>;</span><br><span class="line"><span class="comment">// * 获取容器中最后一个元素。适用于vector、list、deque和queue。</span></span><br><span class="line"><span class="function">T&amp; <span class="title">top</span><span class="params">()</span></span>;和<span class="function"><span class="keyword">const</span> T&amp; <span class="title">top</span><span class="params">()</span> <span class="keyword">const</span></span>;</span><br><span class="line"><span class="comment">// * 获取容器尾部元素（适用于stack）或头部元素（适用于priority_queue）。</span></span><br><span class="line"><span class="function">T&amp; <span class="title">at</span><span class="params">(size_type pos)</span></span>;</span><br><span class="line"><span class="comment">// * 获取容器中某位置pos（序号）上的元素（会进行越界检查）。适用于vector、deque和basic_string。</span></span><br><span class="line">T&amp; <span class="keyword">operator</span>[](size_type pos);</span><br><span class="line"><span class="comment">// * 获取容器中某位置pos（序号）上的元素。适用于vector、deque和basic_string。</span></span><br><span class="line">ValueType&amp; <span class="keyword">operator</span>[](<span class="keyword">const</span> KeyType&amp; key); </span><br><span class="line"><span class="comment">// * 获取容器中某个关键字所关联的值。适用于map。</span></span><br><span class="line"><span class="function">iterator <span class="title">begin</span><span class="params">()</span></span>;</span><br><span class="line"><span class="function">const_iterator <span class="title">begin</span><span class="params">()</span> <span class="keyword">const</span></span>;</span><br><span class="line"><span class="comment">// * 获取指向容器中第一个元素位置的迭代器。适用于除queue、stack和priority_queue以外的所有容器。</span></span><br><span class="line"><span class="function">iterator <span class="title">end</span><span class="params">()</span></span>;</span><br><span class="line"><span class="function">const_iterator <span class="title">end</span><span class="params">()</span> <span class="keyword">const</span></span>;</span><br><span class="line"><span class="comment">// * 获取指向容器中最后一个元素的下一个位置的迭代器。适用于除queue、stack和priority_queue以外的所有容器。</span></span><br><span class="line"><span class="function">iterator <span class="title">insert</span><span class="params">(iterator pos, <span class="keyword">const</span> T&amp; x)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">insert</span><span class="params">(iterator pos, InputIt first, InputIt last)</span></span>;</span><br><span class="line"><span class="comment">// * 分别在容器中的指定位置pos（迭代器）之前插入一个和多个元素，返回插入的(第一个)元素的迭代器。适用于vector、list和deque。</span></span><br><span class="line"><span class="function">iterator <span class="title">erase</span><span class="params">(iterator pos)</span></span>;</span><br><span class="line"><span class="function">iterator <span class="title">erase</span><span class="params">(iterator first, iterator last)</span></span>;</span><br><span class="line"><span class="comment">// * 分别在容器中删除指定位置pos（迭代器）上的一个和某范围内的多个元素，返回删除后下一个元素的迭代器。适用于vector、list、deque、map/multimap、set/multiset以及basic_string。</span></span><br><span class="line"><span class="function">iterator <span class="title">find</span><span class="params">(<span class="keyword">const</span> T&amp; key)</span></span>;</span><br><span class="line"><span class="comment">// * 根据关键字在容器中查找某个元素，返回指向元素的迭代器（找到）或最后一个元素的下一个位置（未找到）。适用于map/multimap和set/multiset。</span></span><br><span class="line"><span class="function">size_type <span class="title">size</span><span class="params">()</span> <span class="keyword">const</span></span>;</span><br><span class="line"><span class="comment">// * 获取容器中元素个数。适用于所有容器。</span></span><br><span class="line"><span class="function">size_type <span class="title">max_size</span><span class="params">()</span> <span class="keyword">const</span></span>;</span><br><span class="line"><span class="comment">// * 获取容器中所允许的元素最大个数。适用于除stack、queue和priority_queue以外的所有容器。</span></span><br></pre></td></tr></table></figure></li><li><p>注意：如果容器的元素类型是一个类，则针对该类可能需要：</p><ul><li>自定义拷贝构造函数和赋值操作符重载函数<ul><li>对容器进行的一些操作中可能会创建新的元素（对象的拷贝构造）或进行元素间的赋值（对象赋值）。</li></ul></li><li>重载小于操作符（&lt;）<ul><li>对容器进行的一些操作中可能要进行元素比较运算。<h2 id="迭代器"><a href="#迭代器" class="headerlink" title="迭代器"></a>迭代器</h2></li></ul></li></ul></li><li>迭代器（iterator）实现了抽象的指针（智能指针）功能，它们用于指向容器中的元素，对容器中的元素进行访问和遍历</li><li>迭代器(类模板实现)的类型<ul><li>输出迭代器（output iterator，记为：OutIt）<ul><li>可以修改它所指向的容器元素</li><li>间接访问操作（*）</li><li>++操作</li></ul></li><li>输入迭代器（input iterator，记为：InIt）<ul><li>只能读取它所指向的容器元素</li><li>间接访问操作（*）和元素成员间接访问（-&gt;）</li><li>++、==、!=操作。</li></ul></li><li>前向迭代器（forward iterator，记为：FwdIt）<ul><li>可以读取/修改它所指向的容器元素</li><li>元素间接访问操作（*）和元素成员间接访问操作（-&gt;）</li><li>++、==、!=操作</li></ul></li><li>双向迭代器（bidirectional iterator，记为：BidIt）<ul><li>可以读取/修改它所指向的容器元素</li><li>元素间接访问操作（*）和元素成员间接访问操作（-&gt;）</li><li>++、–、==、!=操作</li></ul></li><li>随机访问迭代器（random-access iterator，记为：RanIt）<ul><li>可以读取/修改它所指向的容器元素</li><li>元素间接访问操作（*）、元素成员间接访问操作（-&gt;）和下标访问元素操作（[]）</li><li>++、–、+、-、+=、-=、==、!=、&lt;、&gt;、&lt;=、&gt;=操作</li></ul></li></ul></li><li>容器的迭代器<ul><li>vector, deque, basic_string: RanIt</li><li>list, map/multimap, set/multiset: BidIt</li><li>queue, stack, priority_queue: 不支持迭代器</li></ul></li><li>迭代器相容<ul><li>InIt/OutIt &lt;- FwdIt &lt;- BidIt &lt;- RanIt<h2 id="算法"><a href="#算法" class="headerlink" title="算法"></a>算法</h2></li></ul></li><li>在STL中，除了用容器类模板自身提供的成员函数来操作容器元素外，还提供了一系列<strong>通用的对容器中元素进行操作</strong>的函数模板，称为算法（algorithm）</li><li>大部分STL算法都是遍历指定容器中某范围内的元素，对满足条件的元素执行某项操作</li><li>算法的内部实现往往隐含着循环操作，但这对使用者是隐藏的。使用者只需要提供：<strong>容器（迭代器）</strong>、<strong>操作条件</strong>以及可能的<strong>自定义操作</strong>，而算法的控制逻辑则由算法内部实现，这体现了一种抽象的编程模式。</li><li>算法与容器之间的关系<ul><li>不是把容器传给算法，而是把容器的某些<strong>迭代器</strong>传给它们</li><li>这样做的好处是：使得<strong>算法不依赖于具体的容器</strong>，提高了算法的通用性</li></ul></li><li><p>一个算法能接收的迭代器的类型是通过算法模板参数的名字来体现的。例如</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span> &lt;<span class="class"><span class="keyword">class</span> <span class="title">InIt</span>, <span class="title">class</span> <span class="title">OutIt</span>&gt;</span></span><br><span class="line"><span class="class"><span class="title">OutIt</span> <span class="title">copy</span>(<span class="title">InIt</span> <span class="title">src_first</span>, <span class="title">InIt</span> <span class="title">src_last</span>, <span class="title">OutIt</span> <span class="title">dst_first</span>) &#123;</span> ...... &#125;</span><br></pre></td></tr></table></figure></li><li><p>算法的操作范围</p><ul><li><p>用算法对容器中的元素进行操作时，大都需要用<strong>两个迭代器</strong>来指出要操作的元素的范围</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">sort</span><span class="params">(RanIt first, RanIt last)</span></span>;</span><br></pre></td></tr></table></figure><ul><li>first是第一个元素的位置</li><li>last是最后一个元素的[下一个位置]</li></ul></li><li>有些算法可以有<strong>多个操作范围</strong>，这时，除第一个范围外，其它范围可以不指定最后一个元素位置，它由第一个范围中元素的个数决定</li><li>一个操作范围的两个迭代器必须属于<strong>同一个容器</strong>，而不同操作范围的迭代器可以属于不同的容器</li></ul></li><li><p>算法的自定义操作条件</p><ul><li>有些算法可以让使用者提供一个函数或函数对象来作为自定义操作条件（或称为谓词），其参数类型为相应容器的元素类型，返回值类型为bool</li><li><p>自定义操作条件可分为：</p><ul><li><p>Pred：一元“谓词”，需要一个元素作为参数</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">size_t</span> count_if(InIt first, InIt last, Pred cond);</span><br><span class="line"><span class="function"><span class="keyword">bool</span> <span class="title">f</span><span class="params">(<span class="keyword">int</span> x)</span> </span>&#123; <span class="keyword">return</span> x &gt; <span class="number">0</span>; &#125;</span><br><span class="line"><span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; v;</span><br><span class="line">...... <span class="comment">//往容器中放了元素</span></span><br><span class="line"><span class="built_in">cout</span>&lt;&lt;count_if(v.begin(),v.end(),f); <span class="comment">//统计v中正数的个数</span></span><br></pre></td></tr></table></figure></li><li><p>BinPred：二元“谓词”，需要两个元素作为参数</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">sort</span><span class="params">(RanIt first, RanIt last)</span></span>; <span class="comment">//按“&lt;”排序</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">sort</span><span class="params">(RanIt first, RanIt last, BinPred comp)</span></span>;  <span class="comment">//按comp返回true规定的次序</span></span><br><span class="line"><span class="function"><span class="keyword">bool</span> <span class="title">greater</span><span class="params">(<span class="keyword">int</span> x1, <span class="keyword">int</span> x2)</span> </span>&#123; <span class="keyword">return</span> x1&gt;x2; &#125;</span><br><span class="line"><span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; v;</span><br><span class="line">...... <span class="comment">//往容器中放了元素</span></span><br><span class="line">sort(v.begin(),v.end()); <span class="comment">//从小到大排序</span></span><br><span class="line">sort(v.begin(),v.end(),greater); <span class="comment">//从大到小排序</span></span><br></pre></td></tr></table></figure></li></ul></li></ul></li><li><p>算法的自定义操作</p><ul><li>有些算法可以让使用者提供一个函数或函数对象作为自定义操作，其参数和返回值类型由相应的算法决定。</li><li><p>自定义操作可分为：</p><ul><li><p>Op或Fun：一元操作，需要一个参数</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">Fun <span class="title">for_each</span><span class="params">(InIt first, InIt last, Fun f)</span></span>; </span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">f</span><span class="params">(<span class="keyword">int</span> x)</span> </span>&#123; <span class="built_in">cout</span> &lt;&lt; <span class="string">' '</span> &lt;&lt; x; &#125;</span><br><span class="line"><span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; v;</span><br><span class="line">...... <span class="comment">//往容器中放了元素</span></span><br><span class="line">for_each(v.begin(),v.end(),f); <span class="comment">//对v中的每个元素去调用函数f进行操作</span></span><br></pre></td></tr></table></figure></li><li><p>BinOp或BinFun：二元操作，需要两个参数</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">T <span class="title">accumulate</span><span class="params">(InIt first, InIt last, T val)</span></span>; <span class="comment">//按“+”操作</span></span><br><span class="line"><span class="function">T <span class="title">accumulate</span><span class="params">(InIt first, InIt last, T val, BinOp op)</span></span>; <span class="comment">//由op决定累积的含义</span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">f1</span><span class="params">(<span class="keyword">int</span> partial, <span class="keyword">int</span> x)</span> </span>&#123; <span class="keyword">return</span> partial*x; &#125;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">f2</span><span class="params">(<span class="keyword">int</span> partial, <span class="keyword">int</span> x)</span> </span>&#123; <span class="keyword">return</span> partial+x*x; &#125;</span><br><span class="line"><span class="function"><span class="keyword">double</span> <span class="title">f3</span><span class="params">(<span class="keyword">double</span> partial, <span class="keyword">int</span> x)</span> </span>&#123; <span class="keyword">return</span> partial+<span class="number">1.0</span>/x; &#125;</span><br><span class="line"><span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; v;</span><br><span class="line">...... <span class="comment">//往容器中放了元素</span></span><br><span class="line">accumulate(v.begin(),v.end(),<span class="number">0</span>); <span class="comment">//所有元素和</span></span><br><span class="line">accumulate(v.begin(),v.end(),<span class="number">1</span>,f1); <span class="comment">//所有元素的乘积</span></span><br><span class="line">accumulate(v.begin(),v.end(),<span class="number">0</span>,f2); <span class="comment">//所有元素平方和</span></span><br><span class="line">accumulate(v.begin(),v.end(),<span class="number">0.0</span>,f3); <span class="comment">//所有元素倒数和</span></span><br></pre></td></tr></table></figure></li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">OutIt <span class="title">transform</span><span class="params">(InIt src_first, InIt src_last,  OutIt dst_first, Op f)</span></span>;</span><br><span class="line"><span class="function">OutIt <span class="title">transform</span><span class="params">(InIt1 src_first1, InIt1 src_last1,  InIt2 src_first2, OutIt dst_first, BinOp f)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">f1</span><span class="params">(<span class="keyword">int</span> x)</span> </span>&#123; <span class="keyword">return</span> x*x; &#125;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">f2</span><span class="params">(<span class="keyword">int</span> x1, <span class="keyword">int</span> x2)</span> </span>&#123; <span class="keyword">return</span> x1+x2; &#125;</span><br><span class="line"><span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; v1,v2,v3,v4;</span><br><span class="line">...... <span class="comment">//往v1和v2容器中放了元素</span></span><br><span class="line">transform(v1.begin(),v1.end(),v3.begin(),f1);  <span class="comment">//v3中的元素是v1相应元素的平方</span></span><br><span class="line">transform(v1.begin(),v1.end(),v2.begin(),v4.begin(),f2);  <span class="comment">//v4中的元素是v1和v2相应元素的和</span></span><br></pre></td></tr></table></figure></li></ul></li></ul><h1 id="23-输入输出-面向对象"><a href="#23-输入输出-面向对象" class="headerlink" title="23.输入输出(面向对象)"></a>23.输入输出(面向对象)</h1><h2 id="输入-输出（I-O）概述"><a href="#输入-输出（I-O）概述" class="headerlink" title="输入/输出（I/O）概述"></a>输入/输出（I/O）概述</h2><ul><li>在C++中，输入/输出是一种基于<strong>字节流</strong>的操作：<ul><li>输入的数据看成逐个字节地从外设流入到计算机内部（内存）</li><li>输出的数据看成逐个字节地从内存流出到外设</li></ul></li><li>在C++的标准类库提供了用于C++基本数据类型数据的输入/输出操作：<ul><li>在这些操作的内部实现了基本数据类型与字节流之间的<strong>转换</strong>。</li></ul></li><li>另外，还可以对“&lt;&lt;”和“&gt;&gt;”进行<strong>重载</strong>，以实现对自定义类型的数据（对象）进行输入/输出操作。</li><li>C++输入输出的实现途径<ul><li>过程式——通过从C语言保留下来的函数库中的输入/输出函数来实现。<ul><li>不是强类型，不利于类型检查，会导致类型相关的运行错误</li></ul></li><li>面向对象——通过C++的I/O类库中的类/对象来实现。<ul><li>不需要额外指定数据的类型和个数，由数据本身决定，避免了类型与个数相关的错误！</li></ul></li></ul></li><li>I/O分类<ul><li>面向控制台的I/O<ul><li>从标准输入设备（如：键盘）获得数据</li><li>把程序结果从标准输出设备（如：显示器）输出</li></ul></li><li>面向文件的I/O<ul><li>从外存文件获得数据</li><li>把程序结果保存到外存文件中</li></ul></li><li>面向字符串变量的I/O<ul><li>从程序中的字符串变量中获得数据</li><li>把程序结果保存到字符串变量中</li></ul></li></ul></li><li>I/O类<ul><li>ios<ul><li>istream: ifstream, istrstream</li><li>ostream: ofstream, ostrstream</li><li>iostream: fstream, strstream</li></ul></li></ul></li></ul><h2 id="面向控制台的I-O"><a href="#面向控制台的I-O" class="headerlink" title="面向控制台的I/O"></a>面向控制台的I/O</h2><ul><li>预定义的io对象<ul><li>cin（istream类的对象）对应着计算机系统的标准输入设备。（通常为键盘）</li><li>cout（ostream类的对象）对应着计算机系统的用于输出程序正常运行结果的标准输出设备。（通常为显示器）</li><li>cerr和clog（ostream类的对象）对应着计算机系统的用于输出程序错误信息的设备（不带和带缓冲），通常情况下它们都对应着显示器。（不受输出重定向的影响）<h3 id="控制台输出"><a href="#控制台输出" class="headerlink" title="控制台输出"></a>控制台输出</h3></li></ul></li><li>输出格式控制<ul><li>操纵符<ul><li>dec, oct, hex: 进制</li><li>endl: 换行+flush</li><li>flush: 缓存中内容立刻输出</li><li>setprecision(int n): <ul><li>当输出格式为ios::scientific或ios::fixed时，操纵符setprecision用于设置浮点数小数点后面的位数；</li><li>当输出格式为自动方式（既不为ios::scientific也不为ios::fixed，或两者都有）时，操纵符setprecision用于设置浮点数有效数字的个数，这时的输出格式根据有效数字自动确定</li></ul></li><li>setiosflags(long flags)/resetiosflags(long flags) : </li></ul></li><li>基于字节流的操作<ul><li>cout.put(char)</li><li>cout.write(const char *, int)<h3 id="控制台输入"><a href="#控制台输入" class="headerlink" title="控制台输入"></a>控制台输入</h3></li></ul></li></ul></li><li>空白符（空格、\t、\n）分开输入的各个数据</li><li>操纵符<ul><li>cin &gt;&gt; setw(10) &gt;&gt; str; //把输入的字符串和一个’\0’放入str中，最多输入9个字符。</li></ul></li><li>基于字节流的操作<ul><li>get(char &amp;ch); </li><li>getline(char *p, int count, char delim=’\n’); 输入count个或遇到delim</li><li>read(char *p,int count);</li></ul></li><li><p>输入/输出操作符“&gt;&gt;”和“&lt;&lt;”的重载</p><ul><li><p>一般情况</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span> &#123;</span></span><br><span class="line">  <span class="keyword">int</span> x,y;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">  <span class="keyword">friend</span> ostream&amp; <span class="keyword">operator</span> &lt;&lt; (ostream&amp; out, <span class="keyword">const</span> A &amp;a)；</span><br><span class="line">&#125;;</span><br><span class="line">ostream&amp; <span class="keyword">operator</span> &lt;&lt; (ostream&amp; out, <span class="keyword">const</span> A &amp;a)</span><br><span class="line">&#123;out &lt;&lt; a.x &lt;&lt; <span class="string">','</span> &lt;&lt; a.y; <span class="keyword">return</span> out; &#125;</span><br></pre></td></tr></table></figure></li><li><p>派生类</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span> &#123;</span></span><br><span class="line">  <span class="keyword">int</span> x,y;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">  ......</span><br><span class="line">  <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">display</span><span class="params">(ostream&amp; out)</span> <span class="keyword">const</span></span></span><br><span class="line"><span class="function">  </span>&#123;out &lt;&lt; x &lt;&lt; <span class="string">','</span> &lt;&lt; y ; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">B</span>:</span> <span class="keyword">public</span> A &#123;</span><br><span class="line">  <span class="keyword">double</span> z;</span><br><span class="line">  <span class="keyword">public</span>:</span><br><span class="line">  ......</span><br><span class="line">  <span class="function"><span class="keyword">void</span> <span class="title">display</span><span class="params">(ostream&amp; out)</span> <span class="keyword">const</span></span></span><br><span class="line"><span class="function">  </span>&#123;A::display(out); out &lt;&lt; <span class="string">','</span> &lt;&lt; z ;   &#125;</span><br><span class="line">&#125;</span><br><span class="line">ostream&amp; <span class="keyword">operator</span> &lt;&lt; (ostream&amp; out, <span class="keyword">const</span> A&amp; a) &#123;</span><br><span class="line">  a.display(out); <span class="comment">//动态绑定到A类或B类对象的display。</span></span><br><span class="line">  <span class="keyword">return</span> out;</span><br><span class="line">&#125;</span><br><span class="line">A a1; B b1;</span><br><span class="line"><span class="built_in">cout</span> &lt;&lt; a1 &lt;&lt; <span class="built_in">endl</span> &lt;&lt; b1 &lt;&lt; <span class="built_in">endl</span>;</span><br></pre></td></tr></table></figure></li></ul></li></ul><h2 id="面向文件的I-O"><a href="#面向文件的I-O" class="headerlink" title="面向文件的I/O"></a>面向文件的I/O</h2><ul><li>文件基本概念<ul><li>在C++中，把文件看成是由一系列字节所构成的字节串，对文件中数据的操作（输入/输出）通常是逐个字节顺序进行，因此称为流式文件。 </li><li>每个打开的文件都有一个隐藏的位置指针，它指出文件的当前读写位置。</li><li>进行读/写操作时，每读入/写出一个字节，文件位置指针会自动往后移动一个字节的位置。 </li></ul></li><li>文件数据的存储方式<ul><li>文本方式（text）: 只包含可显示的字符和有限的几个控制字符（如：‘\r’、‘\n’、‘\t’等）的编码。<ul><li>一般用于存储具有“行”结构的文本数据。（可用记事本等软件打开察看）</li></ul></li><li>二进制方式（binary）: 包含任意的没有显式含义的纯二进制字节。<ul><li>一般用于存储无显式结构的数据。</li></ul></li></ul></li><li>对文件数据进行读写的过程：<ul><li>打开文件：把程序内部的一个表示文件的变量/对象与外部的一个具体文件关联起来，并创建内存缓冲区。</li><li>文件读/写：存取文件中的内容。</li><li>关闭文件：把暂存在内存缓冲区中的内容写入到文件中，并归还打开文件时申请的内存资源。  <h3 id="文件输出"><a href="#文件输出" class="headerlink" title="文件输出"></a>文件输出</h3></li></ul></li><li>首先创建一个ofstream类的对象，并建立与外部文件之间的联系（打开文件）。<ul><li>直接方式：ofstream out_file(&lt;文件名&gt;,&lt;打开方式&gt;);<br>例如：ofstream out_file(“d:\\myfile.txt”,ios::out);</li><li>间接方式: ofstream out_file; out_file.open(&lt;文件名&gt;,&lt;打开方式&gt;);<br>例如：out_file.open(“d:\\myfile.txt”,ios::out);</li></ul></li><li>打开方式<ul><li>打开方式 <ul><li>ios::out 默认打开方式<ul><li>打开一个外部文件用于写操作。</li><li>如果外部文件已存在，则首先把它的内容清除；否则，先创建该外部文件。</li></ul></li><li>ios::app<ul><li>打开一个外部文件用于添加（文件位置指针在末尾）操作。</li><li>如果外部文件不存在，则先创建该外部文件。 </li></ul></li><li>ios::out或ios::app分别与ios::binary的按位或（|）<ul><li>表示按二进制方式打开文件。（默认的是文本方式）</li><li>对以文本方式打开的文件，当输出的字符为’\n’时，在某些平台上（如：DOS和Windows平台）将自动转换成’\r’和’\n’两个字符写入外部文件。 </li></ul></li></ul></li><li>判断打开操作是否成功<ul><li>!out_file.is_open()  或 out_file.fail()  或 !out_file</li></ul></li></ul></li><li>输出数据: &lt;&lt;或成员函数, 与控制台类似</li><li>关闭文件<ul><li>文件输出操作结束时，要使用ofstream的成员函数close关闭文件：out_file.close(); </li><li>关闭文件的目的：<ul><li>把文件内存缓冲区的内容写到磁盘文件中！</li></ul></li><li>程序正常结束时，系统也会自动关闭打开的文件。<ul><li>程序中为什么要显式关闭文件？</li></ul></li></ul></li></ul><h3 id="文件输入"><a href="#文件输入" class="headerlink" title="文件输入"></a>文件输入</h3><ul><li>首先创建一个ifstream类（istream类的派生类）的对象，并与外部文件建立联系。<ul><li>例如：ifstream in_file(&lt;文件名&gt;,&lt;打开方式&gt;); </li><li>或: fstream in_file; in_file.open(&lt;文件名&gt;,&lt;打开方式&gt;); </li></ul></li><li>打开方式<ul><li>ios::in，打开一个外部文件用于读操作。<ul><li>也可以把ios::in与ios::binary通过按位或操作（|）实现二进制打开方式。默认为文本方式。</li><li>对以文本方式打开的文件，当文件中的字符为连续的’\r’和’\n’时，在某些平台上（如：DOS和Windows平台）将自动转换成一个字符’\n’输入。</li></ul></li><li>打开文件时要判断打开是否成功。<ul><li>判断方式与文件输出的判断一样。</li></ul></li></ul></li><li>判断成功与否: 读取数据过程中有时需要判断是否正确读入了数据（尤其是在文件末尾处）。<ul><li>判断是否正确读入了数据，可以调用ios类的成员函数fail来实现：</li><li>bool ios::fail() const;</li><li>该函数返回true表示文件操作失败；返回false表示操作成功。 </li></ul></li><li>文件输入操作结束时，要使用ifstream的一个成员函数close关闭文件：in_file.close(); </li><li>有关文件读写的几点注意: <ul><li>输入输出格式统一<ul><li>以文本方式输出的文件要以文本方式输入；以二进制方式输出的文件要以二进制方式输入！</li><li>以文本方式读写的文件要以文本方式打开；以二进制方式读写的文件要以二进制方式打开！</li></ul></li><li>以二进制方式存取文件不利于程序的兼容性和可移植性。例如，<ul><li>在不同计算机平台上，整型数的各字节在内存中的存储次序可能不一样。</li><li>在不同的编译环境下，同样的结构类型数据的尺寸（字节数）可能不一样。</li></ul></li></ul></li><li>文件输入/输出<ul><li>如果需要打开一个既能读入数据、也能输出数据的文件，则需要创建一个fstream类的对象。 </li><li>在创建fstream类的对象并建立与外部文件的联系时，文件打开方式应为下面之一：<ul><li>ios::in|ios::out（可在文件任意位置写）</li><li>ios::in|ios::app（只能在文件末尾写） </li></ul></li></ul></li><li>文件随机存取<ul><li>为了能够随机读写文件中的数据，可以显示地指出读写的位置。</li><li>对于以输入方式打开的文件，可用下面的操作来指定文件内部指针位置： <ul><li>istream&amp; istream::seekg(&lt;位置&gt;)；//指定绝对位置</li><li>istream&amp; istream::seekg(&lt;偏移量&gt;,&lt;参照位置&gt;);  //指定相对位置</li><li>streampos istream::tellg();  //获得指针位置</li></ul></li><li>对于输出文件，可用下面的操作来指定文件内部指针位置： <ul><li>ostream&amp; ostream::seekp(&lt;位置&gt;)；//指定绝对位置</li><li>ostream&amp; ostream::seekp(&lt;偏移量&gt;,&lt;参照位置&gt;); //指定相对位置</li><li>streampos ostream::tellp();  //获得指针位置 </li></ul></li><li>&lt;参照位置&gt;可以是：ios::beg（文件头），ios::cur（当前位置）和ios::end（文件尾）。</li></ul></li></ul><h1 id="24-异常处理"><a href="#24-异常处理" class="headerlink" title="24.异常处理"></a>24.异常处理</h1><h2 id="异常概述"><a href="#异常概述" class="headerlink" title="异常概述"></a>异常概述</h2><ul><li>程序的错误通常包括：<ul><li><strong>语法错误</strong>：指程序的书写不符合语言的语法规则。<br>例如：<br>使用了未定义或未声明的标识符<br>左右括号不匹配<br>……<br>这类错误可由编译程序发现。</li><li><strong>逻辑错误</strong>（或语义错误）：指程序设计不当造成程序没有完成预期的功能。<br>例如：<br>把两个数相加写成了相乘<br>排序功能未能正确排序<br>……<br>这类错误可通过对程序进行静态分析和动态测试发现。</li><li><strong>运行异常</strong>：指程序设计对程序运行环境考虑不周而造成的程序运行错误。<br>例如：<br>对于“x/y”操作，给y输入了“零”。<br>由内存空间不足导致的内存访问错误：<br>int <em>p=new int; //动态分配空间，可能失败！</em>p = 10; //如果上面new操作失败，p可能为空指针！<br>输入数据的数量超过存放它们的数组的大小，导致数组下标越界。<br>多任务环境可能导致的文件操作错误。</li></ul></li><li>在程序运行环境正常的情况下，运行异常的错误是不会出现的。</li><li>导致程序运行异常的情况是<strong>可以预料</strong>的，但它是<strong>无法避免</strong>的。</li><li>为了保证程序的<strong>鲁棒性</strong>（Robustness），必须在程序中对<strong>可能出现的异常进行预见性处理</strong>。</li><li>异常处理的策略<ul><li>就地处理: 在发现异常错误的地方处理异常</li><li>异地处理: 在其它地方（非异常发现地）处理异常<h3 id="异常的就地处理"><a href="#异常的就地处理" class="headerlink" title="异常的就地处理"></a>异常的就地处理</h3></li></ul></li><li>常用做法是调用C++标准库中的函数exit或abort终止程序执行（在cstdlib或stdlib.h中声明）<ul><li>abort立即终止程序的执行，不作任何的善后处理工作。</li><li>exit在终止程序的运行前，会做关闭被程序打开的文件、调用全局对象和static存储类的局部对象的析构函数（注意：不要在这些对象类的析构函数中调用exit）等工作。<h3 id="异常的异地处理"><a href="#异常的异地处理" class="headerlink" title="异常的异地处理"></a>异常的异地处理</h3></li></ul></li><li>发现异常时，在发现地（如在被调用的函数中）有时不知道如何处理这个异常，或者不能很好地处理这个异常，要由程序的其它地方（如函数的调用者）来处理</li><li>一种途径<ul><li>通过函数的返回值，或指针/引用类型的参数，或全局变量把异常情况通知函数的调用者，由调用者处理异常</li><li>通过函数的返回值返回异常情况会导致正常返回值和异常返回值交织在一起，有时无法区分。<ul><li>通过指针/引用类型的参数返回异常情况，需要引入额外的参数，给函数的使用带来负担。</li><li>通过全局变量返回异常情况会导致使用者忽视这个全局变量的问题。（不知道它的存在）</li><li>程序的可读性差！程序的正常处理与异常处理混杂在一起。<h2 id="C-异常处理机制"><a href="#C-异常处理机制" class="headerlink" title="C++异常处理机制"></a>C++异常处理机制</h2></li></ul></li></ul></li><li>把有可能遭遇异常的一系列操作（语句或函数调用）构成一个try语句块。</li><li>如果try语句块中的某个操作在执行中发现了异常，则通过执行一个throw语句抛掷（产生）一个异常对象，之后的操作不再进行。</li><li><p>抛掷的异常对象将由程序中能够处理这个异常的地方通过catch语句块来捕获并处理之。 </p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">f</span><span class="params">(<span class="keyword">char</span> *filename)</span></span></span><br><span class="line"><span class="function"></span>&#123; <span class="function">ifstream <span class="title">file</span><span class="params">(filename)</span></span>;</span><br><span class="line">   <span class="keyword">if</span> (file.fail()) </span><br><span class="line">     <span class="keyword">throw</span> filename; <span class="comment">//产生异常对象，报告错误情况</span></span><br><span class="line">   <span class="keyword">int</span> x;</span><br><span class="line">   <span class="built_in">cin</span> &gt;&gt; x;</span><br><span class="line">   ......</span><br><span class="line">   <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125; </span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;  <span class="keyword">char</span> str[<span class="number">100</span>];</span><br><span class="line">    ......</span><br><span class="line">    <span class="keyword">try</span> &#123; f(str); &#125;</span><br><span class="line">    <span class="keyword">catch</span> (<span class="keyword">char</span> *fn) <span class="comment">//捕获异常</span></span><br><span class="line">    &#123; ...... <span class="comment">//处理异常</span></span><br><span class="line">    &#125;</span><br><span class="line">    ...... <span class="comment">//正常情况</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>try语句</p><ul><li>try语句块的作用是启动异常处理机制, 上述的&lt;语句序列&gt;中可以有函数调用。格式为：<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">try</span> </span><br><span class="line">&#123; &lt;语句序列&gt;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ul></li><li><p>throw语句</p><ul><li>throw语句用于在发现异常情况时抛掷（产生）异常对象; 执行throw语句后，接在其后的语句将不再继续执行，而是转向异常处理（由某个catch语句给出）<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">throw</span> &lt;表达式&gt;;</span><br><span class="line">&lt;表达式&gt;为任意类型的C++表达式（<span class="keyword">void</span>除外）。</span><br></pre></td></tr></table></figure></li></ul></li><li><p>catch语句</p><ul><li><p>catch语句块用于捕获throw抛掷的异常对象并处理相应的异常, catch语句块要紧接在某个try语句的后面</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">catch</span> (&lt;类型&gt; [&lt;变量&gt;])</span><br><span class="line">&#123; &lt;语句序列&gt;</span><br><span class="line">&#125;</span><br><span class="line">&lt;类型&gt;用于指出捕获何种异常对象，它与<span class="keyword">throw</span>所产生的异常对象的类型匹配规则与函数重载的绑定规则类似；</span><br><span class="line">&lt;变量&gt;用于存储异常对象，它可以缺省，缺省时表明<span class="keyword">catch</span>语句块只关心异常对象的类型，而不考虑具体的异常对象。</span><br></pre></td></tr></table></figure></li><li><p>一个try语句块的后面可以跟多个catch语句块，用于捕获不同类型的异常对象并进行处理。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">g</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123; ......</span><br><span class="line">  <span class="keyword">try</span></span><br><span class="line">  &#123; f();</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">catch</span> (<span class="keyword">int</span>) <span class="comment">//处理函数f中的throw 1;</span></span><br><span class="line">  &#123; &lt;语句序列<span class="number">1</span>&gt;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">catch</span> (<span class="keyword">double</span>) <span class="comment">//处理函数f中的throw 1.0</span></span><br><span class="line">  &#123; &lt;语句序列<span class="number">2</span>&gt;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">catch</span> (<span class="keyword">char</span> *) <span class="comment">//处理函数f中的throw "abcd"</span></span><br><span class="line">  &#123; &lt;语句序列<span class="number">3</span>&gt;</span><br><span class="line">  &#125;</span><br><span class="line">  &lt;非<span class="keyword">catch</span>语句&gt;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ul></li><li><p>如果在try语句块的&lt;语句序列&gt;执行中没有抛掷（throw）异常对象，则其后的catch语句不执行，而是继续执行try语句块之后的非catch语句。</p></li><li>如果在try语句块的&lt;语句序列&gt;执行中抛掷了（throw）异常对象，<ul><li>如果该try语句块之后有能够捕获该异常对象的catch语句，则执行这个catch语句中的&lt;语句序列&gt;，然后继续执行这个catch语句之后的非catch语句。</li><li>如果该try语句块之后没有能够捕获该异常对象的catch语句，则按嵌套的异常处理规则进行处理。<h3 id="异常处理的嵌套"><a href="#异常处理的嵌套" class="headerlink" title="异常处理的嵌套"></a>异常处理的嵌套</h3></li></ul></li><li>try语句是可以嵌套的：<ul><li>在try语句块的语句序列执行过程中还可以包含try语句块。</li></ul></li><li>当在内层的try语句的执行中产生了异常，则首先在内层try语句块之后的catch语句序列中查找与之匹配的处理，如果内层不存在能捕获相应异常的catch，则逐步向外层进行查找。 </li><li>如果抛掷的异常对象在程序的函数调用链上没有给出捕获，则调用系统的terminate函数进行标准的异常处理。<ul><li>默认情况下，terminate函数将会去调用abort函数。</li></ul></li><li>实现机制示意<ul><li>每个函数都有一个catch表。</li><li>每进入一个try，都会把其后的所有catch入口地址记录在相应函数的catch表中。</li><li>执行throw时，<ul><li>顺着函数调用链去搜索catch入口；</li><li>对之前函数调用的栈空间进行退栈处理；</li><li>转到搜索到的catch入口。</li></ul></li></ul></li></ul><h2 id="基于断言的程序调试"><a href="#基于断言的程序调试" class="headerlink" title="基于断言的程序调试"></a>基于断言的程序调试</h2><ul><li>一个处于开发阶段的程序可能会含有一些错误（逻辑错误或异常）。<ul><li>通过测试可以发现程序存在错误。</li><li>通过调试可以对错误进行定位。</li></ul></li><li>除了利用调试工具以外，一种常用的调试手段是：<ul><li>在程序中的某些地方加上一些输出语句，在程序运行时把一些调试信息（如变量的值）输出到显示器。</li></ul></li><li>这种调试手段存在以下问题：<ul><li>调试者需要对输出的值做一定的分析才能知道程序是否有错。</li><li>在开发结束后，去掉调试信息有时是一件很繁琐的工作。</li></ul></li><li>实际上，在调试程序时输出程序在一些地方的某些变量或表达式的值，其目的是为了确认程序运行到这些地方时状态是否正确。</li><li>上述目的可以在程序的一些关键或容易出错的点上插入一些断言来表达。<ul><li>断言（assertion）是一个逻辑表达式，它描述了程序执行到断言处应满足的条件。</li><li>如果条件满足则程序继续执行下去，否则程序异常终止。</li></ul></li><li>在程序开发阶段，断言既可以用来帮助开发者发现程序的错误，也可以用于错误定位。<h3 id="宏ASSERT"><a href="#宏ASSERT" class="headerlink" title="宏ASSERT"></a>宏ASSERT</h3></li><li>C++标准库提供的一个宏assert（在头文件cassert或assert.h中定义），可以用来实现断言。其格式为：<ul><li>assert(&lt;表达式&gt;);</li><li>&lt;表达式&gt;一般为一个关系/逻辑表达式</li></ul></li><li>assert执行时，<ul><li>如果&lt;表达式&gt;的值为true，程序继续正常执行。</li><li>如果&lt;表达式&gt;的值为false，则它会:<ul><li>首先，显示出相应的表达式、该assert所在的源文件名以及所在的行号等诊断信息；</li><li>然后，调用库函数abort终止程序的运行。<h3 id="宏ASSERT的实现"><a href="#宏ASSERT的实现" class="headerlink" title="宏ASSERT的实现"></a>宏ASSERT的实现</h3></li></ul></li></ul></li><li><p>宏assert是通过条件编译预处理命令来实现的，其实现细节大致如下：</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//cassert 或 assert.h</span></span><br><span class="line">......</span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span>  NDEBUG</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> assert(exp)  ((void)0)</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">else</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> assert(exp)  ((exp)?(void)0:<span class="meta-string">&lt;输出诊断信息并调用库函数abort&gt;)</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line">......</span><br></pre></td></tr></table></figure></li><li><p>宏assert只有在宏名NDEBUG没定义时才有效，这时，程序一般处于开发、测试阶段。程序开发结束提交时，应该让宏名NDEBUG有定义，然后重新编译程序，这样，assert就不再有效了。</p></li><li>宏名NDEBUG在哪儿定义？<ul><li>在编译命令中指出。例如：<br><code>cl &lt;源文件1&gt; &lt;源文件2&gt; ... -D NDEBUG ...</code></li><li>在开发环境中的“项目|…属性|C/C++|预处理器|预处理器定义”中指出。（VC++2015）</li></ul></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;高级程序设计 课程的重点知识&lt;br&gt;
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Advanced Programming" scheme="https://Maxwell-lyu.github.io/tags/Advanced-Programming/"/>
    
  </entry>
  
  <entry>
    <title>编译原理 5</title>
    <link href="https://Maxwell-lyu.github.io/2020/03/17/Learn-PTC-20200317-PTC-05/"/>
    <id>https://Maxwell-lyu.github.io/2020/03/17/Learn-PTC-20200317-PTC-05/</id>
    <published>2020-03-17T03:15:20.000Z</published>
    <updated>2020-04-02T04:18:41.662Z</updated>
    
    <content type="html"><![CDATA[<h1 id="第五章-语法制导的翻译"><a href="#第五章-语法制导的翻译" class="headerlink" title="第五章: 语法制导的翻译"></a>第五章: 语法制导的翻译</h1><ul><li>翻译<ul><li>CFG非终结符号代表了语言的某个构造</li><li>程序设计语言的构造由更小的构造组合而成</li><li>一个构造的语义可以由更小的构造的含义综合而来</li><li>也可以从附近的构造继承而来</li></ul></li><li>语法制导定义: 将文法符号与某些属性相关联, 并用语义规则来描述如何计算属性的值</li><li>语法制导翻译: 在产生式体中加入语义动作, 并在适当时候执行动作<h2 id="语法制导的定义SDD"><a href="#语法制导的定义SDD" class="headerlink" title="语法制导的定义SDD"></a>语法制导的定义SDD</h2><ul><li>上下文无关文法和属性/规则的结合</li><li>关联关系: 属性-&gt;符号, 规则-&gt;产生式</li><li>X.a: 文法符号X的属性a的值, 可进行计算<ul><li>属性计算规则</li></ul></li><li>综合属性和继承属性<ul><li>综合属性: N的子节点和N本身的属性值来定义,  来自产生式的语义规则</li><li>继承属性: 依赖于父节点, 兄弟节点和本身的属性值来定义, 来自父节点所关联的语义规则</li><li>继承属性不能依赖于子节点, 但综合属性可依赖于继承属性, 终结符号有综合属性, 无继承属性</li></ul></li><li>S属性的SDD<ul><li>只包含综合属性</li><li>S属性的SDD可以和LR语法分析器一起实现<ul><li>栈中状态/符号可以附加属性值</li><li>归约时, 按照语义规则计算规约得到的符号的属性值</li><li>语义规则不应该有复杂的副作用: 不影响其他属性的求值</li></ul></li><li>语法分析树上的SDD求值: 注释分析树<ul><li>计算顺序: 先算被依赖的结点</li><li>S属性SDD: 自底向上的计算顺序可以求值</li></ul></li><li>自顶向下分析的SDD<ul><li>消除左递归后, 无法直接用val进行处理, 需要用继承属性完成计算</li><li>属性值计算规律<ul><li>假设<br>$$\begin{aligned}<br>  &amp;A\to A_1Y      &amp;A.a=g(A_1.a, Y.y)  \\<br>  &amp;A\to X         &amp;A.a=f(X.x)  \\<br>  \end{aligned}$$</li><li>那么, 消除左递归后<br>$$\begin{aligned}<br>  &amp;A\to XR        &amp;R.i=f(X.x); A.a=R.s \\<br>  &amp;R\to YR_i         &amp;R_1.i = g(R.i, Y.y);R.s=R_1.s  \\<br>  &amp;R\to \epsilon         &amp;R.s=R.i  \\<br>  \end{aligned}$$</li></ul></li></ul></li></ul></li><li>SDD的求值顺序<ul><li>求值过程中, 求算一个值, 必须先计算出其依赖的所有属性</li><li>依赖关系是偏序, 构造依赖图, 有环则无法计算</li><li>依赖图<ul><li>每个分析树结点N, 其每个属性a都对应一个依赖图结点N.a</li><li>虚线边来自分析树, 箭头表示数据流向, 比如a依赖b, 则数据从b流向a</li><li>计算时, 按照拓扑顺序进行计算</li><li>特定类型的SDD一定不包含环, 且有固定的计算顺序: L属性SDD和S属性SDD</li></ul></li><li>S属性SDD: 总是通过子节点计算父节点, 可以和自底向上或自顶向下的语法分析过程, 一同计算<ul><li>自底向上: 构造结点时, 计算相关属性, 因子节点已构造</li><li>自顶向下: 递归时, 在结点过程的最后计算该结点属性, 此时其递归过程(子节点)已经计算完毕</li></ul></li><li>L属性SDD: 每个属性可能是综合属性或继承属性<ul><li>继承属性: 每个$X_i$只能依赖产生式中, 其左边的那些文法符号的属性</li><li>计算时<ul><li>综合属性从下到上, 继承属性从上到下, 或从左到右</li></ul></li><li>递归子程序法<ul><li>非终结符号A, 其对应过程的参数为继承属性, 返回值为综合属性</li><li>处理规则$A\to X_1X_1\cdots X_n$<ul><li>调用$X_i()$之前, 计算其继承属性的值, 用作参数调用 </li><li>该产生式代码的最后, 计算$A$的综合属性</li></ul></li></ul></li></ul></li></ul></li><li>受控副作用的语义规则<ul><li>属性文法没有副作用, 但增加了复杂度</li><li>将标识符表作为全局变量, 用函数添加新的标识符</li><li>受控: 不会对属性求值进行约束, 或者只进行简单约束</li></ul></li><li>抽象语法树<ul><li>结点代表语法结构, 相当于运算符</li><li>节点的子节点代表子结构, 对应于运算分量</li><li>可以忽略掉标点等非本质的东西</li><li>表示方法<ul><li>每个节点用一个对象表示</li><li>对象有多个域: 叶节点存词法值, 内部结点存op值和参数, 参数指向其他节点 </li></ul></li><li>构建方法: 基于分析树, 似乎只有终结符, 其树边实箭头, 而分析树的中间结点用虚线箭头指向对应的抽象语法树结点<h2 id="语法制导的翻译SDT"><a href="#语法制导的翻译SDT" class="headerlink" title="语法制导的翻译SDT"></a>语法制导的翻译SDT</h2></li></ul></li></ul></li><li>在产生式体中嵌入的语义动作(程序片段)</li><li>实现方法<ul><li>建立语法分析树</li><li>将语义动作看作虚拟结点</li><li>从左到右, 深度优先遍历, 访问虚拟结点时执行相应动作</li><li>SDT实现SDD<ul><li>LR文法, SDD是S属性</li><li>LL文法, SDD是L属性</li></ul></li></ul></li><li>可在语法分析过程中实现的SDT<ul><li>可在分析过程中执行语义动作,  判断方法<ul><li>将每个语义动作替换为一个独有的非终结符以及产生式$M_i\to\epsilon$</li><li>如果新的文法可以由某种方法分析, 则SDT可在这个分析过程中实现</li></ul></li><li>后缀SDT: 所有动作都发生在产生式的最右端<ul><li>文法是LR, 且其SDD是S属性, 必然可构造出后缀SDT</li><li>后缀SDT和L属性对应的SDT, 可在分析时完成</li></ul></li><li>带有内部语义动作的SDT<ul><li>动作左边的符号处理完成后, 就立刻执行这个动作$B\to X \{a\} Y$<ul><li>自底向上: X出现在栈顶时, 执行其后的动作a</li><li>自顶向下: 试图展开Y或在输入中检测到Y时, 执行其前的动作a</li></ul></li><li>一般的SDT, 都可先建立分析树, 之后前序遍历并执行动作</li><li>不是所有的SDT都可在分析过程中实现</li></ul></li><li>消除左递归时SDT的转换<ul><li>动作不涉及属性值, 可以把动作当作终结符号处理, 消除左递归</li><li>涉及属性值:<ul><li>原文法</li><li>$$\begin{cases}A\to A_1Y\{A.a=g(A_1.a, Y.y)\}\\A\to X\{A.a=f(X.x)\}\end{cases}$$</li><li>消除后</li><li>$$\begin{cases}A\to X\{R.i = f(X.x)\}R\{A.a = R.s\}\\R\to Y\{R_1.i = g(R.i, Y.y)\}R_1\{R.s = R_1.s\}\\R\to \epsilon\{R.s = R.i\}\end{cases}$$</li></ul></li></ul></li><li>L属性的SDT<ul><li>如果文法是LL的, 就可以将L属性的SDD转换成一个SDT, 可在分析过程中实现</li><li>将赋值语义动作放到相应产生式的适当位置<ul><li>计算$X_i$继承属性的动作放在其体部位置的左边</li><li>计算产生式头部综合属性的动作在产生式的最右边</li></ul></li></ul></li><li>L属性的SDD实现<ul><li>每个非终结符号对应一个函数, 函数参数接受继承属性, 返回值包含综合属性</li><li>函数体中<ul><li>首先选择适当的产生式</li><li>局部变量保存属性</li><li>对于产生式体中的终结符号, 读入符号并获取其综合属性(词法分析得到)</li><li>对于非终结符号, 使用适当的方式调用相应函数, 并记录返回值</li></ul></li><li>边扫描边生成属性<ul><li>可以逐步生成属性的各个部分, 并增量式地添加到最终的属性值中</li><li>三个条件<ul><li>存在一个主属性, 且是综合属性</li><li>综合属性是由产生式体中的各非终结符号的主属性连接而得到, 同时还会连接一些其他元素</li><li>主属性的连接顺序与产生式体顺序相同</li></ul></li><li>思想: 适当的时候”发出”元素, 拼接到适当的地方</li></ul></li></ul></li></ul></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;第五章-语法制导的翻译&quot;&gt;&lt;a href=&quot;#第五章-语法制导的翻译&quot; class=&quot;headerlink&quot; title=&quot;第五章: 语法制导的翻译&quot;&gt;&lt;/a&gt;第五章: 语法制导的翻译&lt;/h1&gt;&lt;ul&gt;
&lt;li&gt;翻译&lt;ul&gt;
&lt;li&gt;CFG非终结符号代表了语言的某
      
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Principles and Techniques of Compilers" scheme="https://Maxwell-lyu.github.io/tags/Principles-and-Techniques-of-Compilers/"/>
    
  </entry>
  
  <entry>
    <title>编译原理 4</title>
    <link href="https://Maxwell-lyu.github.io/2020/02/27/Learn-PTC-20200227-PTC-04/"/>
    <id>https://Maxwell-lyu.github.io/2020/02/27/Learn-PTC-20200227-PTC-04/</id>
    <published>2020-02-27T02:14:32.000Z</published>
    <updated>2020-03-19T09:32:31.251Z</updated>
    
    <content type="html"><![CDATA[<h1 id="第四章-语法分析"><a href="#第四章-语法分析" class="headerlink" title="第四章: 语法分析"></a>第四章: 语法分析</h1><h2 id="语法分析器"><a href="#语法分析器" class="headerlink" title="语法分析器"></a>语法分析器</h2><ul><li>基本作用<ul><li>从词法分析器获得词法单元序列, 判断能否由该语言的文法生成</li><li>错误, 则报错</li><li>正确, 则生成语法树 </li></ul></li><li>分类<ul><li>自顶向下分析器: 根部开始构造(LL文法)</li><li>自底向上分析器: 从叶开始构造(LR文法)</li><li>总是从左到右扫描, 只处理特定类型的文法</li></ul></li></ul><h2 id="上下文无关文法"><a href="#上下文无关文法" class="headerlink" title="上下文无关文法"></a>上下文无关文法</h2><ul><li>终结符号: 组成串的基本符号</li><li>非终结符号: 表示串集合的语法变量</li><li>开始符号: 某个被指定的非终结符号(其对应的集合, 就是文法的语言)</li><li>产生式: 描述终结符号和非终结符号组成串的方法<ul><li>形式: 头部(左部)-&gt;体部(右部)</li><li>头部是非终结符, 体部是符号串</li></ul></li><li>元符号: 文法描述用的符号</li></ul><h3 id="推导"><a href="#推导" class="headerlink" title="推导"></a>推导</h3><ul><li>将待处理的串中的某个非终结符号替换为这个符号某个产生式的体</li><li>不断替换, 就能得到文法的不同句型</li><li>正则定义<ul><li>如果$A\to\gamma$是一个产生式, 那么$\alpha A\beta\Rightarrow \alpha\gamma\beta$</li><li>最左(右)推导: $\alpha(\beta)$中不包含非终结符号<ul><li>含有多个非终结符, 始终坚持替换最左侧的非终结符</li><li>$\xRightarrow[lm]{<em>}$ $\xRightarrow[rm]{</em>}$</li></ul></li><li>零步或多步: $\xRightarrow{*}$</li><li>一步或多步: $\xRightarrow{+}$, 等价于$\alpha\xRightarrow{*}\beta\wedge \alpha\ne\beta$</li></ul></li></ul><h3 id="句型句子语言"><a href="#句型句子语言" class="headerlink" title="句型句子语言"></a>句型句子语言</h3><ul><li>句型: $S\xRightarrow{*}\alpha$, $S$为开始符号</li><li>句子: 不包含非终结符号的句型</li><li>语言: 文法$G$的语言, 是$G$句子的集合, $L(G)$. $w\in G\Leftrightarrow S\xRightarrow{*}w$</li></ul><h3 id="语法分析树"><a href="#语法分析树" class="headerlink" title="语法分析树"></a>语法分析树</h3><ul><li>根结点的标号是文法的开始符号</li><li>叶子结点的标号是非终结符号, 终结符号或空字符</li><li>内部结点的标号是非终结符号</li><li>每个内部结点代表了某个产生式的一次应用<ul><li>结点标号为产生式头, 其子节点从左到右为产生式的体</li></ul></li><li>叶子的序列是一个句型</li><li>一个语法分析树, 可对应多个推导序列<ul><li>但只有唯一的最左推导和最右推导</li></ul></li></ul><h3 id="二义性"><a href="#二义性" class="headerlink" title="二义性"></a>二义性</h3><ul><li>一个文法可以为某个句子生成多课语法分析树, 则这个文法就是二义的</li></ul><h3 id="上下文无关文法与正则表达式"><a href="#上下文无关文法与正则表达式" class="headerlink" title="上下文无关文法与正则表达式"></a>上下文无关文法与正则表达式</h3><ul><li>上下文无关文法更强</li><li>正则表达式不足以表达<ul><li>直观例子: 有穷自动机不能计数</li></ul></li><li>上下文无关文法能表达任意正则语言<ul><li>对于NFA, 构造上下上下文无关文法</li><li>状态$i$, 构造非终结符$A_i$</li><li>输入$a$的转换, 则$A_i\yo aA_j$</li><li>空输入转换, 则$A_i\to A_j$</li><li>接受状态, 则$A_i\to\epsilon$</li><li>开始状态, 为开始符号</li></ul></li></ul><h3 id="文法及其生成的语言"><a href="#文法及其生成的语言" class="headerlink" title="文法及其生成的语言"></a>文法及其生成的语言</h3><ul><li>证明$G$生成的每个串都在$L$中</li><li>证明$L$中每个串都能被$G$生成</li></ul><h3 id="设计文法"><a href="#设计文法" class="headerlink" title="设计文法"></a>设计文法</h3><ul><li>消除二义性</li><li>消除左递归: $A\xRightarrow{+}A\alpha$<ul><li>左递归的定义: 存在非终结符号$A\xRightarrow{+}A\alpha$, 则它是左递归的</li><li>立即左递归: 存在形如$A\to A\alpha$的规则</li><li>自顶向下: 不能处理左递归</li></ul></li><li>消除立即左递归<ul><li>$$A\to A\alpha|\beta \equiv \begin{cases}<br>A&amp;\to\beta A’\\<br>A’&amp;\to\alpha A’|\epsilon\\<br>\end{cases}$$</li></ul></li><li>消除多步左递归<ul><li>算法: 消除所有左递归</li><li>所有非终结符排序</li><li>对每一个原有的$A_i\to A_j\gamma, j &lt; i$的产生式, 换成一系列$A_i\to \sigma_k\gamma$, 其中$\sigma_k$来自$A_j\to \sigma_k$的产生式</li><li>完成对一个$A_i$的转化后, 消除其立即左递归</li></ul></li><li>预测分析法: 试图从开始符号推导出输入符号串<ul><li>两个产生式有相同前缀时, 无法预测</li><li>消除相同前缀: 提取左公因子</li></ul></li></ul><h2 id="语法分析技术"><a href="#语法分析技术" class="headerlink" title="语法分析技术"></a>语法分析技术</h2><h3 id="自顶向下"><a href="#自顶向下" class="headerlink" title="自顶向下"></a>自顶向下</h3><ul><li>从分析树根节点开始, 按照先根次序, 深度优先, 创建节点</li><li>对应于最左推导</li><li>步骤<ul><li>确定最左边的非终结符应当应用那个产生式</li><li>用产生式去匹配</li><li>关键: 选择合适的 产生式</li></ul></li><li>递归下降<ul><li>搜索回溯<ul><li>回溯: 遇到错误, 退回之前的扫描结果</li><li>错误: 可能是输入的不是句子, 也可能选错产生式</li><li>改进选择产生式: 做记录, 一个产生式选一次, 都不行, 则输入不是句子</li></ul></li><li>问题<ul><li>回溯需要来回扫描, 甚至撤销已完成的语义动作</li><li>有可能明明是句子, 却不能被回溯出来</li></ul></li><li>预测分析法<ul><li>向前看几个符号, 确定产生式(通常只看1个), 若可能的产生式仅有一个, 则避免回溯. 对于句型$xA\beta$和输入$xa…$, 选择$A\to\alpha$可能性有:<ul><li>$\alpha\xRightarrow{*}a$</li><li>$\alpha\xRightarrow{<em>}\epsilon$, 且$\beta\xRightarrow{</em>}a$</li></ul></li><li>FIRST和FOLLOW<ul><li>FIRST<ul><li>$\mathrm{FIRST}(\alpha)$: 可以从$a$推导得到串的首符号的集合</li><li>例: $A\to \alpha | \beta$, 且$\mathrm{FIRST}(\alpha)$与$\mathrm{FIRST}(\beta)$不相交, 输入属于哪个, 就选哪个产生式</li><li>计算<ul><li>$\mathrm{FIRST}(X_1X_2\cdots X_n)$<ul><li>加入$X_1$中所有非$\epsilon$符号</li><li>若$\epsilon$在$\mathrm{FIRST}(X_1)$中, 则加入$\mathrm{FIRST}(X_2)$中所有非$\epsilon$符号, 对每一个都是其前面的都含有$\epsilon$</li><li>$X_i$都含有$\epsilon$, 也加入$\epsilon$</li></ul></li></ul></li></ul></li><li>FOLLOW<ul><li>$\mathrm{FOLLOW}(A)$: 可能在某些句型中紧跟在$A$右边的终结符号的集合</li><li>计算<ul><li>右端结束标记$$$加入$\mathrm{FOLLOW}(S)$</li><li>按照以下两个规则迭代, 直到不再增长<ul><li>存在产生式$A\to\alpha B\beta$, 那么$\mathrm{FIRST}(\beta)$中的所有非$\epsilon$符号加入$\mathrm{FOLLOW}(B)$</li><li>存在产生式$A\to\alpha B$, 或者$A\to\alpha B\beta$且$\mathrm{FIRST}(\beta)$中包含$\epsilon$, 那么$\mathrm{FOLLOW}(A)$中的所有符号加入$\mathrm{FOLLOW}(B)$</li></ul></li></ul></li></ul></li></ul></li></ul></li></ul></li></ul><h3 id="LL-1-文法"><a href="#LL-1-文法" class="headerlink" title="LL(1)文法"></a>LL(1)文法</h3><ul><li>对于文法的任意两个产生式$A\to\alpha|\beta$<ul><li>不存在终结符$a$, 使得$\alpha$和$\beta$都推导出以$a$开头的串</li><li>$\alpha$和$\beta$至多一个可推出空串</li><li>如果$\beta$可推导出空串, 那么$\alpha$不能推导出以$\mathrm{FOLLOW}(A)$中任何终结符号开头的串</li></ul></li><li>等价于<ul><li>$\mathrm{FIRST}(\alpha)\cap\mathrm{FIRST}(\beta)  =\emptyset$</li><li>若$\epsilon\in\mathrm{FIRST}(\beta)$, 那么$\mathrm{FIRST}(\alpha)\cap\mathrm{FOLLOW}(A)=\emptyset$, 反之亦然</li></ul></li><li>预测分析表构造算法<ul><li>输入: 文法G</li><li>输出: 预测分析表M</li><li>方法: <ul><li>对于文法$G$的每个产生式$A\to \alpha$<ul><li>对于$\mathrm{FIRST}(\alpha)$中的每个终结符号$a$, 将$A\to \alpha$加入到$M[A,a]$</li><li>如果$\epsilon\in\mathrm{FIRST}(\alpha)$, 那么对于$\mathrm{FOLLOW}(A)$中的每个符号$b$, 将$A\to \alpha$加入到$M[A,b]$</li></ul></li><li>剩下的空白条目填写error</li></ul></li><li>一格内仅有一个产生式, 否则二义性</li></ul></li><li>LL(1)文法的递归下降分析<ul><li>构造预测分析表后, 可以用当前的输入符号选择唯一的产生式</li></ul></li><li>非递归的预测分析<ul><li>总是匹配掉句型左边的所有终结符号</li><li>接下来的动作均发生于左边, 用栈完成</li><li>处理过程<ul><li>初始化时, 栈中仅有开始符号$S$(和$)</li><li>若栈顶是终结符号, 那么进行匹配</li><li>若是非终结符号, 用分析表选择产生式, 并用它的右部替换栈顶的左部(选不出来, 报错)</li></ul></li><li>算法<ul><li>输入: 串w, 预测分析表M</li><li>输出: w是句子, 则输出最左推导, 否则报错</li><li>初始化: 栈中S$, 输入缓冲区w$, ip指向w第一个符号</li><li>令X=栈顶符号, ip指向输入符号a<ul><li>if(X==a), X出栈, ip移动—&gt;匹配到终结符号</li><li>else if(X是终结符号) error—&gt;失配</li><li>else if(M[X,a]是报错条目) error—&gt;没有产生式</li><li>else if(M[X,a]=$X\to Y_1Y_2\cdots Y_k$)<ul><li>输出产生式$X\to Y_1Y_2\cdots Y_k$</li><li>弹出栈顶符号$X$, 并将$Y_1Y_2\cdots Y_k$放入(左边的在顶部)</li></ul></li></ul></li><li>不断执行, 直到栈空或报错</li></ul></li></ul></li></ul><h3 id="自底向上"><a href="#自底向上" class="headerlink" title="自底向上"></a>自底向上</h3><ul><li>为一个输入串构造语法分析树的过程<ul><li>从叶子开始向上到达根节点</li><li>移入-归约 框架</li><li>简单LR技术(SLR), LR技术(LR)</li></ul></li><li>归约: 右部换成左部(何时归约, 归约成什么符号串)</li><li>句柄<ul><li>对输入从左到右扫描, 自底向上分析, 可反向构造出最右推导</li><li>句柄：最右句型中和某个产生式体相匹配的字串, 对他的归约代表了该最右句型的最右推导的最后一步</li><li>句柄右边只有终结符号</li><li>如果文法是无二义的, 每个句型有且仅有一个句柄</li><li>正则定义: $S\xRightarrow[rm]{*}\alpha A w\xRightarrow[rm] \alpha\beta w$, 那么紧跟在$\alpha$后的$\beta$是$A\to \beta$的一个句柄</li></ul></li><li>移入-归约<ul><li>使用一个栈: 栈中符号描述了一个最右句型</li><li>开始: 栈中只有$, 输入为w$</li><li>结束时刻: 栈中S$, 输入为$</li><li>不断移入符号, 识别到句柄就归约</li><li>分析动作<ul><li>移入: 将下一个输入符号移到栈顶</li><li>归约: 将句柄归约为对应的非终结符<ul><li>句柄总在栈顶</li><li>具体操作时, 弹出句柄, 压入被归约到的非终结符号</li></ul></li><li>接受: 宣布分析成功完成</li><li>报错: 发现语法错误, 调用错误恢复子程序</li></ul></li><li>冲突<ul><li>移入-归约冲突: 不知道是否应该继续移入, 因为移不移都能归约</li><li>归约-归约冲突: 多个产生式, 右部相同</li></ul></li></ul></li><li>LR(k)分析: 向前看k个, k一般不超过1<ul><li>优点<ul><li>表格驱动, 通用方法, 无回溯移入-归约分析, 能分析的文法多</li></ul></li><li>LR(0)项<ul><li>文法的产生式, 在右部加一个点, 每个空位都可能加</li><li>点: 代表阶段性成果: 其前部已经被扫描, 后部是期望扫描到的东西</li></ul></li><li>LR(0)项集规范族的构造<ul><li>增广文法: 原文法加新开始符号S’, 并添加产生式$S’\to S$</li><li>项集闭包: CLOSURE(I): 根据以下规则构造, I为文法G的一个顶集<ul><li>I中各项加入CLOSURE(I)</li><li>如果$A\to\alpha \cdot B\beta$在CLOSURE(I), 而$B\to\cdot\gamma$不在, 则加入其中, 并不断迭代</li></ul></li><li>GOTO函数:<ul><li>GOTO(I,X): I中所有形如$[A\to \alpha\cdot X\beta]$对应的项$[A\to \alpha X\cdot\beta]$的集合的闭包</li></ul></li><li>求规范族<ul><li>从初始项集开始, 不断计算各种可能的后继, 直到生成所有可能的项集</li><li>对C中每个项集I, 对每个文法符号X, 如果GOTO(I,X)非空且不在C中, 将GOTO(I,X)加入C</li><li>直到某一轮没有新的项集被加入</li></ul></li></ul></li><li>LR(0)自动机的构造<ul><li>构造方法<ul><li>根据项集族构造</li><li>每个项集族的顶集对应于自动机的一个状态</li><li>状态转换: GOTO(I,X)=J, 则从I到J有标号X的转换</li><li>开始状态为CLOSURE({$S’\to \cdot S$})</li></ul></li><li>作用<ul><li>假设输入$\gamma$使自动机从开始状态运行到状态j</li><li>如果j中存在项$A\to\alpha\cdot$<ul><li>$\gamma$后添加一些终结符可以得到一个最右句型</li><li>$\alpha$是$\gamma$的后缀, 且是句型的句柄</li><li>表示可能找到了当前最右句型的句柄, 可以归约</li></ul></li><li>如果j中存在项$B\to \alpha\cdot X\beta$, 那么<ul><li>在$\gamma$后添加$X\beta$和一些终结符号, 可得到一个最右句型</li><li>该句型中$\alpha X \beta$是句柄, 但还没找到, 应当移入</li></ul></li><li>如果能给出明确的移入-归约建议, 则可以用来分析句型<ul><li>已得到的文法符号序列对应于自动机的一条路径</li></ul></li></ul></li></ul></li><li>LR语法分析器的结构<ul><li>输入, 栈, 分析程序, 输出</li><li>栈中存放状态序列, 可求出符号序列</li><li>分析表确定动作: ACTION和GOTO</li><li>LR分析表的结构<ul><li>ACTION: 参数: 状态i, 终结符号a<ul><li>移入j: j是新状态, 将j压入栈, 同时移入a</li><li>归约$A\to \beta$: 栈顶的$\beta$归约成A, 因此根据GOTO表项压入新状态</li><li>接受</li><li>报错</li></ul></li><li>GOTO: 如果GOTO($I_i$,A) = $I_j$(函数), 则GOTO[$i$,A] = $j$(表项)</li></ul></li></ul></li><li>语法分析器的格局<ul><li>栈中内容和余下输入</li><li>每一个状态都对应一个文法符号(进入该状态的边的标号), 除了$s_0$</li><li>动作与格局<ul><li>移入: 输入拿掉一个, 栈增加一个</li><li>归约: 输入不变, 栈拿掉r个(右部长度), 加上1个(左部)</li><li>接受</li><li>报错</li></ul></li><li>ACTION表<ul><li>s5: 表示移入, 并压入状态5</li><li>r8: 表示用8号产生式归约</li></ul></li><li>GOTO表: 3表示弹出之后的栈顶, 根据归约产生式左部 , 应当压入状态3</li></ul></li></ul></li><li>SLR语法分析表<ul><li>构造<ul><li>以自动机为基础, 构造规范族</li><li>状态$i$对应项集$I_i$, 相关的ACTION和GOTO如下<ul><li>$[A\to\alpha\cdot a\beta]$在$I_i$中, 且GOTO($I_i$,a) = $I_j$, 则ACTION[i,a]=移入j</li><li>$[A\to\alpha\cdot]$在$I_i$中, 那么对FOLLOW(S)中的所有a, ACTION[$I_i$, a]</li><li>=按$A\to\alpha$归约</li><li>如果$[S’\to S\cdot]$在$I_i$中, 那么将ACTION[$I_i$,$]设为接受</li><li>如果GOTO($I_i$, A)=$I_j$, 那么在GOTO表中, GOTO[i,A]=j</li><li>空白的是error</li></ul></li><li>SLR表无冲突, 则该文法是SLR的</li></ul></li><li>弱点<ul><li>项集包含$[A\to\alpha\cdot]$, 按照$A\to \alpha$归约的条件是, 下一个输入符号$a$在某个句型中可以跟在$A$后</li><li>假设此时栈中的符号串为$\beta\alpha$, 如果$\beta Aa$不是任何最右句型的前缀, 那么即使a满足FOLLOW这个条件, 依然不应当按照$A\to\alpha$归约</li></ul></li><li>改进<ul><li>$[A\to\alpha\cdot]$在顶集中的条件是, $[A\to \cdot\alpha]$出现在某个顶集中, 而这个的条件是, $B\to\beta\cdot A\gamma$出现在项中</li><li>据此, 按此归约, 需要下一个输入符号是$\gamma$的第一个符号, 但LR(0)项集中不能确定这个信息</li></ul></li><li>更强大的分析器<ul><li>规范LR方法: LR(1)顶集, 把期望的向前看符号也加入项, 状态很多</li><li>向前看LR方法: LALR方法, 基于LR(0)项集族, 但每个项都带有向前看符号, 强于SLR, 但表一样大</li></ul></li></ul></li></ul><h3 id="LR-1"><a href="#LR-1" class="headerlink" title="LR(1)"></a>LR(1)</h3><ul><li>LR(1)项<ul><li>$[A\to \alpha\cdot\beta, a]$: 向前看符号为$a$</li><li>按照该产生式归约, 则下一个输入必须是$a$, 同一产生式可以配上不同的向前看符号, 有更多状态</li><li>$\beta$非空, 则移入动作不考虑$a$</li></ul></li><li>构造项<ul><li>增广文法<ul><li>$[S’\to S, $]$</li><li>$[A\to \alpha\cdot B\beta, a]$对于可行前缀$\gamma$有效, 那么$[B\to\cdot\theta, b]$有效的条件$b$是什么</li><li>$S\xRightarrow[rm]{<em>}\delta Aw\xRightarrow[rm]{}\delta\alpha B \beta w\xRightarrow[rm]{</em>}\delta\alpha B x w\xRightarrow[rm]{}\delta\alpha \theta x w$</li><li>$b$应当是FIRST(xw), 或$xw$为空时, $b=$$</li><li>若$[A\to \alpha\cdot X\beta, a]$对于可行前缀$\gamma$有效, $[A\to \alpha X\cdot \beta, a]$对$\gamma X$有效</li></ul></li><li>项集<ul><li>CLOSURE中, $[A\to \alpha\cdot B\beta, a]$生成$[B\to\cdot\theta, b]$时, $b$必须在FIRST($\beta a$)</li><li>总有$a$在FOLLOW($A$)中</li></ul></li></ul></li><li>构造分析表<ul><li>做修改: 按照产生式归约的条件, 从FOLLOW(A)改为: 项集的向前看符号a, ACTION[i,a]=按照….归约</li></ul></li></ul><h3 id="LALR语法分析表"><a href="#LALR语法分析表" class="headerlink" title="LALR语法分析表"></a>LALR语法分析表</h3><ul><li>LR(1)语法分析表的合并<ul><li>寻找相同核心(不考虑向前看符号)的LR(1)项集(项的第一分量相同, 向前看符号可能不同), 合并为1个项集</li><li>GOTO(I,X)也可合并, 因GOTO(I,X)的核心只由I的核心决定</li></ul></li><li>合并引起的冲突<ul><li>不会导致移入归约冲突, 若原来无冲突<ul><li>若有, 则合并前, 这两个项也冲突, 于是原来的LR(1)已经存在冲突</li></ul></li><li>归约归约冲突</li></ul></li><li>分析表构造算法<ul><li>先构造LR(1)项集规范族</li><li>对于每个核心, 找出有该核心的项集, 用并集代替他们</li><li>按照LR分析表的方法得到ACTION, 注意检查冲突</li><li>GOTO表, 原目标是项集, 替换为该项集在新的项集规范族中对应的项集(即替换为并集)</li></ul></li><li>比较<ul><li>处理正确的输入, LALR与LR的动作相同</li><li>错误的输入, LALR可能进行额外的归约, 但不会额外移入</li><li>LALR与SLR状态相同, 拥有LR(1)的向前看符号</li></ul></li></ul><h3 id="语法错误的处理"><a href="#语法错误的处理" class="headerlink" title="语法错误的处理"></a>语法错误的处理</h3><ul><li>错误处理的目标: 报错, 指出位置, 错误恢复</li><li>错误恢复<ul><li>出错后继续进行处理</li><li>可能恢复的不成功</li><li>可用信息: 栈中的符号, 待分析的符号</li><li>恢复方法<ul><li>恐慌模式(跳过当前结构, 通用)<ul><li>忽略输入中的一些符号, 直到出现由设计者选定的某个同步词法单元</li><li>同步词法单元<ul><li>将FOLLOW(A)中的所有符号放入A的同步集合中</li><li>高层次开始符号集合, 加入低层次同步集合</li><li>多了: FIRST(A)加入A的同步集合</li><li>漏了: 栈顶终结符错误, 可直接弹出该符号, 并发出消息称, 已经插入了该符号</li></ul></li></ul></li><li>短语层次的恢复(专用)</li></ul></li><li>LR语法分析中的错误恢复<ul><li>报错: 栈顶符号串$\alpha$, 输入$a$, 不存在终结符号$x$, 使得$\alpha a x$是最右句型</li><li>恢复(恐慌恢复)<ul><li>栈顶向下扫描, 找到状态s, s有一对应于终结符号A的GOTO目标(s之上的状态被丢弃)</li><li>输入中丢弃一些符号, 直到一个可以跟在A后的符号b(不丢弃b), 并将GOTO(s,A)压栈, 继续分析</li><li>总结: 设法(扔掉一些状态和输入)扫描完带错的A字串, 假装找到了A的实例</li><li>短语恢复: 不详细讲 </li></ul></li></ul></li></ul></li></ul><h2 id="二义性文法的使用"><a href="#二义性文法的使用" class="headerlink" title="二义性文法的使用"></a>二义性文法的使用</h2><ul><li>对于某些二义性文法, 可通过消除二义性规则, 保证每个句子只有一颗语法树</li></ul><h3 id="优先级-结合性消除冲突"><a href="#优先级-结合性消除冲突" class="headerlink" title="优先级/结合性消除冲突"></a>优先级/结合性消除冲突</h3><ul><li>优先级: 不同时判断顺序(高低)</li><li>结合性: 相同优先级, 判断顺序(左右)</li></ul><h2 id="语法分析器生成工具"><a href="#语法分析器生成工具" class="headerlink" title="语法分析器生成工具"></a>语法分析器生成工具</h2>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;第四章-语法分析&quot;&gt;&lt;a href=&quot;#第四章-语法分析&quot; class=&quot;headerlink&quot; title=&quot;第四章: 语法分析&quot;&gt;&lt;/a&gt;第四章: 语法分析&lt;/h1&gt;&lt;h2 id=&quot;语法分析器&quot;&gt;&lt;a href=&quot;#语法分析器&quot; class=&quot;headerli
      
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Principles and Techniques of Compilers" scheme="https://Maxwell-lyu.github.io/tags/Principles-and-Techniques-of-Compilers/"/>
    
  </entry>
  
  <entry>
    <title>编译原理 3</title>
    <link href="https://Maxwell-lyu.github.io/2020/02/18/Learn-PTC-20200218-PTC-03/"/>
    <id>https://Maxwell-lyu.github.io/2020/02/18/Learn-PTC-20200218-PTC-03/</id>
    <published>2020-02-18T03:58:50.000Z</published>
    <updated>2020-07-20T12:31:48.524Z</updated>
    
    <content type="html"><![CDATA[<h1 id="第三章-词法分析"><a href="#第三章-词法分析" class="headerlink" title="第三章: 词法分析"></a>第三章: 词法分析</h1><h2 id="词法分析器作用-正则表达式"><a href="#词法分析器作用-正则表达式" class="headerlink" title="词法分析器作用(正则表达式)"></a>词法分析器作用(正则表达式)</h2><ul><li>读入: 字符流</li><li>处理: 组成词素<ul><li>过滤: 空白, 换行, 制表符, 注释</li><li>符号: 词素添加到符号表</li></ul></li><li>输出: 词法单元序列</li><li></li><li>独立的词法分析器<ul><li>逻辑上独立于语法分析, 实践上与语法分析在同一趟</li><li>好处<ul><li>简化编译器设计: 由词法分析器完成简单处理</li><li>提高效率: 词法简单, 高效实现, 用有穷自动机</li><li>可移植: 组合多个语法分析器</li></ul></li></ul></li><li>词法单元: <code>&lt;单元名, [属性值]&gt;</code><ul><li>单元名: 种类</li><li>属性: 用于语义分析/代码生成等, 是结构化数据</li></ul></li><li>模式: 描述词素的形式</li><li>词素: 源程序的字符序列, 匹配于模式, 被识别为词法单元的实例</li></ul><h2 id="词法单元的归约-状态转换图"><a href="#词法单元的归约-状态转换图" class="headerlink" title="词法单元的归约(状态转换图)"></a>词法单元的归约(状态转换图)</h2><h3 id="串和语言"><a href="#串和语言" class="headerlink" title="串和语言"></a>串和语言</h3><ul><li>字母表: 有穷的符号集合(任意的有限集)</li><li>(字母表上的)串$s$: 符号的有穷序列<ul><li>长度: $|s|$, $s$中的符号出现次数, 可重复</li><li>空串$\varepsilon$</li></ul></li><li>语言: 串的可数集合</li><li>串术语<ul><li>前缀: 从尾部删除0或多个符号, 得到的串(可为原串或空串)</li><li>后缀: 从前部删除0或多个符号, 得到的串(可为原串或空串)</li><li>字串: 删除某个前缀和某个后缀得到的串(可为原串或空串)</li><li>真前缀, 真后缀, 真子串: 不等于原串, 不为空串</li><li>子序列: 任意删除0或多个符号</li></ul></li><li>串运算<ul><li>连接: $xy$</li><li>幂运算: $s^0=\varepsilon$, $s^1=s$, $s^i=s^{i-1}s$</li></ul></li></ul><h3 id="语言上的运算"><a href="#语言上的运算" class="headerlink" title="语言上的运算"></a>语言上的运算</h3><ul><li>$L$和$M$的并: $L\cup M=\{s|s\in L \vee s\in M\}$</li><li>$L$和$M$的连接: $LM=\{st|s\in L \wedge  t\in M\}$</li><li>$L$的Kleene闭包: $L^*=\bigcup_{i=0}^\infty L^i$</li><li>$L$的正闭包: $L^+=\bigcup_{i=1}^\infty L^i$</li></ul><h3 id="正则表达式和正则定义"><a href="#正则表达式和正则定义" class="headerlink" title="正则表达式和正则定义"></a>正则表达式和正则定义</h3><ul><li>正则表达式的定义<ul><li>基本部分<ul><li>$\varepsilon$是正则表达式, $L(\varepsilon)=\{\varepsilon\}$</li><li>$a$是$\Sigma$中的符号, $a$是正则表达式, $L(a)=\{a\}$</li></ul></li><li>归纳步骤<ul><li>选择: $(r)|(s)$, $L((r)|(s)) = L(r)\cup L(s)$</li><li>连接: $(r)(s)$, $L((r)(s))=L(r)L(s)$</li><li>闭包: $(r)^<em>$, $L((r)^</em>)=(L(r))^*$</li><li>括号: $(r)$, $L((r))=L(r)$</li></ul></li><li>优先级: 闭包&gt;连接&gt;选择</li><li>正则集合: 可以用一个正则表达式定义的语言</li></ul></li><li>正则定义<ul><li>书写方便, 将一个表达式定义为变量: $d_i\to r_i$</li><li>其中<ul><li>$d_i\notin \Sigma$</li><li>$r_i$定义于$\Sigma\cup\{d_1, \cdots , d_{i-1}\}$</li></ul></li></ul></li></ul><h3 id="正则表达式的拓展"><a href="#正则表达式的拓展" class="headerlink" title="正则表达式的拓展"></a>正则表达式的拓展</h3><ul><li>基本运算符: 选择, 连接, Kleene闭包</li><li>拓展运算符<ul><li>一个或多个: $r^+\equiv rr^*$</li><li>零个或一个: $?\equiv \varepsilon | r$</li><li>字符类: $[a_1a_2\cdots a_n]\equiv a_1|a_2|\cdots|a_n$, $[a-e]\equiv a|b|c|d|e$</li><li>表示更简洁, 不增强表达能力(语法糖?)</li></ul></li></ul><h2 id="词法单元的识别"><a href="#词法单元的识别" class="headerlink" title="词法单元的识别"></a>词法单元的识别</h2><ul><li>在源代码的前缀中, 找出与某个模式匹配的词素<ul><li>正则定义模式</li></ul></li><li>状态转换图<ul><li>状态: 识别词素过程中, 阶段性的情况<ul><li>开始状态</li><li>接受状态/最终状态: 找到词素</li><li>带*的接受状态, 则最后读入的符号不在词素中</li></ul></li><li>边: 状态到状态<ul><li>边上的符号: 遇到该符号, 则沿该边走</li></ul></li></ul></li><li>保留字和标识符的识别<ul><li>符号表中先填保留字, 并指明他们不是普通标识符</li><li>专门为保留字建立的, 独立高优先级的状态转换图</li></ul></li><li>从转换图构造词法分析器(模拟状态转换图的运行)<ul><li>变量state记录当前状态</li><li>一个switch根据State值转到相应代码<ul><li>状态的代码: 根据读入符号, 确定下一个状态(边), 找不到则fail(), 进行错误恢复</li></ul></li><li>进入接受状态时, 返回相应词法单元<ul><li>有*标记, 则回退forward指针</li></ul></li></ul></li></ul><h2 id="词法分析器生成工具及设计"><a href="#词法分析器生成工具及设计" class="headerlink" title="词法分析器生成工具及设计"></a>词法分析器生成工具及设计</h2><ul><li>词法分析工具: Lex<ul><li>声明部分<ul><li>常量: 表示常数的标识符</li><li>正则定义</li></ul></li><li>转换规则<ul><li>模式{动作}<ul><li>模式是正则表达式, 动作是表示识别到相应模式时采取的处理方式, C语言代码表示</li></ul></li></ul></li><li>辅助函数<ul><li>动作中使用的函数</li></ul></li></ul></li></ul><h2 id="有穷自动机"><a href="#有穷自动机" class="headerlink" title="有穷自动机"></a>有穷自动机</h2><ul><li>本质上和状态转换图相同, 但只回答Yes/No<ul><li>NFA 不确定的有穷自动机: 边上的标号无限制, 一个符号可出现在离开同一状态的多条边上, 空字符可做标号</li><li>DFA 确定的有穷自动机: 每个状态及每个符号, 有且仅有一条边(或最多只有一条边)</li></ul></li><li>两种自动机都识别正则语言<h3 id="NFA"><a href="#NFA" class="headerlink" title="NFA"></a>NFA</h3></li><li>定义<ul><li>有穷状态集合$S$</li><li>输入符号集合$\Sigma$</li><li>转换函数: 对于每个状态和$\Sigma\cup \{\varepsilon\}$, 给出后继状态的集合</li><li>$s_0\in S$被定义为初始状态</li><li>$F\subset S$被定义为接受状态</li></ul></li><li>接受输入<ul><li>接受$x$, 当且仅当存在从开始状态到结束状态的路径, 边上字符恰好组成$x$</li><li>接受的语言: 开始状态到任一结束状态的所有可能路径<h3 id="DFA"><a href="#DFA" class="headerlink" title="DFA"></a>DFA</h3></li></ul></li><li>定义: NFA的特例<ul><li>没有标号为$\varepsilon$的转换</li><li>每个状态的每个标号, 只有一个后继状态(只有一条离开的边)</li></ul></li></ul><h2 id="从正则表达式到DFA"><a href="#从正则表达式到DFA" class="headerlink" title="从正则表达式到DFA"></a>从正则表达式到DFA</h2><ul><li>正则-&gt;NFA-&gt;DFA</li></ul><h2 id="NFA到DFA-子集构造法"><a href="#NFA到DFA-子集构造法" class="headerlink" title="NFA到DFA: 子集构造法"></a>NFA到DFA: 子集构造法</h2><ul><li>基本思想: 得到的DFA的每个状态和NFA的状态子集对应<ul><li>并行地模拟</li><li>$\varepsilon$转换, 添加进当前状态子集</li><li>对于当前子集, 考虑每个字母$a$:<ul><li>其中每个NFA状态, 由该字母, 将到达一些状态</li><li>这些状态的集合, 即为DFA中, 当前状态子集于字母$a$的后继状态</li></ul></li><li>不断迭代即可</li></ul></li><li>算法操作<ul><li>$\varepsilon-\mathrm{closure}(s)$: 从状态$s$开始, 只通过$\varepsilon$转换能到达的NFA状态集合</li><li>$\varepsilon-\mathrm{closure}(T)$: 从集合$T$中状态$s$开始, 只通过$\varepsilon$转换能到达的NFA状态集合</li><li>$\mathrm{move}(T, a)$: 从集合$T$中状态$s$开始, 通过标号为$a$转换能到达的NFA状态集合</li></ul></li><li>算法<ul><li>$\varepsilon-\mathrm{closure}(T)$<ul><li>实际上是从一个顶点集$T$的图搜索过程, 只考虑标号$\varepsilon$的边</li></ul></li><li>整个算法<ul><li><code>Dstate</code>: DFA状态集合</li><li>初始化: <code>Dstate</code>中仅有$\varepsilon-\mathrm{closure}(s_0)$</li><li><code>while</code> <code>Dstate</code>中有未加标记的状态$T$<ul><li>给$T$加标记</li><li><code>for</code> 每个输入符号$a$<ul><li><code>U=</code>$\varepsilon-\mathrm{closure}(\mathrm{move}(T, a))$</li><li><code>if</code> $U$不在<code>Dstate</code>中, 则加入之, 不加标记</li><li><code>Dtran[T,a]=U</code>, 为新的边和状态</li></ul></li></ul></li></ul></li></ul></li><li>开始与接受<ul><li>含有NFA开始状态的状态子集, 为DFA开始状态</li><li>含有NFA接受状态的状态子集, 为DFA接受状态</li></ul></li></ul><h2 id="正则表达式到NFA"><a href="#正则表达式到NFA" class="headerlink" title="正则表达式到NFA"></a>正则表达式到NFA</h2><ul><li>递归构造: 基本规则, 归纳</li><li>基本规则部分<ul><li>表达式$a$或$\varepsilon$: start-&gt;(i)–[a]–&gt;((f))</li></ul></li><li>归纳部分<ul><li>选择$s|t$<ul><li>新的开始状态, 2个$\varepsilon$, 分别到$s$$t$的表达式开始状态</li><li>两个表达式的接受状态, 2个$\varepsilon$, 都到新的接受状态</li></ul></li><li>连接$st$<ul><li>$s$的结束作为$t$的开始</li><li>$s$开始作为新开始, $t$结束作为新结束</li></ul></li><li>闭包$s^*$<ul><li>新状态: 新开始状态–[$\varepsilon$]–&gt;$s$开始状态, $s$接受状态–[$\varepsilon$]–&gt;新接受状态</li><li>0次匹配: 新开始状态–[$\varepsilon$]–&gt;新接受状态</li><li>多次匹配: $s$接受状态–[$\varepsilon$]–&gt;$s$开始状态</li></ul></li></ul></li><li>NFA合并<ul><li>新开始状态, 到各个表达式的开始状态, 有$\varepsilon$连接</li><li>不同的接受状态, 代表不同的模式</li></ul></li><li>DFA状态合并: 状态的区分<ul><li>一个串, 从两个状态, 一个能到接受状态, 一个不能, 则这两个状态不一样</li><li>基本步骤: 空串区分接受和其他</li><li>如果$s$和$t$可区分, $s-&gt;s’$, $t-&gt;t’$均有标号$a$的边, 则二者可区分</li><li>最终没有被分开的就是等价的<ul><li>死状态都等价</li><li>等价类中的状态, 选取一个代表即可</li></ul></li></ul></li><li>最小化算法<ul><li>设置初始划分: 接受跟别的不一样</li><li>迭代, 不断划分<ul><li>对于等价类集合中的每个元素$G$<ul><li>细分$G$, 使得$G$中$s$, $t$仍在同一组中, iff, 对任意输入$a$, $s$, $t$到达等价类集合中的同一组</li><li>新等价类集合, 将$G$换为细分结果</li></ul></li></ul></li><li>如果结果没变, 则完成, 否则迭代</li></ul></li><li>选代表构造<ul><li>开始状态: 包含原开始状态的组的代表</li><li>接受状态: 原接受状态</li><li>转换关系: 原s–[a]–&gt;t, t所在组代表为r, 则新s–[a]–&gt;r </li></ul></li><li>词法分析器: 多个接受状态<ul><li>这些接受状态之间互相不等价</li></ul></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;第三章-词法分析&quot;&gt;&lt;a href=&quot;#第三章-词法分析&quot; class=&quot;headerlink&quot; title=&quot;第三章: 词法分析&quot;&gt;&lt;/a&gt;第三章: 词法分析&lt;/h1&gt;&lt;h2 id=&quot;词法分析器作用-正则表达式&quot;&gt;&lt;a href=&quot;#词法分析器作用-正则表达式&quot;
      
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Principles and Techniques of Compilers" scheme="https://Maxwell-lyu.github.io/tags/Principles-and-Techniques-of-Compilers/"/>
    
  </entry>
  
  <entry>
    <title>PTC-01</title>
    <link href="https://Maxwell-lyu.github.io/2020/02/18/Learn-PTC-20200218-PTC-01/"/>
    <id>https://Maxwell-lyu.github.io/2020/02/18/Learn-PTC-20200218-PTC-01/</id>
    <published>2020-02-18T03:58:44.000Z</published>
    <updated>2020-02-18T04:01:14.397Z</updated>
    
    <content type="html"><![CDATA[<p># </p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;# &lt;/p&gt;

      
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Principles and Techniques of Compilers" scheme="https://Maxwell-lyu.github.io/tags/Principles-and-Techniques-of-Compilers/"/>
    
  </entry>
  
  <entry>
    <title>TobuDownload</title>
    <link href="https://Maxwell-lyu.github.io/2020/02/09/Tech-20200209-TobuDownload/"/>
    <id>https://Maxwell-lyu.github.io/2020/02/09/Tech-20200209-TobuDownload/</id>
    <published>2020-02-09T04:35:00.000Z</published>
    <updated>2021-03-03T14:32:33.116Z</updated>
    
    <content type="html"><![CDATA[<p>使用Python编写超简单爬虫，从tobu.io下载全部免费歌曲<br><a id="more"></a></p><h1 id="概要"><a href="#概要" class="headerlink" title="概要"></a>概要</h1><p>本文包括简单教程, 也有相关技术的介绍, 具体板块有</p><ul><li>代码</li><li>tobu.io下载流程分析</li><li>关键模块处理</li><li><p>相关Python知识介绍</p><h2 id="依赖和环境"><a href="#依赖和环境" class="headerlink" title="依赖和环境"></a>依赖和环境</h2></li><li><p>Python 3 <strong>REQUIRED</strong> (我使用3.8.1 64-bit)</p><ul><li><code>pip install AdvancedHTMLParser</code>: 极其便利的HTML解析, JavaScript中用到的方法, 其中大部分均有类似实现</li><li><code>pip install requests</code>: HTTP请求, 主要使用其cookiejar和opener</li></ul></li><li>Windows 10 Home Chinese, Windows Powershell <strong>OPTIONAL</strong><ul><li>使用的终端, 需支持ANSI EscapeCode</li></ul></li></ul><h1 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h1><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> urllib.request</span><br><span class="line"><span class="keyword">import</span> http.cookiejar</span><br><span class="line"><span class="keyword">import</span> AdvancedHTMLParser</span><br><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">from</span> contextlib <span class="keyword">import</span> closing</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Song</span>:</span></span><br><span class="line">  <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span></span><br><span class="line">    <span class="keyword">pass</span></span><br><span class="line">  <span class="function"><span class="keyword">def</span> <span class="title">parseTag</span><span class="params">(self, tag: AdvancedHTMLParser.AdvancedTag)</span>:</span></span><br><span class="line">    parser = AdvancedHTMLParser.AdvancedHTMLParser()</span><br><span class="line">    parser.parseStr(tag.innerHTML)</span><br><span class="line">    <span class="comment"># print(tag.innerHTML)</span></span><br><span class="line">    self.url = <span class="string">'https:'</span> + tag.getAttribute(<span class="string">'href'</span>)</span><br><span class="line">    self.title = parser.getElementsByClassName(<span class="string">'title'</span>)[<span class="number">0</span>].innerHTML</span><br><span class="line">    self.artist = parser.getElementsByClassName(<span class="string">'artist'</span>)[<span class="number">0</span>].innerHTML</span><br><span class="line">    self.date = parser.getElementsByClassName(<span class="string">'date'</span>)[<span class="number">0</span>].innerHTML.strip()</span><br><span class="line">    self.isFree = len(parser.getElementsByClassName(<span class="string">'free'</span>)) &gt; <span class="number">0</span></span><br><span class="line">    self.artwork = parser.getElementsByTagName(<span class="string">'img'</span>)[<span class="number">0</span>].getAttribute(<span class="string">'src'</span>)</span><br><span class="line">    <span class="keyword">pass</span></span><br><span class="line">  <span class="function"><span class="keyword">def</span> <span class="title">getSong</span><span class="params">(self)</span>:</span></span><br><span class="line">    <span class="comment"># Step 0: build opener</span></span><br><span class="line">    cookiejar = http.cookiejar.CookieJar()</span><br><span class="line">    opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cookiejar))</span><br><span class="line">    accept = http.cookiejar.Cookie(version=<span class="number">0</span>, name=<span class="string">'accept'</span>, value=<span class="string">'1'</span>, port=<span class="keyword">None</span>, port_specified=<span class="keyword">False</span>, domain=<span class="string">'.tobu.io'</span>, domain_specified=<span class="keyword">True</span>, domain_initial_dot=<span class="keyword">False</span>, path=<span class="string">'/'</span>, path_specified=<span class="keyword">True</span>, secure=<span class="keyword">False</span>, expires=<span class="number">1681201372</span>, discard=<span class="keyword">False</span>, comment=<span class="keyword">None</span>, comment_url=<span class="keyword">None</span>, rest=&#123;&#125;, rfc2109=<span class="keyword">False</span>)</span><br><span class="line">    headers = &#123;<span class="string">"User-Agent"</span>: <span class="string">"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"</span>&#125;</span><br><span class="line">    response = opener.open(self.url + <span class="string">'/download'</span>)</span><br><span class="line">    cookiejar.set_cookie(accept)</span><br><span class="line">    <span class="comment"># Step 2: Go to download page with the right cookie</span></span><br><span class="line">    <span class="keyword">with</span> closing(requests.get(url = self.url + <span class="string">'/download/mp3'</span>, headers=headers, cookies = cookiejar, stream=<span class="keyword">True</span>)) <span class="keyword">as</span> response:</span><br><span class="line">      chunk_size = <span class="number">1024</span>  <span class="comment"># 单次请求最大值</span></span><br><span class="line">      content_size = int(response.headers[<span class="string">'content-length'</span>])  <span class="comment"># 内容体总大小</span></span><br><span class="line">      self.title = response.headers[<span class="string">'content-disposition'</span>].split(sep=<span class="string">'"'</span>)[<span class="number">1</span>]</span><br><span class="line">      file_path = <span class="string">'download/'</span> + self.title</span><br><span class="line">      data_count = <span class="number">0</span></span><br><span class="line">      <span class="keyword">with</span> open(file_path, <span class="string">"wb+"</span>) <span class="keyword">as</span> file:</span><br><span class="line">        <span class="keyword">for</span> data <span class="keyword">in</span> response.iter_content(chunk_size=chunk_size):</span><br><span class="line">          file.write(data)</span><br><span class="line">          data_count = data_count + len(data)</span><br><span class="line">          now_jd = (data_count / content_size) * <span class="number">100</span></span><br><span class="line">          print(<span class="string">'\033[K[\033[33mWORK\033[0m]'</span> + <span class="string">' '</span> + <span class="string">'Downloading Song:'</span> + <span class="string">" %d%%(%d/%d) - %s"</span> % (now_jd, data_count, content_size, file_path), end=<span class="string">"\r"</span>)</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">def</span> <span class="title">__str__</span><span class="params">(self)</span>:</span></span><br><span class="line">    <span class="keyword">return</span> self.title + <span class="string">' '</span> + self.artist + <span class="string">' '</span> + self.date + <span class="string">' '</span> + self.isFree.__str__() + <span class="string">' '</span> + self.artwork + <span class="string">' '</span> + self.url</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">TobuGrab</span>:</span></span><br><span class="line">  url = <span class="string">'https://tobu.io'</span></span><br><span class="line">  prefix = <span class="string">'https:'</span></span><br><span class="line">  headers = &#123;<span class="string">"User-Agent"</span>: <span class="string">"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"</span>&#125;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span> </span><br><span class="line">    <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">def</span> <span class="title">getPageList</span><span class="params">(self)</span>:</span></span><br><span class="line">    request = urllib.request.Request(url=self.url, headers=self.headers)</span><br><span class="line">    response = urllib.request.urlopen(request)</span><br><span class="line">    html = response.read().decode(<span class="string">'utf-8'</span>)</span><br><span class="line">    parser = AdvancedHTMLParser.AdvancedHTMLParser()</span><br><span class="line">    parser.parseStr(html)</span><br><span class="line">    tagList = parser.getElementsByClassName(<span class="string">'pg'</span>).getAllNodes().filterCollection(<span class="keyword">lambda</span> tag: type(tag.getAttribute(<span class="string">'href'</span>)) == type(str()))</span><br><span class="line">    self.pageList = map(<span class="keyword">lambda</span> node: node.getAttribute(<span class="string">'href'</span>), tagList.getAllNodes())</span><br><span class="line">    <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">def</span> <span class="title">getSongList</span><span class="params">(self)</span>:</span></span><br><span class="line">    songList = list()</span><br><span class="line">    <span class="keyword">for</span> page <span class="keyword">in</span> self.pageList:</span><br><span class="line">      request = urllib.request.Request(url=self.prefix + page, headers=self.headers)</span><br><span class="line">      response = urllib.request.urlopen(request)</span><br><span class="line">      html = response.read().decode(<span class="string">'utf-8'</span>)</span><br><span class="line">      parser = AdvancedHTMLParser.AdvancedHTMLParser()</span><br><span class="line">      parser.parseStr(html)</span><br><span class="line">      tagList = parser.getElementsByClassName(<span class="string">'track'</span>)</span><br><span class="line">      <span class="keyword">for</span> tag <span class="keyword">in</span> tagList:</span><br><span class="line">        newSong = Song()</span><br><span class="line">        newSong.parseTag(tag)</span><br><span class="line">        songList.append(newSong)</span><br><span class="line">    self.songList = songList</span><br><span class="line"><span class="comment"># Load list    </span></span><br><span class="line">x = TobuGrab()</span><br><span class="line">x.getPageList()</span><br><span class="line">x.getSongList()</span><br><span class="line">print(<span class="string">'[\033[36mINFO\033[0m]'</span> + <span class="string">' '</span> + <span class="string">'List Loaded'</span>)</span><br><span class="line"><span class="comment"># Download songs in the list</span></span><br><span class="line">i = <span class="number">1</span> <span class="comment"># index starts at 1</span></span><br><span class="line"><span class="keyword">for</span> song <span class="keyword">in</span> x.songList[i<span class="number">-1</span>::]:</span><br><span class="line">  print(<span class="string">'[\033[36mINFO\033[0m]'</span> + <span class="string">' '</span> + <span class="string">'Loading Song:'</span> + <span class="string">' '</span> + song.title, end=<span class="string">"\r"</span>)</span><br><span class="line">  <span class="keyword">if</span> song.isFree == <span class="keyword">True</span>:</span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">      song.getSong()</span><br><span class="line">    <span class="keyword">except</span>:</span><br><span class="line">      print(<span class="string">'[%03d]\033[K[\033[31mFAIL\033[0m]'</span> % (i) + <span class="string">' '</span> + <span class="string">'Bad Song:'</span> + <span class="string">' '</span> + song.title + <span class="string">'                                '</span>)</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">      print(<span class="string">'[%03d]\033[K[\033[32mSUCC\033[0m]'</span> % (i) + <span class="string">' '</span> + <span class="string">'Downloaded Song:'</span> + <span class="string">' '</span> + song.title + <span class="string">'                                '</span>)</span><br><span class="line">  <span class="keyword">else</span>:</span><br><span class="line">    print(<span class="string">'[%03d]\033[K[\033[33mSKIP\033[0m]'</span> % (i) + <span class="string">' '</span> + <span class="string">'Paid Song:'</span> + <span class="string">' '</span> + song.title + <span class="string">'                                '</span>)</span><br><span class="line">  i += <span class="number">1</span></span><br></pre></td></tr></table></figure><ul><li>代码的质量相当糟糕, 因为:<ul><li>博主学艺不精</li><li>编写时想着能用就行, 反正就100行, 注释逻辑随便写写</li><li>异常处理写的稀烂, 甚至连<code>Ctrl+C</code>都没单独处理, <del>根本停不下来</del></li><li>没有多线程, web访问直接阻塞, 一次只能下一首歌, 更别提多线程下载了</li><li>面向对象乱写, 能放<strong>init</strong>的全部硬编码, 成员不初始化</li></ul></li><li>能WORK, <del>有歌听就完事了噢</del></li></ul><h1 id="下载流程分析"><a href="#下载流程分析" class="headerlink" title="下载流程分析"></a>下载流程分析</h1><h2 id="tobu-io歌曲"><a href="#tobu-io歌曲" class="headerlink" title="tobu.io歌曲"></a>tobu.io歌曲</h2><p>该网站的歌曲主要有以下几种</p><ul><li><strong>没戏</strong>: 5个, 付费歌曲, 不提供下载链接, 只有到其他音乐商店的链接</li><li><strong>自动</strong>: <del>84个</del>, 83个, 免费单曲(MP3), 站内页面, dropbox存储<ul><li>删去的1个, 文件名包含特殊字符, 很气, 也<strong>手动</strong>了</li></ul></li><li><strong>自动</strong>: 4个, 免费专辑(ZIP), 站内页面, dropbox存储</li><li><strong>手动</strong>: 1个, 免费单曲(MP3), NCS页面<h2 id="tobu-io流程"><a href="#tobu-io流程" class="headerlink" title="tobu.io流程"></a>tobu.io流程</h2></li></ul><p>仅分析<strong>站内页面, dropbox存储</strong>这一类的获取流程</p><ul><li>进入网站, 翻页查看歌曲</li><li>访问<code>https://tobu.io/&lt;track&gt;/download</code>, 查看歌曲详情</li><li>一系列点击事件, 最终访问到<code>https://tobu.io/&lt;track&gt;/download/mp3</code>, 该请求处理时, 会重定向至dropbox</li><li>得到来自dropbox的response, 其中就是带下载的文件<h2 id="tobu-io机制"><a href="#tobu-io机制" class="headerlink" title="tobu.io机制"></a>tobu.io机制</h2></li></ul><p>这个网站为了防止直连下载, 做了如下对策</p><ul><li>Cookies<ul><li>设置Cookie<ul><li>访问<code>https://tobu.io/&lt;track&gt;/download</code>时, 将设置<code>track_dl = &lt;trackID&gt;</code>的Cookie</li><li>访问<code>https://tobu.io/&lt;track&gt;/download#open-dl</code>时, 会进行一系列点击事件, 其中<code>&lt;btn class=&#39;unlock&#39;&gt;</code>按钮将设置<code>accept = 1</code>的Cookie</li></ul></li><li>检查Cookie: 访问<code>https://tobu.io/&lt;track&gt;/download/mp3</code>时, 将检查上述两个Cookie<ul><li><code>track_dl</code>必须匹配于<code>&lt;track&gt;</code></li><li>必须存在<code>accept = 1</code></li><li>Cookie不能过期, 但不检查期限是否合理(自己添加Cookie时, 可以将期限设置的离谱大, 几乎永不过期)</li></ul></li></ul></li><li>重定向<ul><li>dropbox的重定向由后台进行, 无法直接得到直连<h1 id="爬虫设计与关键模块分析"><a href="#爬虫设计与关键模块分析" class="headerlink" title="爬虫设计与关键模块分析"></a>爬虫设计与关键模块分析</h1></li></ul></li></ul><p>超烂代码再放送!</p><ol><li><p>访问<code>https://tobu.io</code>, 元素<code>&lt;div class=&#39;pg&#39;&gt;</code>得到歌曲列表全部页面<br>简单的爬虫, 其中<code>getAllNodes</code>方法将返回包含根节点的列表, 需要扔掉根节点, 根据<code>href</code>属性进行判断, 需要含有页面的url</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">getPageList</span><span class="params">(self)</span>:</span></span><br><span class="line">  request = urllib.request.Request(url=self.url, headers=self.headers)</span><br><span class="line">  response = urllib.request.urlopen(request)</span><br><span class="line">  html = response.read().decode(<span class="string">'utf-8'</span>)</span><br><span class="line">  parser = AdvancedHTMLParser.AdvancedHTMLParser()</span><br><span class="line">  parser.parseStr(html)</span><br><span class="line">  tagList = parser.getElementsByClassName(<span class="string">'pg'</span>).getAllNodes().filterCollection(<span class="keyword">lambda</span> tag: type(tag.getAttribute(<span class="string">'href'</span>)) == type(str()))</span><br><span class="line">  self.pageList = map(<span class="keyword">lambda</span> node: node.getAttribute(<span class="string">'href'</span>), tagList.getAllNodes())</span><br><span class="line">  <span class="keyword">pass</span></span><br></pre></td></tr></table></figure></li><li><p>访问每个页面, <code>https://tobu.io/page/&lt;pg_no&gt;</code>, 元素<code>&lt;div class=&#39;track&gt;</code>为单曲<br>简单的爬虫, 对元素的解析交给<code>Song</code>类实现<code>parseTag</code>方法</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">getSongList</span><span class="params">(self)</span>:</span></span><br><span class="line">  songList = list()</span><br><span class="line">  <span class="keyword">for</span> page <span class="keyword">in</span> self.pageList:</span><br><span class="line">    request = urllib.request.Request(url=self.prefix + page, headers=self.headers)</span><br><span class="line">    response = urllib.request.urlopen(request)</span><br><span class="line">    html = response.read().decode(<span class="string">'utf-8'</span>)</span><br><span class="line">    parser = AdvancedHTMLParser.AdvancedHTMLParser()</span><br><span class="line">    parser.parseStr(html)</span><br><span class="line">    tagList = parser.getElementsByClassName(<span class="string">'track'</span>)</span><br><span class="line">    <span class="keyword">for</span> tag <span class="keyword">in</span> tagList:</span><br><span class="line">      newSong = Song()</span><br><span class="line">      newSong.parseTag(tag)</span><br><span class="line">      songList.append(newSong)</span><br><span class="line">  self.songList = songList</span><br><span class="line">  <span class="keyword">pass</span></span><br></pre></td></tr></table></figure><ol><li>分析单曲, 主要是该元素的<code>href</code>属性, 将得到歌曲详情页, 其余部分没用  <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">parseTag</span><span class="params">(self, tag: AdvancedHTMLParser.AdvancedTag)</span>:</span></span><br><span class="line"> parser = AdvancedHTMLParser.AdvancedHTMLParser()</span><br><span class="line"> parser.parseStr(tag.innerHTML)</span><br><span class="line"> <span class="comment"># print(tag.innerHTML)</span></span><br><span class="line"> self.url = <span class="string">'https:'</span> + tag.getAttribute(<span class="string">'href'</span>)</span><br><span class="line"> self.title = parser.getElementsByClassName(<span class="string">'title'</span>)[<span class="number">0</span>].innerHTML</span><br><span class="line"> self.artist = parser.getElementsByClassName(<span class="string">'artist'</span>)[<span class="number">0</span>].innerHTML</span><br><span class="line"> self.date = parser.getElementsByClassName(<span class="string">'date'</span>)[<span class="number">0</span>].innerHTML.strip()</span><br><span class="line"> self.isFree = len(parser.getElementsByClassName(<span class="string">'free'</span>)) &gt; <span class="number">0</span></span><br><span class="line"> self.artwork = parser.getElementsByTagName(<span class="string">'img'</span>)[<span class="number">0</span>].getAttribute(<span class="string">'src'</span>)</span><br><span class="line"> <span class="keyword">pass</span></span><br></pre></td></tr></table></figure></li></ol></li><li><p>访问每个歌曲<code>&lt;track&gt;</code>, 其下载页面<code>https://tobu.io/&lt;track&gt;/download/</code>, 得到需要的cookie  </p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">response = opener.open(self.url + <span class="string">'/download'</span>)</span><br></pre></td></tr></table></figure></li><li><p>添加伪造的<code>accept=1</code>, 绕过点击事件<br>这里需要注意, 将cookie的<code>expires</code>搞久一点, 如果反复遇到不允许下载的情况, 可以调高<code>expires</code>. 该cookie于2020.02.09未过期</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">accept = http.cookiejar.Cookie(version=<span class="number">0</span>, name=<span class="string">'accept'</span>, value=<span class="string">'1'</span>, port=<span class="keyword">None</span>, port_specified=<span class="keyword">False</span>, domain=<span class="string">'.tobu.io'</span>, domain_specified=<span class="keyword">True</span>, domain_initial_dot=<span class="keyword">False</span>, path=<span class="string">'/'</span>, path_specified=<span class="keyword">True</span>, secure=<span class="keyword">False</span>, expires=<span class="number">1681201372</span>, discard=<span class="keyword">False</span>, comment=<span class="keyword">None</span>, comment_url=<span class="keyword">None</span>, rest=&#123;&#125;, rfc2109=<span class="keyword">False</span>)</span><br><span class="line">cookiejar.set_cookie(accept)</span><br></pre></td></tr></table></figure></li><li><p>携带上述cookie, 访问<code>https://tobu.io/&lt;track&gt;/download/mp3</code>, 静候佳音<br>参考了<a href="https://www.cnblogs.com/chen0307/articles/9706977.html" target="_blank" rel="noopener">chen~先生的cnblog</a>  </p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">with</span> closing(requests.get(url = self.url + <span class="string">'/download/mp3'</span>, headers=headers, cookies = cookiejar, stream=<span class="keyword">True</span>)) <span class="keyword">as</span> response:</span><br><span class="line">  chunk_size = <span class="number">1024</span>  <span class="comment"># 单次请求最大值</span></span><br><span class="line">  content_size = int(response.headers[<span class="string">'content-length'</span>])  <span class="comment"># 内容体总大小</span></span><br><span class="line">  self.title = response.headers[<span class="string">'content-disposition'</span>].split(sep=<span class="string">'"'</span>)[<span class="number">1</span>]</span><br><span class="line">  file_path = <span class="string">'download/'</span> + self.title</span><br><span class="line">  data_count = <span class="number">0</span></span><br><span class="line">  <span class="keyword">with</span> open(file_path, <span class="string">"wb+"</span>) <span class="keyword">as</span> file:</span><br><span class="line">    <span class="keyword">for</span> data <span class="keyword">in</span> response.iter_content(chunk_size=chunk_size):</span><br><span class="line">      file.write(data)</span><br><span class="line">      data_count = data_count + len(data)</span><br><span class="line">      now_jd = (data_count / content_size) * <span class="number">100</span></span><br><span class="line">      print(<span class="string">'\033[K[\033[33mWORK\033[0m]'</span> + <span class="string">' '</span> + <span class="string">'Downloading Song:'</span> + <span class="string">" %d%%(%d/%d) - %s"</span> % (now_jd, data_count, content_size, file_path), end=<span class="string">"\r"</span>)</span><br></pre></td></tr></table></figure></li></ol><h1 id="相关知识介绍"><a href="#相关知识介绍" class="headerlink" title="相关知识介绍"></a>相关知识介绍</h1><p>写给自己的, 以备后用, 先留空吧</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;使用Python编写超简单爬虫，从tobu.io下载全部免费歌曲&lt;br&gt;
    
    </summary>
    
      <category term="Technique" scheme="https://Maxwell-lyu.github.io/categories/Technique/"/>
    
    
      <category term="Utility" scheme="https://Maxwell-lyu.github.io/tags/Utility/"/>
    
  </entry>
  
  <entry>
    <title>DB-FIN</title>
    <link href="https://Maxwell-lyu.github.io/2019/12/19/Learn-DB-20191219-DB-FIN/"/>
    <id>https://Maxwell-lyu.github.io/2019/12/19/Learn-DB-20191219-DB-FIN/</id>
    <published>2019-12-19T02:19:09.000Z</published>
    <updated>2020-02-18T12:01:06.080Z</updated>
    
    <content type="html"><![CDATA[<h1 id="第一章-数据库系统概述"><a href="#第一章-数据库系统概述" class="headerlink" title="第一章:数据库系统概述"></a>第一章:数据库系统概述</h1><h2 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h2><ul><li><strong>数据库</strong>(DB): 是数据集合, 具有统一的结构形式并存放于统一的存储介质内, 它由多种应用数据集成, 并可被应用所共享</li><li><strong>数据库管理系统</strong>(DBMS): 是管理数据库的系统软件</li><li><strong>数据库系统</strong>(DBS): 是一个以对海量的、具有复杂数据结构的、可以持久保存的、可供多用户共享的数据进行统一管理为目标的计算机系统</li><li><strong>数据库管理员</strong>(DBA): 对数据库进行规划、设计、维护、监视的专职人员</li><li>相互之间的关系<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">数据库应用系统---+-[数据库系统]---+-[数据库] &lt;------------+---------------+</span><br><span class="line">                 |                |                       |               |</span><br><span class="line">                 +-应用软件       +-[数据库管理系统] : 管理               |</span><br><span class="line">                 |                |                                       |</span><br><span class="line">                 +-应用界面       +-[数据库管理员] : 规划, 设计, 维护, 监视</span><br><span class="line">                 |                |</span><br><span class="line">                 +-数据库用户     +-软件平台</span><br><span class="line">                                  |</span><br><span class="line">                                  +-硬件平台</span><br></pre></td></tr></table></figure></li></ul><h2 id="数据库系统的特点"><a href="#数据库系统的特点" class="headerlink" title="数据库系统的特点"></a>数据库系统的特点</h2><ul><li>数据<strong>集成化</strong>: 统一的数据结构/数据模式</li><li>数据<strong>独立性</strong>: 数据或数据结构(物理, 逻辑) <--> 应用程序</--></li><li>数据<strong>共享性</strong>: 高</li><li>数据<strong>冗余性</strong>: 低</li><li>数据的<strong>安全性，完整性和一致性</strong></li><li><strong>并发控制和故障恢复</strong></li></ul><h2 id="数据库内部结构体系"><a href="#数据库内部结构体系" class="headerlink" title="数据库内部结构体系"></a>数据库内部结构体系</h2><ul><li><strong>数据模式</strong>: 数据库中数据结构的具体表示与描述</li><li>三级模式<ul><li><strong>概念模式</strong>: 整个数据库中数据的全局逻辑结构 -&gt; 概念数据库</li><li><strong>外模式</strong>: 某个用户所需数据的逻辑结构 -&gt; 用户数据库</li><li><strong>内模式</strong>: 物理存储结构和物理存取方法 -&gt; 物理数据库</li></ul></li><li>二级映射<ul><li><strong>概念-&gt;内</strong>: 全局逻辑结构 -&gt; 数据的物理存储结构</li><li><strong>外-&gt;概念</strong>: 多个外模式 -&gt; 一个概念模式, 而每个外模式是概念模式的一个基本视图</li></ul></li><li>三级模式与数据独立性的关系<ul><li>概念-&gt;内: <strong>物理独立性</strong></li><li>外-&gt;概念: <strong>逻辑独立性</strong></li></ul></li></ul><h1 id="第二章-数据模型"><a href="#第二章-数据模型" class="headerlink" title="第二章:数据模型"></a>第二章:数据模型</h1><h2 id="数据模型的基本概念"><a href="#数据模型的基本概念" class="headerlink" title="数据模型的基本概念"></a>数据模型的基本概念</h2><ul><li><strong>数据模型</strong>: 数据基本特征的抽象<ul><li>描述<strong>数据结构</strong>: 数据的类型, 内容, 性质, 数据间联系</li><li>定义<strong>数据操作</strong>: 操作的类型, 方式</li><li>定义<strong>数据约束</strong>: 数据间的相互关系: 语法语义联系, 制约与依存, 动态变化规则</li></ul></li><li>数据模型的<strong>核心</strong>: 数据结构</li><li>不同类型数据模型的<strong>区分依据</strong>: 应用层次</li><li>三个抽象层次<ul><li><strong>概念数据模型</strong>: 面向客观世界, 面向用户; 客观对象的数据特征及相互关系<blockquote><p>E-R模型, EE-R模型; 面向对象模型; 谓词模型</p></blockquote></li><li><strong>逻辑数据模型</strong>: 面向数据库系统; 事物及关系在选定的DBMS中的实现结构<blockquote><p>层次, 网状模型; 关系, 面向对象, 谓词模型; 对象关系模型</p></blockquote></li><li><strong>物理数据模型</strong>: 面向计算机物理表示; 数据模型的物理表示</li></ul></li></ul><h2 id="数据模型的四个世界"><a href="#数据模型的四个世界" class="headerlink" title="数据模型的四个世界"></a>数据模型的四个世界</h2><ul><li><strong>现实世界</strong>: 客观世界中的应用环境</li><li><strong>概念世界</strong>: 基于现实世界, 进一步的抽象而形成</li><li><strong>信息世界</strong>: 基于概念世界, 用特定的DBMS构造而成的逻辑数据模型</li><li><strong>计算机世界</strong>: 逻辑数据模型在计算机中的物理实现<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">现实世界                           用户1    ...   用户n</span><br><span class="line">  |                                  |              |</span><br><span class="line">概念世界------&gt;概念模型              |              |     </span><br><span class="line">  |              |                   |              |</span><br><span class="line">  |              |            +---&gt;外模式1   ...  外模式n     </span><br><span class="line">信息世界------&gt;逻辑模型-------|      |              |</span><br><span class="line">  |              |            +---&gt;概念模式---------+</span><br><span class="line">  |              |                   | </span><br><span class="line">计算机世界----&gt;物理模型-----------&gt;内模式</span><br></pre></td></tr></table></figure></li></ul><h2 id="概念世界与概念模型"><a href="#概念世界与概念模型" class="headerlink" title="概念世界与概念模型"></a>概念世界与概念模型</h2><ul><li>E-R模型与E-R图（包括扩充E-R模型）<ul><li>实体: 客观存在且又能相互区别的事物</li><li>属性: 实体所具有的某种特性或特征<ul><li>多值属性: 一个实体, 多个取值(例如爱好, 可有多个)</li><li>组合属性: 一个性质, 多个属性(名字 <-> 姓, 名, 中间名)</-></li></ul></li><li>联系: 不同实体集中, 实体间的对应关系</li><li>联系上的函数对应关系: 一一, 一多/多一, 多多</li><li>参与方式<ul><li>参与方式标一个数, 参与基数标范围</li><li>考虑一个实体e, 在关系R的函数对应关系中, 有x条线与他相连, 则其参与基数为x</li><li>考虑实体集E, min-card(E,R): 其中实体参与基数最小值, max-card(E,R)同理</li></ul></li><li>IS-A联系: 超集-&gt;子集</li><li>弱实体: 依赖于其他某个实体, 多个弱实体依赖一个实体, 从弱实体到依赖联系的有向箭头</li></ul></li><li>面向对象模型<ul><li>对象: 客观世界中能够相互区别开来的事物</li><li>对象标识符: OID: 每对象有仅有一个, 用以相互区别</li><li>类: 具有相同属性, 方法的对象集合</li><li>方法: 施加在对象上的程序, 可审视或改变属性值</li><li>超类和子类: 类的子集叫做子类, 原来的类叫做超类 </li><li>聚合: 若干个简单类聚合成一个复杂的类的过程</li><li>分解: 复杂类分解成若干层次上的简单类的过程</li><li>继承: (超类与子类)单向不循环的层次结构, 共享实现和定义</li><li>合成: (聚合与分解)</li></ul></li></ul><h2 id="信息世界和逻辑模型"><a href="#信息世界和逻辑模型" class="headerlink" title="信息世界和逻辑模型"></a>信息世界和逻辑模型</h2><ul><li>关系模型<ul><li>关系: 由行和列组成的二维表格(表框架 + 元组*n)</li><li>属性: 表框架中的每一列</li><li>值域(域): 元组在某一属性下的取值范围</li><li>元组: 关系中的每一行</li><li>关系数据库模式: 该关系数据库中所有关系的关系模式的集合</li><li>关键字: 能唯一标识关系中的一个元组, 且又不含多余的属性值 的 属性集</li></ul></li></ul><h2 id="计算机世界与物理模型"><a href="#计算机世界与物理模型" class="headerlink" title="计算机世界与物理模型"></a>计算机世界与物理模型</h2><ul><li>逻辑模型的物理存储<ul><li>项: 文件系统中最小基本单位, 项内符号是不能继续分割</li><li>记录: 由若干项组成, 有内在语义联系</li><li>文件: 记录的集合</li></ul></li><li>提高文件访问效率的常用方法<ul><li>索引: 将文件中的记录与其物理地址(即磁盘块)间建立一张对应关系表</li><li>集簇: 将具有相同或相邻项值的记录聚集在相同磁盘块内或圆柱体内以减少读盘次数</li><li>HASH: 通过一个hash函数, 将要查找的记录转换成该记录所在的物理地址</li></ul></li></ul><h1 id="第三章-关系数据库系统"><a href="#第三章-关系数据库系统" class="headerlink" title="第三章:关系数据库系统"></a>第三章:关系数据库系统</h1><h2 id="关系数据库系统概述"><a href="#关系数据库系统概述" class="headerlink" title="关系数据库系统概述"></a>关系数据库系统概述</h2><h2 id="关系数据库系统的衡量准则"><a href="#关系数据库系统的衡量准则" class="headerlink" title="关系数据库系统的衡量准则"></a>关系数据库系统的衡量准则</h2><ul><li>完全关系型的十二条衡量准则<ol><li>信息准则: 逻辑一级<ul><li>所有信息 -&gt; 表中的值, 唯一且显式地表示</li><li>结构描述信息 -&gt; 组织成关系形式</li></ul></li><li>确保访问准则<ul><li>表名+关键字值+列名 -&gt; 访问到每一个原子数据</li></ul></li><li>空值的关系处理准则<ul><li>空值: 无意义/当前未知</li><li>系统应当可以处理有空值参与的: 比较运算, 表达式运算, 统计运算</li></ul></li><li>基于资源管理的动态联机目录<ul><li>数据库的描述信息(数据字典) 与 用户数据 有 相同的表示形式和操作方式</li><li>被授权用户可对 数据库的描述信息 进行 查询与扩充</li></ul></li><li>统一易用的数据子语言: 至少一种子语言支持以下功能<ul><li>数据定义</li><li>视图(view)定义</li><li>数据操纵</li><li>完整性约束能力</li><li>授权机制</li><li>事务处理能力</li></ul></li><li>视图更新准则: 视图除查询外, 还可增加, 删除, 修改数据</li><li>高级的插入、删除及修改操作: 一条命令可以插入、删除及修改操作多条元组</li><li>物理数据独立性</li><li>逻辑数据独立性</li><li>数据完整性准则: 提供三类数据完整性约束的定义功能</li><li>分布独立性: 数据分布的改变不影响原有的应用程序</li><li>无损害原则: 对提供低级数据子语言的要求</li></ol></li><li>空值（NULL）的定义: 无意义/当前未知的值</li></ul><h2 id="关系模型数学理论—关系代数"><a href="#关系模型数学理论—关系代数" class="headerlink" title="关系模型数学理论—关系代数"></a>关系模型数学理论—关系代数</h2><h3 id="关系模型（概念）"><a href="#关系模型（概念）" class="headerlink" title="关系模型（概念）"></a>关系模型（概念）</h3><ul><li>关系数据结构<ul><li>表结构（表头）: <ul><li>表框架: 属性组成表框架</li><li>表的元数: n个属性<->表的元数</-></li><li>表的基数: m个元组<->表的基数</-></li></ul></li><li>关系：关系的性质<ul><li>元组: 个数有限, 唯一, 次序无关, 分量原子性, 分量值域同一</li><li>属性: 名称唯一, 次序无关</li></ul></li><li>关键字：候选关键字，主关键字，外关键字<ul><li>关键字: 唯一最小标识元组的属性集, 每张表至少一个</li><li>主关键字: 被选中的关键字</li><li>候选关键字: 其他</li><li>外关键字: 如果表A中的属性集F是表B的关键字, 则称该属性集F为表A的外关键字</li></ul></li><li>关系数据库：关系子模式-视图（view）</li></ul></li><li>关系操纵<ul><li>数据查询：步骤<ul><li>两个关系的合并: 有多张表, 先合并为单个关系</li><li>单个关系内的元组选择: 选择符合条件的元组(行指定)</li><li>单个关系内的属性指定: 执行属性(列指定)</li></ul></li><li>元组: 单个关系内的操作<ul><li>删除: 确定被删除的元组-&gt;执行删除</li><li>插入: 添加元组</li><li>修改: 删旧-&gt;插新</li></ul></li><li>空值的处理<ul><li>主键不允许空值</li><li>算数表达式: 含空值, 结果为空值</li><li>逻辑表达式: 含空值, 结果为false</li><li>统计计算: 空值不计入(视而不见)</li></ul></li></ul></li><li>关系中的数据约束<ul><li>实体完整性约束: 主关键字属性不为空值</li><li>参照完整性约束: 外键要么取空值, 要么是被引用表中的主键值</li><li>用户定义的完整性: 用户自己定义的属性取值约束</li></ul></li></ul><h3 id="关系的表示"><a href="#关系的表示" class="headerlink" title="关系的表示"></a>关系的表示</h3><ul><li>关系的表示<br>设属性域为$D_1, D_2, \cdots, D_n$<br>关系$R\subseteq D_1\times D_2\times\cdots\times D_n$  </li><li>迪卡尔乘积<br>$D_1, D_2, \cdots, D_n$是$n$个集合<br>$D_1\times D_2\times\cdots\times D_n=\{(d_1, d_2, \cdots, d_n): d_i\in D_i, i\in (1, 2, \cdots, n)\}$<br>$|D_1\times D_2\times\cdots\times D_n| = \prod_{i=1}^n |D_i|$  </li></ul><h3 id="关系操纵的表示"><a href="#关系操纵的表示" class="headerlink" title="关系操纵的表示"></a>关系操纵的表示</h3><ul><li>关系代数中的五种基本运算：选择，投影，笛卡儿积，并，差（请注意每个运算符的执行条件和结果关系的关系模式）<ul><li>投影运算: $\pi_A(R)$<ul><li>略去某些列, 重排剩余列的次序<br>关系$R$有属性$\{A_1,A_2, \cdots, A_n\}$, 在其中$m$个属性上的投影运算如下<br>$\pi_{B_1, B_2, \cdots, B_n}(R), B_i\in\{A_1,A_2, \cdots, A_n\}$  </li><li>注意消除可能出现的重复元组</li></ul></li><li>选择运算: $\sigma_F(R)$<ul><li>关系模式不变, 由属于$R$且满足条件$F$的元组构成</li></ul></li><li>笛卡尔乘积 - 关系的合并: 交换律, 结合律<ul><li>若有相同的属性名, 必须在结果关系中对其中一个换名<br>&lt;!– + 交运算: 同类关系</li><li>用$R\cap S = R-(R-S)$代替, 不是基本运算 –&gt;</li></ul></li><li>并运算: $R\cup S$同类关系<ul><li>关系模式不变, 属于$R$或者$S$</li></ul></li><li>差运算: $R-S$同类关系<ul><li>关系模式不变, 属于$R$且不属于$S$</li></ul></li></ul></li><li>基本运算的应用<ul><li>插入: $R^*=R\cup R_{new}$</li><li>删除: $R^* = R-R_{old}$</li><li>修改: $R^* = (R-R_{old})\cup R_{new}$</li><li>查询: $\pi_A(\sigma_B(R))$简写为$\pi_A\sigma_B(R)$: 不能交换位置</li></ul></li></ul><h3 id="关系模型与关系代数"><a href="#关系模型与关系代数" class="headerlink" title="关系模型与关系代数"></a>关系模型与关系代数</h3><ul><li>关系: $n$元有序组的集合</li><li>关系操纵: 关系上的集合运算</li><li>关系代数: 关系集合$A$及5种基运算构成的代数</li><li>关系模型<ul><li>关系模型的数据结构</li><li>关系模型上的数据操纵</li><li>关系模型上的数据约束</li></ul></li></ul><h3 id="关系代数中的扩充运算"><a href="#关系代数中的扩充运算" class="headerlink" title="关系代数中的扩充运算"></a>关系代数中的扩充运算</h3><ul><li>交运算: 同类关系<ul><li>$R\cap S = R-(R-S)$</li><li>关系模式不变, 既属于$R$也属于$S$的元组组成的集合</li></ul></li><li>除运算: $\textrm{Head}(S)\subset \textrm{Head}(R)$<ul><li>关系模式: $\textrm{Head}(T)=\textrm{Head}(R) - \textrm{Head}(S)$</li><li>设$x\in T$, 则$\forall y\in S$, $(x,y)\in R$, 所有满足条件的$x$构成结果</li><li>如果$R=T\times S$, 则$T=R\div S$, $S=R\div T$; 如果$T=R\div S$, 则$T\times S\subseteq R$</li></ul></li><li>联接运算<ul><li>根据联接条件合并: $R\bowtie_F S=\sigma_F(R\times S)$</li><li>自然联接: $R\bowtie S$所有同名属性上的取值都一样, 就联接元组, 同名属性保留一份</li><li>外联接: 有”外”的一侧, 其所有元组均出现, 另一侧无匹配元组就用null代替</li></ul></li><li>扩充运算与基本运算之间的关系<ul><li>交: 可由差运算实现: $R\cap S=R-(R-S)=S-(S-R)$</li><li>除: <ul><li>$\textrm{Head}(R) = \{A_1, \cdots, A_n, B_1, \cdots, B_m\}$</li><li>$\textrm{Head}(S) = \{B_1, \cdots, B_m\}$</li><li>$R\div S=\pi_{A_1,\cdots A_n}(R)-\pi_{A_1,\cdots A_n}((\pi_{A_1,\cdots A_n}(R)\times S)-R)$</li></ul></li></ul></li><li>扩充运算的应用实例</li></ul><h3 id="关系代数的应用"><a href="#关系代数的应用" class="headerlink" title="关系代数的应用"></a>关系代数的应用</h3><blockquote><p>写在后面的大题部分</p><ul><li>综合的关系代数应用表示，复杂查询的关系代数表达式</li><li>关系代数的应用<ul><li>单个关系上的选择与投影</li><li>两个关系的并、交、差</li><li>两个关系的迪卡尔乘积、自然联接、θ-联接</li><li>两个关系的除法</li></ul></li><li>难点<ul><li>查询条件带有‘否定’语义：‘不等’比较 &amp; 减法运算</li><li>使用表联接查询，还是使用除法?</li><li>正确使用自然连接运算 和 除法运算</li><li>表的自联接</li></ul></li></ul></blockquote><h3 id="关系演算"><a href="#关系演算" class="headerlink" title="关系演算"></a>关系演算</h3><ul><li>原子公式<ul><li>谓词是公式</li><li>$u(i) \theta v(j)$是原子公式, 其中$u(i), v(j)$是元组中属性的值, $\theta$是比较运算符</li><li>$u(i) \theta a$是原子公式, 其中$a$是常量</li></ul></li><li>公式的定义: 以下三种方式, 有限次数组合构成<ul><li>原子公式是公式</li><li>公式的与, 或, 蕴含, 非 均为公式</li><li>量词约束一个公式, 构成新公式</li></ul></li><li>基于关系演算的数据查询表示<ul><li>投影<br>$$\pi_{A_{1},A_{2},\cdots,A_{k}}(R)=\exists x_{k+1},x_{k+2},\cdots ,x_n(R(x_1,x_2,\cdots,x_n))$$</li><li>选择<br>$$\sigma_F(R)=R(x_1,x_2,\cdots,x_n)\wedge F$$<ul><li>相等比较可以直接用常量代替: $\sigma_{x_1=’a’}(R)=R(‘a’,x_2,\cdots,x_n)\wedge F$</li></ul></li><li>笛卡尔积<br>$$R\times S = R(p)\wedge S(q)$$</li><li>$\theta$-联接<br>$$R\underset{F}{\bowtie} S = R(p)\wedge S(q)\wedge F$$</li><li>自然联接<br>$$R\bowtie S = R(x,y,z)\wedge S(t,u,v)$$</li><li>自联接, 重命名<br>$$R(x, g_1)\wedge R(x, g_2)$$</li><li>除法<br>$$R\div S=\forall y(S(y)\rightarrow R(x,y))$$</li><li>删除<br>$$R-S = R(u)\wedge \neg S(u)$$</li><li>插入<br>$$R\cup S = R(t)\vee S(t)$$</li><li>修改 = 删除再插入</li></ul></li><li>公式的表示 <ul><li>$\phi_1\wedge\phi_2$<ul><li>有公共变元, 等价于自然联接$R_1\bowtie R_2$</li><li>无公共变元, 等价于笛卡尔乘积$R_1\times R_2$</li></ul></li><li>$\phi_1\vee\phi_2$: $R_1\cup R_2$</li><li>$\phi_1\rightarrow\phi_2$: $R_2\div R_1$</li><li>$\neg\phi$: $(\prod^nD_i)-R$, $D_i$为第$i$个自由变元的值域</li><li>$\exists r(\phi)$: $\pi_{A_1,A_2,\cdots,A_k}(R)$</li><li>$\forall r(\phi)$: $R\div S$</li></ul></li></ul><h2 id="关系数据库语言SQL’92"><a href="#关系数据库语言SQL’92" class="headerlink" title="关系数据库语言SQL’92"></a>关系数据库语言SQL’92</h2><h3 id="SQL概貌"><a href="#SQL概貌" class="headerlink" title="SQL概貌"></a>SQL概貌</h3><ul><li>SQL的基本概念: 结构化查询语言<ul><li>使用方式  <ul><li>自含式: 独立的交互式命令行语言</li><li>嵌入式: 嵌入到某种高级语言当中</li></ul></li><li>基表: 关系</li><li>虚表(视图): 关系子模式</li><li>行: 元组</li><li>列: 属性</li></ul></li></ul><h3 id="SQL数据定义功能"><a href="#SQL数据定义功能" class="headerlink" title="SQL数据定义功能"></a>SQL数据定义功能</h3><blockquote><p>啥也没有?怎么回事啊, 算了写一点乱七八糟的吧</p><ul><li>创建基表<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> tabname &#123;</span><br><span class="line">  colname datatype <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">  colname2 datatype2</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ul></blockquote><ul><li><p>修改基表</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">ALTER</span> <span class="keyword">TABLE</span> tabname <span class="keyword">ADD</span> colname datatype</span><br><span class="line"><span class="keyword">ALTER</span> <span class="keyword">TABLE</span> tabname <span class="keyword">DROP</span> colname</span><br></pre></td></tr></table></figure></li><li><p>删除基表</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span> tabname</span><br></pre></td></tr></table></figure></li></ul><h3 id="SQL数据操纵功能"><a href="#SQL数据操纵功能" class="headerlink" title="SQL数据操纵功能"></a>SQL数据操纵功能</h3><ul><li>SQL语言与关系代数的关系</li><li>映像语句（select statement）的结构<ul><li>目标子句: <code>SELECT  * | colname { , colname ... }</code><blockquote><p>最后执行, 有排序时倒数第二执行</p></blockquote></li><li>范围子句: <code>FROM  tabname { , tabname ... }</code><blockquote><p>在SQL中, 这些表相当于被笛卡尔乘积连接, 因此联结时需要在where中给出条件</p></blockquote></li><li>条件子句: <code>[ WHERE  search_condition ]</code></li><li>分组子句: <code>[ GROUP BY  colname { , colname ... }</code></li><li>分组查询子句: <code>[ HAVING  group_condition ]</code></li><li>排序输出子句: <code>[ ORDER BY  colname [ ASC | DESC ] { , colname [ ASC | DESC ] ... } ]</code><blockquote><p>最后执行</p><ul><li>两个必须的子句: <code>select</code>/<code>from</code></li><li>having子句的前面必须有group by子句</li></ul></blockquote></li></ul></li><li>基本查询功能<ul><li>distinct谓词: <code>DISTINCT colname</code> 统计查询使用, 去重统计</li><li>LIKE: <code>colname [NOT] LIKE val1 [ESCAPE val2]</code><ul><li><code>val1</code>是模板, 其中<code>_</code>匹配任意一个字符, <code>%</code>匹配任意一个字符串</li><li><code>val2</code>定义转义指示字符, 跟在其后的, <code>val1</code>中的通配符和转义字符将表示原义</li></ul></li><li>IS NULL谓词: <code>colname IS [NOT] NULL</code>判断是否为NULL</li><li>多表联接查询: <code>WHERE</code>当中, 通过属性的相等, 实现表与表之间的连接</li><li>表的自联接查询: <code>tabname [[AS] alias]</code> 给表起别名</li></ul></li><li>嵌套查询<ul><li>IN: <code>expr [NOT] IN (subquery)</code>标量与集合量之间的属于比较</li><li>SOME/ANY/ALL: <code>expr θ SOME|ANY|ALL (subquery)</code>标量与集合中元素之间的量化比较</li><li>EXISTS: <code>[NOT] EXIST</code>是否为空集的判断谓词</li><li>相关子查询与独立子查询: 子查询内部引用了外部查询的表或元组变量, 因此每当外部取值变化, 都要再运行子查询</li></ul></li><li>子查询的合并: 带<code>ALL</code>意为允许重复<ul><li>UNION: <code>(subquery) UNION [ALL] (subquery)</code>并</li><li>INTERSECT: <code>(subquery) INTERSECT [ALL] (subquery)</code>交</li><li>EXCEPT: <code>(subquery) EXCEPT [ALL] (subquery)</code>减<!-- + 统计查询（GROUP BY和HAVING）：统计与分组统计查询；空值与空集在统计函数中的处理方法 --></li></ul></li><li><p>复杂数据查询</p><ul><li>统计查询<ul><li><code>COUNT(colname)</code>: 计数, 空值忽略<blockquote><p><code>COUNT(DISTINCT colname)</code>: 计数互不相同的值, 空值忽略</p></blockquote></li><li><code>SUM(colname)</code>: 求和, 空值忽略</li><li><code>AVG(colname)</code>: 求平均, 空值忽略</li><li><code>MIN(colname)</code>: 求最小, 空值忽略</li><li><code>MAX(colname)</code>: 求最大, 空值忽略</li></ul></li><li>分组统计查询: <code>GROUP BY colname {, colname}</code>按照<code>colname</code>的取值不同, 分组统计<blockquote><p><code>SELECT</code>当中必须包括<code>GROUP BY</code>当中的属性</p></blockquote></li><li>分组选择统计查询: <code>HAVING group_cond</code>必须先分组, 之后满足<code>group_confd</code>的组才会被保留</li><li><p>关系代数中的除法运算功能在SQL中的表示方法<br>待构造的除法: $\pi_{sno, cno}(SC)\div \pi_{cno}(C)$ </p><blockquote><p>语义: 对于符合要求的SC中sno, (对于任意的C中cno, 都有sno选修过cno的记录)<br>等价于: 对于符合要求的SC中元组S, 对于任意C中元组x, 都能找到元组y,使得y.sno=S.sno and y.cno=x.cno<br>任意-&gt;不存在不满足-&gt;不存在(不存在):</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">对SC中S, 不存在  </span><br><span class="line">  对C中x, 不存在</span><br><span class="line">    SC中的S-x元组y, 即y.sno=S.sno and y.cno=x.cno</span><br></pre></td></tr></table></figure></blockquote><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> <span class="keyword">DISTINCT</span> SC.sno                        <span class="comment"># </span></span><br><span class="line"><span class="keyword">FROM</span> SC S                                     <span class="comment"># 被除数当中的元组, 作为目标元组, 将目标属性传入(S.sno)</span></span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">NOT</span> <span class="keyword">EXISTS</span> (                            <span class="comment"># 不存在不满足条件的元组</span></span><br><span class="line">    <span class="keyword">SELECT</span> *                                  <span class="comment"># </span></span><br><span class="line">    <span class="keyword">FROM</span> C x                                  <span class="comment"># 除数当中的元组, 被要求对任意S.sno全都有</span></span><br><span class="line">    <span class="keyword">WHERE</span> <span class="keyword">NOT</span> <span class="keyword">EXISTS</span> (                        <span class="comment"># 为了表示"不满足", 构造对S.sno不含有, 即不存在满足的元组</span></span><br><span class="line">        <span class="keyword">SELECT</span> *                              <span class="comment"># </span></span><br><span class="line">        <span class="keyword">FROM</span> SC y                             <span class="comment"># 被除数元组的任意元组, 寻找满足的元组</span></span><br><span class="line">        <span class="keyword">WHERE</span> y.sno = S.sno <span class="keyword">AND</span> y.cno = x.cno <span class="comment"># 一个[除数,被除数]的元组, 两组相等关系, 分别约束: (对被除数进行查询), (对除数进行查询)</span></span><br><span class="line">    )                                         <span class="comment"># 这个子查询可以由NOT IN代替, 表示不含有</span></span><br><span class="line">)                                             <span class="comment">#</span></span><br></pre></td></tr></table></figure></li></ul><!-- + 多层嵌套的NOT EXISTS查询 --><ul><li>在FROM子句中嵌入子查询: <code>FROM (subquery) [[AS] alias]</code><br>&lt;!– + 查询结果输出</li><li>结果元组去重：distinct</li><li>结果元组排序：order by –&gt;</li></ul></li></ul><h3 id="SQL的更新功能"><a href="#SQL的更新功能" class="headerlink" title="SQL的更新功能"></a>SQL的更新功能</h3><ul><li>元组删除: <code>DELETE FROM tabname [WHERE cond]</code></li><li><p>元组插入: </p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> tabname [(colname &#123;,colname&#125;)]</span><br><span class="line"><span class="keyword">VALUES</span> (expr | <span class="literal">NULL</span> &#123;,expr | <span class="literal">NULL</span>&#125;) | (subquery)</span><br></pre></td></tr></table></figure></li><li><p>元组修改: </p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">UPDATE</span> tabname </span><br><span class="line"><span class="keyword">SET</span> colname=expr | <span class="literal">NULL</span> | subquery, ...</span><br><span class="line">[<span class="keyword">WHERE</span> cond]</span><br></pre></td></tr></table></figure></li></ul><h3 id="视图"><a href="#视图" class="headerlink" title="视图"></a>视图</h3><ul><li>视图概念: 若干张表经映像语句构筑而成的表(导出表)</li><li>视图与基表的区别: 同样有构造信息, 但视图不存储(虚表)</li><li>创建: <code>CREATE VIEW &lt;视图名&gt; [(&lt;列名&gt;{, &lt;列名&gt;})] AS &lt;映像语句&gt; [WITH CHECK OPTION]</code><blockquote><p>映像语句实际上就是子查询, CHECK OPTICON 不知道什么意思</p></blockquote></li><li>删除: <code>DROP VIEW &lt;视图名&gt;</code></li><li>视图的嵌套定义</li><li>视图删除中的连锁反应: 视图的删除操作时，将连带删除定义在该视图上的其它视图</li><li>可更新视图的判断准则: 视图每一行对应基表每一行, 视图每一列对应基表每一列</li><li>视图的作用: 提高数据独立性, 简化用户观点, 自动的安全保护</li></ul><h1 id="第四章-数据库的安全性与完整性保护"><a href="#第四章-数据库的安全性与完整性保护" class="headerlink" title="第四章:数据库的安全性与完整性保护"></a>第四章:数据库的安全性与完整性保护</h1><h2 id="数据库的安全性保护"><a href="#数据库的安全性保护" class="headerlink" title="数据库的安全性保护"></a>数据库的安全性保护</h2><ul><li>数据库安全的基本概念: 防止非法使用数据库(规定的途径和规则)<ul><li>主体: 数据访问者</li><li>客体: 数据及其载体</li><li>身份标识与鉴别: 主体具有标识符和口令</li><li>自主访问控制: 基于存取矩阵的安全控制模型(用户给定权限, 访问时检查权限)<blockquote><p>客体所有者(创建者)自动拥有全部权限, 有权限的可授予他人权限, 权限仅限这两种方法获得<br>登陆时检查: 是不是管理员-&gt;是不是所有者-&gt;有没有被授权<br>存储矩阵: 行标签: 客体; 列标签: 主体</p></blockquote></li><li>审计: 跟踪记录用户对数据的访问操作<blockquote><p>时间, 内容, 用户名, 终端名, 操作类型, 操作结果; 给出报警信息</p></blockquote></li></ul></li><li>SQL对数据库安全的支持<ul><li>SQL中的存取权限<blockquote><p>权限: SELECT INSERT DELETE UPDATE REFERENCE EXECUTE USAGE<br>对象: 表/视图 属性 域(数据类型) 存储过程/函数/触发器</p></blockquote></li><li>授权命令: <code>GRANT &lt;权限列表&gt; ON &lt;对象&gt; TO &lt;用户名列表&gt; [WITH GRANT OPTION]</code></li><li>回收命令: <code>REVOKE &lt;权限列表&gt; ON &lt;对象&gt; FROM &lt;用户名列表&gt; [RESTRICT | CASCADE]</code><blockquote><p>CASCADE连锁回收; RESTRICT不连锁才回收, 否则拒绝回收</p></blockquote></li></ul></li></ul><h2 id="数据库的完整性保护"><a href="#数据库的完整性保护" class="headerlink" title="数据库的完整性保护"></a>数据库的完整性保护</h2><ul><li>数据库完整性保护: 对数据库中数据的正确性和一致性的维护</li><li>功能: 设置功能; 检查功能; 处理功能</li><li>目的: 及时发现错误-&gt;防止错误的蔓延-&gt;恢复到正确状态</li><li>常用实现措施<ul><li>完整性约束条件的定义及检查</li><li>触发器</li><li>并发控制技术</li></ul></li><li>实体完整性: 关键字不为空</li><li>参照完整性: 不能引用不存在的实体(外关键字要么与被引相同, 要么为空值)</li><li>用户定义完整性: 用户自己定义</li><li>完整的CREATE TABLE命令<ul><li>基表的创建</li><li>完整性约束的定义：主关键字，外关键字，CHECK约束，UNIQUE，NOT NULL, DEFAULT<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&#123;  NOT NULL   |</span><br><span class="line">  [ CONSTRAINT constraint_name ] </span><br><span class="line"><span class="comment"># 给约束起名</span></span><br><span class="line">    UNIQUE</span><br><span class="line">    | PRIMARY KEY</span><br><span class="line">    | <span class="keyword">CHECK</span> ( search_condition )</span><br><span class="line">    | <span class="keyword">REFERENCES</span> table_name [ ( column_name ) ]</span><br><span class="line">    [ <span class="keyword">ON</span> <span class="keyword">DELETE</span> <span class="keyword">CASCADE</span> | RESTRICT | <span class="keyword">SET</span> <span class="literal">NULL</span> ]</span><br><span class="line">    [ <span class="keyword">ON</span> <span class="keyword">UPDATE</span> <span class="keyword">CASCADE</span> | RESTRICT | <span class="keyword">SET</span> <span class="literal">NULL</span> ] </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ul></li></ul><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">FOREIGN KEY ( colname &#123; , colname ... &#125; ) </span><br><span class="line"><span class="comment"># 定义主外键的引用关系</span></span><br><span class="line">  REFERENCES table_name [ ( colname &#123; ,colname... &#125; ) ] </span><br><span class="line">    </span><br><span class="line"><span class="comment"># 当在被引用表中删除元组或修改主键值时，需要维护引用表中外键值的正确性</span></span><br><span class="line">    [ ON <span class="keyword">DELETE</span> <span class="keyword">CASCADE</span> | RESTRICT | <span class="keyword">SET</span> <span class="literal">NULL</span> ]</span><br><span class="line">    [ <span class="keyword">ON</span> <span class="keyword">UPDATE</span> <span class="keyword">CASCADE</span> | RESTRICT | <span class="keyword">SET</span> <span class="literal">NULL</span> ]   &#125;</span><br><span class="line">    </span><br><span class="line"><span class="comment"># CASCADE 同步改变 | RESTRICT 拒绝(默认模式) | SET NULL 外键设为空</span></span><br></pre></td></tr></table></figure><ul><li>触发器: 在数据库系统中，一个事件的发生会导致另外一些事件的发生，这样的功能被称为触发器</li><li>创建命令<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TRIGGER</span> trigger_name &#123; <span class="keyword">BEFORE</span> | <span class="keyword">AFTER</span> &#125; </span><br><span class="line"><span class="comment"># 定义时机</span></span><br><span class="line">&#123; <span class="keyword">INSERT</span> | <span class="keyword">DELETE</span>                              </span><br><span class="line"><span class="comment"># 触发事件</span></span><br><span class="line">  | <span class="keyword">UPDATE</span> [ <span class="keyword">OF</span> colname &#123; , colname ... &#125; ] &#125;</span><br><span class="line">    <span class="keyword">ON</span> table_name </span><br><span class="line">  [ <span class="keyword">REFERENCING</span> corr_name_def &#123; , ...... &#125; ]</span><br><span class="line">  [ <span class="keyword">FOR</span> <span class="keyword">EACH</span> <span class="keyword">ROW</span> | <span class="keyword">FOR</span> <span class="keyword">EACH</span> <span class="keyword">STATEMENT</span> ]        </span><br><span class="line"><span class="comment"># 执行方式</span></span><br><span class="line">  [ <span class="keyword">WHEN</span> ( search_condition ) ]</span><br><span class="line">  &#123; <span class="keyword">statement</span>                                  </span><br><span class="line"><span class="comment"># 结果事件</span></span><br><span class="line">  | BEGIN ATOMIC statement; &#123; statement; ... &#125; END</span><br></pre></td></tr></table></figure></li></ul><h1 id="第五章-事务处理并发控制与故障恢复技术"><a href="#第五章-事务处理并发控制与故障恢复技术" class="headerlink" title="第五章:事务处理并发控制与故障恢复技术"></a>第五章:事务处理并发控制与故障恢复技术</h1><h2 id="事务处理（概念）"><a href="#事务处理（概念）" class="headerlink" title="事务处理（概念）"></a>事务处理（概念）</h2><ul><li>事务的定义: 某个用户所执行的一个不能被打断的对数据库的操作序列</li><li>ACID性质<ul><li>A原子性: 不可分割的操作序列, 要么全部, 要么不执行</li><li>C一致性: 执行前后都满足一致性</li><li>I隔离性: 并发结果与某种串行执行结果相同, 即相互独立</li><li>D持久性: 事务完成，它对数据库的所有更新应永久地反映在数据库中</li></ul></li><li>事务活动图<br><img src="01.png" alt="image"></li><li>状态转换图<br><img src="02.png" alt="image"></li><li>事务控制语句<ul><li>commit transaction</li><li>rollback transaction: 可以恢复到存在的保存点, 或者回到事务起点</li><li>savepoint: 设置保存点</li></ul></li><li>相关的参数设置语句<ul><li>自动提交: <code>SET AUTOCOMMIT ON|OFF</code></li><li>读写: <code>SET TRANSACTION READONLY|READWRITE</code></li><li>隔离级别: <code>SET TRANSACTION ISOLATION LEVEL READUNCOMMITTED|READCOMMITTED|   READREPEATABLE|SERIALIZABLE</code><blockquote><p>READUNCOMMITTED无封锁; READCOMMITTED读加共享锁到读完; READREPEATABLE读加共享锁到事务结束; SERIALIZABLE串行化调度执行</p></blockquote></li></ul></li><li>事务的语句组成成分: 开始, 结束(正常结束-&gt;提交事务, 非正常结束-&gt;回滚)</li></ul><h2 id="并发控制技术（概念）"><a href="#并发控制技术（概念）" class="headerlink" title="并发控制技术（概念）"></a>并发控制技术（概念）</h2><ul><li>事务<ul><li>事务的并发性: 数据库是一个多用户共享系统, 以事务为单位访问</li><li>并发控制: 实现多个用户事务的并发执行的技术</li><li>调度: DBMS中事务执行的操作序列, 按时间排序</li><li>串行调度: 做完一个接下一个事务(首先是一个事务的所有操作，然后是另一个事务的所有操作, 原句真啰嗦)</li><li>可串行化调度: 一个调度对数据库状态的影响和某个串行调度相同</li><li>冲突: 调度中一对相邻操作, 交换顺序，涉及的事务中至少有一个的行为会改变</li><li>冲突可串行化(可串行化的充分条件): 冲突可串行化调度”冲突等价”于一个串行调度<blockquote><p>冲突等价: 如果通过一系列相邻操作的非冲突交换能够将一个调度转换为另一个调度，则我们称这两个调度是冲突等价的</p></blockquote></li><li>视图可串行化: 视图可串行化调度”视图等价”于一个串行调度<blockquote><p>视图等价<br>  [视图等价]相同的一组事务，两个不同的调度S与H。S和H被称为“视图等价”当且仅当满足下列三个条件：<br>  对每一个数据项D<br>  如果在调度S中事务Tk读到D的初始值，则在调度H中事务Tk也必须读到D的初始值；<br>  如果在调度S中事务Tk执行了rk(D)，并且读到的是由事务Tj写入的D的值，则在调度H中事务Tk的rk(D)读到的也必须是由事务Tj 所写入的D的值；<br>  如果在调度S中是由事务Tk来执行最后一条关于D的写操作wk(D)，则在调度H中也一定是事务Tk执行最后一条关于D的写操作wk(D)。  </p></blockquote></li><li>冲突可串行化的判定方法: 事务优先图没环 <-> 是冲突可串行化  <blockquote><p>事务优先图<br>  优先: 给出的调度H中, 两个动作来自不同事务, 若其涉及同一个数据库对象且至少一个为写, 则这两个事务不可交换, 定义了优先关系<br>  优先关系画出有向图<br>盲写: 没读就写</p></blockquote></-></li><li>不正确的事务并发所导致的数据不一致现象</li></ul></li></ul><table><thead><tr><th>不一致现象</th><th>描述</th><th>原因</th></tr></thead><tbody><tr><td>丢失修改</td><td>一个修改破坏另一个修改结果</td><td>多个事务并发修改同一个数据</td></tr><tr><td>脏读</td><td>读到错误的数据</td><td>其他事务未提交的修改</td></tr><tr><td>不可重复读</td><td>前后两次读不一致</td><td>其他事务已提交的写操作</td></tr><tr><td>幻像读</td><td>一个事务中, 执行相同的查询多次, 结果不同</td><td>其他事务已提交的插入操作</td></tr></tbody></table><ul><li>封锁<ul><li>排它锁（X锁）: 一个对象同时只能上一次, 维持到事务结束<blockquote><p>自己可以读写, 别人啥也不行</p></blockquote></li><li>共享锁（S锁）: 可以与其他S锁并存<blockquote><p>全员只读</p></blockquote></li><li>锁申请: 能锁就锁, 锁了就睡, 被叫醒且能锁就锁</li><li>锁释放: 解锁, 唤醒</li><li>基于封锁技术的并发控制实现方法<ul><li>过程: 访问发给调度器-&gt;调度器申请锁, 封锁管理器-&gt;管理器返回结果-&gt;(成功, 操作发给执行引擎; 失败, 进队列)</li><li>三级封锁协议<ul><li>一级: 写之前加X锁, 事务结束释放</li><li>二级: 一级 + 读前加S锁, 读完释放</li><li>三级: 二级 + 读前加S锁, 事务结束释放</li></ul></li><li>三级封锁协议防止的不一致<ul><li>一级: 丢失修改</li><li>二级: 丢失修改, 脏读</li><li>三级: 丢失修改, 脏读, 不可重复读</li></ul></li><li>两阶段封锁协议<ul><li>一阶段: 申请整个过程需要的锁</li><li>二阶段: 释放所有锁, 不能再申请</li></ul></li><li>两阶段封锁协议与冲突可串行化的关系: 两阶段任意合法调度S都是冲突可串行化的</li></ul></li></ul></li><li>多粒度封锁<ul><li>封锁粒度/并发度/并发控制实现开销 之间的关系<ul><li>锁粒度大, 并发度低, 控制开销小</li><li>锁粒度小, 并发度高, 控制开销大</li></ul></li><li>多粒度封锁: 同时支持多种封锁粒度供事务选择</li><li>多粒度树: 按照封锁粒度的大小构造出一棵 ‘多粒度树’，以树中的每个结点作为封锁对象，可以构成一个‘多粒度封锁协议’</li><li>基于意向锁的多粒度封锁协议<ul><li>意向锁: 节点加意向锁, 其下层节点正被加锁(必须上层先加意向锁, 才能给下层加锁)<ul><li>IS: 下层打算加S</li><li>IX: 下层打算加X</li><li>SIX: 当前加S, 下层加X</li></ul></li><li>意向锁锁相容矩阵</li><li>意向锁锁申请算法，意向锁锁释放算法: 对任何一个节点加锁, 必须先对其父节点加意向锁(也就是从根开始加)</li></ul></li></ul></li></ul><table><thead><tr><th>已经有的锁</th><th>S</th><th>X</th><th>IS</th><th>IX</th><th>SIX</th><th></th></tr></thead><tbody><tr><td>已经持有S</td><td>✔</td><td></td><td>✔</td><td></td><td></td><td>S加了, 当前及其下层没有X</td></tr><tr><td>已经持有X</td><td></td><td></td><td></td><td></td><td></td><td>X排他, 加了别的都没有</td></tr><tr><td>已经持有IS</td><td>✔</td><td></td><td>✔</td><td>✔</td><td>✔</td><td>IS加了, 当前没X</td></tr><tr><td>已经持有IX</td><td></td><td></td><td>✔</td><td>✔</td><td></td><td>IX加了, 当前没S没X</td></tr><tr><td>已经持有SIX</td><td></td><td></td><td>✔</td><td></td><td></td><td>SIX加了, 相当于同时S和IX</td></tr></tbody></table><ul><li>死锁的检测与预防<ul><li>死锁: 每个事务持有部分锁, 循环等待</li><li>活锁: 有部分事务长期等待锁, 其他事务可以继续运行</li><li>死锁的检测及其处理办法<ul><li>等待图法</li><li>超时死锁检测法<ul><li>锁申请等待超时</li><li>事务执行超时</li></ul></li><li>时间戳死锁检测法: (时间戳反映事务已经执行的时间)当T要等待U持有的锁<ul><li>等待-死亡方案: T比U老, T等待; U比T老, 则T被回滚</li><li>伤害-等待方案: T比U老, U回滚; U比T老, T等待</li></ul></li></ul></li></ul></li></ul><h2 id="数据库恢复技术"><a href="#数据库恢复技术" class="headerlink" title="数据库恢复技术"></a>数据库恢复技术</h2><ul><li>数据库恢复的含义: 在数据库遭受破坏后及时进行恢复的功能</li><li>方法: 不同介质上冗余存储，利用冗余信息恢复</li><li>常用措施: 数据转储, 日志, 数据库镜像</li><li>数据库故障的分类<ul><li>小型: 事务内部故障, 不影响系统</li><li>中型: 系统停止, 磁盘不坏, 重启靠日志能恢复<ul><li>系统故障</li><li>外部影响</li></ul></li><li>大型: 内存磁盘严重破坏, 需要彻底恢复<ul><li>磁盘故障</li><li>计算机病毒</li><li>黑客入侵</li></ul></li></ul></li><li>数据库故障恢复三大技术<ul><li>数据转储: 定期将数据库中的内容复制到其它存储设备中去的过程</li><li>日志: 自动记载数据库中修改型操作的数据更新情况的文件</li><li>数据库镜像: 整个数据库中的数据实时复制到另一个磁盘</li></ul></li><li>数据转储<ul><li>静态转储</li><li>动态转储: 修改前记录原值<blockquote><p>需要结合日志恢复(记录转储开始和结束点, 事务更新的对象和前后值, 事务结束状态)</p></blockquote></li><li>海量转储</li><li>增量转储</li></ul></li><li>日志：<ul><li>内容: 事务标识、更新对象、更新前的值 和/或 更新后的值; 每个事务执行情况; 其他</li><li>组成: 日志记录 的序列, 并发时, 各个事务的日志是交错的</li><li>作用: 确保原子性, 实现增量转储, 实现故障恢复</li><li>记载原则: 操作执行的先后次序, 先写日志, 后修改数据库</li><li>在日志中设置检查点的作用: 降低数据库故障恢复的开销, 到<code>&lt;CKPT&gt;</code>就可以结束恢复过程<ul><li>停止接收新任务 -&gt; 等待当前所有事物提交或终止 -&gt; 刷新日志到磁盘</li><li>写入<code>&lt;CKPT&gt;</code> -&gt; 刷新日志到磁盘</li><li>继续接收新事务</li></ul></li><li>事务的撤销（UNDO）与重做（REDO）</li><li>UNDO日志<ul><li>UNDO日志的内容<ul><li>开始事务: <code>&lt;Start T&gt;</code></li><li>提交事务: <code>&lt;Commit T&gt;</code></li><li>放弃事务: <code>&lt;Abort T&gt;</code></li><li>更新记录: <code>&lt;T, X, V&gt;</code>事务T修改了X, 原值是V</li></ul></li><li>记载规则: 更新记录 先于 更新操作; 事务提交 先于 提交日志</li><li>作用: 用于被放弃事务(故障时中断的事务)的撤消工作</li><li>基于UNDO日志的故障恢复流程<ul><li>从后向前扫, 对每一个<code>&lt;T, X, V&gt;</code>:<ul><li>若<code>&lt;Commit T&gt;</code>被扫到过, 则继续扫</li><li>否则将X改成V</li></ul></li><li>日志尾部为所有未结束事务写入<code>&lt;Abort T&gt;</code>, 刷新日志</li></ul></li></ul></li><li>REDO日志<ul><li>REDO日志的内容: 跟UNDO一样, 唯一不同: 更新记录<code>&lt;T, X, V&gt;</code>中记载的是更新后的值</li><li>记载规则: 修改前, 必须有更新记录和事务提交记录</li><li>作用: 已提交事务的重做工作</li><li>基于REDO日志的故障恢复流程<ul><li>确定所有已提交的事务</li><li>从前向后扫, 对每条更新<ul><li>如果未提交, 继续扫</li><li>如果提交了, 写入新值</li></ul></li><li>日志尾部为所有未结束事务写入<code>&lt;Abort T&gt;</code>, 刷新日志</li></ul></li></ul></li><li>UNDO/REDO日志<ul><li>UNDO/REDO日志的内容: 跟UNDO一样, 唯一不同: 更新记录<code>&lt;T, X, V, W&gt;</code>中记载前与后的值</li><li>记载规则: 修改前需要有更新记录</li><li>作用: 兼有两者</li><li>基于UNDO/REDO日志的故障恢复流程<ul><li>根据提交记录, 确定事务是否被提交<ul><li>按照从后往前的顺序，撤消(undo)所有未提交的事务</li><li>按照从前往后的顺序，重做(redo)所有已提交的事务<!-- + UNDO日志、REDO日志、UNDO/REDO日志的优点与缺点 --></li></ul></li></ul></li></ul></li></ul></li><li>恢复策略<ul><li>小型: 未结束的事务的undo</li><li>中型: 非正常终止: undo; 完成提交: redo</li><li>大型: 先用后备副本恢复, 之后用日志undo + redo</li></ul></li></ul><h1 id="第六章-amp-第七章"><a href="#第六章-amp-第七章" class="headerlink" title="第六章&amp;第七章"></a>第六章&amp;第七章</h1><ul><li><p>游标管理</p><ul><li>游标的作用: 集合量逐个取出后送入应用程序变量内供其使用</li><li><p>定义: 查询结果为多个元组时, 必须使用游标获取每个元组</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">EXEC SQL <span class="keyword">DECLARE</span> <span class="keyword">cursor</span>-<span class="keyword">name</span> <span class="keyword">CURSOR</span> <span class="keyword">FOR</span></span><br><span class="line">subquery</span><br><span class="line">[ <span class="keyword">ORDER</span> <span class="keyword">BY</span> ...... ]</span><br><span class="line">[ <span class="keyword">FOR</span> &#123; <span class="keyword">READ</span> <span class="keyword">ONLY</span> |</span><br><span class="line">   <span class="keyword">UPDATE</span> [ <span class="keyword">OF</span> columnname, ...... ] &#125; ] ;</span><br></pre></td></tr></table></figure></li><li><p>打开: <code>EXEC  SQL  OPEN agent_dollars</code></p></li><li><p>使用</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">while (TRUE) &#123;/* loop to fetch rows */</span><br><span class="line">    exec  sql  fetch agent_dollars</span><br><span class="line">                     into :agent_id, :dollar_sum;</span><br><span class="line"></span><br><span class="line">    printf("%s %11.2f\n", agent_id, dollar_sum);</span><br><span class="line">&#125;/* end fetch loop */</span><br></pre></td></tr></table></figure></li><li><p>关闭: <code>exec  sql  whenever  not  found  goto  finish</code>定义结束, <code>exec  sql  close  agent_dollars</code>关闭游标</p></li><li><p>可滚动游标的定义</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">EXEC  SQL  <span class="keyword">DECLARE</span>  cursor_name</span><br><span class="line">  [ INSENSITIVE ]  [ <span class="keyword">SCROLL</span> ]</span><br><span class="line">  <span class="keyword">CURSOR</span>  [ <span class="keyword">WITH</span>  HOLD ]  <span class="keyword">FOR</span></span><br><span class="line">    subquery  &#123; <span class="keyword">UNION</span>  subquery &#125;</span><br><span class="line">    [ <span class="keyword">ORDER</span>  <span class="keyword">BY</span> ...... ]</span><br><span class="line">  [ <span class="keyword">FOR</span>  <span class="keyword">READ</span>  <span class="keyword">ONLY</span>  |</span><br><span class="line">    <span class="keyword">FOR</span>  <span class="keyword">UPDATE</span>  <span class="keyword">OF</span>  columnname ...... ];</span><br></pre></td></tr></table></figure></li><li><p>在数据更新命令中的使用</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">EXEC  SQL  FETCH</span><br><span class="line">  [ &#123; NEXT | PRIOR | FIRST | LAST |</span><br><span class="line">    &#123; ABSOLUTE | RELATIVE &#125; value_spec &#125; FROM ]</span><br><span class="line">  cursor_name INTO ......;</span><br></pre></td></tr></table></figure></li></ul></li><li><p>索引 (index)</p><ul><li>B+索引的数据结构: 定义秩为n<ul><li>结点: 取m&lt;=n, 结点含有m个键$K_i$和m+1个指针$P_i$, 五花肉式存放,</li><li>约束<ul><li>叶节点: $\lfloor (n+1)/2\rfloor\leq m\leq n$, $P_i$指向$K_i$, $P_{m+1}$指向下一个叶子</li><li>根结点: $1\leq m\leq n$; 内部结点: $\lceil (n-1)/2\rceil\leq m\leq n$, $P_i$均指向子树根节点</li></ul></li><li>性质<ul><li>非叶节点, 在$P_i$所指子树的任意关键字$K$, 有$K_{i-1}\leq K&lt; K_i$</li><li>只有一个结点, 则根节点也是叶节点; 否则, 根节点跟内部节点类似</li></ul></li></ul></li><li>搜索算法<ul><li>随机查找<ul><li>结点上的关键字划分了值域, 层层向下在相应区间中搜索合适的叶节点, 最后在叶结点遍历搜索</li></ul></li><li>区间查找<ul><li>先找区间下限a, 之后在叶节点(类似链表)中遍历, 直到超过上限b</li></ul></li></ul></li></ul></li></ul><h1 id="第八章-关系数据库规范化理论"><a href="#第八章-关系数据库规范化理论" class="headerlink" title="第八章:关系数据库规范化理论"></a>第八章:关系数据库规范化理论</h1><h2 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h2><ul><li>模式设计质量的评价指标<ul><li>数据冗余度: 合理的数据冗余度</li><li>插入/删除等更新异常: 没有插入和删除操作异常<!-- + 为什么要研究关系的规划化设计：规范化的目的与手段: 按照给定范式要求设计关系模式 --></li></ul></li><li>关系的规范化<ul><li>按照给定范式要求设计关系模式</li><li>范式: 对一个关系中允许存在的函数依赖的要求<h2 id="规范化理论"><a href="#规范化理论" class="headerlink" title="规范化理论"></a>规范化理论</h2></li></ul></li></ul><h3 id="函数依赖（FD）"><a href="#函数依赖（FD）" class="headerlink" title="函数依赖（FD）"></a>函数依赖（FD）</h3><ul><li>函数依赖: 一个关系中 两组属性之间的 取值约束<ul><li>表示: $X\to Y$: $Y$函数依赖于$X$</li><li>直观: 在关系$R$中, 每个$X$的值都有唯一的一个$Y$值与之对应</li><li>定义: 关系模式$R(U)$中, 关系$r$中元组$r_i$在$X$中的取值确定后, $Y$中取值必被确定, 则$X\to Y$</li><li>$X$决定因素, $Y$依赖因素</li></ul></li><li>发现函数依赖<ul><li>直接根据语义</li><li>根据取值对应关系<ul><li>一一对应: $X\to Y$, $Y\to X$</li><li>一多对应/多一对应: $Y\to X$, $X\to Y$</li><li>多多对应: 没有</li></ul></li></ul></li><li>平凡函数依赖<ul><li>非平凡函数依赖: $X\to Y, Y\not\subseteq X$, 默认是这个</li><li>平凡函数依赖: 反之</li></ul></li><li>完全函数依赖<ul><li>完全函数依赖: $X\to Y, \forall X’\subset X, X’\not\to Y$, 则$X\overset{f}{\to}Y$</li><li>部分函数依赖: $X\to Y, \exists X’\subset X, X’\to Y$, 则$X\overset{p}{\to}Y$</li></ul></li><li>传递函数依赖<ul><li>$X\to Y, Y\not\subset X, Y\not\to X, Y\to Z$, 则 $X\to Z$为传递函数依赖</li></ul></li><li>Armstrong公理系统<ul><li>基本规则<ul><li>自反规则: $Y\subseteq X$, 则$X\to Y$</li><li>增广规则: $X\to Y$, 则$XZ\to YZ$</li><li>传递规则: $X\to Y\wedge Y\to Z$, 则$X\to Z$</li></ul></li><li>扩充规则<ul><li>分解规则: $X\to YZ$, 则$X\to Y\wedge X\to Z$</li><li>合并规则: $X\to Y\wedge X\to Z$则$X\to YZ$</li><li>伪传递规则: $X\to Y\wedge WY\to Z$, 则$WX\to Z$</li></ul></li></ul></li><li>函数依赖的逻辑蕴含概念<ul><li>$F$为关系模式$R(U)$的一个函数依赖集</li><li>从已有的函数依赖出发, 利用公理系统可以推导出$X\to Y$, 则$F\vDash X\to Y$</li></ul></li><li>函数依赖集$F$的闭包$F^+$: $F^+=\{X\to Y|F\vDash X\to Y\}$</li><li>函数依赖集的等价<ul><li>可以互相推导出其中的函数依赖</li></ul></li><li>属性集$X$在函数依赖集$F^+$上的闭包$X_F^+$: $X_F^+=\{A|F\vDash X\to A\}$<ul><li>[解题] 计算闭包<ul><li>$X^+=X$</li><li>不断重复: 对每一个$F$中的依赖$Y\to Z$, 若$Y\subseteq X^+$, 则$X^+ = X^+ \cup Z$</li><li>直到不再变化</li></ul></li></ul></li><li>关键字<ul><li>若$K\subseteq U, K\overset{f}{\to}U$, 则$K$是$R$的关键字</li><li>主属性集: 所有关键字中的属性构成的集合</li><li>非主属性集: 不属于任何一个关键字的属性构成的集合</li><li>关键字与闭包: $K_F^+=U$, $\forall Z\subset F, Z_F^+\ne U$</li><li>[解题] 寻找关键字<ul><li>计算最小依赖集</li><li>不断重复从$U$中删除属性, 直到其闭包不等X于$U$</li><li>将得到一个关键字</li><li>技巧<ul><li>只在左边出现过的属性 属于 每一个关键字</li><li>只在右边出现过的属性 不属于 任何一个关键字</li><li>只需要对两边都有的属性尝试删除即可</li></ul></li></ul></li></ul></li></ul><h3 id="与函数依赖有关的范式"><a href="#与函数依赖有关的范式" class="headerlink" title="与函数依赖有关的范式"></a>与函数依赖有关的范式</h3><ul><li>模式分解<ul><li>分解结果: 子关系模式, 满足<ul><li>$\textrm{Head}(R)=\bigcup^n\textrm{Head}(R_i)$</li><li>$F_i=\{X\to Y|X\to Y\in F^+ \wedge (X\cup Y)\in \textrm{Head}(R_i)\}$</li></ul></li><li>分解方法<ul><li>找出所有不满足范式的依赖</li><li>选择一个依赖, 设$X\overset{f}{\to}Y$为这个依赖, 则将这个依赖所在的关系$R$分解为<ul><li>$R_1=\{X\cup Y, \{X\to Y\}\}$</li><li>$R_2=\{\textrm{Head}(R)-Y, F_2\}$</li><li>其中$F_2=\{A\to B|A\to B\in F^+\wedge (A\cup B)\subseteq \textrm{Head}(R_2)\}$</li></ul></li></ul></li></ul></li><li>1NF: 属性值不可分割, 全都满足</li><li>2NF: 满足1NF, 每个非主属性都完全依赖于关键字<ul><li>检查:<ul><li>找到所有非主属性 和 所有候选关键字</li><li>检查每一个非主属性$A$和每一个候选关键字$K$之间的函数依赖, 看看有没有部分依赖</li></ul></li></ul></li><li>3NF: 满足2NF, 每个非主属性都不传递依赖于关键字<ul><li>检查: 不满足3NF, 则必然存在下列情况之一, 其中$X\overset{f}{\to} Y$<ul><li>$X$是某个关键字的真子集</li><li>$X$不是关键字</li></ul></li></ul></li><li>BCNF: 满足1NF, 若$X\to Y$则$X$必含有该模式的关键字<ul><li>检查: 每个函数依赖, 是否满足$X$是关键字</li><li>BCNF -&gt; 3NF</li></ul></li><li>理解各级范式与数据冗余度、插入/删除异常的关系<ul><li>插入删除异常: 3NF消除异常</li><li>冗余: 2NF存在冗余, 3NF冗余较小</li></ul></li></ul><h3 id="多值依赖与第四范式"><a href="#多值依赖与第四范式" class="headerlink" title="多值依赖与第四范式"></a>多值依赖与第四范式</h3><ul><li>多值依赖: $X\to\to Y$<ul><li>定义: 对$X$的一个取值, 存在一组$Y$与其对应; $Y$的取值与$U-X-Y$不相关</li><li>成因: 两个一对多关系$C\to T$, $C\to L$, 其合并后$T$与$L$就是多值依赖</li><li>平凡多值依赖<ul><li>非平凡多值依赖: $U-X-Y$不为空集</li><li>平凡多值依赖: 反之</li></ul></li></ul></li><li>多值依赖有关的推理规则(需要掌握)<ul><li>求补规则: 若$X\to\to Y$, 则$U-X-Y\to\to Y$</li><li>转换规则: 若$X\to Y$, 则$X\to\to Y$</li></ul></li><li>4NF<ul><li>定义: 若$X\to\to Y$是非平凡多值依赖, 则$X$必含有关键字</li><li>特点: 函数依赖需要满足BCNF; 不是函数依赖的多值依赖只有平凡多值依赖</li></ul></li></ul><h2 id="规范化所引起的一些问题"><a href="#规范化所引起的一些问题" class="headerlink" title="规范化所引起的一些问题"></a>规范化所引起的一些问题</h2><ul><li>函数依赖的逻辑蕴涵: 函数依赖集的逻辑蕴含</li><li>函数依赖集的等价: 可以互相推导出其中的函数依赖</li><li>最小函数依赖集<ul><li>与$F$等价的, 最小的集合</li></ul></li><li>最小函数依赖集的计算算法<ul><li>首先得到题目中的所有函数依赖, 分解成右端只有一个的依赖</li><li>消除部分函数依赖: 右边相同, 左边更多; 左边含右</li><li>消除冗余函数依赖: 能推导就是冗余</li><li>合并依赖</li></ul></li><li>无损联结性<ul><li>设$\rho=\{R_1,\cdots,R_k\}$是对$R$的一个分解</li><li>如果对每个满足$F$的关系实例$r$都满足$r=\pi_{R_1}(r)\Join\cdots\Join\pi_{R_k}(r)$</li><li>则$\rho$是无损联接分解</li><li>充要条件($\rho=\{R_1,R_2\}$)<ul><li>$R_1\cap R_2\to (R_1-R_2)$ 或 $R_1\cap R_2\to (R_2-R_1)$</li></ul></li></ul></li><li>依赖保持性<ul><li>表示$\pi_Z(F)=\{X\to Y|X\to Y\in F^+\wedge (X\cup Y)\subseteq Z\}$</li><li>$F^+=(\pi_{R_1}(F)\cup\cdots\cup\pi_{R_1}(F))^+$</li></ul></li><li>直接到3NF且满足无损联结性和依赖保持性的模式分解算法<ul><li>计算最小依赖集, 代替$F$进行分解</li><li>$S=\emptyset$</li><li>对每一个函数$X\to Y$依赖进行<ul><li>若在$S$中找不到子关系模式$Z$, 使得$X\cup Y\subseteq\textrm{Head}(Z)$</li><li>$X$和$Y$合并成新的子关系模式, 加入$S$</li></ul></li><li>如果$R$中的每个候选关键字$K$均不在$S$中, 则任选一个关键字, 其属性单独构成一个子关系模式, 加入$S$</li></ul></li><li>从3NF到BCNF、4NF的分解方法<ul><li>找不满足所求NF的函数依赖(多值依赖), 分解之</li></ul></li></ul><h1 id="第九章-数据库设计"><a href="#第九章-数据库设计" class="headerlink" title="第九章:数据库设计"></a>第九章:数据库设计</h1><h2 id="数据库设计概述"><a href="#数据库设计概述" class="headerlink" title="数据库设计概述"></a>数据库设计概述</h2><ul><li>数据库设计的基本任务<ul><li>根据用户对象的信息需求、处理需求和数据库的支持环境（包括硬件、操作系统与DBMS）设计出数据模式</li></ul></li><li>数据库的生命周期<ul><li>需求分析: 数据库设计的第1阶段</li><li>概念设计: 数据库设计的第2阶段</li><li>逻辑设计: 数据库设计的第3阶段 &lt;—– DBMS模型</li><li>物理设计: 数据库设计的第4阶段 &lt;—– 软件, 硬件和网络</li><li>编码</li><li>测试</li><li>运行</li><li>进一步修改</li></ul></li></ul><h2 id="数据库设计的需求分析"><a href="#数据库设计的需求分析" class="headerlink" title="数据库设计的需求分析"></a>数据库设计的需求分析</h2><ul><li>需求说明书<ul><li>用户单位对数据的需求 -&gt;</li><li>需求分析(确定数据库中保存信息的客观事物和相互关系) -&gt;<ul><li>事物, 事物属性, 事物关系</li></ul></li><li>需求分析说明书</li></ul></li></ul><h2 id="数据库的概念设计"><a href="#数据库的概念设计" class="headerlink" title="数据库的概念设计"></a>数据库的概念设计</h2><ul><li>数据库概念设计的过程<ul><li>用户分解: 用户 -&gt; 功能独立的用户组</li><li>视图设计: 根据用户需求设计视图</li><li>视图集成: 局部视图*n -&gt; 全局视图</li></ul></li><li>E-R模型: 实体，属性，联系</li><li>EE-R模型: E-R + 嵌套（实体集属性）、继承</li></ul><h2 id="数据库的逻辑设计"><a href="#数据库的逻辑设计" class="headerlink" title="数据库的逻辑设计"></a>数据库的逻辑设计</h2><ul><li>从E－R模型和扩充E－R模型向关系模型的转换<ul><li>实体集: 关系模式</li><li>联系: 关系</li></ul></li><li>对转换得到的关系模式进行规范化设计<ul><li>根据给定的数据完整性约束发现函数依赖（最小函数依赖集）: 第八章内容</li><li>关键字的计算: 第八章内容</li><li>范式的判断及分解: 第八章内容, 至少满足3NF才行</li></ul></li></ul><h2 id="数据库的物理设计"><a href="#数据库的物理设计" class="headerlink" title="数据库的物理设计"></a>数据库的物理设计</h2><ul><li>索引: 将文件中的记录与其物理地址(即磁盘块)间建立一张对应关系表</li><li>作用: 加速</li><li>设计策略<ul><li>在主关键字及外关键字上建立索引: 提速联接查询; 利于检查完整性</li><li>读为主的关系应尽可能多地建立索引</li><li>属性的等值查询所得到的结果元组数量较少，则可以考虑对该属性建立索引</li><li>经常用于统计查询的属性建立索引</li></ul></li></ul><h1 id="答题解法"><a href="#答题解法" class="headerlink" title="答题解法"></a>答题解法</h1><h2 id="数据库设计-ER图"><a href="#数据库设计-ER图" class="headerlink" title="数据库设计(ER图)"></a>数据库设计(ER图)</h2><ul><li>基本概念表示: 图形内写名称<ul><li>实体集: 矩形框</li><li>属性: 椭圆<ul><li>关键字: 椭圆, 属性名加下划线</li></ul></li><li>联系: 菱形框</li></ul></li><li>连线与标注<ul><li>属性与实体: 无向线段, 一个实体<->多个属性; 连线上标注 属性基数( , )</-></li><li>联系上的属性: 无向线段, 一个联系<->多个属性; 因联系而产生的属性</-></li><li>实体与联系: 无向线段, 多个实体<->多个联系; 连线上标注 参与基数( , )<!-- > 弱实体: 有向线段, 弱实体->依赖关系(联系)   --><!-- > 继承: 子集->超集 --></-></li></ul></li><li>其他<ul><li>联系上有太多属性和实体, 可以把这个联系变成实体, 与实体的连线变成新的联系</li></ul></li></ul><h2 id="关系代数和关系演算"><a href="#关系代数和关系演算" class="headerlink" title="关系代数和关系演算"></a>关系代数和关系演算</h2><h3 id="关系代数"><a href="#关系代数" class="headerlink" title="关系代数"></a>关系代数</h3><ul><li>解题步骤<ul><li>确定查询目标（结果关系中的属性）</li><li>明确查询条件</li><li>选择从条件到目标的查找路径，并据此确定操作对象，即: <ul><li>在操作过程中需要使用到那些关系?</li><li>这些关系又是如何被联接成一个关系的?</li></ul></li><li>关系的合并<ul><li>根据步骤 3) 的分析结果进行关系的联接</li></ul></li><li>元组的选择<ul><li>根据步骤 2) 的分析结果(查询条件)进行元组的选择: 用不着的尽快投影掉, 夜长梦多警告</li></ul></li><li>属性的指定<ul><li>根据步骤 1) 的分析结果执行投影操作: 别tm漏属性啊啊啊啊啊啊</li></ul></li></ul></li><li>解题技巧<ul><li>“所有A都…的B”, 用除法, 被除的对象应当先投影, 以免遗漏</li><li>用公共属性查私有属性, 先笛卡尔积, 之后用选择, 条件设为同名属性取值相等, 最后投影</li><li>正面难构造, 就构造反面, 然后用笛卡尔积减去反面</li><li>最大值最小值, 例子: 取C中最大, C为key-value对<br>$$D := C$$<br>$$M = C - \pi_{C.key,C.val}\sigma_{C.val &lt; D.val}(C\times D)$$<br>原理: 每取值跟所有取值比较, 存在更大就会保留, 找出所有的非最大值, 之后减去</li><li>同时满足多个条件, 则取交; 满足多个条件中的一个, 则取并</li><li>联接可以实现”之一”的效果, 也可以实现相等关系</li><li>差运算<ul><li>当查询条件带有‘否定’语义，或者具有明显的‘排它性’的时候，通常需要使用两个子查询之间的‘差’运算</li><li>‘差’运算的运算对象（关系）中，通常需要包含其关键字</li></ul></li><li>“笛卡尔积/θ-连接/自然连接”的使用方法<ul><li>都是关系的合并运算<ul><li>笛卡尔积是基本运算，θ-连接和自然连接则是扩充运算, 请注意三者的结果关系的关系模式之间的区别</li></ul></li><li>笛卡尔积<ul><li>是实现跨不同关系表进行数据访问的基础, 在笛卡尔积的结果关系中，存在着很多无意义的结果元组，通常需要通过后续的选择运算过滤掉</li></ul></li><li>θ-连接<ul><li><strong>相邻的“笛卡尔积+选择运算”可以合并为一个θ-连接</strong></li></ul></li><li>自然连接<ul><li>如果连接条件是基于“两张表中的所有同名属性的相等比较”，可以将θ-连接进一步简写为自然连接</li></ul></li><li>一般方法: 笛卡尔积+选择  or  θ-连接<ul><li>不存在同名属性，或者连接条件不是基于同名属性的相等比较</li><li>在结果关系中可能存在同名属性，需要加以区别</li></ul></li><li>常用方法: 自然连接<ul><li>连接条件是隐含的（所有同名属性的相等比较）</li><li>如果在两个关系之间存在多对‘同名属性’，而本次查询又不需要‘所有’的同名属性都相等，此时有两种选择: </li><li>采用前述的一般方法来实现关系的合并</li><li><strong>先对其中的一个关系执行投影运算</strong>，过滤掉其中不需要相等的那些同名属性，然后再使用自然连接运算</li></ul></li><li>难点: 关系的自连接<ul><li>使用<strong>赋值运算定义‘同质不同名’的两个中间关系</strong>(元组集合相同，但关系名不同)，当然也可以对中间关系中的属性进行重命名</li><li>然后再使用前述的一般方法实现两个中间关系的合并</li></ul></li></ul></li><li>除<ul><li>‘除’ 运算与‘联接’运算的区别</li><li>我们将查询的结果关系称为‘目标对象’，用于定义查询条件的关系称为‘条件对象’</li><li>在决定某个元组t是否属于结果关系时，<ul><li>如果只需要从条件对象中找到<strong>一个元组</strong>c并使得查询条件成立，那么就直接使用‘联接’运算（包括笛卡尔积、θ-连接和自然连接）</li><li>如果需要条件对象集中的<strong>所有元组</strong>都能使得查询条件成立，那么就使用‘除’运算</li></ul></li><li>‘除’ 运算表达式的表示方法<ul><li>被除数关系中必须包含目标对象和条件对象的<strong>关键字</strong></li><li>除数关系中只含条件对象的关键字</li><li>被除数和除数关系中<strong>不能含其它‘不必要’的多余属性</strong>, 先投影再除</li></ul></li></ul></li></ul></li></ul><h3 id="关系演算-1"><a href="#关系演算-1" class="headerlink" title="关系演算"></a>关系演算</h3><ul><li>从关系代数进行转换<ul><li>基于关系演算的数据查询表示</li><li>投影<br>$$\pi_{A_{1},A_{2},\cdots,A_{k}}(R)=\exists x_{k+1},x_{k+2},\cdots ,x_n(R(x_1,x_2,\cdots,x_n))$$</li><li>选择<br>$$\sigma_F(R)=R(x_1,x_2,\cdots,x_n)\wedge F$$<ul><li>相等比较可以直接用常量代替: $\sigma_{x_1=’a’}(R)=R(‘a’,x_2,\cdots,x_n)\wedge F$</li></ul></li><li>笛卡尔积<br>$$R\times S = R(p)\wedge S(q)$$</li><li>$\theta$-联接<br>$$R\underset{F}{\bowtie} S = R(p)\wedge S(q)\wedge F$$</li><li>自然联接<br>$$R\bowtie S = R(x,y,z)\wedge S(t,u,v)$$</li><li>自联接, 重命名<br>$$R(x, g_1)\wedge R(x, g_2)$$</li><li>除法<br>$$R\div S=\forall y(S(y)\rightarrow R(x,y))$$</li><li>删除<br>$$R-S = R(u)\wedge \neg S(u)$$</li><li>插入<br>$$R\cup S = R(t)\vee S(t)$$</li><li>修改 = 删除再插入</li></ul></li><li>直接构造: 不会玩<ul><li>根据题目中的约束, 直接构造公式, 约束元组</li><li>刚刚才学到的技巧：蕴含<ul><li>之前说是除法嘛, 其实不仅仅是除法, 表示 任意-都/仅仅 都可以</li><li>在全称量词后面, 使用蕴含, 记得把蕴含条件的多余变元先 存在掉, 只留下前面限定过的(之前有谓词/量词), 被蕴含的那个也是</li><li>全称蕴含外面, 有必要的话, 再补一个谓词</li><li>别TM在全称里面用 且, 根本不可能满足的</li></ul></li></ul></li></ul><h2 id="规范化设计"><a href="#规范化设计" class="headerlink" title="规范化设计"></a>规范化设计</h2><h3 id="函数依赖"><a href="#函数依赖" class="headerlink" title="函数依赖"></a>函数依赖</h3><ul><li>找函数依赖: 随缘, 真的很迷, 不考虑常识, 做卷子的一点体会<ul><li>一对多, 多-&gt;一应该有一个函数依赖</li><li>一对一, 2个依赖妥妥的</li><li>多值依赖: 两个一多, 这里可能会有一个多值依赖, 那两个一之间</li></ul></li><li>最小依赖集<ul><li>拆 -&gt; 消部分/平凡 -&gt; 消冗余(楞猜) -&gt; 合并</li></ul></li><li>关键字<ul><li>只在左, 必在关键字; 只在右, 不在关键字; 都有, 挨个讨论<h3 id="规范化设计-1"><a href="#规范化设计-1" class="headerlink" title="规范化设计"></a>规范化设计</h3></li></ul></li><li>条件: 关键在于非主属性(不在任何关键字的属性)<ul><li>不满足2NF: 非主属性依赖于一个关键字的子集</li><li>不满足3NF: 非主属性依赖于一个关键字的子集 或 非主属性依赖于非关键字</li><li>不满足4NF: 能找到多值依赖(非平凡)</li><li>不满足BCNF: 任何依赖左边不是其关键字</li></ul></li><li>注意!分解得到的新关系, 得重新找关键字和非主属性, 在判断满不满足更高要求的范式</li></ul><h2 id="事务和并发"><a href="#事务和并发" class="headerlink" title="事务和并发"></a>事务和并发</h2><h3 id="能不能冲突串行"><a href="#能不能冲突串行" class="headerlink" title="能不能冲突串行"></a>能不能冲突串行</h3><ul><li>优先图: 顶点是事务, 有向边是优先关系</li><li>找出全部对象, 对每个对象<ul><li>列出所有对这个对象的操作, 看每一对相邻的操作</li><li>有至少一个是写操作, 则构成一个优先关系, 优先图画一个有向边</li></ul></li><li>图中有向边有环, 则不能冲突串行化, 否则可以, 按照图中的偏序关系, 依次执行各个事务就得到可行的串行调度<h3 id="能不能视图串行"><a href="#能不能视图串行" class="headerlink" title="能不能视图串行"></a>能不能视图串行</h3></li><li>整一个串行调度出来, 一般按照每个对象谁先读, 定一个初步的优先关系</li><li>三个条件, 若原调度视图等价于这个串行调度, 那就视图可串行<ul><li>对每个对象, 哪个事务读初始值, 两个调度一样</li><li>对每个事务的每次读, 两个调度的读取结果一样(指来自同一个事务的同一次写)</li><li>对每个对象, 哪个事务最后写, 两个调度一样</li></ul></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;第一章-数据库系统概述&quot;&gt;&lt;a href=&quot;#第一章-数据库系统概述&quot; class=&quot;headerlink&quot; title=&quot;第一章:数据库系统概述&quot;&gt;&lt;/a&gt;第一章:数据库系统概述&lt;/h1&gt;&lt;h2 id=&quot;基本概念&quot;&gt;&lt;a href=&quot;#基本概念&quot; class=&quot;
      
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Introduction to Database" scheme="https://Maxwell-lyu.github.io/tags/Introduction-to-Database/"/>
    
  </entry>
  
  <entry>
    <title>CN-FIN</title>
    <link href="https://Maxwell-lyu.github.io/2019/12/18/Learn-CN-20191031-CN-FIN/"/>
    <id>https://Maxwell-lyu.github.io/2019/12/18/Learn-CN-20191031-CN-FIN/</id>
    <published>2019-12-18T01:32:48.000Z</published>
    <updated>2021-01-10T02:26:50.981Z</updated>
    
    <content type="html"><![CDATA[<p>计算机网络期末复习资料, 是结合给出的考点重新整理的资料<br><a id="more"></a></p><h1 id="考点"><a href="#考点" class="headerlink" title="考点"></a>考点</h1><ul><li><a href="#第一章">重点</a>               1.x</li><li><a href="#多路复用与多路分解">概念</a>   3.2 3.3</li><li><a href="#面向连接的运输TCP">重点</a>    3.5 3.6 3.7</li><li><a href="#第四章">重点</a>               4.2 4.3</li><li><a href="#路由选择算法">重点</a>         5.2 5.3</li><li><a href="#ISP之间的路由选择BGP">概念</a> 5.4 5.6(了解ICMP)</li><li><a href="#第六章">重点</a>               6.3(除去6.3.4) 6.4(以及本章以太网相关内容) CSMA/CD</li><li><a href="#第七章">概念</a>               7.3(CSMA/CA)<!-- + [概念] 8.x 网络安全的概念, 几种密码方法(MD5 RSA) --></li><li><a href="#第九章">概念</a>               9.x QoS相关内容</li></ul><h1 id="第一章"><a href="#第一章" class="headerlink" title="第一章"></a>第一章</h1><h2 id="什么是因特网"><a href="#什么是因特网" class="headerlink" title="什么是因特网"></a>什么是因特网</h2><h3 id="具体构成描述"><a href="#具体构成描述" class="headerlink" title="具体构成描述"></a>具体构成描述</h3><ul><li>主机 / 端系统: 与因特网相连的设备</li><li>通信链路: 同轴电缆, 铜缆, 光纤, 无线电频谱</li><li>分组交换机<ul><li>路由器: 通常在网络核心</li><li>链路层交换机: 通常在接入网</li></ul></li><li>传输速率: 比特/秒 bps</li><li>分组: 数据分段并加上首部字节(发送系统)</li><li>路径: 分组经历的通信链路和分组交换机</li><li>因特网服务提供商(ISP): 因特网接入服务</li><li>协议: 控制因特网中信息的接收和发送<ul><li>TCP: 传输控制协议</li><li>IP: 网际协议</li></ul></li><li>因特网标准: 由IETF研发</li><li>RFC: 请求评论, 因特网标准文档</li></ul><h3 id="服务描述"><a href="#服务描述" class="headerlink" title="服务描述"></a>服务描述</h3><ul><li>分布式应用程序: 涉及到多个相互交换数据的端系统</li><li>套接字接口: 规定了端系统上的程序, 请求因特网基础设施, 向另一个端系统上程序, 交付数据的方式</li></ul><h3 id="什么是协议"><a href="#什么是协议" class="headerlink" title="什么是协议"></a>什么是协议</h3><ul><li>协议定义了:<ul><li>在两个或多个通信实体之间, 交换报文的格式和顺序</li><li>报文发送和/或接收报文, 或其他事件, 所采取的动作</li></ul></li></ul><h2 id="网络边缘"><a href="#网络边缘" class="headerlink" title="网络边缘"></a>网络边缘</h2><ul><li>端系统: 运行应用程序</li><li>P2S模型<ul><li>客户端: 发送请求, 接受服务</li><li>服务器: 响应请求, 提供服务, 始终在线, 性能更强</li></ul></li><li>P2P模型<ul><li>无专用服务器, 每设备既是客户端也是服务器</li></ul></li></ul><h3 id="接入网"><a href="#接入网" class="headerlink" title="接入网"></a>接入网</h3><ul><li>接入网: 端系统物理连接到边缘路由器的网络</li><li>边缘路由器: 端系统接入到远程端系统的第一台路由器</li><li><p>接入链路与接入环境</p><ul><li><p>家庭接入</p><ul><li>拨号<ul><li>介质: 电话线, 有调制解调器, 执行的操作相当于给接入号(服务台)打个电话, 独占一个线路</li><li>速率: 56kbps</li></ul></li><li>卫星: 1Mbps</li><li><p>DSL: 数字用户线</p><ul><li>介质: 电话线</li><li><p>拓扑</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">家庭电话-----------(电话线)----分配器----(现有电话线)----DSLAM----电话网</span><br><span class="line">                               |                             |</span><br><span class="line">PC--(双绞线)--Modem--(电话线)--+                             +----因特网</span><br></pre></td></tr></table></figure></li><li><p>DSLAM: 数字用户线接入复用器, 位于中心局, 许多端系统共享</p></li><li>频段分布<ul><li>高速下行: 50kHz - 1MHz  12Mbps  55Mbps</li><li>中速上行: 4kHz - 50kHz  1.8Mbps 15Mbps</li><li>双向话音: 0 - 4kHz</li></ul></li></ul></li><li><p>HFC: 混合光纤同轴/电缆因特网接入</p><ul><li>介质: 同轴电缆 + 光纤</li><li><p>拓扑</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">家庭----(同轴电缆)----光纤节点----(光纤)----CMTS----因特网</span><br><span class="line">家庭----(同轴电缆)----|                        |</span><br><span class="line">家庭----(同轴电缆)----+                        +----有线电视服务</span><br></pre></td></tr></table></figure></li><li><p>CMTS: 电缆调制解调器端接系统, 位于电缆头端</p></li><li>速率: 42.8Mbps下行, 30.7Mbps上行</li><li>有碰撞</li></ul></li><li><p>FTTH: 光纤到户(PON: 被动光纤网络)</p><ul><li>介质: 光纤</li><li><p>拓扑</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">ONT----(光纤)----光纤分配器----(光纤)----OLT----因特网</span><br><span class="line">ONT----(光纤)----|                       </span><br><span class="line">ONT----(光纤)----+</span><br></pre></td></tr></table></figure></li><li><p>ONT: 光纤网络端接器; OLT: 光纤线路端接器</p></li></ul></li></ul></li><li>企业(家庭)接入<ul><li>LAN<ul><li>介质: 双绞线</li><li>拓扑: 设备接入以太网交换机, 通过路由器接入因特网</li><li>速率: 10Mbps 100Mbps, 1Gbps, 10Gbps</li></ul></li><li>WiFi(802.11b/g/ac)<ul><li>11Mbps, 54Mbps, 100Mbps+</li></ul></li></ul></li><li>广域无线接入: 通信运营商<ul><li>3G: 1Mbps</li><li>4G LTE / WiMAX(淘汰): 10Mbps+</li><li>5G: 20Gbps?</li></ul></li></ul></li></ul><h3 id="物理媒体"><a href="#物理媒体" class="headerlink" title="物理媒体"></a>物理媒体</h3><ul><li>导向型<ul><li>双绞铜线</li><li>同轴电缆(可用作共享媒体)</li><li>光纤</li></ul></li><li>非导向型<ul><li>陆地无线电</li><li>卫星无线电</li></ul></li></ul><h2 id="网络核心"><a href="#网络核心" class="headerlink" title="网络核心"></a>网络核心</h2><h3 id="分组交换"><a href="#分组交换" class="headerlink" title="分组交换"></a>分组交换</h3><ul><li>数据切分成分组, 加首部</li><li>每个分组发送时独占带宽</li><li>交换机: 链路层交换机, 路由器</li><li>存储转发传输<ul><li>交换机先接收并存储整个分组, 之后再发出</li><li>端到端时延(N个交换机, 分组长度L, 速率R): $d_{e2e}=N\frac{L}{R}$</li></ul></li><li>排队时延和分组丢失<ul><li>输出缓存/输出队列: 位于输出链路前</li><li>拥塞: 分组排队等待链路</li><li>排队时延: 入队到出队的时延</li><li>分组丢失: 队列近满, 概率丢失; 队列满, 直接丢失</li></ul></li><li>转发表和路由选择协议<ul><li>转发表: 目的地址映射到输出链路</li><li>路由选择协议: 自动设置转发表</li></ul></li></ul><h3 id="电路交换"><a href="#电路交换" class="headerlink" title="电路交换"></a>电路交换</h3><ul><li>预留资源, 需要建立连接/断开连接 </li><li>端到端连接: 专用电路, 恒定时延/速率, 稳定的性能</li><li>电路交换中的复用<ul><li>频分复用<ul><li>分频段, 每个电路独占一个频率范围</li></ul></li><li>时分复用<ul><li>划分时隙, 每个电路轮流得到时隙</li><li>统计时分复用: 划分时隙, 高数据率的源得到更多时隙</li></ul></li><li>对比<ul><li>电路: 时延固定</li><li>分组: 时延不可预测, 共享带宽更高, 更简单有效成本低</li><li>电路预先分配, 分组按需分配</li></ul></li><li>虚电路<ul><li>电路交换 + 分组交换</li><li>虚电路建立时, 固定路由, 无需路由选择</li><li>共享资源, 需要拥塞控制</li><li>保证分组按序到达</li><li>可预留资源, 可区别服务(有快有慢, 优先级等)</li><li>需要连接建立和拆除</li></ul></li></ul></li></ul><h3 id="网络的网络"><a href="#网络的网络" class="headerlink" title="网络的网络"></a>网络的网络</h3><ul><li>粗略的层次结构<ul><li>Tier-1 ISP与内容提供商</li><li>区域ISP(与多个Tier-1相连)</li><li>接入ISP: 接入网, 连接端系统和Tier-2 ISP</li><li>IXP: 连接ISP, 可以来自不同级</li></ul></li></ul><h2 id="分组交换网中的时延丢包和吞吐量"><a href="#分组交换网中的时延丢包和吞吐量" class="headerlink" title="分组交换网中的时延丢包和吞吐量"></a>分组交换网中的时延丢包和吞吐量</h2><h3 id="时延概述"><a href="#时延概述" class="headerlink" title="时延概述"></a>时延概述</h3><ul><li>处理时延: 节点 检查首部, 决定转发, 进行校验 的时间, 微秒-</li><li>排队时延: 在链路前的队列等待传输, 微秒~毫秒</li><li>传输时延: $L/R$, 将所有比特推向链路的时间, 微秒~毫秒</li><li>传播时延: $d/s$, 速度s略小于光速, 毫秒</li></ul><h3 id="排队时延和丢包"><a href="#排队时延和丢包" class="headerlink" title="排队时延和丢包"></a>排队时延和丢包</h3><ul><li>排队时延对不同的分组不相通, 以统计量衡量</li><li>流量强度: $La/R$, a为分组到达的速率, 流量强度不能大于1</li><li>流量强度增加, 平均排队时延迅速增加($x^2$)</li><li>丢包<ul><li>(上课提到)队列近满, 部分设备采取按照概率丢弃分组, 队列越长概率越大</li><li>队列满, 再来就丢, 用丢包率衡量</li></ul></li></ul><h3 id="端到端时延"><a href="#端到端时延" class="headerlink" title="端到端时延"></a>端到端时延</h3><ul><li>$N-1$个路由器, 则端到端时延$d_{e2e}=N(d_{proc}+d_{trans}+d_{prop})$</li><li>traceroute: ttl递增的一系列分组, 分别测试到第i跳的时延</li><li>端系统, 应用程序和其他时延<ul><li>向共享媒体传输的端系统, 有意延迟传输</li><li>媒体分组化(AD-DA转换, 填充分组)延迟</li></ul></li></ul><h3 id="吞吐量"><a href="#吞吐量" class="headerlink" title="吞吐量"></a>吞吐量</h3><ul><li>瞬时吞吐量: 主机B接收的速率</li><li>平均吞吐量: $F/T$, 文件大小除以传输时间</li><li>瓶颈链路: 吞吐量是各个子链路吞吐量的最小值<ul><li>因特网中, 吞吐量瓶颈在接入网</li></ul></li><li>共享链路: 多个链路共享某一段链路, 则需要共享这个链路的吞吐量</li></ul><h2 id="协议层级及其服务模型"><a href="#协议层级及其服务模型" class="headerlink" title="协议层级及其服务模型"></a>协议层级及其服务模型</h2><h3 id="分层的协议结构"><a href="#分层的协议结构" class="headerlink" title="分层的协议结构"></a>分层的协议结构</h3><ul><li>协议分层<ul><li>每层向上提供服务， 各层所有协议称为协议栈</li><li>PDU: protocol data units, 也就是分组(控制信息 + 数据)</li></ul></li><li>因特网(TCP/IP)协议栈<ul><li>应用层<ul><li>支持网络应用程序: FTP(端系统文件传输), SMTP(电子邮件报文传输), HTTP(Web文档请求和传送)</li><li>信息分组: 报文</li></ul></li><li>运输层<ul><li>进程间数据传输: TCP, UDP</li><li>信息分组: 报文段</li></ul></li><li>网络层<ul><li>路由数据报: IP</li><li>信息分组: 数据报</li></ul></li><li>链路层<ul><li>在邻接的主机或路由器间传输: Ethernet, PPP</li><li>信息分组: 帧</li></ul></li><li>物理层<ul><li>线路上的比特</li></ul></li></ul></li><li>OSI模型<ul><li>应用层: 应用访问OSI模型的环境</li><li>表示层, 会话层: 并入应用层</li><li>运输层<ul><li>端系统间通信</li><li>可靠传输 或 单块传输</li><li>连接建立, 维持, 释放</li></ul></li><li>网络层<ul><li>分组在多个网络或链路上传输</li><li>编址, 路由, 转发, 拥塞控制</li><li>连接建立, 维持, 拆除</li></ul></li><li>数据链路层<ul><li>链路层帧</li><li>媒体访问控制, 差错检测和重传, 流量控制</li><li>连接激活, 维持和失活</li></ul></li><li>物理层<ul><li>链路上的比特流</li></ul></li></ul></li></ul><h3 id="封装"><a href="#封装" class="headerlink" title="封装"></a>封装</h3><ul><li>封装: 分组 = 首部字段 + 有效载荷字段<ul><li>应用层报文</li><li>运输层报文段: 运输层首部(应用交付信息, 差错检测信息) + (分段的)应用层报文</li><li>网络层数据报: 网络层首部(源目的地址等) + 运输层报文段</li><li>链路层帧: 链路层首部 + 网络层数据报</li></ul></li></ul><h2 id="面对攻击的网络"><a href="#面对攻击的网络" class="headerlink" title="面对攻击的网络"></a>面对攻击的网络</h2><ul><li>攻击个人电脑<ul><li>恶意软件<ul><li>大多数都是自我复制的</li><li>病毒: 需要某种形式的用户交互来感染用户设备</li><li>蠕虫: 无需任何明显用户交互就能进入设备</li><li>木马: 伪装成无害程序, 吸引用户点击</li><li>后门: 绕过授权验证</li><li>广告软件: 访问弹出广告</li><li>间谍软件: 收集用户的输入, 记录用户活动</li></ul></li></ul></li><li>攻击服务器和网络基础设施<ul><li>拒绝服务攻击DoS<ul><li>使得服务不能由合法用户使用</li><li>弱点攻击: 针对易受攻击的程序或操作系统, 引发停止运行或崩溃</li><li>带宽洪泛: 大量发送分组到目标, 使链路拥塞</li><li>连接洪泛: 创建大量半开或全开的TCP连接, 耗尽资源</li></ul></li><li>分布式DoS(DDoS)<ul><li>攻击者控制多个源</li><li>僵尸网路: 攻击者用恶意软件控制大量计算机, 作为DDoS的源头等</li></ul></li></ul></li><li>嗅探分组<ul><li>分组嗅探器: 记录每个流经的分组副本的被动接收机</li><li>防范: 加密</li></ul></li><li>伪装<ul><li>IP欺骗: 将具有虚假源地址的分组注入因特网</li><li>重放攻击</li><li>中间人攻击</li><li>连接劫持</li><li>解决方案: 加密, 数字签名, MAC</li></ul></li></ul><h1 id="第三章"><a href="#第三章" class="headerlink" title="第三章"></a>第三章</h1><h2 id="多路复用与多路分解"><a href="#多路复用与多路分解" class="headerlink" title="多路复用与多路分解"></a>多路复用与多路分解</h2><ul><li>多路分解: 将运输层报文段中的数据, 交付到正确的套接字的工作</li><li>多路复用: 从套接字中收集数据, 加首部生成报文段, 将报文段传递到网络层</li><li>套接字<ul><li>具有唯一标识符</li><li>报文段具有特殊字段(源端口号16bit, 目的端口号16bit), 指示需要交付到的套接字</li><li>周知端口号: 0~1023</li></ul></li></ul><h3 id="无连接的多路复用与多路分解"><a href="#无连接的多路复用与多路分解" class="headerlink" title="无连接的多路复用与多路分解"></a>无连接的多路复用与多路分解</h3><ul><li>UDP套接字由二元组进行标识: 目的IP : 目的端口号</li><li>源端口号: 回复时使用</li></ul><h3 id="面向连接的多路复用与多路分解"><a href="#面向连接的多路复用与多路分解" class="headerlink" title="面向连接的多路复用与多路分解"></a>面向连接的多路复用与多路分解</h3><ul><li>TCP套接字由四元组进行标识: 源IP : 源端口号 : 目的IP : 目的端口号</li><li>不同来源的报文到达同一端口可区分, HTTP服务器</li></ul><h2 id="无连接运输UDP"><a href="#无连接运输UDP" class="headerlink" title="无连接运输UDP"></a>无连接运输UDP</h2><ul><li>仅提供复用分解, 差错检测</li><li>无连接: 发送报文段之前, 没有握手</li><li>优点: 首部短, 时间灵活, 无连接建立, 无连接状态</li><li>无拥塞控制, 可以由应用层构建可靠传输</li></ul><h3 id="报文段结构"><a href="#报文段结构" class="headerlink" title="报文段结构"></a>报文段结构</h3><table><thead><tr><th>源端口号</th><th>目的端口号</th><th>长度(首部+数据)</th><th>检验和</th><th>应用数据(报文)</th></tr></thead><tbody><tr><td>16bit</td><td>16bit</td><td>16bit</td><td>16bit</td><td>…</td></tr></tbody></table><ul><li>UDP变长数据段</li><li>检验和计算: UDP报文段 + IP首部的部分字段()</li></ul><h3 id="UDP检验和"><a href="#UDP检验和" class="headerlink" title="UDP检验和"></a>UDP检验和</h3><ul><li>计算方法<ul><li>报文段分为16bit字, 相加求和</li><li>最高位进位回卷, 加到最低位</li><li>取反码</li></ul></li><li>检验方法: 接收方做前两步, 得到全1, 则没问题</li><li>能检测, 不能纠错, 端到端差错控制</li></ul><h2 id="面向连接的运输TCP"><a href="#面向连接的运输TCP" class="headerlink" title="面向连接的运输TCP"></a>面向连接的运输TCP</h2><ul><li>提供差错检测, 重传, 累积确认, 定时器, 序号和确认号的首部字段</li><li>全双工</li></ul><h3 id="TCP连接"><a href="#TCP连接" class="headerlink" title="TCP连接"></a>TCP连接</h3><ul><li>三次握手<ul><li>客户发送</li><li>服务端发送</li><li>客户发送</li></ul></li><li>MSS最大报文段长度(其实是应用层数据的最大长度): 根据 MTU(链路层)最大传输单元 确定, 典型值1460字节</li></ul><h3 id="TCP报文段结构"><a href="#TCP报文段结构" class="headerlink" title="TCP报文段结构"></a>TCP报文段结构</h3><table><thead><tr><th>源端口号</th><th>目的端口号</th><th>序号</th><th>确认号</th><th>(第一堆)</th><th>接收窗口</th><th>因特网校验和-紧急数据指针</th><th>选项</th><th>数据</th></tr></thead><tbody><tr><td>16bit</td><td>16bit</td><td>32bit</td><td>32bit</td><td>16bit</td><td>16bit</td><td>16bit+16bit</td><td>0bit+</td><td>…</td></tr></tbody></table><ul><li>第一堆里面有: 首部长度4bit(以字为单位, 1=4字节) + 保留未用6bit + (URG ACK PSH RST SYN FIN)标志字段6bit</li><li>SYN FIN RST 用于连接建立和拆除, PSH代表必须立即将数据交给上层, URG与紧急数据指表示指向位置是紧急数据的最后一个字节, 需要通知上层</li><li>序号和确认号<ul><li>序号: 是该报文段的首字节的字节流编号<blockquote><p>单纯的ACK不包含数据字节, 因此不引发编号增加</p></blockquote></li><li>确认号: 表示这一序号之前的字节均被正确接收, 它和其后的未接收<blockquote><p>一个报文可以同时有确认号和序号, 是捎带ACK</p></blockquote></li></ul></li></ul><h3 id="往返时间的估计与超时"><a href="#往返时间的估计与超时" class="headerlink" title="往返时间的估计与超时"></a>往返时间的估计与超时</h3><ul><li>估计往返时间<ul><li>SampleRTT: 某一报文被发出(交给IP)到其确认被接收的时间量(一个来回)<blockquote><p>重传的报文不进行测量</p></blockquote></li><li>EstimatedRTT: 初始为第一个测得的SampleRTT, 之后根据下式更新<br>$$\textrm{EstimatedRTT} = (1-\alpha)\cdot\textrm{EstimatedRTT} + \alpha \cdot \textrm{SampleRTT}$$<blockquote><p>指数移动加权平均</p></blockquote></li><li>DevRTT: RTT的偏差, 是Sample和Estimated的差的绝对值, 也用指数移动加权平均<br>$$\textrm{DevRTT} = (1-\beta)\cdot\textrm{DevRTT} + \beta \cdot |\textrm{SampleRTT}-\textrm{EstimatedRTT}|$$</li></ul></li><li>设置和管理重传超时间隔<ul><li>重传间隔<ul><li>默认初始值为1s</li><li>超时后, 设为先前值的2倍</li><li>若有新的EstimatedRTT, 立刻据下式更新<br>$$\textrm{TimeInterval} = \textrm{EstimatedRTT} + 4\cdot \textrm{DevRTT}$$</li></ul></li></ul></li></ul><h3 id="可靠数据传输"><a href="#可靠数据传输" class="headerlink" title="可靠数据传输"></a>可靠数据传输</h3><ul><li>累积ACK<ul><li>ACK中的数字, 表示其之前的字节均被接收</li></ul></li><li>重传<ul><li>规则: 一个报文到达重传间隔, 仍未收到ACK(ACK&gt;SEQ+LEN), 则重传</li><li>超时间隔加倍: 重传过后, 下一次的定时将会加倍; </li><li>推算超时间隔: 若收到ACK或得到上层应用数据, 则又改为使用$\textrm{TimeInterval}$计算</li></ul></li><li>快速重传<ul><li>ACK生成策略<ul><li>延迟ACK: 某一报文到达, 等待500ms, 若下一个按序报文没到, 发这一报文ACK</li><li>立刻发送累积ACK: 一个按序报文到了, 前一个在等待发ACK, 发累积ACK, ACK后一个报文</li><li>冗余ACK: 到达一个报文, 其序号大于期望的序号, 立刻发送冗余ACK, 其序号为期望序号</li><li>收到的报文填补空缺, 且起始于空缺的低端, 则立刻发ACK</li></ul></li><li>收到3个冗余ACK, 则进行快速重传, 假定被ACK的报文后的报文全部丢失</li></ul></li><li>回退N步还是选择重传<ul><li>第n个报文重传, 若之后的报文被缓存, 且其ACK及时到达, 那么后续可以不用重传<blockquote><p>这意味着TCP不是单纯的GBN, 而含有一部分SN</p></blockquote></li></ul></li></ul><h3 id="流量控制"><a href="#流量控制" class="headerlink" title="流量控制"></a>流量控制</h3><ul><li>接收窗口<ul><li>接收方跟踪<ul><li>应用读取的最后一个字节的编号: LastByteRead</li><li>接收到的最后一个字节的编号: LastByteRcvd</li><li>接收缓存大小: RcvBuffer</li><li>接收窗口大小: rwnd = RcvBuffer-(LastByteRcvd-LastByteRead)<blockquote><p>也就是缓存余量</p></blockquote></li><li>接收方将rwnd放入发给发送方的报文中</li></ul></li><li>发送方跟踪<ul><li>发送的最后一个字节的编号: LastByteSent</li><li>被确认的最后一个字节的编号: LastByteAcked</li><li>从接收到的报文中得到的rwnd</li><li>需要始终保证 LastByteSent - LastByteAcked &lt;= rwnd</li><li>若出现rwnd=0, 则需要继续发送含有一字节数据的报文<blockquote><p>为了防止接收方无数据要发, 引发发送端阻塞. 这个一字节的报文总会被ACK, 有机会获得一个非0的rwnd值</p></blockquote></li></ul></li></ul></li></ul><h3 id="TCP连接管理"><a href="#TCP连接管理" class="headerlink" title="TCP连接管理"></a>TCP连接管理</h3><ul><li>建立: 三次握手</li></ul><table><thead><tr><th>通信</th><th>SYN</th><th>ACK</th><th>ACK</th><th>SEQ</th><th>数据</th><th>操作</th></tr></thead><tbody><tr><td>客户-&gt;服务</td><td>+</td><td></td><td></td><td>client_isn</td><td></td><td>客户端随机选择起始序号</td></tr><tr><td>服务-&gt;客户</td><td>+</td><td>+</td><td>client_isn+1</td><td>server_isn</td><td></td><td>服务器分配资源, 随机选择起始序号</td></tr><tr><td>客户-&gt;服务</td><td></td><td>+</td><td>server_isn+1</td><td>client_isn+1</td><td>可携带</td><td>客户端分配资源</td></tr></tbody></table><ul><li>终止(以客户终止为例)  </li></ul><table><thead><tr><th>通信</th><th>FIN</th><th>SEQ</th><th>ACK</th><th>ACK</th><th>操作</th></tr></thead><tbody><tr><td>客户-&gt;服务</td><td>+</td><td>client_isn</td><td></td><td>(server_isn)</td><td>客户发送FIN</td></tr><tr><td>服务-&gt;客户</td><td></td><td>server_isn</td><td>+</td><td>client_isn + 1</td><td>服务器ACK这个FIN, 之后还可以发数据(len)</td></tr><tr><td>服务-&gt;客户</td><td>+</td><td>server_isn + len</td><td></td><td>(client_isn + 1)</td><td>服务器发送FIN, 收到客户端的ACK后关闭, 释放资源</td></tr><tr><td>客户-&gt;服务</td><td></td><td>client_isn + 1</td><td>+</td><td>server_isn + len + 1</td><td>客户端ACK这个FIN, 定时等待之后关闭, 释放资源</td></tr></tbody></table><ul><li>防范SYN洪泛攻击<ul><li>第一步的isn使用散列函数, 用源地址, 目的地址和端口号, 和一个只有服务器知道的散列函数</li><li>第二步不分配资源</li><li>第三步根据ACK里面的seq, 可以验证这个ACK是由先前的某个SYN生成的, 于是分配资源建立连接</li></ul></li><li>拒绝通信<ul><li>发送RST(RST标志位1)</li></ul></li></ul><h2 id="拥塞控制原理"><a href="#拥塞控制原理" class="headerlink" title="拥塞控制原理"></a>拥塞控制原理</h2><ul><li>一堆废话, 我只关心TCP</li></ul><h2 id="TCP拥塞控制"><a href="#TCP拥塞控制" class="headerlink" title="TCP拥塞控制"></a>TCP拥塞控制</h2><ul><li>拥塞窗口cwnd6;<ul><li>对发送进行限制: LastByteSent - LastByteAcked &lt;= min(rwnd, cwnd)</li></ul></li><li>窗口与速率的关系: B = S(发出的包数量)/RTT(往返时间)</li><li>TCP拥塞控制算法<ul><li>总结<ul><li>ssthresh变化: 丢包事件: ssthresh = cwnd / 2</li><li>cwnd变化: 状态初始值<ul><li>进入慢启动: cwnd = 1</li><li>进入拥塞避免: cwnd = ssthresh</li><li>进入快速恢复: cwnd = ssthresh + 3</li></ul></li><li>cwnd变化: 增长方式<ul><li>慢启动: 每个ACK, +1, 相当于每轮乘二</li><li>拥塞避免: 每轮 +1</li><li>快速恢复: 每个冗余ACK +1</li></ul></li></ul></li><li>慢启动<ul><li>初始: cwnd = 1 (MSS)</li><li>加倍: 每一轮, cwnd加倍</li><li>结束<ul><li>超时, 取cwnd = 1, ssthresh = cwnd/2</li><li>到达ssthresh, 进入拥塞避免模式</li><li>3个冗余ACK, ssthresh = cwnd/2, cwnd = cwnd/2+3, 进入快速恢复</li></ul></li></ul></li><li>拥塞避免<ul><li>线性增加: 每一轮, cwnd+1</li><li>结束<ul><li>超时, 取cwnd = 1, ssthresh = cwnd/2, 相当于慢启动</li><li>3个冗余ACK, ssthresh = cwnd/2, cwnd = cwnd/2+3, 进入快速恢复</li></ul></li></ul></li><li>快速恢复<ul><li>接下来收到的冗余ACK, cwnd都加1(之前的3个冗余ACK已经加过3, 至少加3)</li><li>结束<ul><li>收到期待的ACK, 将cwnd = ssthresh, 进入拥塞避免</li><li>超时, ssthresh = cwnd/2, cwnd = 1</li></ul></li></ul></li><li>TCP拥塞控制: 回顾<ul><li>TCP Tahoe: 没有快速恢复, 3个ACK也进入慢启动</li><li>TCP Reno: 上文的方案<blockquote><p>加3根据协议不同, 看具体情况做<br>慢启动: 其实是收到的每个ACK都加1, 因为ACK数等于发送数, 相当于翻倍</p></blockquote></li></ul></li></ul></li><li>需要拥塞控制的原因: 浪费带宽<ul><li>速率接近容量 -&gt; 队列满 + 大排队时延</li><li>大时延 -&gt; 不必要的超时重传</li><li>队列满 -&gt; 丢包 -&gt; 浪费上游流量</li><li>丢包 -&gt; 重传代价</li></ul></li></ul><h3 id="公平性"><a href="#公平性" class="headerlink" title="公平性"></a>公平性</h3><ul><li>TCP AIMD<ul><li>相同的RTT: 公平, 最终会达到平均分配带宽</li><li>RTT不同: RTT小的更快扩大窗口, 将得到更多带宽, 最终似乎与RTT成反比</li></ul></li><li>UDP参与<ul><li>UDP没有公平可言, 抢占资源</li><li>UDP将挤压TCP资源</li></ul></li><li>并行TCP<ul><li>一个应用使用多个TCP连接, 就获得了多倍其应得的带宽</li></ul></li></ul><h3 id="网络辅助拥塞控制"><a href="#网络辅助拥塞控制" class="headerlink" title="网络辅助拥塞控制"></a>网络辅助拥塞控制</h3><ul><li>IP首部设置ECN(2比特, 4状态), 送到接收主机</li><li>接受主机在TCP ACK中设置ECE, 发到发送主机</li><li>发送主机减半cwnd, 并在下一个报文头中设置CWD, 发到接收主机</li></ul><h1 id="第四章"><a href="#第四章" class="headerlink" title="第四章"></a>第四章</h1><h2 id="路由器工作原理"><a href="#路由器工作原理" class="headerlink" title="路由器工作原理"></a>路由器工作原理</h2><ul><li>输入端口<ul><li>线路端接: 物理线路接入</li><li>数据链路处理: 协议, 拆封</li><li>查找转发排队: 查找转发表, 存帧排队</li></ul></li><li>交换结构<ul><li>经内存交换</li><li>经总线交换</li><li>经互连网络交换(纵横式)</li></ul></li><li>输出端口: 排队, 数据链路处理, 线路端接</li><li>路由选择处理器: 执行控制平面功能, 维护路由选择表和链路状态, 计算转发表<ul><li>基于目的地转发: 仅考虑目的地</li><li>通用转发: 考虑更多因素</li></ul></li></ul><h3 id="输入端口处理和基于目的地转发"><a href="#输入端口处理和基于目的地转发" class="headerlink" title="输入端口处理和基于目的地转发"></a>输入端口处理和基于目的地转发</h3><ul><li>转发表在输入端口有副本, 在输入端口本地做出转发决策</li><li>前缀匹配<ul><li>转发表不存储所有目的地址, 而是根据最长前缀匹配确定转发</li><li>使用DRAM, SRAM, TCAM(三态内容可寻址存储器), 纳秒级</li></ul></li><li>其他动作<ul><li>出现物理层和链路层处理</li><li>检查版本号, 检验和, 寿命, 重写后两个</li><li>更新网络管理信息(如 计数器)</li></ul></li></ul><h3 id="交换"><a href="#交换" class="headerlink" title="交换"></a>交换</h3><ul><li>经内存交换: 输入卡处理地址查找和分组存储, 所有输入共享内存</li><li>经总线交换<ul><li>输入端口为分组计划一个交换机内部标签(首部)</li><li>与首部匹配的输出端口存分组, 并去除标签</li></ul></li><li>经互连网络交换<ul><li>优点: 可以并行</li><li>纵横式, N纵N横N*N交叉点</li><li>非阻塞: 到不同输出端的分组不会互相阻塞</li></ul></li><li>更复杂(去数据通信笔记看)<ul><li>三级非阻塞网络</li></ul></li></ul><h3 id="输出端口处理"><a href="#输出端口处理" class="headerlink" title="输出端口处理"></a>输出端口处理</h3><ul><li>输出缓存, 数据链路处理(协议, 封装), 线路端接</li></ul><h3 id="何处出现排队"><a href="#何处出现排队" class="headerlink" title="何处出现排队"></a>何处出现排队</h3><ul><li>丢包: 没有缓存可以用来存储到达的分组</li><li>输入排队<ul><li>交换结构不足以使所有到达分组无时延地通过它传送</li><li>HOL阻塞(线路前部阻塞): 被线路前部的一个分组阻塞, 例如两个分组发往一个目的地</li></ul></li><li>输出排队<ul><li>没有足够的内存存储到达的分组</li><li>主动队列管理AQM<ul><li>弃尾: 丢弃到达的分组</li><li>也可以删除正在排队的部分分组</li><li>向发送方提供阻塞信号</li></ul></li><li>随机早期检测RED</li><li>缓存大小: $B=\textrm{RTT}\cdot C/\sqrt{N}$, $C$为链路容量, $N$链路上的TCP流数量, $\textrm{RTT}$平均往返时延</li></ul></li></ul><h3 id="分组调度"><a href="#分组调度" class="headerlink" title="分组调度"></a>分组调度</h3><ul><li>先进先出FIFO 先来先服务FCFS<ul><li>维护一个队列, 来了进入队尾, 队首挨个处理</li></ul></li><li>优先权排队<ul><li>每个优先权类有自己的队列, 各自FIFO</li><li>不同优先级, 高的队列空了才处理低的</li><li>非抢占: 已经开始的传输不会被打断</li></ul></li><li>循环排队规则<ul><li>多个队列, 不分优先级, 轮流提供服务</li><li>保持工作排队规则: 有任何类的分组在等待, 则不允许链路保持空闲</li></ul></li><li>加权公平排队<ul><li>在循环排队的基础上加上优先级</li><li>每一循环, 每个类得到多次服务, 次数与权重成正比</li></ul></li></ul><h2 id="网际协议"><a href="#网际协议" class="headerlink" title="网际协议"></a>网际协议</h2><h3 id="IPv4数据报格式"><a href="#IPv4数据报格式" class="headerlink" title="IPv4数据报格式"></a>IPv4数据报格式</h3><ul><li><p>数据报格式</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">|    $版本 4   |  首部长度 4  |  服务类型 8  | 数据报长度16 |</span><br><span class="line">|          $标识16             | 标志 3 |       片偏移13    |</span><br><span class="line">|    寿命 8    |  $上层协议 8  |         首部检验和16       |</span><br><span class="line">|                  (NoNAT)$源地址32                         |</span><br><span class="line">|                 (NoNAT)$目的地址32                        |</span><br><span class="line">|                      选项(可选)                           |</span><br><span class="line">|                         数据                              |</span><br></pre></td></tr></table></figure><ul><li>服务类型: 优先级(3bit), 可靠性(1bit, 一般/高), 时延(1bit, 一般/低), 吞吐量(1bit, 一般/高)</li><li>标识, 标志, 片偏移: 与IPv4分片有关</li><li>选项: 长度不定, 默认首部长度为20字节, 可变</li><li>数据报长度: 首部加数据的长度, 字节为单位</li><li>寿命: 经过一个路由器, 减1, 为0丢弃</li><li>协议: 到达目的地才有用, 6-TCP, 17-UDP, 类似端口号</li></ul></li></ul><h3 id="IPv4数据报分片"><a href="#IPv4数据报分片" class="headerlink" title="IPv4数据报分片"></a>IPv4数据报分片</h3><ul><li>原因: 链路层最大传输单元MTU, 限制IP数据报的长度</li><li>对数据报分片, 并设置标识等<ul><li>标识: 每个数据报+1, 一个数据报的各个分片相同</li><li>标志: 最后一个为0, 其他是1</li><li>片偏移: 以64bit为单位</li></ul></li></ul><h3 id="IPv4编址"><a href="#IPv4编址" class="headerlink" title="IPv4编址"></a>IPv4编址</h3><ul><li>接口: 主机与物理线路的边界</li><li>点分十进制记法: 192.168.0.255, 就这样的, 每个8位当作十进制数, 点分开</li><li>地址分类: <ul><li>A: 0开头/8</li><li>B: 10开头/16</li><li>C: 110开头/24</li></ul></li><li>子网(IP网络): CIDR无类别域间路由选择<ul><li>子网掩码: xxx.xxx.xxx.xxx/yy, yy为子网掩码, </li><li>网络前缀: 地址的前yy位</li><li>子网内的地址: 剩下的位数</li><li>另一种表示: 前yy位为1, 剩下为0, 用点分十进制写出来</li><li>路由聚合/路由摘要: 一个组织共享相同前缀</li></ul></li><li>主机得到地址的过程<ul><li>获取一块地址<ul><li>来自ISP, ISP来自ICANN</li><li>管理员划分这些地址给子网</li></ul></li><li>获取主机地址: DHCP<ul><li>所有的目的地址都是 255.255.255.255</li><li>DHCP服务器发现: 新到达的主机发送DHCP发现报文<ul><li>UDP端口67的报文</li><li>目的: 255.255.255.255</li><li>内容: 事务ID</li></ul></li><li>DHCP服务器提供: 服务器的相应<ul><li>UDP端口68的报文</li><li>源: DHCP服务器地址</li><li>内容<ul><li>事务ID, 推荐IP地址, 掩码, 地址租期</li></ul></li></ul></li><li>DHCP请求: 主机选择一个服务器, 相应<ul><li>UDP端口67的报文</li><li>源: 0.0.0.0</li><li>内容: 回显配置信息, 事务ID+1</li></ul></li><li>DHCP ACK: 确认配置<ul><li>UDP端口68的报文</li><li>源: DHCP服务器地址</li><li>内容: 证实参数, 事务ID+1</li></ul></li></ul></li></ul></li></ul><h3 id="网络地址转换NAT"><a href="#网络地址转换NAT" class="headerlink" title="网络地址转换NAT"></a>网络地址转换NAT</h3><ul><li>NAT路由器: 它和它背后的网路对外界是一台单一的设备</li><li>允许内部外部通信, 使用不同的地址</li><li>NAT路由器将重写IP地址和端口号字段</li><li>NAT转换表<ul><li>内部地址:端口 - 外部地址:端口</li></ul></li><li>NAT穿越: 解决内网服务器周知端口问题</li><li>UPnP: 通用即插即用协议, 解决NAT自动配置</li><li>跨越网络层和传输层</li></ul><h3 id="IPv6"><a href="#IPv6" class="headerlink" title="IPv6"></a>IPv6</h3><ul><li><p>数据报格式</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">|    版本 4    |  流量类型 8  |         流量标签 20         |</span><br><span class="line">|       有效载荷长度 16      | 下一个首部 8 |    寿命 8     |</span><br><span class="line">|                       源地址 128                          |</span><br><span class="line">|                      目的地址 128                         |</span><br><span class="line">|                         数据                              |</span><br></pre></td></tr></table></figure><ul><li>首部定长40字节</li><li>版本: 6</li><li>流量类型: 与IP的服务类型字段类似</li><li>流标签: 识别数据报的流, 用于优先权等</li><li>有效载荷长度: 给出数据段的长度, 不含头部</li><li>下一个首部 = 上层协议类型, 与IPv4的协议类型同值</li></ul></li><li>与IPv4的不同<ul><li>IPv6不允许由路由器进行分片, 因此没有分片3字段</li><li>首部检验和: 运输层和数据链路层进行过检验, 因此丢掉</li><li>选项: 不是标准IP的一部分了, 可能出现在”下一个首部”指定的地方</li></ul></li><li>从IPv4到IPv6<ul><li>隧道: IPv6数据报放入IPv4的有效载荷字段中, 上层协议41</li></ul></li></ul><h1 id="第五章"><a href="#第五章" class="headerlink" title="第五章"></a>第五章</h1><h2 id="路由选择算法"><a href="#路由选择算法" class="headerlink" title="路由选择算法"></a>路由选择算法</h2><ul><li>路由选择算法: 从发送方到接收方, 确定一条通过路由器网络的好的路径</li><li>图, 节点, 路径, 最低开销路径, 最短路径</li><li>分类1<ul><li>集中式路由选择算法(链路状态算法): 完整, 全局的网络知识, 计算源到目的的最低开销路径</li><li>分散式路由选择算法(距离向量算法): 迭代, 分布式地计算出最低开销路径</li></ul></li><li>分类2<ul><li>静态路由选择算法: 变化很慢, 人工配置</li><li>动态路由选择算法: 随着网络流量负载变化或拓扑发生变化而改变路由选择路径</li></ul></li><li>分类3<ul><li>负载敏感: 链路开销反映拥塞水平</li><li>负载迟钝: 反之</li></ul></li></ul><h3 id="链路状态路由选择算法"><a href="#链路状态路由选择算法" class="headerlink" title="链路状态路由选择算法"></a>链路状态路由选择算法</h3><ul><li>算法流程<ul><li>$u$源, $D(v)$从源到$v$的距离, $p(v)$到$v$的最短路上的下一个节点</li><li>首先$D(v)$正无穷, 若有边设为边的开销</li><li>每一轮, 找出$D(v)$中最小的一个$v$, 进行如下操作<ul><li>用这个$D(v)$更新$v$的所有邻点的开销, 值为$D(v)$加边开销</li></ul></li><li>直到不再变化</li></ul></li><li>复杂性: $O(n^2)$</li><li>出现的问题<ul><li>同时运行LS算法的路由器</li><li>链路选择的震荡, 由于一侧拥塞, 都选择另一侧, 而恰好使得这一侧也拥塞, 不断往返</li><li>解决: 随机化发送链路通告的时间</li></ul></li></ul><h3 id="距离向量路由选择算法"><a href="#距离向量路由选择算法" class="headerlink" title="距离向量路由选择算法"></a>距离向量路由选择算法</h3><ul><li>算法流程: 对于每个节点<ul><li>更新距离向量估计值, 当直接相连的链路开销发生变化, 或从邻居接收到距离向量的更新</li><li>更新规则: 取最小值, 对所有$D_v(y)+c(x,v)$以及原有的距离, $v$是$x$的邻居</li></ul></li><li>路由选择环路<ul><li>无穷计数: 有环路的情况下, 链路代价的增加, 将会反复震荡, 长时间后才能达到稳定</li><li>毒性逆转: 如果z通过y路由选择到x, 则z将通告y, z到x的距离是无穷大</li><li>涉及到3个或更多节点的环路还是不能解决无穷计数</li></ul></li></ul><h2 id="算法比较"><a href="#算法比较" class="headerlink" title="算法比较"></a>算法比较</h2><ul><li>报文复杂性<ul><li>LS: $O(|N||E|)$</li><li>DV: 仅在新的链路开销导致与该链路相连节点的最低开销路径发生改变, 才传播开销</li></ul></li><li>收敛速度<ul><li>LS: 收敛块</li><li>DV: 较慢, 还有无穷计数</li></ul></li><li>健壮性<ul><li>LS: 节点分别计算自己的最短路径, 一定程度健壮性</li><li>DV: 一个节点的错误计算值, 扩散到整个网络</li></ul></li></ul><h2 id="因特网中自治系统内部的路由选择OSPF"><a href="#因特网中自治系统内部的路由选择OSPF" class="headerlink" title="因特网中自治系统内部的路由选择OSPF"></a>因特网中自治系统内部的路由选择OSPF</h2><ul><li>自治系统AS<ul><li>由处在相同管理控制下的路由器组成</li><li>具有 自治系统内部路由选择协议</li><li>具有 独有的AS编号 ASN</li></ul></li></ul><h3 id="开放最短路优先OSPF"><a href="#开放最短路优先OSPF" class="headerlink" title="开放最短路优先OSPF"></a>开放最短路优先OSPF</h3><ul><li>是一种链路状态协议: 洪泛状态信息 + Dijkstra算法</li><li>各个链路的开销: 管理员进行配置</li><li>路由选择信息: 向全部路由器广播</li><li>广播条件: 有链路状态发生变化 / 至少每30min一次</li><li>报文: 直接由IP承担, 上层协议的值为89, 自己实现可靠传输和链路状态广播</li><li>其他功能: 检查链路运行(发送OSPF HELLO), 获得相邻路由的链路状态数据库</li><li>优点<ul><li>安全: 鉴别报文防止伪造(使用口令或MD5), 序号防范重放攻击</li><li>多条相同开销的路径: 允许使用多条路径</li><li>单播与多播: MOSPF使用现有的链路数据库, 链路状态广播机制增加新型链路状态通告</li><li>AS内层次结构: OSPF自治系统内部也可以配置多个区域, 运行自己的OSPF算法</li></ul></li></ul><h2 id="ISP之间的路由选择BGP"><a href="#ISP之间的路由选择BGP" class="headerlink" title="ISP之间的路由选择BGP"></a>ISP之间的路由选择BGP</h2><ul><li>自治系统间路由选择协议</li><li>边界网关协议: BGP</li></ul><h3 id="BGP的作用"><a href="#BGP的作用" class="headerlink" title="BGP的作用"></a>BGP的作用</h3><ul><li>BGP中, 分组不是路由到特定的地址, 而是路由到CIDR化的前缀</li><li>协议提供的手段<ul><li>从邻居AS获得前缀的可达性信息: 允许子网广播自己的存在</li><li>确定到该前缀的”最好的”路由: 本地运行BGP路由选择过程, 基于策略和可达性信息</li></ul></li></ul><h3 id="通告BGP路由信息"><a href="#通告BGP路由信息" class="headerlink" title="通告BGP路由信息"></a>通告BGP路由信息</h3><ul><li>网关路由器: AS边缘的路由器, 直接连接到其他AS中的路由器</li><li>内部路由器: 只连接了同一AS内的路由器</li><li>BGP连接<ul><li>在端口179的半永久TCP连接</li><li>eBGP: 跨越AS的BGP连接</li><li>iBGP: 相同的AS内的两台路由器的连接</li></ul></li><li>传递可达信息: 不断重复 AS内广播, 网关传递到其他AS 的过程</li></ul><h3 id="确定最好的路由"><a href="#确定最好的路由" class="headerlink" title="确定最好的路由"></a>确定最好的路由</h3><ul><li>BGP属性: 路由器通告前缀时, 会在前缀中包括BGP属性<ul><li>AS-PATH属性<ul><li>每当前缀通过(离开)一个AS, (网关路由器)就在AS-PATH属性末尾, 加上自己的ASN</li><li>若其中已有自己的ASN, 则拒绝该通告, 以防止环路</li><li>于是, 接到这个通告的路由器, AS-PATH从头到尾恰为到达目标需要经过的AS的顺序</li></ul></li><li>NEXT-HOP属性<ul><li>是该AS-PATH起始路由器接口的IP地址, 也就是连接AS1, AS2的子网中, AS2网关路由器的地址</li></ul></li><li>目的前缀属性</li><li>更多</li></ul></li><li>热土豆(烫手山芋)路由选择<ul><li>不考虑AS-PATH, 只关注NEXT-HOP</li><li>用内部路由协议确定, 所有的NEXT-HOP中, 开销最小的一个</li><li>目的是尽快将分组送出AS, 如同烫手山芋</li></ul></li><li>路由器选择算法<ul><li>依次使用规则, 直到只剩一个<ul><li>选择本地偏好最高的<ul><li>路由被指派本地偏好(是BGP属性之一), 可由该路由器设置或学习到, 取决于网络管理员</li></ul></li><li>选择最短AS-PATH的路由, 使用DV确定路径, 距离测度使用AS跳的跳数</li><li>使用热土豆路由选择</li><li>使用BGP标识选择</li></ul></li></ul></li></ul><h3 id="IP任播"><a href="#IP任播" class="headerlink" title="IP任播"></a>IP任播</h3><ul><li>访问某任播地址的请求, 到达一系列主机中的一个</li><li>CDN<ul><li>多台服务器, 相同IP地址, 都用BGP通告各自的IP地址</li><li>路由器将认为收到的多个通告, 是到达同一服务器的不同路径(其实是不同的服务器, 只是配置为相同的服务)</li><li>客户请求时, 路由器将路由到”较近”的CDN服务器</li></ul></li><li>DNS<ul><li>根服务器13个地址, 每个地址有许多镜像</li><li>类似CDN, 可以让DNS请求到达”最近的”镜像</li></ul></li></ul><h3 id="路由选择策略"><a href="#路由选择策略" class="headerlink" title="路由选择策略"></a>路由选择策略</h3><ul><li>选择的路由通告策略<ul><li>ISP协商等, 确定BGP通告规则, 拒绝某些通告, 尽管这些通告能够提供有效的路径</li><li>例如BC直连, 另有BXC路线, X可以选择拒绝通告B和C自己能到达C或B, 以达到不转发BC流量的目的</li></ul></li></ul><h3 id="拼装在一起-在因特网中呈现"><a href="#拼装在一起-在因特网中呈现" class="headerlink" title="拼装在一起: 在因特网中呈现"></a>拼装在一起: 在因特网中呈现</h3><ul><li>[木大警告] 这节不知道在讲什么玩意, 全是例子</li></ul><h2 id="因特网控制报文协议ICMP"><a href="#因特网控制报文协议ICMP" class="headerlink" title="因特网控制报文协议ICMP"></a>因特网控制报文协议ICMP</h2><ul><li>ICMP在IP之上, 位于IP分组的有效载荷字段, 上层协议字段为1</li><li>字段<ul><li>类型</li><li>编码</li><li>引发该ICMP报文生成的IP数据报的首部, 及其前8字节</li></ul></li><li>详细<ul><li>0-0: PING回显</li><li>3-[0~3]: 目的[网络/主机/协议/端口]不可达</li><li>3-[6-7]: 目的[网络/主机]未知</li><li>4-0: 源抑制</li><li>8-0: PING请求</li><li>9-0: 路由器通告</li><li>10-0: 路由器发现</li><li>11-0: TTL过期</li><li>12-0: IP首部损坏</li></ul></li><li>例子<ul><li>PING: 类型8编码0, 回显: 类型0编码0</li><li>ICMP源抑制: 网络层拥塞控制, 然而TCP有了, 废物一件</li><li>TRACEROUTE<ul><li>利用报文过期的ICMP的TTL过期报文(内含路由器的地址和名字)</li><li>每个包的目的端口号都不可达, 使用ICMP的目的端口不可达报文, 确定探索结束</li></ul></li></ul></li><li>IPv6新的ICMPv6<ul><li>分组太大</li><li>未被承认的IPv6选项</li></ul></li></ul><h1 id="第六章"><a href="#第六章" class="headerlink" title="第六章"></a>第六章</h1><h2 id="多路访问链路和协议"><a href="#多路访问链路和协议" class="headerlink" title="多路访问链路和协议"></a>多路访问链路和协议</h2><ul><li>广播链路: 多点, 一个信道</li><li>碰撞: 多个结点同时发送</li></ul><h3 id="信道划分协议"><a href="#信道划分协议" class="headerlink" title="信道划分协议"></a>信道划分协议</h3><ul><li>时分复用TDM<ul><li>时隙slot, 每轮每结点一个时隙</li><li>速率: R/N, 负载不均衡时浪费, 统计时分复用解决, 有额外开销</li></ul></li><li>频分复用FDM<ul><li>分频率, 一人一频</li><li>速率: R/N, 负载不均衡时浪费</li></ul></li><li>码分多址CDMA<ul><li>每结点一个编码, 1电平为此编码, 0为编码取反</li><li>速率: R, 可同时发送(每个结点的编码必须线性不相关), 抗干扰</li></ul></li></ul><h3 id="随机接入协议"><a href="#随机接入协议" class="headerlink" title="随机接入协议"></a>随机接入协议</h3><ul><li>时隙ALOHA<ul><li>有ACK</li><li>前提: 每帧长L, 每时隙L/R, 结点同步, 且在时隙开始时才传输, 碰撞检测够快</li><li>流程<ul><li>发送: 结点在一个时隙开始发送帧<ul><li>成功: 若没检测到碰撞, 则认为成功传输</li></ul></li><li>失败: 检测到碰撞, 在之后的时隙中以概率p不断尝试重传, 直到没有碰撞</li></ul></li><li>效率: 取p=1/N时最大化, 当N趋于无穷时, 效率为1/e</li></ul></li><li>ALOHA<ul><li>有ACK<blockquote><p>除了不同步, 跟时隙ALOHA一样</p></blockquote></li><li>流程<ul><li>发送: 结点发送帧<ul><li>成功: 若没检测到碰撞, 则认为成功传输</li></ul></li><li>失败: 检测到碰撞, 立刻以概率p不断尝试重传, 直到没有碰撞</li></ul></li><li>效率: 取p=1/N时最大化, 当N趋于无穷时, 效率为1/2e(前后都可能有重叠)</li></ul></li><li>CSMA/CD<ul><li>无ACK</li><li>不做同步</li><li>流程<ul><li>监听: 监听信道是否空闲, 空闲时才开始传输, 传输前得等96比特时间(最小帧间隔)</li><li>传输: 传输时也不断监听是否有其他结点的信号能量<ul><li>成功: 未发现其他能量, 认为发送成功</li></ul></li><li>失败: 发现其他能量, 立刻停止; <strong>发送48bit干扰信号</strong></li><li>等待(非持续): 等待一个随机时间, 回到”监听”重传</li><li>回退(p持续): 之后的时间当中以概率p重传</li><li>回退(1持续, 以太网): 使用二进制指数后退<ul><li>经历过了k次碰撞, 就从[0,…,2^k-1]中选一个K值, 等待512K个比特时间</li><li>k最大为10</li><li>最多尝试16次发送</li></ul></li></ul></li><li>效率: 近似为<br>$$\frac{1}{1+5d_{prop}/d_{trans}}$$</li><li>最小帧长: 检测冲突的时长不超过端到端传播时延的2倍, 取这一值为最小帧长</li></ul></li></ul><h3 id="轮流协议"><a href="#轮流协议" class="headerlink" title="轮流协议"></a>轮流协议</h3><ul><li>轮询协议<ul><li>流程: 每个从结点n<ul><li>主节点发帧, 告诉从节点n能够发送的最大包数</li><li>从节点发送不超过n帧</li><li>主节点发现没有信号了, 继续轮询下一个从节点</li></ul></li><li>缺点: 轮询时延(第一步耗时); 主节点损坏则信道无用</li></ul></li><li>令牌传递协议<ul><li>流程<ul><li>收到令牌</li><li>如果有帧要发, 则发送不超过最大数目的帧数</li><li>传递令牌</li></ul></li><li>缺点: 令牌传播时延, 令牌丢失, 单点故障则信道崩溃</li></ul></li></ul><h2 id="交换局域网"><a href="#交换局域网" class="headerlink" title="交换局域网"></a>交换局域网</h2><h3 id="链路层寻址和ARP"><a href="#链路层寻址和ARP" class="headerlink" title="链路层寻址和ARP"></a>链路层寻址和ARP</h3><ul><li>媒体访问控制 MAC地址<ul><li>长度: 6字节</li><li>与适配器(NIC等)绑定</li><li>广播地址: 全1, 即12个F</li><li>每个主机都检查MAC是否与自己相同, 相同则接收</li></ul></li><li>地址解析协议 ARP协议<ul><li>子网内解析</li><li>每台主机或路由器存有ARP表, 保存了其知晓的MAC-IP对应关系, 每个条目有过期时间</li><li>流程<ul><li>若有表项, 直接构造包并发送</li><li>若无, 向适配器发送ARP分组(内容: 发送和接收的IP地址, 目的MAC: 广播地址)</li><li>每个主机都收到, 若IP相同, 则响应ARP分组, 用标准链路层帧回复</li></ul></li></ul></li><li>发送数据报到子网以外<ul><li>路由器每个端口均有MAC和IP</li><li>路由器将相应ARP, 主机获得的此IP的MAC地址是路由器这一端口的MAC</li></ul></li></ul><h3 id="以太网"><a href="#以太网" class="headerlink" title="以太网"></a>以太网</h3><ul><li>以太网帧结构<ul><li>帧字段<ul><li>前同步码: 8字节: 前7个字节都是10101010, 同步时钟并唤醒适配器; 最后一个是10101011, “11”警告适配器数据到来</li><li>目的MAC地址: 6字节: 与自己的MAC相同才会接收</li><li>源MAC地址: 6字节</li><li>类型字段: 2字节: 允许以太网复用多种网络层协议</li><li>数据: 46-1500: 承载IP数据报, 超长将分片</li><li>CRC: 4字节: 适配器丢弃校验出错的帧</li></ul></li><li>无连接服务: 不事先握手</li><li>不可靠服务: 成功无ACK, 失败无REJ</li></ul></li><li>以太网技术<ul><li>命名: [速率]BASE[距离 或 介质], T指铜双绞线, FX/SX/BX指光纤</li><li>10Mbps: 10BASE[%d], 距离, 使用同轴电缆</li><li>100Mbps: 100BASE-TX/T4/T2双绞线, -FX/SX/BX光纤</li><li>1000Mbps: 1000BASE-T等, 又名802.3z, 双绞线, 兼容旧标准, 点对点(交换机)信道全双工, 另有广播(集线器)</li><li>10Gbps: 10GBASE-T</li></ul></li></ul><h3 id="链路层交换机"><a href="#链路层交换机" class="headerlink" title="链路层交换机"></a>链路层交换机</h3><ul><li>交换机转发和过滤<ul><li>过滤: 决定帧应该发到某个接口还是将其丢弃</li><li>转发: 决定帧去往哪个接口<ul><li>流程: 借助交换机表(MAC - 接口 - 时间)<ul><li>没找到目的MAC, 向源以外的所有端口广播</li><li>找到MAC, 与源端口匹配, 则丢弃</li><li>找到MAC, 与另一端口匹配, 转发到这一端口(进入端口的缓存)</li></ul></li></ul></li></ul></li><li>自学习<ul><li>流程<ul><li>初始: 交换表为空</li><li>学习: 收到帧, 则将[源MAC地址 - 到达的接口 - 当前时间]存入交换表</li><li>老化: 一段时间后未收到这一地址作为源的帧, 则此表项移除</li></ul></li><li>即插即用设备: 无需进行配置</li><li>双工: 每个接口可同时发送和接收</li></ul></li><li>链路层交换机的性质<ul><li>消除碰撞: 星型拓扑, 没有因碰撞而浪费的带宽</li><li>异质链路: 链路彼此隔离, 允许不同速率, 新旧混用</li><li>管理: 检测异常适配器并断开之, 等</li></ul></li><li>交换机与路由器<ul><li>交换机<ul><li>优: 即插即用, 分组过滤, 高速率</li><li>缺: 拓扑限制为树形, 不提供广播风暴的保护</li></ul></li><li>路由器<ul><li>优: 拓扑灵活, 提供防火墙保护</li><li>缺: 需要配置, 处理延迟大</li></ul></li></ul></li></ul><h3 id="网桥"><a href="#网桥" class="headerlink" title="网桥"></a>网桥</h3><ul><li>功能: 读取A网(总线)的所有帧, 在B(总线)上重发每个帧; B-&gt;A同理</li><li>特点: 不更改帧, 原样转发; 带缓存; 路由寻址能力(基于MAC, 只转发需要转发的帧)</li><li>协议体系<ul><li>层次: 数据链路层 - MAC层</li><li>链接模式<ol><li><code>局域网 - 网桥 - 局域网</code>, 原样转发</li><li><code>局域网 - 网桥 - [网络或链路] - 网桥 - 局域网</code>, 需要适当封装, 但原始MAC帧不修改</li></ol></li></ul></li><li>固定路由选择<ul><li>每对点均有一条选定的路由, 跳数最少, 仅在拓扑变化时改变(生成树算法)</li></ul></li><li>生成树方法<ul><li>帧转发<ul><li>x收到帧</li><li>检查目的地址: 若在某一端口的列表中, 且非阻塞, 发送; 不在任何列表, 则x除以外的端口全部转发</li></ul></li><li>地址探索: 同交换机<ul><li>收到帧, 则帧源地址MAC与此端口关联, 加入此端口数据库</li><li>数据库项带计时器, 超时删除</li></ul></li><li>最小生成树算法: Prim<ul><li>Prim算法流程<ul><li>选取起始点(根网桥), 加入集合S</li><li>对于S中所有点(网桥), 在他们所有邻居里面找离S中点最短的距离, 把这个邻居加入S, 这条边(网桥间的最短距离)加入生成树</li><li>直到所有点都加入S, 边集合构成生成树</li></ul></li><li>网桥阻塞规则<ul><li>选择根网桥: ID最小的网桥</li><li>为每个网桥选择root port: 到根网桥最低开销的端口</li><li>为每个LAN指定网桥: 拥有到根网桥最低开销路径的, 与这个LAN相连的网桥</li><li>Designated port: 这个指定网桥与这个LAN相连的端口</li><li>Designated port 和 root port 不阻塞, 别的都阻塞</li></ul></li></ul></li></ul></li></ul><h3 id="虚拟局域网"><a href="#虚拟局域网" class="headerlink" title="虚拟局域网"></a>虚拟局域网</h3><ul><li>树形交换局域网的缺陷<ul><li>缺乏流量隔离: 单播能够隔离, 但广播不行; 缺乏安全隐私的隔离</li><li>交换机无效使用: 为了分组造成交换机端口的浪费</li><li>管理用户: 用户在分组间移动, 则需要改变物理布线, 连接到不同交换机</li></ul></li><li>VLAN: 单一的物理交换机定义多个虚拟局域网, 广播流量仅到达同一分组的端口<ul><li>跨VLAN需要路由器</li><li>VLAN划分: 端口 或 MAC</li><li>VLAN干线连接<ul><li>干线接口: VLAN交换机之间交换帧</li><li>帧格式802.1Q: 以太网帧的源地址和类型之间, 加入VLAN标志</li></ul></li></ul></li></ul><h1 id="第七章"><a href="#第七章" class="headerlink" title="第七章"></a>第七章</h1><h2 id="802-11-体系结构"><a href="#802-11-体系结构" class="headerlink" title="802.11 体系结构"></a>802.11 体系结构</h2><ul><li>接入点AP： 中央基站</li><li>基本服务集BSS: 1AP + 若干站点(其NIC有唯一MAC)</li><li>基础设施无线LAN: AP和将AP连接到路由器的有线以太网</li><li>信道与关联<ul><li>服务集标识符SSID: 热点名(单字/双字)</li><li>信道: 一共11个, 1 6 11是三个不重叠信道</li><li>关联: 站点选择一个AP, 仅通过它接入因特网<ul><li>信标帧: AP周期性广播发送, 包含SSID和MAC</li><li>被动扫描: 站点等待信标帧</li><li>主动扫描: 站点广播探测帧, AP回复探测响应帧</li><li>关联流程: 类似DHCP<ul><li>关联请求帧 -&gt; 关联响应帧 -&gt; (第二次握手, 与想关联的AP)</li></ul></li></ul></li></ul></li></ul><h2 id="CSMA-CA-802-11-MAC协议"><a href="#CSMA-CA-802-11-MAC协议" class="headerlink" title="CSMA/CA: 802.11 MAC协议"></a>CSMA/CA: 802.11 MAC协议</h2><ul><li>带碰撞避免的CSMA: CSMA/CA<ul><li>载波侦听</li><li>碰撞避免</li><li>使用链路层ARQ: 确认/重传, 有ACK</li></ul></li><li>不适用碰撞检测的原因<ul><li>接收信号的强度远小于发送信号的强度, 检测碰撞代价大</li><li>由于隐藏终端, 衰减问题, 无法检测所有的碰撞</li></ul></li><li>链路层确认方案<ul><li>目的接到帧, 且通过了CRC检验, 则等待”短帧间间隔SIFS”, 发回确认帧</li><li>发送站点在给定时间内未收到确认, 将会假定发生错误, 并重传该帧</li><li>多次重传失败, 将放弃发送并丢弃该帧</li></ul></li><li>CSMA/CA流程<ul><li>监听到信道空闲, 则在”分布式帧间间隔DIFS”的短时间后发送</li><li>否则, 选取一个随机回退值, 并在侦听信道空闲时递减该值, 若信道忙, 则不变</li><li>当值为0时, 发送整个帧</li><li>如果收到确认, 则该帧已被正确接收<ul><li>如果此时需要发下一帧, 直接从第二步开始</li><li>如果没有确认, 则进入第二步的回退, 并从更大的范围选取随机值</li></ul></li></ul></li><li>处理隐藏终端<ul><li>隐藏终端: AP与节点A B均相互可见, 但由于信号衰减, AB之间互相接收不到对方的信号, 无从进行载波侦听</li><li>请求发送(RTS)帧, 短: 站点广播, 指示传输DATA帧和ACK需要的总时间</li><li>允许发送(CTS)帧, 短: AP广播, 给发送方明确地许可, 并让其他站点知道不要发送<ul><li>收到CTS且不是自己发送RTS的站点, 将在其中的时间段内, 抑制发送</li></ul></li><li>效果<ul><li>解决隐藏终端, 长DATA只会在预约后才被传输</li><li>发生RTS和CTS的碰撞, 因为他们很短, 仅持续很短时间</li></ul></li><li>实际<ul><li>RTS门限值, 大于此的数据才会预约</li><li>许多站点的RTS门限大于帧长, 默认不使用RTS/CTS</li></ul></li></ul></li><li>点对点网络<ul><li>定向天线, 没其他站点, 相当于是AP与站点的点对点</li></ul></li></ul><h1 id="第九章"><a href="#第九章" class="headerlink" title="第九章"></a>第九章</h1><h2 id="提供多种类型的服务"><a href="#提供多种类型的服务" class="headerlink" title="提供多种类型的服务"></a>提供多种类型的服务</h2><ul><li>监管: 漏桶<ul><li>监管准则<ul><li>平均速率: 长时间速率存在最大值 - 漏桶的令牌产生速率</li><li>峰值速率: 短时间速率存在最大值 - (将桶容量定为1, 此时能够限制峰值速率)</li><li>突发长度: 极短时间(趋近0)发送的分组数量存在最大值 - 漏桶的高度</li></ul></li><li>漏桶描述<ul><li>分组首先进入令牌等待队列</li><li>在漏桶处取得令牌的分组将被发送</li><li>桶高度不超过b</li><li>每秒生成r个令牌加入桶</li></ul></li><li>效果<ul><li>平均速率: r + b/t, 时间足够长, 该值为r</li><li>突发长度: b</li><li>峰值速率: 在已有的一个漏桶后, 串联一个高度为1的桶, 其速率r’可限制峰值速率</li></ul></li></ul></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;计算机网络期末复习资料, 是结合给出的考点重新整理的资料&lt;br&gt;
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Computer Network" scheme="https://Maxwell-lyu.github.io/tags/Computer-Network/"/>
    
  </entry>
  
  <entry>
    <title>CN-ALT</title>
    <link href="https://Maxwell-lyu.github.io/2019/10/31/Learn-CN-20191031-CN-ALT/"/>
    <id>https://Maxwell-lyu.github.io/2019/10/31/Learn-CN-20191031-CN-ALT/</id>
    <published>2019-10-31T01:32:48.000Z</published>
    <updated>2019-11-03T11:30:54.887Z</updated>
    
    <content type="html"><![CDATA[<h1 id="局域网"><a href="#局域网" class="headerlink" title="局域网"></a>局域网</h1><h2 id="局域网概述"><a href="#局域网概述" class="headerlink" title="局域网概述"></a>局域网概述</h2><h3 id="总线和星型拓扑"><a href="#总线和星型拓扑" class="headerlink" title="总线和星型拓扑"></a>总线和星型拓扑</h3><ul><li>总线: 站点-&gt;分线头-&gt;总线<ul><li>帧: 数据块, 标明接收者</li><li>端接器: 总线尽头, 吸收帧</li></ul></li><li>星形: 站点-&gt;中心结点<ul><li>帧广播模式: 集线器</li><li>帧交换模式: 二层交换机<h3 id="局域网协议体系结构"><a href="#局域网协议体系结构" class="headerlink" title="局域网协议体系结构"></a>局域网协议体系结构</h3></li></ul></li><li><p>IEEE 802<br>层次结构</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">+--------------+----------------</span><br><span class="line">|              | 逻辑链路控制 LLC: 流量控制+差错控制</span><br><span class="line">|  数据链路层  +----------------</span><br><span class="line">|              | 媒体接入控制 MAC: 组帧+拆帧+差错检测+媒体接入</span><br><span class="line">+--------------+----------------</span><br></pre></td></tr></table></figure><p>帧结构</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">|           MAC帧           |            LLC PDU           | CRC |</span><br><span class="line">| MAC控制 | 目的MAC | 源MAC | DSAP | SSAP | LLC控制 | 信息 |     |</span><br><span class="line">                            /      |      \</span><br><span class="line">                   | I/G | DSAP 值 | C/R | SSAP值 |</span><br></pre></td></tr></table></figure></li><li><p>逻辑链路控制</p><ul><li>服务模式<ul><li>不确认的无链接服务: 数据报服务, 无流量控制和差错控制, 由上层提供</li><li>链接模式服务: 类似HDLC, 有逻辑链接</li><li>确认的无连接服务: 有ACK, 无逻辑链接</li></ul></li><li>协议<ul><li>[略]</li></ul></li></ul></li><li>媒体接入控制<ul><li>同步方法<ul><li>FDM, TDM</li></ul></li><li>异步方法<ul><li>循环: 轮流发送, 发送不超过上限的包<br>轮询(集中式), 令牌传递(分布式)</li><li>预约: 分时隙, 预约部分时隙</li><li>争用: 分布式, 适用于突发通信</li></ul></li></ul></li></ul><h3 id="网桥"><a href="#网桥" class="headerlink" title="网桥"></a>网桥</h3><ul><li>功能: 读取A网的所有帧, 在B上重发每个帧; B-&gt;A同理</li><li>特点: 不更改帧, 原样转发; 带缓存; 路由寻址能力</li><li>协议体系<ul><li>层次: 数据链路层 - MAC层</li><li>链接模式<ol><li><code>局域网 - 网桥 - 局域网</code>, 原样转发</li><li><code>局域网 - 网桥 - [网络或链路] - 网桥 - 局域网</code>, 需要适当封装, 但原始MAC帧不修改</li></ol></li></ul></li><li>固定路由选择<ul><li>每对点均有一条选定的路由, 跳数最少, 仅在拓扑变化时改变</li></ul></li><li>生成树方法<ul><li>帧转发<ul><li>x收到帧</li><li>检查目的地址: 若在某一端口的列表中, 且非阻塞, 发送; 不在任何列表, 则x除以外的端口全部转发</li></ul></li><li>地址探索<ul><li>收到帧, 则帧源地址MAC与此端口关联, 加入此端口数据库</li><li>数据库项带计时器, 超时删除</li></ul></li><li>生成树算法<ul><li>算法构造生成树, 部分网桥的部分端口被阻塞<h3 id="集线器和交换机"><a href="#集线器和交换机" class="headerlink" title="集线器和交换机"></a>集线器和交换机</h3></li></ul></li></ul></li><li>集线器<ul><li>站点发送, 集线器在到每个站点的出口转发信号</li><li>每节点容量: R/N</li></ul></li><li>第二层交换机<ul><li>类型<ul><li>直通交换机: 用目的MAC决定转发到哪</li><li>存储转发交换机: 存帧, 做CRC校验, 用目的MAC决定转发到哪</li></ul></li><li>与网桥的对比<ul><li>网桥软件分析帧, 交换机用硬件分析帧</li><li>网桥一次一个, 交换机有多个并行通道</li><li>网桥必须存储帧, 交换机可以不存</li></ul></li><li>转发流程类似网桥, 不赘述</li><li>每节点容量: R <h2 id="虚拟局域网"><a href="#虚拟局域网" class="headerlink" title="虚拟局域网"></a>虚拟局域网</h2></li></ul></li><li>单播地址: MAC指向唯一终点</li><li>广播地址: 局域网中的所有设备都应当接收</li><li>广播域: 彼此能够接收到刚广播帧的设备的集合</li></ul><h3 id="虚拟局域网的应用"><a href="#虚拟局域网的应用" class="headerlink" title="虚拟局域网的应用"></a>虚拟局域网的应用</h3><ul><li>虚拟局域网: 局域网中用软件创建的逻辑子集</li><li>层次: 在局域网交换机实现, 基于MAC, 工作在第二层</li><li>定义VLAN<ul><li>利用端口的成员关系: 每个终端端口分配给VLAN</li><li>利用MAC的成员关系: MAC固化在NIC, 据此分配VLAN</li><li>利用协议信息的成员关系: 交换机将查看高层协议内容</li></ul></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;局域网&quot;&gt;&lt;a href=&quot;#局域网&quot; class=&quot;headerlink&quot; title=&quot;局域网&quot;&gt;&lt;/a&gt;局域网&lt;/h1&gt;&lt;h2 id=&quot;局域网概述&quot;&gt;&lt;a href=&quot;#局域网概述&quot; class=&quot;headerlink&quot; title=&quot;局域网概述&quot;&gt;&lt;/a&gt;
      
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Computer Network" scheme="https://Maxwell-lyu.github.io/tags/Computer-Network/"/>
    
  </entry>
  
  <entry>
    <title>在VSCode中使用Jupyter Notebook</title>
    <link href="https://Maxwell-lyu.github.io/2019/10/11/Tech-20191011-juptyer-vscode/"/>
    <id>https://Maxwell-lyu.github.io/2019/10/11/Tech-20191011-juptyer-vscode/</id>
    <published>2019-10-11T02:04:03.000Z</published>
    <updated>2019-10-11T03:30:42.000Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>这个不是Jupyter Notebook的介绍啦, 默认本文的读者拥有使用Jupyter Notebook的经验<br><a id="more"></a> </p></blockquote><p>环境:  </p><ul><li>Python 3.7.4 64-bit  </li><li>VSCode 1.39.0</li><li>Windows 10 1903 <del>x64, 废话</del>  </li></ul><p>2019年10月9日, M$发布了Python插件的更新, 提供对<code>*.ipynb</code>文件的支持, 即Jupyter支持. 于是就可以通过更新Python插件, 直接在VSCode里面使用Jupyter nb啦</p><h1 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h1><h2 id="安装Python插件"><a href="#安装Python插件" class="headerlink" title="安装Python插件"></a>安装Python插件</h2><p>点击插件信息页, 查看Extensions-Installed, 确认你的插件版本是<code>2019.10.41019</code>, 若不是, 请检查自动更新插件设置, 应当为以下:<br><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">"extensions.autoUpdate": true</span><br></pre></td></tr></table></figure></p><p>或者手动点击<code>Update</code>, 或者卸载插件重装</p><p>你可能会遇到以下问题:  </p><ul><li>我不是<strong>Insider</strong>: 根本不需要Insider版</li><li>没安装过Python插件: <del>咋回事啊小老弟</del> 在Extensions当中搜索<code>python @sort:installs</code>, 列表顶端的即为所需的插件, 点击<code>Install</code>安装  </li></ul><h2 id="重启VSCode"><a href="#重启VSCode" class="headerlink" title="重启VSCode"></a>重启VSCode</h2><p><strong>重启VSCode</strong>,请<strong>重启VSCode</strong><br>这个重启可以解决: </p><ul><li><strong>Command Panel</strong> 没有 Jupyter NB 相关命令</li><li>我没遇到的<strong>疑难杂症</strong>中的一部分</li></ul><h2 id="安装Jupyter及其依赖"><a href="#安装Jupyter及其依赖" class="headerlink" title="安装Jupyter及其依赖"></a>安装Jupyter及其依赖</h2><blockquote><p>如果你已经在用Jupyter NB, 这段不用看辣  </p></blockquote><p>按下组合键<code>Ctrl+Shift+P</code>, 输入<code>&gt; Python: Create New Blank Jupyter Notebook</code>, 按<code>Enter</code>, 可以建立一个<code>*.ipynb</code>文件<br>在一个新的cell当中写<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">print(<span class="string">'anything'</span>)</span><br></pre></td></tr></table></figure></p><p>点按钮执行cell, 如果未曾安装过Jupyter, 将会报错, 点击报错信息中的<code>Install</code>按钮, VSCode会帮你<strong>搞定一切</strong>, 除非你网络不好</p><h2 id="重启VSCode-1"><a href="#重启VSCode-1" class="headerlink" title="重启VSCode"></a>重启VSCode</h2><p><strong>重启VSCode</strong>,请<strong>重启VSCode</strong><br>这个重启可以解决: </p><ul><li><code>*.ipynb</code>文件<strong>没有Intellisense</strong></li><li>我没遇到的<strong>疑难杂症</strong>中的一部分</li></ul><h1 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h1><p>这里主要说点废话  </p><ul><li>打开VSCode后, 如果你的Jupyter Server是local, 建议你随便执行点什么cell, 这时会start jupyter server(嗯, 半自动), 要等一会儿, 之后就可以丝滑写码了  </li><li><strong>导出图像</strong>, 想要啥配色就先换VSCode的color theme, 导出图像目前还是只能按照这个来</li><li><p><strong>远程配置</strong>? 我不会, 用的local, url贴在这里, token应该包含在url里面</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">"python.dataScience.jupyterServerURI": "&gt;&gt;&gt;YOUR URL HERE&lt;&lt;&lt;"</span><br></pre></td></tr></table></figure></li><li><p>BUG: </p><ul><li>没法<strong>折叠执行结果框</strong></li><li>文件末尾的cell执行时, 会<strong>自动创建一个新cell</strong>, 有时候很烦, 这其实可以说是feature</li><li><del>convert to python script 之后, 里面还会显示<code>Run Cell</code>等按钮, 尽量别点, 有可能<strong>VSCode直接崩溃</strong></del><br>当我没说, 重启VSCode之后问题就消失了, 重启大法好</li></ul></li></ul><h1 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h1><p><a href="https://zhuanlan.zhihu.com/p/85445777" target="_blank" rel="noopener">韩骏的知乎专栏</a><br>请给这篇文章点赞, 另外评论区有很多问题的解决方案, 遇到问题可以看下评论区</p>]]></content>
    
    <summary type="html">
    
      &lt;blockquote&gt;
&lt;p&gt;这个不是Jupyter Notebook的介绍啦, 默认本文的读者拥有使用Jupyter Notebook的经验&lt;br&gt;
    
    </summary>
    
      <category term="Technique" scheme="https://Maxwell-lyu.github.io/categories/Technique/"/>
    
    
      <category term="Utility" scheme="https://Maxwell-lyu.github.io/tags/Utility/"/>
    
  </entry>
  
  <entry>
    <title>DIP-ALL</title>
    <link href="https://Maxwell-lyu.github.io/2019/09/12/Learn-DIP-20190912-DIP-ALL/"/>
    <id>https://Maxwell-lyu.github.io/2019/09/12/Learn-DIP-20190912-DIP-ALL/</id>
    <published>2019-09-12T04:53:15.000Z</published>
    <updated>2019-12-09T01:47:33.648Z</updated>
    
    <content type="html"><![CDATA[<h1 id="第二讲-空间域图像增强-Part-I"><a href="#第二讲-空间域图像增强-Part-I" class="headerlink" title="第二讲: 空间域图像增强(Part I)"></a>第二讲: 空间域图像增强(Part I)</h1><h2 id="图像内插"><a href="#图像内插" class="headerlink" title="图像内插"></a>图像内插</h2><ul><li>用已知的数据来估计未知位置的数值</li><li>按照边角对齐像素点阵, 之后有如下插值方法</li></ul><h3 id="最近邻内插法"><a href="#最近邻内插法" class="headerlink" title="最近邻内插法"></a>最近邻内插法</h3><ul><li>取最近邻像素的灰度为此像素的灰度</li></ul><h3 id="双线性内插法"><a href="#双线性内插法" class="headerlink" title="双线性内插法"></a>双线性内插法</h3><ul><li>4个最近邻进行估计, 解有4个等式组成的方程组<br>$$v(x,y)=ax+by+cxy+d$$</li></ul><h3 id="双三次内插法"><a href="#双三次内插法" class="headerlink" title="双三次内插法"></a>双三次内插法</h3><ul><li>16个最近邻去估计, 解16个等式组成的方程组<br>$$v(x,y)=\sum_{i=0}^3\sum_{j=0}^3a_{ij}x^iy^j$$</li></ul><h2 id="像素间的基本关系"><a href="#像素间的基本关系" class="headerlink" title="像素间的基本关系"></a>像素间的基本关系</h2><h3 id="相邻像素"><a href="#相邻像素" class="headerlink" title="相邻像素"></a>相邻像素</h3><p>设$p:(x,y)$为一像素</p><ul><li>4邻域: 上下左右<br>$$N_4(p)=(x-1,y), (x+1,y), (x,y-1), (x,y+1)$$</li><li>4对角邻域: 对角线四个方向<br>$$N_D(p)=(x-1,y-1), (x-1,y+1), (x+1,y-1), (x+1,y+1)$$</li><li>8邻域(p): 周围的8个像素<br>$$N_8=N_4+N_D$$</li></ul><h3 id="邻接性"><a href="#邻接性" class="headerlink" title="邻接性"></a>邻接性</h3><ul><li>定义: 令$V$为用于定义邻接性的灰度值集合<ul><li>二值图像: $V=\{1\}$或$V=\{0\}$</li><li>非二值图像: 灰度级的子集, 如$V=\{128, 129,\cdots, 255\}$</li></ul></li><li>$V$集合将灰度级化为2个等价类, 也可认为它将灰度图像染成二值图像</li><li>4邻接: $q\in N_4(p)$, $q$与$p$的灰度都在$V$中</li><li>8邻接: $q\in N_8(p)$, $q$与$p$的灰度都在$V$中</li><li>m邻接(混合邻接): $q$与$p$的灰度都在$V$中, 且:<br>若$q\in N_4(p)$;<br>或$q\in N_D(p)$, 且$N_4(p)\cap N_4(q)$的灰度都不在集合$V$中</li></ul><h3 id="连通性"><a href="#连通性" class="headerlink" title="连通性"></a>连通性</h3><ul><li>通路: $(x_0=x, y_0=y),(x_1, y_1), \cdots, (x_{N-1}, y_{N-1}),(x_N=s,y_N=t)$<ul><li>相邻的像素点是邻接的</li><li>长度为$N$</li><li>若$(x,y)=(s,t)$, 则为闭合通路</li></ul></li><li>连通集<ul><li>在$S$中是连通: 取$S$额外i图像中像素的子集. 如果在$S$中全部u像素之间存在一条$p$到$q$的通路, 则说明$p$和$q$在$S$中是连通的</li><li>连通分量: 对于$S$中任何像素$p$, $S$中连通到该像素的像素集叫做$S$的连通分量</li><li>连通集: 若$S$仅有一个连通分量, 则$S$叫做连通集</li></ul></li></ul><h3 id="区域"><a href="#区域" class="headerlink" title="区域"></a>区域</h3><ul><li>区域: $R$为连通集, 则$R$称为区域</li><li>邻接区域: 如果两个区域联合形成一个连通集, 那么他们是邻接区域</li><li>假设图像包括$K$个不连接的区域, 即$R_1, R_2, \cdots, R_K$, 且不接触边界<ul><li>前景: $K$个区域的并集$R_u$</li><li>背景: 其补集$(R_u)^C$</li></ul></li></ul><h3 id="边界"><a href="#边界" class="headerlink" title="边界"></a>边界</h3><ul><li>一个区域R的边界（也称为边缘或轮廓线）是区域$R$中像素的集合<ul><li>这些点与R补集中的点邻近</li><li>这些点至少有一个背景邻点</li></ul></li><li>用8连通定义</li><li>边界与边缘<ul><li>边界：一个有限区域的边界（通常）形成一条闭合通路, 是个“整体”概念</li><li>边缘：具有某些导数值（超过预先设定的阈值）的像素形成, 是个“局部”概念</li><li>边界只考察其邻点是否属于集合V, 属于二值判断。边缘考察灰度级的差别, 粒度更细。边缘可能不闭合</li><li>什么时候边缘=边界？二值图像</li></ul></li></ul><h3 id="距离度量"><a href="#距离度量" class="headerlink" title="距离度量"></a>距离度量</h3><ul><li>$D$为距离函数, 若<ul><li>$D(p,q)\geq 0$, 且$D(p,q)=0$当且仅当$p=q$</li><li>$D(p,q)=D(q,p)$</li><li>$D(p,z)\leq D(p,q)+D(q,z)$</li></ul></li><li>欧式距离<br>$$D_r(p,q)=\sqrt{(x-s)^2+(y-t)^2}$$</li><li>$D_4$距离(曼哈顿距离)<br>$$D_4(p,q)=|x-s| + |y-t|$$</li><li>$D_8$距离(棋盘距离)<br>$$D_8(p,q)=\max(|x-s|,|y-t|)$$</li></ul><h2 id="空间域图像增强背景知识"><a href="#空间域图像增强背景知识" class="headerlink" title="空间域图像增强背景知识"></a>空间域图像增强背景知识</h2><ul><li>增强的首要目标是处理图像, 使其比原始图像更适合于特定应用, 没有通用的理论和标准</li><li>方法<ul><li>空间域方法: 图像平面本身, 直接处理像素: 离散</li><li>变换域方法: 频域(傅里叶变换): 连续<blockquote><p>空间域-&gt;变换域-&gt;处理-&gt;空间域</p></blockquote></li></ul></li><li>空间域方法是直接对像素操作的过程<br>$g(x,y)=T(f(x,y))$<br>$g$: 输出图像; $T$: 操作算子, 定义在$(x,y)$的邻域; $f$: 原始图像<blockquote><p>边界: 忽略外部, 填充</p></blockquote></li><li>类型<ul><li>空间滤波<ul><li>空间滤波器: 邻域, 预定义的操作</li></ul></li><li>灰度变换<ul><li>邻域大小为1的空间滤波</li><li>灰度变换函数$s=T(r)$</li><li>函数可以存储在一维数组, 查表实现映射</li></ul></li></ul></li></ul><h2 id="基本灰度变换"><a href="#基本灰度变换" class="headerlink" title="基本灰度变换"></a>基本灰度变换</h2><ul><li>线性函数<ul><li>图像反转公式: $s=L-1-r$, $L=2^b$</li><li>改变分析图象的难易</li></ul></li><li>对数函数<ul><li>低灰度值拉伸, 高灰度值压缩: $s=c\log(1+r)$</li><li>看到更多细节</li></ul></li><li>幂律函数<ul><li>伽马变换: $s=cr^\gamma$</li><li>更接近真实值(显示器)</li><li>调节参数$\gamma$可以在细节和对比度当中权衡</li></ul></li><li><p>分段线性函数</p><blockquote><p>折线: $(0,0)-&gt;(r_1,s_1)-&gt;(r_2,s_2)-&gt;(L-1, L-1)$</p><ul><li>对比拉伸变换: 单调递增</li><li>线性函数: $s_1=r_1$, $s_2=r_2$</li><li>阈值处理函数: $r_1=r_2$, $s_1=0$, $s_2=L-1$</li><li>灰度级分层: 突出特定灰度范围的亮度<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">   +---+</span><br><span class="line">   |   |</span><br><span class="line">---+   +---</span><br></pre></td></tr></table></figure></li></ul></blockquote></li><li><p>比特平面分层</p><ul><li>突出特定比特的作用: 8比特图像可认为有8个1比特平面组成</li><li>高阶比特: 视觉上重要的数据</li><li>低阶比特: 精细的灰度细节</li><li>函数实现: 第$n$比特平面: $r=(s&gt;&gt;(n-1)) \&amp; 1$</li><li>应用: 确定量化该图像比特数的充分性, 图像压缩(伪轮廓)</li></ul></li></ul><h2 id="直方图处理"><a href="#直方图处理" class="headerlink" title="直方图处理"></a>直方图处理</h2><ul><li>灰度直方图$H(D)$<ul><li>横坐标: 灰度级</li><li>纵坐标: 该灰度级出现的频率(此灰度级像素的数量)</li></ul></li><li>阈值面积函数$A(D)$<ul><li>连续图像中具有灰度级$\geq D$的轮廓线所包围的面积<br>$$A(D)-\int_D^\infty H(p)dp$$</li></ul></li><li>概率密度函数(PDF)<ul><li>归一化到单位面积的直方图<br>$$PDF=P(D)=\frac{1}{A_0}H(D)$$</li></ul></li><li>累计分布函数(CDF)<ul><li>归一化后灰度级$\geq D$的轮廓线所包围的面积<br>$$CDF=P(D)=\inf_0^Dp(u)du=\frac{1}{A_0}H(u)du$$</li></ul></li><li>严格的数学定义<br>$$H(D=\lim_{\delta D\to 0}\frac{A(D)-A(D+\delta D)}{D+\delta D-D}=\lim_{\delta D\to 0}\frac{A(D)-A(D+\delta D)}{\delta D}=-\frac{d}{dD}A(D)$$<ul><li>数字图像时, 简化为<br>$$H(D)=A(D)-A(D+1)$$</li></ul></li><li>实现<ol><li>初始化hist[k]=0; k=0, …, L-1</li><li>统计hist[f(x,y)]++; x=0, …, M-1; y=0, …,N-1</li><li>归一化hist[f(x,y)]/(M*N)</li></ol></li><li>应用<ol><li>图像快速检测: 是否合理的利用了全部被允许的灰度级范围, 从而及早发现数字化中出现的问题</li><li>分割前景背景: 双峰直方图, 取低谷灰度值作为分割点</li><li>面积计算: 类似前景背景, 用直方图计数像素</li></ol></li></ul><h1 id="第三讲-空间域图像增强-Part-II"><a href="#第三讲-空间域图像增强-Part-II" class="headerlink" title="第三讲: 空间域图像增强(Part II)"></a>第三讲: 空间域图像增强(Part II)</h1><h2 id="直方图均衡化"><a href="#直方图均衡化" class="headerlink" title="直方图均衡化"></a>直方图均衡化</h2><ul><li>直方图均匀分布时, 对比度会有明显增强</li><li>通过灰度变换函数, 将原图像直方图的分布均衡化, 这一过程称为直方图均衡化用灰度变换函数让直方图均匀分布</li><li>线性运算: $s=T(r)=a\times r + b$</li><li>灰度变换函数与直方图<ul><li>输入图像的概率密度: $p_r(r)$; 输出图像的概率密度: $p_s(s)$; 变换函数$T$<blockquote><p>这里只考虑单调递增函数</p></blockquote></li><li>单调连续函数<ul><li>$r\in [0,L-1]$<br>$$s=T(r)$$<ul><li>$T(r)$在区间$[0,L-1]$内是单调递增函数</li><li>当$0\leq r\leq L-1$时, $0\leq T(r)\leq L-1$</li></ul></li><li>更强的假设<ul><li>$T(r)$在区间$[0,L-1]$是严格单调递增函数, 此时有逆函数<br>$$r=T^{-1}(s)$$</li></ul></li></ul></li><li>概率密度公式<br>$$p_s(s)=p_r(r)|\frac{dr}{ds}|=p_r(r)|(\frac{ds}{dr}06{-1}|=p_r(T^{-1}(s))|\frac{1}{T’(T^{-1}(s))}|$$</li></ul></li><li>连续函数<ul><li>设计$T(r)$, 使得$p_s(s)$是均匀分布<br>$$s=T(r)=(L-1)\int_0^rp_r(w)dw$$</li></ul></li><li>离散直方图<br>$$s_k=T(r_k)=(L-1)\sum_{j=0}^k p_r(r_j)$$<h2 id="直方图匹配-规定化"><a href="#直方图匹配-规定化" class="headerlink" title="直方图匹配(规定化)"></a>直方图匹配(规定化)</h2></li><li>处理后的图像具有某种指定的直方图形状</li><li>这种用于产生处理后有特殊直方图的图像的方法, 叫做直方图匹配或直方图规定化处理</li><li>以均衡化直方图为桥梁: A:$p_r(r)$–&gt;B(均衡化图像):$p_s(s)$–&gt;C:$p_z(z)$<ul><li>输入图像灰度值概率密度$p_r(r)$<br>$$s=T(r)=(L-1)\int_0^rp_r(w)dw$$</li><li>指定灰度值概率密度$p_z(z)$<br>$$G(z)=(L-1)\int_0^zp_z(t)dt=s$$</li><li>反函数唯一<br>$$z=G^{-1}(s)=G^{-1}(T(r))$$</li></ul></li><li>离散直方图<ul><li>输入离散直方图$p_r(r_k)$<br>$$s_k=\frac{L-1}{MN}\sum_{j=0}^kn_j$$</li><li>指定离散直方图$p_z(z_k)$<br>$$G(z_q)=(L-1)\sum_{i=0}^qp_z(z_i)=s_k$$</li><li>查表实现: 取邻近值, 不唯一时取最小的<br>$$z_q=G^{-1}(s_k)$$<h2 id="局部直方图均衡化"><a href="#局部直方图均衡化" class="headerlink" title="局部直方图均衡化"></a>局部直方图均衡化</h2></li></ul></li><li>特性<ul><li>整体处理, 小细节易被忽略</li><li>只希望对局部进行增强</li><li>图像中每个像素的邻域中灰度分布为基础设计变换函数</li></ul></li><li>步骤<ul><li>定义一个邻域, 不断平移中心位置<ul><li>每一位置, 计算该领域中, 点的直方图</li><li>利用直方图均衡化或匹配得到变换函数</li><li>将变换函数作用到邻域中心像素</li></ul></li><li>重复上述过程<h2 id="直方图统计量用于局部图像增强"><a href="#直方图统计量用于局部图像增强" class="headerlink" title="直方图统计量用于局部图像增强"></a>直方图统计量用于局部图像增强</h2></li></ul></li><li>局部均值<br>$$m_{s_{xy}}=\sum_{i=0}^{L-1}r_ip_{s_{xy}}(r_i)$$</li><li>局部方差<br>$$\sigma^2_{s_{xy}}=\sum_{i=0}^{L-1}(r_i-m_{s_{xy}})^2p_{s_{xy}}(r_i)$$</li><li>局部直方图统计增强<br>$$g(x,y)=\begin{cases}<br>  E\cdot f(x,y) &amp;\textrm{if }m_{s_{xy}}\leq k_0m_G\textrm{ AND }k_1\sigma_G\leq \sigma_{s_{xy}}\leq k_2\sigma_G \\<br>  f(x,y) &amp;\textrm{otherwise}<br>\end{cases}$$</li></ul><h1 id="第四讲-空间域图像增强-Part-III"><a href="#第四讲-空间域图像增强-Part-III" class="headerlink" title="第四讲: 空间域图像增强(Part III)"></a>第四讲: 空间域图像增强(Part III)</h1><h2 id="空间滤波"><a href="#空间滤波" class="headerlink" title="空间滤波"></a>空间滤波</h2><h3 id="空间滤波基础"><a href="#空间滤波基础" class="headerlink" title="空间滤波基础"></a>空间滤波基础</h3><ul><li>空间滤波机理<ul><li>空间滤波器<ul><li>邻域(矩形)</li><li>预定义的操作</li></ul></li><li>$m\times n$的模板<ul><li>$m=2a+1$, $n=2b+1$</li><li>最小为$3\times3$</li></ul></li><li>滤波操作</li><li>线性滤波<->频率域滤波</-></li></ul></li><li>空间相关与卷积<ul><li>相关: 平移滤波器模板, 计算每个位置乘积求和<ul><li>补零, 计算, 滑动, 裁剪</li><li>[补公式]</li><li>寻找匹配: 归一化乘积(向量长度为1), 值最大时, 图像与模板相同</li></ul></li><li>卷积: 滤波器要旋转180, 其他与相关相同<ul><li>旋转, 补零, 计算, 滑动, 裁剪</li><li>[补公式]</li></ul></li><li>线性滤波的向量表示: 矩阵相乘拉成向量相乘</li></ul></li><li>空间滤波器模板<ul><li>计算平均灰度</li><li>两变量的连续函数</li><li>非线性滤波器<h3 id="平滑空间滤波器"><a href="#平滑空间滤波器" class="headerlink" title="平滑空间滤波器"></a>平滑空间滤波器</h3></li></ul></li><li>均值滤波器<ul><li>优点: 降低噪声; 缺点: 边缘模糊</li><li>先求和, 再归一化(先乘全1矩阵, 后除以9)</li></ul></li><li>加权线性滤波器<ul><li>非均匀权重, 降低模糊</li></ul></li><li>非线性滤波器<ul><li>对滤波器覆盖的像素排序, 排序决定的值替代中心线像素</li></ul></li><li>中值滤波器, 最大值滤波器, 最小值滤波器<h3 id="锐化空间滤波器"><a href="#锐化空间滤波器" class="headerlink" title="锐化空间滤波器"></a>锐化空间滤波器</h3>突出灰度的过渡部分</li><li>数学基础<ul><li>微分取值<br>||恒定灰度|恒定斜率|突变|<br>|-|-|-|-|<br>|一阶微分|0|非0|非0|<br>|二阶微分|0|0|非0|</li><li>使用二阶微分对图像锐化</li></ul></li><li>各向同性滤波器</li><li>拉普拉斯算子<ul><li>标准形式: 四角0, 四边1, 中间-4</li><li>对角形式: 四角四边1, 中间-8</li><li>拉普拉斯算子的结果叠加到图像中, 取中心系数为-1</li></ul></li><li>非锐化掩蔽<ul><li>模糊图像, 原图减去模糊图像得到模板, 加到原图像</li></ul></li><li>梯度<ul><li>利用梯度的大小<ul><li>梯度: 最大变化率的方向<br>$$\nabla f\equiv\mathrm{grad}(f)\equiv \begin{bmatrix} g_x \\ g_y \end{bmatrix} = \begin{bmatrix} \frac{\partial f}{\partial x} \\ \frac{\partial f}{\partial y} \end{bmatrix}$$</li><li>大小:<br>$$M(x,y)=\mathrm{mag}(\nabla f)=\sqrt{g_x^2 + g_y^2}\approx |g_x|+|g_y|$$</li></ul></li><li>梯度的离散近似<ul><li>最简单的近似:<br>$$\begin{aligned}<br>  g_x &amp;= z_8 - z_5\\<br>  g_y &amp;= z_6 - z_5\\<br>\end{aligned}$$</li><li>交叉差分: 罗伯特交叉梯度算子<br>$$\begin{aligned}<br>  g_x &amp;= (z_7+2z_8+z_9) - (z_1+2z_2+z_3)\\<br>  g_y &amp;= (z_3+2z_6+z_9) - (z_1+2z_4+z_7)\\<br>\end{aligned}$$</li><li>对称模板: Soble算子<h3 id="混合空间增强法"><a href="#混合空间增强法" class="headerlink" title="混合空间增强法"></a>混合空间增强法</h3></li></ul></li></ul></li><li>综合使用各种增强方法</li></ul><h2 id="算术操作增强"><a href="#算术操作增强" class="headerlink" title="算术操作增强"></a>算术操作增强</h2><p>像素对像素为基础, 在两幅或多幅图像之间进行</p><ul><li>加法<ul><li>定理: 对M幅加性噪声图像进行平均, 可以使图像的平方信噪比提高M倍</li></ul></li><li>减法<ul><li>图像差别的细节被观察到</li></ul></li><li>乘法：通常用来进行掩模运算</li><li>除法：通常可以用来归一化</li></ul><h1 id="第五讲-空间域图像增强-Part-IV"><a href="#第五讲-空间域图像增强-Part-IV" class="headerlink" title="第五讲: 空间域图像增强(Part IV)"></a>第五讲: 空间域图像增强(Part IV)</h1><h2 id="集合操作"><a href="#集合操作" class="headerlink" title="集合操作"></a>集合操作</h2><h3 id="灰度图像的集合操作"><a href="#灰度图像的集合操作" class="headerlink" title="灰度图像的集合操作"></a>灰度图像的集合操作</h3><ul><li>灰度图像集合$A$, 其元素为三元组$(x,y,z)$</li><li>补集<br>$$A^C=\{(x,y,K-z)|(x,y,z)\in A\}$$</li><li>并集<br>$$A\cup B=\{\max_{z}(a,b),a\in A,b\in B\}$$</li></ul><h2 id="逻辑操作"><a href="#逻辑操作" class="headerlink" title="逻辑操作"></a>逻辑操作</h2><ul><li>针对二值图像: 前景1, 背景0</li><li>OR(集合并), AND(集合交), NOT(集合补)逻辑操作</li><li>减(属于A不属于B)</li><li>XOR操作</li><li>功能完备操作: AND OR NOT三者可表达其他操作</li></ul><h2 id="空间操作"><a href="#空间操作" class="headerlink" title="空间操作"></a>空间操作</h2><h3 id="单像素操作-改变单个像素的灰度"><a href="#单像素操作-改变单个像素的灰度" class="headerlink" title="单像素操作: 改变单个像素的灰度"></a>单像素操作: 改变单个像素的灰度</h3><p>  灰度变换: $s=T(z)$</p><h3 id="邻域操作-由输入像素的邻域像素决定"><a href="#邻域操作-由输入像素的邻域像素决定" class="headerlink" title="邻域操作: 由输入像素的邻域像素决定"></a>邻域操作: 由输入像素的邻域像素决定</h3><p>  空间滤波: $g(x,y)=\frac{1}{mn}\sum_{(r,c)\in S_{xy}}f(r,c)$</p><h3 id="几何变换"><a href="#几何变换" class="headerlink" title="几何变换"></a>几何变换</h3><ul><li>橡皮膜操作: 在橡皮膜上印刷图像, 然后拉伸橡皮膜</li><li>两个独立算法<ul><li>空间变换<ul><li>每个左边点变换到新坐标点$(x,y)=T\{(v,w)\}$, 可能不在网格点上</li><li>需要满足: 相邻输入产生相邻输出(保持曲线连续性和物体连通性)</li><li>仿射变换<br>$$\begin{cases}<br>  x &amp;= t_{11}v + t_{21}w+t_{31}\\<br>  y &amp;= t_{12}v + t_{22}w+t_{32}\\<br>\end{cases}$$<br>$$\begin{bmatrix}<br>  t_{11} &amp;t_{11} &amp;0\\<br>  t_{21} &amp;t_{21} &amp;0\\<br>  t_{31} &amp;t_{31} &amp;1<br>\end{bmatrix}$$<ul><li>$t_{31}$, $t_{32}$平移</li><li>$t_{11}$, $t_{22}$伸缩比例</li><li>$t_{12}$, $t_{21}$倾斜</li><li>保持共线性, 保持距离比例(线的中心变换后依然是中心)</li><li>基本仿射变换: 恒等, 平移, 旋转, 伸缩, 倾斜(x), 倾斜(y)</li><li>复杂仿射变换: 简单仿射变换矩阵的乘积(右乘)</li><li>逆仿射变换: 需要每个仿射变换均可逆(基本仿射变换均可逆)</li></ul></li></ul></li><li>图像配准<ul><li>具体问题<ul><li>图像B中的$n$个点<br>$$P=\begin{bmatrix}<br>  v_0 &amp;w_0 &amp;1\\<br>  v_1 &amp;w_1 &amp;1\\<br>  \cdots &amp;\cdots &amp;1\\<br>  v_{n-1} &amp;w_{n-1} &amp;1\\<br>\end{bmatrix}$$</li><li>图像A中的$n$个点<br>$$Q=\begin{bmatrix}<br>  x_0 &amp;y_0 &amp;1\\<br>  x_1 &amp;y_1 &amp;1\\<br>  \cdots &amp;\cdots &amp;1\\<br>  x_{n-1} &amp;y_{n-1} &amp;1\\<br>\end{bmatrix}$$</li><li>寻找最优仿射变换<br>$$Q=PT$$</li><li>求解线性方程</li><li>求解最小二乘<br>$$\min_{t}||Q-PT||^2_F$$<ul><li>闭合解<br>$$T=(P^TP)^{-1}P^TQ$$</li></ul></li></ul></li><li>一般流程<ul><li>建模: 双线性近似(8个参数)<br>$$\begin{cases}<br>  x &amp;= c_1v + c_2w + c_3vw + c_4\\<br>  y &amp;= c_5v + c_6w + c_7vw + c_8\\<br>\end{cases}$$</li><li>寻找约束点: 4个约束点, 8个方程, 求解方程组</li><li>执行映射: 灰度内插</li><li>增加约束点: 原图分成多个四边形, 逐个处理</li></ul></li></ul></li></ul></li></ul><h2 id="灰度内插"><a href="#灰度内插" class="headerlink" title="灰度内插"></a>灰度内插</h2><ul><li>前向映射<ul><li>根据输入$(v,w)$计算$(x,y)=T\{(v,w)\}$</li><li>将该像素的灰度值分配给相邻的四个网格位置</li></ul></li><li>反向映射<ul><li>根据输出$(x,y)$寻找输入$(v,w)=T^{-1}\{(x,y)\}$, 灰度内插, 更加有效</li><li>找到相关的四个源像素灰度值, 据此计算该点的灰度值</li></ul></li><li>插值方法<ul><li>最邻近: 选取最邻近的那个点的灰度, 直接使用</li><li>(1维函数)线性内插: 某一邻近点所占比重, 为距离的倒数</li><li>双线性内插(4邻点)<ul><li>方法1<ul><li>先在x方向, 两两线性内插, 得到的2个点再在y方向线性内插<br>$$f(x,y)=\frac{1}{(x_2-x_1)(y_2-y_1)}\begin{bmatrix}<br>  x_2-x &amp;x-x_1<br>\end{bmatrix}\begin{bmatrix}<br>  f(Q_{11}) &amp;f(Q_{12})\\<br>  f(Q_{21}) &amp;f(Q_{22})<br>\end{bmatrix}\begin{bmatrix}<br>  y_2-y\\<br>  y-y_1<br>\end{bmatrix}$$</li></ul></li><li>方法2<ul><li>灰度值表示为坐标的函数<br>$$f(x,y)\approx a_0+a_1x+a_2y+a_3xy$$</li><li>用周围4个点求解这些系数, 之后带入x,y即可</li><li>解出来是一大堆东西, 不抄了, 值应当与方法1是一致的</li></ul></li></ul></li><li>双三次内插<ul><li>方法1(4邻点)<ul><li>使用以下4个公式, 用4个邻点列出16个方程<br>$$\begin{cases}<br>  p(x,y) &amp;= \sum_{i=0}^3\sum_{j=0}^3a_{ij}x^iy^j\\<br>  p_x(x,y) &amp;= \sum_{i=1}^3\sum_{j=0}^3a_{ij}ix^{i-1}y^j\\<br>  p_y(x,y) &amp;= \sum_{i=0}^3\sum_{j=1}^3a_{ij}x^ijy^{j-1}\\<br>  p_{xy}(x,y) &amp;= \sum_{i=1}^3\sum_{j=1}^3a_{ij}ix^{i-1}jy^{j-1}<br>\end{cases}$$</li></ul></li><li>方法2(16邻点)<ul><li>只用第一个公式, 带入16个邻点求解系数, 再带回x,y</li></ul></li></ul></li></ul></li></ul><h1 id="第六讲-频率域图像增强-Part-I"><a href="#第六讲-频率域图像增强-Part-I" class="headerlink" title="第六讲: 频率域图像增强(Part I)"></a>第六讲: 频率域图像增强(Part I)</h1><h2 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h2><ul><li>图像增强方法比较<ul><li>空间域方法: 图像平面本身, 对像素直接处理</li><li>频率域方法: 修改图像的频谱, 例如傅里叶变换为基础</li></ul></li><li>图像是连续信号的量化采样<ul><li>信号通常包括丰富的频域信息</li><li>傅里叶级数<ul><li>周期函数: 表示为不同频率的正弦函数和/或余弦函数 加权之和</li><li>非周期函数: 表示为不同频率的正弦函数和/或余弦函数 加权之后的积分</li><li>意义: 频域信息如何表示, 热扩散, 信号处理</li></ul></li></ul></li></ul><h2 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h2><h3 id="复数-C"><a href="#复数-C" class="headerlink" title="复数$C$"></a>复数$C$</h3><ul><li>一般表示<br>$$C=R+jH$$<br>$R,H\in\mathbb{R}, i=\sqrt{-1}$ </li><li>极坐标表示<br>$$C=|C|(\cos\theta +j\sin\theta)$$<br>$|C|=\sqrt{R^2+I^2}$为长度, $\theta$为夹角</li><li>欧拉公式<br>$$e^{j\theta}=\cos\theta+j\sin\theta$$</li><li>极坐标表示<br>$$C=|C|e^{j\theta}$$</li><li>共轭<br>$$C^*=R-jI$$</li><li>复函数<br>$$F(u)=R(u)+jI(u)$$<br>幅值$|F(u)|=\sqrt{R(u)^2+I(u)^2}$<br>角度$\theta=\arctan(I(u)/R(u)),[-\pi,\pi]$</li><li>复共轭函数<br>$$F(u)=R(u)-jI(u)$$</li></ul><h3 id="冲激与采样"><a href="#冲激与采样" class="headerlink" title="冲激与采样"></a>冲激与采样</h3><ul><li>连续冲激与采样<ul><li>在0处的连续单位冲激<br>$$\delta(t)=\begin{cases}<br>  \infty\quad&amp;\text{if }t=0\\<br>  0\quad &amp;\text{if }t\ne0<br>\end{cases}$$<br>并且满足<br>$$\int_{-\infty}^{\infty}\delta(t)dt=1$$<ul><li>采样性质<br>$$\int_{-\infty}^{\infty}f(t)\delta(t)dt=f(0)$$</li></ul></li><li>在$t_0$处的连续单位冲激<br>$$\delta(t-t_0)=\begin{cases}<br>  \infty\quad&amp;\text{if }t=t_0\\<br>  0\quad &amp;\text{if }t\ne t_0<br>\end{cases}$$<br>并且满足<br>$$\int_{-\infty}^{\infty}\delta(t-t_0)dt=1$$<ul><li>采样性质<br>$$\int_{-\infty}^{\infty}f(t)\delta(t-t_0)dt=f(t_0)$$</li></ul></li></ul></li><li>离散冲激与采样<ul><li>在0处的离散单位冲激<br>$$\delta(x)=\begin{cases}<br>  1\quad&amp;\text{if }x=0\\<br>  0\quad &amp;\text{if }x\ne 0<br>\end{cases}$$<br>并且满足<br>$$\sum_{x=-\infty}^\infty\delta(x)=1$$<ul><li>采样性质<br>$$\sum_{x=-\infty}^\infty f(x)\delta(x)=f(0)$$</li></ul></li><li>在$x_0$处的离散单位冲激<br>$$\delta(x-x_0)=\begin{cases}<br>  1\quad&amp;\text{if }x=x_0\\<br>  0\quad &amp;\text{if }x\ne x_0<br>\end{cases}$$<br>并且满足<br>$$\sum_{x=-\infty}^\infty\delta(x-x_0)=1$$<ul><li>采样性质<br>$$\sum_{x=-\infty}^\infty f(x-x_0)\delta(x)=f(x_0)$$</li></ul></li></ul></li><li>冲激串: 无穷个以$\Delta T$为间距的周期性冲激之和<br>$$s_{\Delta T}(t)=\sum_{n=-\infty}^\infty\delta(t-n\Delta T)$$</li></ul><h2 id="傅里叶变换"><a href="#傅里叶变换" class="headerlink" title="傅里叶变换"></a>傅里叶变换</h2><h3 id="傅里叶级数"><a href="#傅里叶级数" class="headerlink" title="傅里叶级数"></a>傅里叶级数</h3><ul><li>周期为$T$的连续函数$f(t)$可以表示为正弦和余弦函数的加权之和<br>$$f(t)=\sum_{n=-\infty}^\infty c_ne^{j\frac{2\pi n}{\tau}t}$$<br>其中<br>$$c_n=\frac{1}{T}\int_{-T/2}^{T/2}f(t)e^{-j\frac{2\pi n}{T}t}dt$$</li><li>连续傅里叶变换<br>$$F(\mu)=\mathfrak{J}\{f(t)\}=\int_{-\infty}^\infty f(t)e^{-j2\pi\mu t}dt$$</li><li>傅里叶变换对<br>变换<br>$$F(\mu)=\int_{-\infty}^\infty f(t)e^{-j2\pi\mu t}dt$$<br>反变换<br>$$f(t)=\int_{-\infty}^\infty F(\mu)e^{j2\pi\mu t}d\mu$$</li><li>对称性<br>$f(t)$—&gt;$F(\mu)$—&gt;$f(-t)$—&gt;$F(-\mu)$</li><li>傅里叶变换的幅值<br>$|F(\mu)|=AT\mathfrak{J}$<br>$$\mathfrak{J}\{f(t)\}=\sum_{n=-\infty}^\infty c_ne^{j\frac{2\pi n}{T}t}$$</li><li>冲激串的傅里叶变换还是冲激串</li></ul><h3 id="卷积定理"><a href="#卷积定理" class="headerlink" title="卷积定理"></a>卷积定理</h3><ul><li>离散卷积<ul><li>旋转: 其中一个向量旋转180度</li><li>补零</li><li>计算+滑动</li><li>裁剪</li></ul></li><li>连续函数的卷积<br>$$f(t)\star h(t)=\int_{-\infty}^\infty f(\tau)h(t-\tau)d\tau$$<br>$t$是位移, $-$表示反转</li><li>卷积定理<br>$$\mathfrak{J}\{f(t)\star h(t)\}\Leftrightarrow H(\mu)F(\mu)$$</li></ul><h2 id="采样"><a href="#采样" class="headerlink" title="采样"></a>采样</h2><h3 id="函数采样"><a href="#函数采样" class="headerlink" title="函数采样"></a>函数采样</h3><ul><li>连续函数采样  <ul><li>函数相乘<br>$$\tilde{f}(t)=f(t)s_{\Delta T}(t)=\sum_{n=-\infty}^\infty f(t)\delta(t-\Delta T)$$</li><li>采样值<br>$$f_k=f(k\Delta T)$$</li></ul></li></ul><h3 id="采样定理"><a href="#采样定理" class="headerlink" title="采样定理"></a>采样定理</h3><ul><li>采样后函数的傅里叶变换<ul><li>采样后函数<br>$$\tilde{f}(t)=f(t)s_{\Delta T}(t)=\sum_{n=-\infty}^\infty f(t)\delta(t-\Delta T)$$</li><li>卷积定理<br>$$\tilde{F}(\mu)=\mathfrak{J}\{\tilde{f}(t)\}=\mathfrak{J}\{f(t)s_{\Delta T}(t)\}=F(\mu)\star S(\mu)$$<br>其中<br>$$S(\mu)=\frac{1}{\Delta T}\sum_{n=-\infty}^\infty \delta(\mu-\frac{n}{\Delta T})$$ </li><li>化简<br>$$\tilde{F}(\mu)=\frac{1}{\Delta T}\sum_{n=-\infty}^\infty F(\mu-\frac{n}{\Delta T})$$</li></ul></li><li>采样定理<ul><li>带限函数$f(t)$<br>傅里叶变换后非0频率属于$[-\mu_{max},\mu_{max}]$<br>如果<br>$$\frac{1}{2\Delta T}&gt;\mu_{max}\Leftrightarrow \frac{1}{\Delta T}&gt;2\mu_{max}$$<br>就可以从$\tilde{F}$中分理出$F$, $2\mu_{max}$为奈奎斯特频率</li></ul></li><li>混淆<ul><li>欠采样: 带限函数以低于奈奎斯特频率采样<br>无法分离, 无法补救++</li><li>无法避免: 函数带限, 但采样依然是有限的, 有限长度采样引入无限频率分量</li></ul></li><li>抗混淆<ul><li>平滑输入函数, 减少高频分量(图像散焦)</li></ul></li></ul><h3 id="函数恢复"><a href="#函数恢复" class="headerlink" title="函数恢复"></a>函数恢复</h3><ul><li><p>由样本恢复函数<br>$$\tilde{f}(t)=f(t)s_{\Delta T}(t)=\sum_{n=-\infty}^\infty f(t)\delta(t-n\Delta T)$$<br>$$h(t)=\frac{\sin(\pi t/\Delta T)}{\pi t/\Delta T}$$<br>函数内插<br>$$f(t)=\sum_{n=-\infty}^\infty f(n\Delta T)\text{sinc}((t-n\Delta T)/n\Delta T)$$</p></li><li><p>连续函数采样<br>采样是有限的</p><p>带限函数一定是$-\infty$到$\infty$的<br>有限长度的采样, 混淆是不可避免的</p><p>平滑输入函数, 减少高频分量(图像散焦)</p></li></ul><h1 id="第七讲-频率域图像增强-Part-II"><a href="#第七讲-频率域图像增强-Part-II" class="headerlink" title="第七讲: 频率域图像增强(Part II)"></a>第七讲: 频率域图像增强(Part II)</h1><h2 id="离散傅里叶变换-一维"><a href="#离散傅里叶变换-一维" class="headerlink" title="离散傅里叶变换(一维)"></a>离散傅里叶变换(一维)</h2><h3 id="采样后函数的傅里叶变换"><a href="#采样后函数的傅里叶变换" class="headerlink" title="采样后函数的傅里叶变换"></a>采样后函数的傅里叶变换</h3><ul><li>周期函数<ul><li>采样后函数<br>$$\tilde{f}(t)=f(t)s_{\Delta T}(t)=\sum_{n=-\infty}^\infty f(t)\delta(t-\Delta T)$$</li><li>卷积定理<br>$$\begin{aligned}<br>\tilde{F}(\mu)&amp;=\mathfrak{J}\{\tilde{f}(t)\}=\mathfrak{J}\{f(t)s_{\Delta T}(t)\}=F(\mu)\star S(\mu)\\<br>&amp;=\int_{-\infty}^{\infty}F(\tau)S(\mu-\tau)d\tau<br>\end{aligned}$$</li><li>冲激串的傅里叶变换还是冲激串<br>$$\begin{aligned}<br>  \tilde{F}(\mu)&amp;=\int_{-\infty}^{\infty}F(\tau)S(\mu-\tau)d\tau\\<br>  &amp;=\frac{1}{\Delta T}\int_{-\infty}^{\infty}F(\tau)\sum_{n=-\infty}^{\infty}\sigma(\mu-\tau-\frac{n}{\Delta T})d\tau\\<br>  &amp;=\frac{1}{\Delta T}\sum_{n=-\infty}^{\infty}\int_{-\infty}^{\infty}F(\tau)\sigma(\mu-\tau-\frac{n}{\Delta T})d\tau\\<br>  &amp;=\frac{1}{\Delta T}\sum_{n=-\infty}^{\infty}F(\mu-\frac{n}{\Delta T})d\tau<br>\end{aligned}$$</li></ul></li><li>连续函数<ul><li>采样后函数<br>$$\tilde{f}(t)=f(t)s_{\Delta T}(t)=\sum_{n=-\infty}^\infty f(t)\delta(t-\Delta T)$$</li><li>傅里叶变换<br>$$\begin{aligned}<br>  \tilde{F}(\mu) &amp;= \int_{-\infty}^{\infty}\tilde{f}(t)e^{-j2\pi \mu t}dt\\<br>  &amp;= \int_{-\infty}^{\infty}\sum_{n=-\infty}^{\infty}f(t)\sigma(t-n\Delta T)e^{-j2\pi \mu t}dt\\<br>  &amp;= \sum_{n=-\infty}^{\infty}\int_{-\infty}^{\infty}f(t)\sigma(t-n\Delta T)e^{-j2\pi \mu t}dt\\<br>  &amp;= \sum_{n=-\infty}^{\infty}f(n\Delta T)e^{-j2\pi \mu n\Delta T}<br>\end{aligned}$$</li></ul></li><li>离散傅里叶变换对: 不依赖采样间隔/频率间隔<br>$$\mu=\frac{m}{M\Delta T}$$<ul><li>离散傅里叶变换<br>$$F(u)=\sum_{n=0}^{M-1}f(x)e^{-j2\pi ux/M},\quad u=0,1,2,\cdots,M-1$$</li><li>离散傅里叶反变换<br>$$f(x)=\sum_{n=0}^{M-1}F(u)e^{j2\pi ux/M},\quad u=0,1,2,\cdots,M-1$$</li><li>离散卷积: 对于周期函数, 也叫循环卷积; 卷积定理依然成立<br>$$f(x)\star h(x)=\sum_{m=0}^{M-1}f(m)h(x-m)$$  </li></ul></li><li>采样间隔和频率间隔<ul><li>时间间隔$\Delta T$采样$f$<br>$$\{f(x)|x=0,1,\cdots,M-1\}$$</li><li>总时间长度<br>$$T=M\Delta T$$</li><li>离散频域间隔<br>$$\Delta u=\frac{1}{M\Delta T}=\frac{1}{T}$$</li><li>离散频域范围(最大频率)<br>$$\Delta u=M \Delta u=\frac{1}{\Delta T}$$<h2 id="连续傅里叶变换-二维"><a href="#连续傅里叶变换-二维" class="headerlink" title="连续傅里叶变换(二维)"></a>连续傅里叶变换(二维)</h2></li></ul></li></ul><h2 id="离散傅里叶变换-二维"><a href="#离散傅里叶变换-二维" class="headerlink" title="离散傅里叶变换(二维)"></a>离散傅里叶变换(二维)</h2>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;第二讲-空间域图像增强-Part-I&quot;&gt;&lt;a href=&quot;#第二讲-空间域图像增强-Part-I&quot; class=&quot;headerlink&quot; title=&quot;第二讲: 空间域图像增强(Part I)&quot;&gt;&lt;/a&gt;第二讲: 空间域图像增强(Part I)&lt;/h1&gt;&lt;h2 i
      
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Digital Image Processing" scheme="https://Maxwell-lyu.github.io/tags/Digital-Image-Processing/"/>
    
  </entry>
  
  <entry>
    <title>CM-ALL</title>
    <link href="https://Maxwell-lyu.github.io/2019/09/04/Learn-CM-20190904-CM-ALL/"/>
    <id>https://Maxwell-lyu.github.io/2019/09/04/Learn-CM-20190904-CM-ALL/</id>
    <published>2019-09-04T06:02:01.000Z</published>
    <updated>2019-10-09T13:00:36.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="Lesson-1"><a href="#Lesson-1" class="headerlink" title="Lesson 1"></a>Lesson 1</h1><ul><li><p>combinatorial $\sim$ discrete &amp; finite</p><ul><li>solution combinatorial object</li><li>constraint combinatorial structure</li></ul></li><li><p>Enumeration: How many solutions satisfying the constraints</p></li><li>Existence: Does there exist a solution</li><li>Extremal: How large/small a solution can be to preserve/avoid structure</li><li>Ramsey: when a solution is sufficiently large, some structures must emerge</li><li>Optimization: find the optimal solution</li><li><p>Construction: construct a solution</p></li><li><p>Enumeration(Counting)</p><ul><li>How many ways are there:<ol><li>$n!$ to rank $n$ people</li><li>$12^n$ to assign $m$ zodiac signs to $n$ people</li><li>$n \choose m$ to choose $m$ people out of $n$ people</li><li>$n-1 \choose m-1$ to partition $n$ people into $m$ groups</li><li>$?$ to distribute $m$ yuan to $n$ people </li><li>$?$ to partition $m$ yuan to $n$ parts </li></ol></li></ul></li></ul><table><thead><tr><th>Name</th><th>Description</th><th>Notation</th><th>Number</th><th>Repetition</th><th>Ordered</th></tr></thead><tbody><tr><td>Tuple</td><td>$n$-tuples of $[m]$</td><td>$[m]^n$</td><td>$m^n$</td><td>Y</td><td>Y</td></tr><tr><td>Nultiset</td><td>$k$-multiset of $n$-set</td><td>-</td><td>${n+k-1\choose k}$</td><td>Y</td><td>N</td></tr><tr><td>Subset</td><td>$k$-uniform of $n$-set, $\</td><td>S\</td><td>=n$</td><td>-</td><td>$\binom{n}{k}$</td><td>N</td><td>N</td></tr><tr><td>Partition</td><td>$k$-partition of $n$-set</td><td>-</td><td>$\{ {n\atop k} \}$</td><td>N</td><td>N</td></tr></tbody></table><ul><li>The product rule: $|S\times T|=|S|\cdot|T|$ </li><li>The bijection rule: if there exists a bijection between finite sets $S$ and $T$, then $|S|=|T|$.</li></ul><ul><li>Tuples<ul><li>$[m]=\{1,2,\cdots,m\}$</li><li>$[m]^n=[m] \times [m] \times\cdots\times [m]$</li><li>$#$ of tuples: $|[m]^n|=m^n$</li></ul></li><li>Functions<ul><li>$f:[n]\to[m]$</li><li>$#$ of functions: $m^n$<blockquote><p>Proof: $f:[n]\to[m]\Leftrightarrow v_f\in[m]^n$</p></blockquote></li></ul></li><li>Subsets<ul><li>Power set: $2^{[n]}={S|S\subseteq [n]}$</li><li>$|2^{[n]}|=2^n$</li><li>Proof: $S\subseteq [n]\leftrightarrow \{0,1\}^n$</li></ul></li><li>Subsets of fixed size<ul><li>$#$ of $k$-uniform: ${n \choose k}=\frac{n!}{k!(n-k)!}$</li><li>$(n)_k=n(n-1)\cdots(n-k+1)$ is $n$ lower factorial of $k$</li></ul></li><li>Binomial coefficients<ul><li>${n \choose k}={n\choose n-k}$</li><li>$\sum_{k=0}^{n}{n \choose k}=2^n$</li><li>$(1+x)^n=\sum_{k=0}^{n}{n \choose k}x^k$<blockquote><p>Proof: $(1+x)^n=(1+x)(1+x)\cdots(1+x)$, $#$ of $x^k$ is $n\choose k$</p></blockquote></li><li>$S=\{x_1, x_2,\cdots,x_n\}$, $#$ of odd subsets $=$ $#$ of even subsets<blockquote><p>proof: let $x=-1$</p></blockquote></li></ul></li><li>Compositions of an integer<ul><li>$k$-composition of $n$: $k$-tuple that $x_1+x_2+\cdots+x_n=n$, $x_i\in\{1,2,\cdots x_n\}$</li><li>$#$ of $k$-composition: $n-1 \choose k-1$</li><li>weak $k$-composition of $n$: $x_i$ can be 0, aka $(x_1+1)+(x_2+1)+\cdots+(x_n+1)=n+k$</li><li>$#$ of weak $k$-composition: $n+k-1\choose k-1$</li></ul></li><li>Multisets<ul><li>Combinations with repetitions can be formally defined as multisets.</li><li>$({n \choose k})={n+k-1\choose k}$</li></ul></li><li>Multinomial coefficients<ul><li>$\binom{n}{m_1,m_2,\cdots, m_k}=\frac{n!}{m_1!m_2!\cdots m_k!}$, $\sum_i m_i=n$</li><li>$\binom{n}{m, n-m}=\binom{n}{m}$</li><li>$(x_1,x_2,\cdots,x_k)^n=\sum_{m_1+m_2+\cdots+m_k=n}\binom{n}{m_1,m_2,\cdots, m_k}x_1^{m_1}\cdots x_k^{m_k}$</li></ul></li><li>Partitions of a set<ul><li>partition of $S$: $P={S_1,S_2,\cdots,S_k}$, $S_i\ne\emptyset$, $S_i\cap S_j$ if $i\ne j$, $\bigcup S_i=S$</li><li>if $|P|=k$, then $P$ is a $k$-partition of $S$</li><li>$#$ of $k$-partitions of a $n$-set is $\{ {n\atop k} \}$</li><li>Stirling number of the second kind</li></ul></li><li>The twelvfold way  </li></ul><table><thead><tr><th style="text-align:center">$n$ balls</th><th style="text-align:center">$m$ bins</th><th style="text-align:center">unrestricted</th><th style="text-align:center">$\leq 1$ for all bin</th><th style="text-align:center">$\geq 1$ for all bin</th></tr></thead><tbody><tr><td style="text-align:center">distinct</td><td style="text-align:center">distinct</td><td style="text-align:center">$m^n$</td><td style="text-align:center">$(m)_n=n!\binom{m}{n}$</td><td style="text-align:center">$m!\{ {n\atop m} \}$</td></tr><tr><td style="text-align:center">identical</td><td style="text-align:center">distinct</td><td style="text-align:center">$(\binom{m}{n})$</td><td style="text-align:center">$m\choose n$</td><td style="text-align:center">$\binom{m-1}{n-1}$</td></tr><tr><td style="text-align:center">distinct</td><td style="text-align:center">identical</td><td style="text-align:center">$\sum_{k=1}^m\{ {n\atop k} \}$</td><td style="text-align:center">$1$</td><td style="text-align:center">$\{ {n\atop m} \}$</td></tr><tr><td style="text-align:center">identical</td><td style="text-align:center">identical</td><td style="text-align:center">$-$</td><td style="text-align:center">$-$</td><td style="text-align:center">$-$</td></tr></tbody></table>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;Lesson-1&quot;&gt;&lt;a href=&quot;#Lesson-1&quot; class=&quot;headerlink&quot; title=&quot;Lesson 1&quot;&gt;&lt;/a&gt;Lesson 1&lt;/h1&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;combinatorial $\sim$ discrete &amp;amp; f
      
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Combinatorics" scheme="https://Maxwell-lyu.github.io/tags/Combinatorics/"/>
    
  </entry>
  
  <entry>
    <title>CN-ALL</title>
    <link href="https://Maxwell-lyu.github.io/2019/09/04/Learn-CN-20190904-CN-ALL/"/>
    <id>https://Maxwell-lyu.github.io/2019/09/04/Learn-CN-20190904-CN-ALL/</id>
    <published>2019-09-04T01:33:26.000Z</published>
    <updated>2019-12-22T12:06:08.777Z</updated>
    
    <content type="html"><![CDATA[<p>[Textbook]: Computer Networking: A Top-Down Approach(7th Edition) by James F. Kurose, Keith W. Ross<br>搜索”#解题”查看所有计算题解题方法<br><a id="more"></a> </p><h1 id="Chapter-1-Introduction-of-Networking"><a href="#Chapter-1-Introduction-of-Networking" class="headerlink" title="Chapter 1: Introduction of Networking"></a>Chapter 1: Introduction of Networking</h1><blockquote><p>[Textbook] 1.x, 2.7 </p></blockquote><h2 id="What’s-the-Internet"><a href="#What’s-the-Internet" class="headerlink" title="What’s the Internet"></a>What’s the Internet</h2><ul><li>Connected Devices<ul><li>Hosts = End systems</li><li>Run network applications</li></ul></li><li>Communication links<ul><li>Optical fiber, Copper, Radio, Satellite</li><li>Build physical networks</li></ul></li><li>Routers<ul><li>Forward packets between physical networks</li></ul></li></ul><blockquote><p>Com.Dev. <ruby>—&gt;<rt>Com.Lnk.</rt></ruby>Phys.NtWk<ruby>—&gt;<rt>Router</rt></ruby>Internet</p></blockquote><h2 id="Building-Internet"><a href="#Building-Internet" class="headerlink" title="Building Internet"></a>Building Internet</h2><ul><li>Communication Infrastructure<ul><li>Enables distributed applications</li><li>e.g: Web, VoIP, email, online games, e-commerce, file sharing</li></ul></li><li>Communication Services Provided<ul><li>IP: Unreliable, data delivery</li><li>TCP: Reliable data delivery</li><li>QoS: Guaranteed delay and throughput<blockquote><p>Delay: 延迟; Throughput: 吞吐量/网速</p></blockquote></li></ul></li><li>Network Protocols<ul><li>Control sending, receiving of messages</li><li>e.g: HTTP, Skype; TCP, IP; PPP, Ethernet</li></ul></li><li>Internet Standards <ul><li>IETF: Internet Engineering Task Force</li><li>RFC: Request for comments</li></ul></li><li>Internet: “network of networks”<ul><li>Public Internet versus private Intranet</li><li>Loosely hierarchical<blockquote><p>Intranet: 内部网</p></blockquote></li></ul></li></ul><h2 id="Internet-History"><a href="#Internet-History" class="headerlink" title="Internet History"></a>Internet History</h2><ul><li>1961-1972: Early packet-switching principles</li><li>1972-1980: Internetworking, new and proprietary nets</li><li>1980-1990: new protocols, a proliferation of networks</li><li>1990’s, 2000’s: commercialization, the Web, new apps</li><li>2007~Now:<ul><li>P2P applications</li><li>Iot: Internet of things</li><li>SON: Self-Organizing Network</li><li>SDN: Software Defined Network</li><li>CDN: Content Distribution Network</li><li>ICN: Information-Centric Network</li></ul></li></ul><h2 id="Access-Internet"><a href="#Access-Internet" class="headerlink" title="Access Internet"></a>Access Internet</h2><h3 id="Network-Edge"><a href="#Network-Edge" class="headerlink" title="Network Edge"></a>Network Edge</h3><ul><li>End systems (hosts)<ul><li>Run application programs</li><li>e.g. Web, Email </li></ul></li><li>Client/Server model(P2S)<ul><li>Client host requests, receives service from always-on server</li><li>e.g. Web browser/server; Email client/server</li></ul></li><li>Peer-to-peer model(P2P)<ul><li>Minimal (or no) use of dedicated servers</li><li>e.g. Skype, BitTorrent</li></ul></li></ul><h3 id="Access-Networks"><a href="#Access-Networks" class="headerlink" title="Access Networks"></a>Access Networks</h3><ul><li>Physical media(Wired and wireless com.lnk.)</li><li>Connect end systems to edge router<ul><li>Residential access networks (Home)<ul><li>Dialup via modem: <ul><li>Up to 56Kbps</li><li>direct access to router</li></ul></li><li>DSL: Digital Subscriber line<ul><li>Deployment: Telephone company </li><li>Upstream: 1~3Mbps, Downstream: 8~24Mbps</li><li>Dedicated physical line to telephone central office</li></ul></li></ul></li><li>HFC: hybrid fiber coax<ul><li>Asymmetric: up to 30Mbps downstream, 2 Mbps upstream</li><li>Homes share access to ISP router</li><li>Deployment: cable TV companies</li></ul></li><li>Institutional networks (school, company)<ul><li>LAN connects end systems to router</li><li>Ethernet:<ul><li>10Mbps, 100Mbps, 1Gbps, 10Gbps</li><li>Modern configuration: Ethernet switch backbone connect end systems</li></ul></li></ul></li><li>Mobile access networks<ul><li><blockquote><p>End systems <ruby><--------><rt>Shared wireless media</rt></--------></ruby>Router</p></blockquote></li><li>Wireless LANs (WLAN)<ul><li>802.11b/g(WiFi): 11 or 54Mbps</li></ul></li><li>Wider-area wireless access<ul><li>Provided by telecommunication operator</li><li>10Mbps over cell network</li><li>LTE(4G) and WiMAX</li><li>20Gbps(5G?)</li></ul></li><li>Modern family<ul><li><blockquote><p><ruby>———=<rt>to/from cable headend</rt></ruby> Modem =—-= Router/Firewall =—-= Wireless AP - - - - Wireless Device</p></blockquote></li><li><blockquote><p><ruby>———=<rt>to/from cable headend</rt></ruby> Modem =—-= Router/Firewall <ruby>=—-=<rt>Ethernet</rt></ruby> Device</p></blockquote></li></ul></li></ul></li></ul></li><li>Performance<ul><li>Bandwidth (bps)</li><li>Shared or dedicated<blockquote><p>Dedicated: 专用的</p></blockquote></li></ul></li></ul><h3 id="Network-Core"><a href="#Network-Core" class="headerlink" title="Network Core"></a>Network Core</h3><ul><li>Interconnected routers(Network of networks)</li><li>Circuit Switching<ul><li>Performance: Link bandwidth, switch capacity</li><li>Dedicated circuit per call, e.g: telephone</li><li>Circuit-like (guaranteed) performance</li><li>Require call setup/teardown</li></ul></li><li>Packet Switching<ul><li>Each end-to-end data stream divided into packets</li><li>Application A, B packets share network resources</li><li>Store and forward: packets move one hop at a time, stored (queued) at switches</li><li>Each packet uses full link bandwidth</li><li>Resource contention: aggregate (burst-up) resource demand can exceed amount available</li><li>Congestion: packets queue and wait for link use</li></ul></li><li>Statistical Multiplexing<ul><li>Link bandwidth dedicated or shared</li><li>Sequence of packets have or have not fixed pattern</li><li>Source that has higher bit rate occupies more time intervals</li></ul></li><li>Virtual Circuit<ul><li>Circuit Swithching + Packet Switching</li><li>Fixed router and main cross roads</li><li>Shared resource, requird congestion control</li><li>Resource can be preserved, leadingto different performance</li><li>Require connection setup/teardown</li></ul></li><li>Internet Structure – Network of Networks<ul><li>Roughly hierarchical</li><li>At center: “Tier-1” (National) ISPs</li><li>“Tier-2” ISPs: smaller (often regional) ISPs</li><li>“Tier-3” ISPs and local/edge ISPs, connect access networks</li></ul></li></ul><h2 id="Typical-Network-Applications"><a href="#Typical-Network-Applications" class="headerlink" title="Typical Network Applications"></a>Typical Network Applications</h2><ul><li>Client/Server Applications</li><li>P2P Applications</li><li><h3 id="Client-Server-Architecture"><a href="#Client-Server-Architecture" class="headerlink" title="Client-Server Architecture"></a>Client-Server Architecture</h3></li></ul><ul><li>Server<ul><li>Always-on host</li><li>Permanent IP address</li><li>Server farms for scaling</li></ul></li><li>Clients<ul><li>Communicate with server</li><li>May be intermittently connected</li><li>May have dynamic IP addresses</li><li>Do not communicate directly with each other</li></ul></li><li>Web and HTTP<ul><li>Request: Clients use browser to send URL(URI)s via HTTP to servers requesting a Web page</li><li>Construct: Web pages constructed using HTML (or other markup language), inter-connected by URL</li><li>Respond: Servers (or caches) respond with requested Web page</li><li>Display: Client’s browser displays Web page returned by server</li></ul></li><li>FTP<ul><li>Transfer file to/from remote host</li><li>Control connection: Login/logout, file trans command/reply</li><li>Data connection: File contents, client side initiates file transfer</li></ul></li><li>E-Mail<ul><li>MIME: Multi-purpose Internet Mail<blockquote><p>Non-text data</p></blockquote></li><li>SMTP: Simple Mail Transfer Protocol<blockquote><p>Simple text mail</p></blockquote></li><li>POP: Post Office Protocol<blockquote><p>Mail retrieval from server, including authorization and download</p></blockquote></li><li>IMAP: Internet Mail Access Protocol<blockquote><p>Manipulation of stored mails on server</p></blockquote></li></ul></li></ul><h3 id="P2P-Application"><a href="#P2P-Application" class="headerlink" title="P2P Application"></a>P2P Application</h3><ul><li>BitTorrent<ul><li>File divided into chunks</li><li>Peer join torrent<ul><li>Register to tracker to get list of peers</li><li>Connect to some peers</li><li>Issue requests for missing chunks</li></ul></li><li>Upload chunks<ul><li>send </li></ul></li><li>Peers may come and go </li></ul></li><li>Skype<ul><li>P2P VoIP: PC/Phone</li><li>Proprietary application layer protocol<blockquote><p>Proprietary: 专有的</p></blockquote></li><li>Make a call<ul><li>Register: SC(skype client) register with SN(super node)</li><li>Authenticate: SC authenticate(log in)</li><li>Call: SC contact SN with caller ID</li><li>SN contacts other SNs to find callee address</li><li>SC directly contacts callee over UDP/TCP</li></ul></li><li>Login server: authentication; Super node: exchange address</li><li><h2 id="Protocol-Layers-and-Service-Model"><a href="#Protocol-Layers-and-Service-Model" class="headerlink" title="Protocol Layers and Service Model"></a>Protocol Layers and Service Model</h2></li></ul></li></ul><h3 id="OSI"><a href="#OSI" class="headerlink" title="OSI"></a>OSI</h3><ul><li>Physical<ul><li>bits across link</li><li>Physical interface</li><li>Physical aspects: Mechanical, Electrical/Optical, Functional/Procedural</li></ul></li><li>Data Link<ul><li>frames</li><li>activation, maintenance, deactivation of connection</li><li>medium access control for muiltiple access</li><li>error detection and retransmission: error-free transmission</li><li>flow control</li></ul></li><li>Network<ul><li>packet across mulltiple links/networks</li><li>addressing and routing</li><li>Forwarding transfers packet across a node</li><li>Congestion control to deal with traffic surges</li><li>Connection setup, maintenance, and teardown</li></ul></li><li>Transport<ul><li>data between end systems</li><li>Reliable stream transfer or quick-and-simple single-block transfer</li><li>Connection setup, maintenance, and release</li></ul></li><li>-Session- into App.</li><li>-Presentation- into App.</li><li>Application<ul><li>Means for applications to access OSI environment</li></ul></li><li>Service Primitives and Parameters<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">      ServiceUserA                  ServiceUserB</span><br><span class="line">          +  |                            +  |</span><br><span class="line">Confirm   |  |   Request     Indication   |  |  Response</span><br><span class="line">          |  +                            |  +</span><br><span class="line">             (N-1) Layer Service Provider</span><br></pre></td></tr></table></figure></li></ul><h3 id="TCP-IP-Protocol-Architecture"><a href="#TCP-IP-Protocol-Architecture" class="headerlink" title="TCP/IP Protocol Architecture"></a>TCP/IP Protocol Architecture</h3><blockquote><p>Used by global Internet</p></blockquote><ul><li>Application: supporting network applications<blockquote><p>FTP, SMTP, HTTP</p></blockquote></li><li>Transport: process-process data transfer<blockquote><p>TCP, UDP</p></blockquote></li><li>Internetwork: routing of datagrams across net of nets<blockquote><p>IP, routing protocols</p></blockquote></li><li>Link: data transfer between neighboring routers / hosts<blockquote><p>PPP, Ethernet</p></blockquote></li><li>Physical: bits “on the wire”<br>Protocol Data Units(PDU)</li><li>Control info is added to user data at each layer</li><li>Segment and Header: Transport layer segments application data, a transport header added<ul><li>Destination SAP, Sequence number, Error detection code<br>The IP Layer in Detail</li></ul></li><li>Sender encapsulates segments into datagrams</li><li>Receiver delivers segments to transport layer</li><li>Router examines header fields in all IP datagrams</li></ul><h2 id="Network-Programming"><a href="#Network-Programming" class="headerlink" title="Network Programming"></a>Network Programming</h2><ul><li>Socket programming<ul><li>Build client/server application that communicate using sockets</li><li>A socket is a pair of [IP addresses, port]</li></ul></li><li>Socket API<ul><li>Introduced in BSD4.1 UNIX, 1981</li><li>Explicitly created, used, and released by applications</li><li>Implementing client/server paradigm</li></ul></li><li>2 types of transport service via socket API<ul><li>Unreliable datagram, i.e. UDP</li><li>Reliable, byte stream-oriented, i.e. TCP</li></ul></li></ul><h3 id="Socket-Programming-with-TCP"><a href="#Socket-Programming-with-TCP" class="headerlink" title="Socket Programming with TCP"></a>Socket Programming with TCP</h3><ul><li>Client: Create socket-&gt;Specify [IP<sub>s</sub>, Port<sub>s</sub>]-&gt;Recieve reply, connection [IP<sub>c</sub>, Port<sub>c</sub>; IP<sub>s</sub>,Port<sub>s</sub>]</li><li>Server: Create listening Socket-&gt;Accept contact, create new socket-&gt;connection [IP<sub>c</sub>, Port<sub>c</sub>; IP<sub>s</sub>, Port<sub>s</sub>]</li><li>Server distinguish clients using [IP<sub>c</sub>, Port<sub>c</sub>]</li><li>Interaction:<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">    SERVER                                        CLIENT </span><br><span class="line">    create listening socket  </span><br><span class="line">      |                         TCP con. setup</span><br><span class="line">+-&gt; wait for connection      &lt;----------------&gt;  create socket</span><br><span class="line">|     |                                             |</span><br><span class="line">|   read request             &lt;-----------------  send request</span><br><span class="line">|     |                                             |</span><br><span class="line">|   write reply              -----------------&gt;  read reply</span><br><span class="line">|     |                                             |</span><br><span class="line">+-- close                                         close</span><br></pre></td></tr></table></figure></li></ul><h3 id="Socket-Programming-with-UDP"><a href="#Socket-Programming-with-UDP" class="headerlink" title="Socket Programming with UDP"></a>Socket Programming with UDP</h3><ul><li>No connection</li><li>Sender attaches IP address, port of destination to each packet</li><li>Receiver extract IP address, port of sender from received packet</li><li>Transmitted data may be received out of order, or lost</li><li>Interaction:<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">    SERVER                                        CLIENT </span><br><span class="line">    create listening socket  </span><br><span class="line">      |                                             </span><br><span class="line">+-&gt; read request             &lt;-----------------  send request</span><br><span class="line">|     |                                             |</span><br><span class="line">|   write reply              -----------------&gt;  read reply</span><br><span class="line">|     |                                             |</span><br><span class="line">+-- close                                         close</span><br></pre></td></tr></table></figure></li></ul><h2 id="Delay-Loss-and-Throughput"><a href="#Delay-Loss-and-Throughput" class="headerlink" title="Delay, Loss and Throughput"></a>Delay, Loss and Throughput</h2><h3 id="Delay"><a href="#Delay" class="headerlink" title="Delay"></a>Delay</h3><ul><li>Source of delay<ul><li>Transmission: $L/R$; microseconds</li><li>Propagation: $d/s$; microseconds</li><li>Nodal processing: Error-check &amp; determine link; microseconds</li><li>Queuing: wait in queue, congestion level; seconds</li></ul></li><li>Queuing Delay<ul><li>Traffic intensity: $\rho = L\times\alpha/R$<blockquote><p>$\alpha$: average packet arrival rate</p><ul><li>$\rho\sim 0$: average queuing delay small</li><li>$\rho\to 1$: delays become large</li><li>$\rho\geq 1$: delays infinite</li></ul></blockquote></li></ul></li><li>“Real” Internet Delays and Routes<ul><li>traceroute<ul><li>Provides delay measurement from source to router along end-to-end Internet path towards destination</li><li>Each intermediate router will return packets to sender</li><li>Sender records time interval between transmission and reply</li></ul></li></ul></li></ul><h3 id="Loss"><a href="#Loss" class="headerlink" title="Loss"></a>Loss</h3><ul><li>Buffer of a router has finite capacity</li><li>Packet arriving to full queue dropped</li><li>Lost packet may be retransmitted, if not, it’s lost</li></ul><h3 id="Throughput"><a href="#Throughput" class="headerlink" title="Throughput"></a>Throughput</h3><ul><li>Rate (bits/unit per time) at which bits transferred between sender/receiver</li><li>Instantaneous or Average</li><li>Multiplexing: $\min(R_c, R_s, R/N_l)$</li></ul><h2 id="Networks-under-Attack-Security"><a href="#Networks-under-Attack-Security" class="headerlink" title="Networks under Attack: Security"></a>Networks under Attack: Security</h2><ul><li>Attacks on Internet infrastructure<ul><li>Infecting/attacking hosts: malware, spyware, worms,   unauthorized access</li><li>Packet sniffing, replay, masquerade</li><li>Denial of service: deny access to resources (servers, link bandwidth)</li></ul></li><li>Internet not originally designed with security in mind<ul><li>Original vision: “a group of mutually trusting users attached to a transparent network”</li><li>Internet protocol designers playing “catch-up”</li><li>Security considerations in all layers!</li></ul></li></ul><h3 id="Different-Types-of-Malware"><a href="#Different-Types-of-Malware" class="headerlink" title="Different Types of Malware"></a>Different Types of Malware</h3><ul><li>Virus: Infection, Run executables, Self-replicating</li><li>Worm:  Transmitting over a network</li><li>Trojan horses: Disguised as innocuous or desirable, Tempting user to run</li><li>Backdoor: Bypassing authentication procedures</li><li>Adware: Advertisements</li><li>Spyware: Recording activity</li></ul><h3 id="Types-of-Attack"><a href="#Types-of-Attack" class="headerlink" title="Types of Attack"></a>Types of Attack</h3><ul><li>Denial of Service(DoS)<ul><li>overwhelming resource with bogus traffic</li><li>Break into hosts -&gt; use compromised hosts to send packets to target</li></ul></li><li>Packet Sniffing<ul><li>Broadcast media required</li><li>Promiscuous NIC reads/records all packets passing by</li></ul></li><li>IP Spoofing<ul><li>putting any value into IP source address field</li><li>Receiver can’t tell if source is spoofed</li></ul></li><li>Masquerade<ul><li>IP spoofing: send packet with false source address</li><li>Record-and-playback: sniff sensitive info (e.g.,password), and use later</li></ul></li></ul><h3 id="Catch-Up"><a href="#Catch-Up" class="headerlink" title="Catch-Up"></a>Catch-Up</h3><ul><li>What Trudy Might Do<ul><li>Eavesdrop: intercept messages</li><li>Insert messages into connection</li><li>Impersonation: can fake (spoof) source address</li><li>Hijacking: “take over” ongoing connection by removing sender or receiver, inserting himself in place</li><li>Denial of service: prevent service from being used by others</li></ul></li><li>How to Handle This<ul><li>Encryption: the message cannot be understood</li><li>MAC: the message cannot be altered</li><li>Sign: the source cannot be forged</li></ul></li></ul><h1 id="Chapter-2-Direct-Link-Networks"><a href="#Chapter-2-Direct-Link-Networks" class="headerlink" title="Chapter 2. Direct Link Networks"></a>Chapter 2. Direct Link Networks</h1><blockquote><p>[Textbook] 5.x, 6.x</p></blockquote><h2 id="链路层概述"><a href="#链路层概述" class="headerlink" title="链路层概述"></a>链路层概述</h2><ul><li>结点(Node): 主机(Host), 路由器(Router)</li><li>链路(Link): 连接相邻节点的通信通道</li></ul><h3 id="链路层服务"><a href="#链路层服务" class="headerlink" title="链路层服务"></a>链路层服务</h3><ul><li>成帧: 数据组合成帧, 若干首部+数据字段(网络层数据报)</li><li>接入: 媒体访问控制(MAC), 协调结点在共享媒体的传输</li><li>可靠交付: 保证无差错地传输网络层数据报(有线连接有时不提供这一服务)</li><li>检错和纠错: 硬件完成, 比运输层和网络层复杂</li></ul><h3 id="链路层实现"><a href="#链路层实现" class="headerlink" title="链路层实现"></a>链路层实现</h3><ul><li>网络适配器/网络接口卡(Adapter/NIC)<ul><li>核心是链路层控制器</li><li>单独的PCI卡 或 集成到主板</li></ul></li></ul><h2 id="差错检测和纠正技术"><a href="#差错检测和纠正技术" class="headerlink" title="差错检测和纠正技术"></a>差错检测和纠正技术</h2><ul><li>差错检测和纠正比特(EDC):<br>[D]–(发送)–&gt;[D+EDC]–(易出错链路)–&gt;[D’+EDC’]–(接收)–&gt;有错丢弃, 无错则D’=D</li><li>未检出比特差错: D’&lt;&gt;D, 但仍然有效, 未检出错误</li><li>前向纠错: 接收方检测和纠正错误<h3 id="奇偶校验"><a href="#奇偶校验" class="headerlink" title="奇偶校验"></a>奇偶校验</h3></li><li>单个奇偶校验位<ul><li>|EDC|=1 </li><li>检测奇数个错误比特</li></ul></li><li>二维奇偶校验<ul><li>数据d组成i×j矩阵, 每行每列有校验比特</li><li>可以检测任意2比特差错, 纠正单比特差错<h3 id="检验和-方法"><a href="#检验和-方法" class="headerlink" title="检验和 方法"></a>检验和 方法</h3></li></ul></li><li>因特网校验和<ul><li>数据作为16比特整数进行求和, 取反码作为校验和, |EDC|=16</li><li>D+EDC同样求和, 全1则正确, 有任意0则有错</li></ul></li><li>#解题: 因特网检验和计算方法<ul><li>分段: 16bit一段</li><li>求和: 挨个加和, 最高位进位到最低位</li><li>取反: 取反码, 接在数据后面发送</li><li>检验: 对收到的信息进行以上三步, 全1则无误<h3 id="循环冗余检测"><a href="#循环冗余检测" class="headerlink" title="循环冗余检测"></a>循环冗余检测</h3></li></ul></li><li>循环冗余检测/多项式编码<ul><li>r+1比特的多项式, 生成r比特CRC, 不断按位异或</li><li>检测小于r+1比特的突发(连续)比特差错, 检测任何奇数个比特差错</li></ul></li><li>#解题: CRC计算方法(r+1比特的多项式)<ul><li>补0: 补r个0到需检验的数据后</li><li>异或: 类似除法, 用异或代替减法, 不断消除最高位的1</li><li>取余: 最后得到的r位余数就是CRC, 代替那r个0, 接在数据后</li><li>检验: 对收到的数据做前三步, 余数为0则无误</li></ul></li></ul><h2 id="流量控制"><a href="#流量控制" class="headerlink" title="流量控制"></a>流量控制</h2><h3 id="停止等待流量控制"><a href="#停止等待流量控制" class="headerlink" title="停止等待流量控制"></a>停止等待流量控制</h3><ul><li>流程<ul><li>源点发送</li><li>终点收到帧, 回复ACK</li><li>原点收到ACK, 发送下一帧</li><li>终点不发ACK终止流</li></ul></li><li>对长帧效果好<h3 id="滑动窗口流量控制"><a href="#滑动窗口流量控制" class="headerlink" title="滑动窗口流量控制"></a>滑动窗口流量控制</h3></li><li>流程<ul><li>接收端缓存大小 W  </li><li>发送端在没有收到ACK前可以发送W个帧  </li><li>每个帧通过序号来标识, 序号大小受字段长度限制(k bits)帧以 2^k 为模编号($0\to 2^{k}-1$)  </li><li>ACK(RRx)包含下一个期望收到的帧编号x</li></ul></li><li>最大窗口大小: $W\leq 2^{k-1}-1$, 防止歧义</li><li>差错控制<ul><li>Go back N: NAK, 然后出错帧及其后的全部重传</li><li>选择拒绝: 被拒绝的帧重传, 接收端缓存后面的</li></ul></li></ul><h2 id="多路访问链路和协议"><a href="#多路访问链路和协议" class="headerlink" title="多路访问链路和协议"></a>多路访问链路和协议</h2><ul><li>广播链路: 多点, 一个信道</li><li>碰撞: 多个结点同时发送<h3 id="信道划分协议"><a href="#信道划分协议" class="headerlink" title="信道划分协议"></a>信道划分协议</h3></li><li>时分复用TDM<ul><li>时隙slot, 每轮每结点一个时隙</li><li>速率: R/N, 负载不均衡时浪费, 统计时分复用解决, 有额外开销</li></ul></li><li>频分复用FDM<ul><li>分频率, 一人一频</li><li>速率: R/N, 负载不均衡时浪费</li></ul></li><li>码分多址CDMA<ul><li>每结点一个编码, 1电平为此编码, 0为编码取反</li><li>速率: R, 可同时发送(每个结点的编码必须线性不相关), 抗干扰</li></ul></li></ul><h3 id="随机接入协议"><a href="#随机接入协议" class="headerlink" title="随机接入协议"></a>随机接入协议</h3><ul><li>时隙ALOHA<ul><li>有ACK</li><li>前提: 每帧长L, 每时隙L/R, 结点同步, 且在时隙开始时才传输, 碰撞检测够快</li><li>流程<ul><li>发送: 结点在一个时隙开始发送帧<ul><li>成功: 若没检测到碰撞, 则认为成功传输</li></ul></li><li>失败: 检测到碰撞, 在之后的时隙中以概率p不断尝试重传, 直到没有碰撞</li></ul></li><li>效率: 取p=1/N时最大化, 当N趋于无穷时, 效率为1/e</li></ul></li><li>ALOHA<ul><li>有ACK<blockquote><p>除了不同步, 跟时隙ALOHA一样</p></blockquote></li><li>流程<ul><li>发送: 结点在一个时隙开始发送帧<ul><li>成功: 若没检测到碰撞, 则认为成功传输</li></ul></li><li>失败: 检测到碰撞, 立刻以概率p不断尝试重传, 直到没有碰撞</li></ul></li><li>效率: 取p=1/N时最大化, 当N趋于无穷时, 效率为1/2e(前后都可能有重叠)</li></ul></li><li>CSMA/CD<ul><li>无ACK</li><li>不做同步</li><li>流程<ul><li>监听: 监听信道是否空闲, 空闲时才开始传输</li><li>传输: 传输时也不断监听是否有其他结点的信号能量<ul><li>成功: 未发现其他能量, 认为发送成功</li></ul></li><li>失败: 发现其他能量, 立刻停止; <strong>发送48bit干扰信号</strong></li><li>等待(非持续): 等待一个随机时间, 回到”监听”重传</li><li>回退(p持续): 之后的时间当中以概率p重传</li><li>回退(1持续, 以太网): 使用二进制指数后退<ul><li>经历过了k次碰撞, 就从[0,…,2^k-1]中选一个K值, 等待512K个比特时间</li><li>k最大为10</li><li>最多尝试16次发送</li></ul></li></ul></li><li>效率: 近似为<br>$$\frac{1}{1+5d_{prop}/d_{trans}}$$</li><li>最小帧长: 检测冲突的时长不超过端到端传播时延的2倍, 取这一值为最小帧长</li></ul></li></ul><h3 id="轮流协议"><a href="#轮流协议" class="headerlink" title="轮流协议"></a>轮流协议</h3><ul><li>轮询协议<ul><li>流程: 每个从结点n<ul><li>主节点发帧, 告诉从节点n能够发送的最大包数</li><li>从节点发送不超过n帧</li><li>主节点发现没有信号了, 继续轮询下一个从节点</li></ul></li><li>缺点: 轮询时延(第一步耗时); 主节点损坏则信道无用</li></ul></li><li>令牌传递协议<ul><li>流程<ul><li>收到令牌</li><li>如果有帧要发, 则发送不超过最大数目的帧数</li><li>传递令牌</li></ul></li><li>缺点: 令牌传播时延, 令牌丢失, 单点故障则信道崩溃</li></ul></li></ul><h3 id="用于电缆因特网接入的链路层协议"><a href="#用于电缆因特网接入的链路层协议" class="headerlink" title="用于电缆因特网接入的链路层协议"></a>用于电缆因特网接入的链路层协议</h3><ul><li>信道划分<ul><li>FDM: 划分为下行和上行, 下行每个6MHz, 上行每个6.4MHz<ul><li>(下行只有一个 CMTS-电缆调制解调器端接系统 在发送, 不存在多路)</li><li>类似TDM: 划分为序列微时隙<ul><li>请求帧微时隙: 可能碰撞, 使用随机接入</li><li>数据帧微时隙: 收到请求后由CMTS通过下行信道分配给Modem, 不碰撞<h2 id="交换局域网"><a href="#交换局域网" class="headerlink" title="交换局域网"></a>交换局域网</h2><h3 id="链路层寻址和ARP"><a href="#链路层寻址和ARP" class="headerlink" title="链路层寻址和ARP"></a>链路层寻址和ARP</h3></li></ul></li></ul></li></ul></li><li>媒体访问控制 MAC地址<ul><li>长度: 6字节</li><li>与适配器(NIC等)绑定</li><li>广播地址: 全1, 即12个F</li><li>每个主机都检查MAC是否与自己相同, 相同则接收</li></ul></li><li>地址解析协议 ARP协议<ul><li>子网内解析</li><li>每台主机或路由器存有ARP表, 保存了其知晓的MAC-IP对应关系, 每个条目有过期时间</li><li>流程<ul><li>若有表项, 直接构造包并发送</li><li>若无, 向适配器发送ARP分组(发送和接收的IP地址, 目的MAC是广播地址)</li><li>每个主机都收到, 若IP相同, 则响应ARP分组, 用标准链路层帧回复</li></ul></li></ul></li><li>发送数据报到子网以外<ul><li>路由器每个端口均有MAC和IP</li><li>路由器将相应ARP, 主机获得的此IP的MAC地址是路由器这一端口的MAC<h3 id="以太网"><a href="#以太网" class="headerlink" title="以太网"></a>以太网</h3></li></ul></li><li>以太网帧结构<ul><li>帧字段<ul><li>前同步码: 8字节: 前7个字节都是10101010, 同步时钟并唤醒适配器; 最后一个是10101011, “11”警告适配器数据到来</li><li>目的MAC地址: 6字节: 与自己的MAC相同才会接收</li><li>源MAC地址: 6字节</li><li>类型字段: 2字节: 允许以太网复用多种网络层协议</li><li>数据: 46-1500: 承载IP数据报, 超长将分片</li><li>CRC: 4字节: 适配器丢弃校验出错的帧</li></ul></li><li>无连接服务: 不事先握手</li><li>不可靠服务: 成功无ACK, 失败无REJ</li></ul></li><li>以太网技术<ul><li>命名: [速率]BASE[距离 或 介质], T指铜双绞线, FX/SX/BX指光纤</li><li>10Mbps: 10BASE[%d], 距离, 使用同轴电缆</li><li>100Mbps: 100BASE-TX/T4/T2双绞线, -FX/SX/BX光纤</li><li>1000Mbps: 1000BASE-T等, 又名802.3z, 双绞线, 兼容旧标准, 点对点(交换机)信道全双工, 另有广播(集线器)</li><li>10Gbps: 10GBASE-T<h3 id="链路层交换机"><a href="#链路层交换机" class="headerlink" title="链路层交换机"></a>链路层交换机</h3></li></ul></li><li>交换机转发和过滤<ul><li>过滤: 决定帧应该发到某个接口还是将其丢弃</li><li>转发: 决定帧去往哪个接口<ul><li>流程: 借助交换机表(MAC - 接口 - 时间)<ul><li>没找到目的MAC, 向源以外的所有端口广播</li><li>找到MAC, 与源端口匹配, 则丢弃</li><li>找到MAC, 与另一端口匹配, 转发到这一端口(进入端口的缓存)</li></ul></li></ul></li></ul></li><li>自学习<ul><li>流程<ul><li>初始: 交换表为空</li><li>学习: 收到帧, 则将[源MAC地址 - 到达的接口 - 当前时间]存入交换表</li><li>老化: 一段时间后未收到这一地址作为源的帧, 则此表项移除</li></ul></li><li>即插即用设备: 无需进行配置</li><li>双工: 每个接口可同时发送和接收</li></ul></li><li>链路层交换机的性质<ul><li>消除碰撞: 星型拓扑, 没有因碰撞而浪费的带宽</li><li>异质链路: 链路彼此隔离, 允许不同速率, 新旧混用</li><li>管理: 检测异常适配器并断开之, 等</li></ul></li><li>交换机与路由器<ul><li>交换机<ul><li>优: 即插即用, 分组过滤, 高速率</li><li>缺: 拓扑限制为树形, 不提供广播风暴的保护</li></ul></li><li>路由器<ul><li>优: 拓扑灵活, 提供防火墙保护</li><li>缺: 需要配置, 处理延迟大<h3 id="虚拟局域网"><a href="#虚拟局域网" class="headerlink" title="虚拟局域网"></a>虚拟局域网</h3></li></ul></li></ul></li><li>树形交换局域网的缺陷<ul><li>缺乏流量隔离: 单播能够隔离, 但广播不行; 缺乏安全隐私的隔离</li><li>交换机无效使用: 为了分组造成交换机端口的浪费</li><li>管理用户: 用户在分组间移动, 则需要改变物理布线, 连接到不同交换机</li></ul></li><li>VLAN: 单一的物理交换机定义多个虚拟局域网, 广播流量仅到达同一分组的端口<ul><li>跨VLAN需要路由器</li><li>VLAN划分: 端口 或 MAC</li><li>VLAN干线连接<ul><li>干线接口: VLAN交换机之间交换帧</li><li>帧格式802.1Q: 以太网帧的源地址和类型之间, 加入VLAN标志</li></ul></li></ul></li></ul><h1 id="Chapter-3-Packet-Switching-Networks"><a href="#Chapter-3-Packet-Switching-Networks" class="headerlink" title="Chapter 3. Packet Switching Networks"></a>Chapter 3. Packet Switching Networks</h1><h2 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h2><h3 id="转发和路由选择"><a href="#转发和路由选择" class="headerlink" title="转发和路由选择"></a>转发和路由选择</h3><ul><li>转发: 分组到达输入链路, 路由器将其移动到适当的输出链路<ul><li>转发表: 首部 - 输出链路, 根据第三层首部, 决定输出链路</li></ul></li><li>路由选择: 网络层决定分组所采用的路由或路径<ul><li>路由选择算法: 决定了首部对应的输出链路的值; 集中式/分布式; 人工配置/路由选择协议</li><li>路由器: 除链路层交换机 以外的 分组交换机</li></ul></li><li>连接建立: 分组流动之前建立状态<h3 id="网络服务模型"><a href="#网络服务模型" class="headerlink" title="网络服务模型"></a>网络服务模型</h3></li><li>网络服务<ul><li>确保交付: 确保到达目的地</li><li>有时延上界的确保交付: 在规定时间内到达</li><li>有序分组交付: 发送与接收的顺序相同</li><li>确保最小带宽</li><li>确保最大时延抖动: 相邻分组发送时的时间差 与 相邻分组接收时的时间差 相差不超过特定值</li><li>安全性服务: 密钥加密</li></ul></li><li>因特网: 尽力而为(没任何网络服务)</li><li>ATM: CBR(恒定比特率, 无丢包, 有序, 维护定时); ABR(可用比特率, 维护最小速率, 有序, 提供拥塞指示)<h2 id="虚电路和数据报网络"><a href="#虚电路和数据报网络" class="headerlink" title="虚电路和数据报网络"></a>虚电路和数据报网络</h2><h3 id="虚电路网络"><a href="#虚电路网络" class="headerlink" title="虚电路网络"></a>虚电路网络</h3></li><li>虚电路: 在网络层使用连接</li><li>组成<ul><li>源和目的的路径</li><li>VC号, 该路径每段链路的号码</li><li>路由转发表表项, [入接口 - 入VC - 出接口 - 出VC]</li></ul></li><li>连接状态信息: 新连接添加表项, 断开连接删除表项<ul><li>虚电路建立<ul><li>运输层联络网络层, 指定接收地址(信令报文-信令协议)</li><li>网络层决定路径, 分配VC号, 添加表项, 预留资源</li></ul></li><li>数据传送</li><li>虚电路拆除<ul><li>接收方或发送方通知网络层终止虚电路</li><li>网络层通知另一端结束呼叫, 更新表项<h3 id="数据报网络"><a href="#数据报网络" class="headerlink" title="数据报网络"></a>数据报网络</h3></li></ul></li></ul></li><li>转发表: [前缀 - 链路接口]<ul><li>最长前缀匹配规则</li><li>转发表的更新: 路由选择算法</li></ul></li></ul><h2 id="路由器工作原理"><a href="#路由器工作原理" class="headerlink" title="路由器工作原理"></a>路由器工作原理</h2><ul><li>输入端口<ul><li>线路端接: 物理线路接入</li><li>数据链路处理: 协议, 拆封</li><li>查找转发排队: 查找转发表, 存帧排队</li></ul></li><li>交换结构<ul><li>经内存交换</li><li>经总线交换</li><li>经互连网络交换(纵横式)</li></ul></li><li>输出端口: 排队, 数据链路处理, 线路端接</li><li>何处出现排队</li></ul><p>&lt;&lt;&lt; TODO &gt;&gt;&gt;</p><h1 id="运输层"><a href="#运输层" class="headerlink" title="运输层"></a>运输层</h1><h2 id="多路复用和多路分解"><a href="#多路复用和多路分解" class="headerlink" title="多路复用和多路分解"></a>多路复用和多路分解</h2><ul><li>套接字Socket: 应用层-网络层 门户<ul><li>具有唯一标识符</li><li>运输层报文开头的2个字段: 源端口号16bit : 目的端口号16bit<ul><li>周知端口号: 0~1023<h3 id="无连接的多路复用与多路分解"><a href="#无连接的多路复用与多路分解" class="headerlink" title="无连接的多路复用与多路分解"></a>无连接的多路复用与多路分解</h3></li></ul></li></ul></li><li>UDP套接字由二元组进行标识: 目的IP : 目的端口号</li><li>源端口号: 回复时使用<h3 id="面向连接的多路复用与多路分解"><a href="#面向连接的多路复用与多路分解" class="headerlink" title="面向连接的多路复用与多路分解"></a>面向连接的多路复用与多路分解</h3></li><li>TCP套接字由四元组进行标识: 源IP : 源端口号 : 目的IP : 目的端口号</li><li>不同来源的报文到达同一端口可区分, HTTP服务器<h2 id="UDP-无连接运输"><a href="#UDP-无连接运输" class="headerlink" title="UDP: 无连接运输"></a>UDP: 无连接运输</h2></li><li>仅提供复用分解, 差错检测</li><li>无连接: 发送报文段之前, 没有握手</li><li>优点: 首部短, 时间灵活, 无连接建立, 无连接状态</li><li>无拥塞控制, 可以由应用层构建可靠传输<h3 id="报文段结构"><a href="#报文段结构" class="headerlink" title="报文段结构"></a>报文段结构</h3>| 源端口号 | 目的端口号 | 长度(首部+数据) | 检验和 | 应用数据(报文) |<br>|-|-|-|-|-|<br>| 16bit | 16bit | 16bit | 16bit | … | <ul><li>UDP变长数据段</li><li>检验和计算: UDP报文段 + IP首部的部分字段()<h3 id="UDP检验和"><a href="#UDP检验和" class="headerlink" title="UDP检验和"></a>UDP检验和</h3></li></ul></li><li>计算方法<ul><li>报文段分为16bit字, 相加求和</li><li>最高位进位回卷, 加到最低位</li><li>取反码</li></ul></li><li>检验方法: 接收方做前两步, 得到全1, 则没问题</li><li>能检测, 不能纠错, 端到端差错控制<h2 id="可靠数据传输原理"><a href="#可靠数据传输原理" class="headerlink" title="可靠数据传输原理"></a>可靠数据传输原理</h2></li><li>可靠数据传输协议: (服务抽象)传输的比特不会受损或丢失, 并且按序到达<h3 id="构造可靠传输协议"><a href="#构造可靠传输协议" class="headerlink" title="构造可靠传输协议"></a>构造可靠传输协议</h3><!-- 不管了, 数据通信学过了, 就那三个差错控制 --><!-- 需要额外补充一点, 之后再做 -->&lt;!– + 经完全可靠信道的可靠数据传输: 废话</li><li>经具有比特差错的信道的可靠数据传输<ul><li>三个功能: 差错检测, 接收方反馈, 重传</li><li>发送端: 2个状态<ul><li>等待上层调用</li><li>等待接收方回复ACK/NAK</li></ul></li><li>接收端: 1个状态: 等待上层调用,  –&gt;</li></ul></li></ul><h2 id="面向连接的运输-TCP"><a href="#面向连接的运输-TCP" class="headerlink" title="面向连接的运输: TCP"></a>面向连接的运输: TCP</h2><ul><li>提供差错检测, 重传, 累积确认, 定时器, 序号和确认号的首部字段</li><li>全双工<h3 id="TCP连接"><a href="#TCP连接" class="headerlink" title="TCP连接"></a>TCP连接</h3></li><li>三次握手<ul><li>客户发送</li><li>服务端发送</li><li>客户发送</li></ul></li><li><p>MSS最大报文段长度(其实是应用层数据的最大长度): 根据 MTU(链路层)最大传输单元 确定, 典型值1460字节</p><h3 id="TCP报文段结构"><a href="#TCP报文段结构" class="headerlink" title="TCP报文段结构"></a>TCP报文段结构</h3><p>| 源端口号 | 目的端口号 | 序号 | 确认号 | (第一堆) | 接收窗口 | 因特网校验和-紧急数据指针 | 选项 | 数据 |<br>|-|-|-|-|-|-|-|-|-|<br>| 16bit | 16bit | 32bit | 32bit | 16bit | 16bit | 16bit+16bit | 0bit+ | … |</p></li><li><p>第一堆里面有: 首部长度4bit(以字为单位, 1=4字节) + 保留未用6bit + (URG ACK PSHRST SYN FIN)标志字段6bit</p></li><li>SYN FIN RST 用于连接建立和拆除, PSH代表必须立即将数据交给上层, URG与紧急数据指表示指向位置是紧急数据的最后一个字节, 需要通知上层</li><li>序号和确认号<ul><li>序号: 是该报文段的首字节的字节流编号<blockquote><p>单纯的ACK不包含数据字节, 因此不引发编号增加</p></blockquote></li><li>确认号: 表示这一序号之前的字节均被正确接收, 它和其后的未接收<blockquote><p>一个报文可以同时有确认号和序号, 是捎带ACK</p></blockquote><h3 id="往返时间的估计与超时"><a href="#往返时间的估计与超时" class="headerlink" title="往返时间的估计与超时"></a>往返时间的估计与超时</h3></li></ul></li><li>估计往返时间<ul><li>SampleRTT: 某一报文被发出(交给IP)到其确认被接收的时间量(一个来回)<blockquote><p>重传的报文不进行测量</p></blockquote></li><li>EstimatedRTT: 初始为第一个测得的SampleRTT, 之后根据下式更新<br>$$\textrm{EstimatedRTT} = (1-\alpha)\cdot\textrm{EstimatedRTT} + \alpha \cdot \textrm{SampleRTT}$$<blockquote><p>指数移动加权平均</p></blockquote></li><li>DevRTT: RTT的偏差, 是Sample和Estimated的差的绝对值, 也用指数移动加权平均<br>$$\textrm{DevRTT} = (1-\beta)\cdot\textrm{DevRTT} + \beta \cdot |\textrm{SampleRTT}-\textrm{EstimatedRTT}|$$</li></ul></li><li>设置和管理重传超时间隔<ul><li>重传间隔<ul><li>默认初始值为1s</li><li>超时后, 设为先前值的2倍</li><li>若有新的EstimatedRTT, 立刻据下式更新<br>$$\textrm{TimeInterval} = \textrm{EstimatedRTT} + 4\cdot \textrm{DevRTT}$$</li></ul></li></ul></li></ul><h3 id="可靠数据传输"><a href="#可靠数据传输" class="headerlink" title="可靠数据传输"></a>可靠数据传输</h3><ul><li>累积ACK<ul><li>ACK中的数字, 表示其之前的字节均被接收</li></ul></li><li>重传<ul><li>规则: 一个报文到达重传间隔, 仍未收到ACK(ACK&gt;SEQ+LEN), 则重传</li><li>超时间隔加倍: 重传过后, 下一次的定时将会加倍; </li><li>推算超时间隔: 若收到ACK或得到上层应用数据, 则又改为使用$\textrm{TimeInterval}$计算</li></ul></li><li>快速重传<ul><li>ACK生成策略<ul><li>延迟ACK: 某一报文到达, 等待500ms, 若下一个按序报文没到, 发这一报文ACK</li><li>立刻发送累积ACK: 一个按序报文到了, 前一个在等待发ACK, 发累积ACK, ACK后一个报文</li><li>冗余ACK: 到达一个报文, 其序号大于期望的序号, 立刻发送冗余ACK, 其序号为期望序号</li><li>收到的报文填补空缺, 且起始于空缺的低端, 则立刻发ACK</li></ul></li><li>收到3个冗余ACK, 则进行快速重传, 假定被ACK的报文后的报文全部丢失</li></ul></li><li>回退N步还是选择重传<ul><li>第n个报文重传, 若之后的报文被缓存, 且其ACK及时到达, 那么后续可以不用重传<blockquote><p>这意味着TCP不是单纯的GBN, 而含有一部分SN</p></blockquote><h3 id="流量控制-1"><a href="#流量控制-1" class="headerlink" title="流量控制"></a>流量控制</h3></li></ul></li><li>接收窗口<ul><li>接收方跟踪<ul><li>应用读取的最后一个字节的编号: LastByteRead</li><li>接收到的最后一个字节的编号: LastByteRcvd</li><li>接收缓存大小: RcvBuffer</li><li>接收窗口大小: rwnd = RcvBuffer-(LastByteRcvd-LastByteRead)<blockquote><p>也就是缓存余量</p></blockquote></li><li>接收方将rwnd放入发给发送方的报文中</li></ul></li><li>发送方跟踪<ul><li>发送的最后一个字节的编号: LastByteSent</li><li>被确认的最后一个字节的编号: LastByteAcked</li><li>从接收到的报文中得到的rwnd</li><li>需要始终保证 LastByteSent - LastByteAcked &lt;= rwnd</li><li>若出现rwnd=0, 则需要继续发送含有一字节数据的报文<blockquote><p>为了防止接收方无数据要发, 引发发送端阻塞. 这个一字节的报文总会被ACK, 有机会获得一个非0的rwnd值</p></blockquote><h3 id="TCP连接管理"><a href="#TCP连接管理" class="headerlink" title="TCP连接管理"></a>TCP连接管理</h3></li></ul></li></ul></li><li><p>建立: 三次握手</p><p>| 通信 | SYN | ACK | SEQ | 操作 |<br>|-|-|-|-|-|<br>| 客户-&gt;服务 | + |  | client_isn | 客户端随机选择起始序号 |<br>| 服务-&gt;客户 |  | client_isn+1 | server_isn | 服务器分配资源, 随机选择起始序号 |<br>| 客户-&gt;服务 |  | server_isn+1 | client_isn+1 | 客户端分配资源 |</p></li><li>终止(以客户终止为例)<ul><li>客户发送FIN(设置首部FIN标志位1)</li><li>服务器ACK这个FIN</li><li>服务器发送FIN, 并立刻关闭, 释放资源</li><li>客户端ACK这个FIN, 定时等待之后关闭, 释放资源</li></ul></li><li>防范SYN洪泛攻击<ul><li>第一步的isn使用散列函数, 用源地址, 目的地址和端口号, 和一个只有服务器知道的散列函数</li><li>第二步不分配资源</li><li>第三步根据ACK里面的seq, 可以验证这个ACK是由先前的某个SYN生成的, 于是分配资源建立连接</li></ul></li><li>拒绝通信<ul><li>发送RST(RST标志位1)</li></ul></li></ul><h2 id="拥塞控制原理"><a href="#拥塞控制原理" class="headerlink" title="拥塞控制原理"></a>拥塞控制原理</h2><ul><li>一堆废话, 我只关心TCP</li></ul><h2 id="TCP拥塞控制"><a href="#TCP拥塞控制" class="headerlink" title="TCP拥塞控制"></a>TCP拥塞控制</h2><ul><li>拥塞窗口cwnd<ul><li>对发送进行限制: LastByteSent - LastByteAcked &lt;= min(rwnd, cwnd)</li></ul></li><li>窗口与速率的关系: B = S(发出的包数量)/RTT(往返时间)</li><li>TCP拥塞控制算法<ul><li>慢启动<ul><li>初始: cwnd = 1 (MSS)</li><li>加倍: 每一轮, cwnd加倍</li><li>结束<ul><li>超时, 取cwnd = 1, ssthresh = cwnd/2</li><li>到达ssthresh, 进入拥塞避免模式</li><li>3个冗余ACK, cwnd = cwnd/2+3, 进入快速恢复</li></ul></li></ul></li><li>拥塞避免<ul><li>线性增加: 每一轮, cwnd+1</li><li>结束<ul><li>超时, 取cwnd = 1, ssthresh = cwnd/2, 相当于慢启动</li><li>3个冗余ACK, cwnd = cwnd/2+3, 进入快速恢复</li></ul></li></ul></li><li>快速恢复<ul><li>接下来收到的冗余ACK, cwnd都加1(之前的3个冗余ACK已经加过3, 至少加3)</li><li>结束: 收到期待的ACK, 将cwnd设置为ssthresh, 进入拥塞避免</li></ul></li><li>TCP拥塞控制: 回顾<ul><li>TCP Tahoe: 没有快速恢复, 3个ACK也进入慢启动</li><li>TCP Reno: 上文的方案</li></ul></li></ul></li></ul><h3 id="公平性"><a href="#公平性" class="headerlink" title="公平性"></a>公平性</h3><ul><li>TCP AIMD<ul><li>相同的RTT: 公平, 最终会达到平均分配带宽</li><li>RTT不同: RTT小的更快扩大窗口, 将得到更多带宽, 最终似乎与RTT成反比</li></ul></li><li>UDP参与<ul><li>UDP没有公平可言, 抢占资源</li><li>UDP将挤压TCP资源</li></ul></li><li>并行TCP<ul><li>一个应用使用多个TCP连接, 就获得了多倍其应得的带宽<h3 id="网络辅助拥塞控制"><a href="#网络辅助拥塞控制" class="headerlink" title="网络辅助拥塞控制"></a>网络辅助拥塞控制</h3></li><li>IP首部设置ECN(2比特, 4状态), 送到接收主机</li><li>接受主机在TCP ACK中设置ECE, 发到发送主机</li><li>发送主机减半cwnd, 并在下一个报文头中设置CWD, 发到接收主机</li></ul></li></ul><h1 id="Chapter-4-Internetworking"><a href="#Chapter-4-Internetworking" class="headerlink" title="Chapter 4. Internetworking"></a>Chapter 4. Internetworking</h1><blockquote><p>[Textbook] 4.3, 5.3, 5.4, 5.5, 5.6</p></blockquote><h1 id="Chapter-5-End-to-End-Protocols"><a href="#Chapter-5-End-to-End-Protocols" class="headerlink" title="Chapter 5. End-to-End Protocols"></a>Chapter 5. End-to-End Protocols</h1><blockquote><p>[Textbook] 3.1, 3.2, 3.3, 3.4, 3.5, 9.x </p></blockquote><h1 id="Chapter-6-Congestion-Control-and-QoS"><a href="#Chapter-6-Congestion-Control-and-QoS" class="headerlink" title="Chapter 6. Congestion Control and QoS"></a>Chapter 6. Congestion Control and QoS</h1><blockquote><p>[Textbook] 3.6, 3.7</p></blockquote><h1 id="Chapter-7-Network-Security"><a href="#Chapter-7-Network-Security" class="headerlink" title="Chapter 7. Network Security"></a>Chapter 7. Network Security</h1><blockquote><p>[Textbook] 8.x</p></blockquote><h1 id="Chapter-8-Internet-Applications"><a href="#Chapter-8-Internet-Applications" class="headerlink" title="Chapter 8. Internet Applications"></a>Chapter 8. Internet Applications</h1><blockquote><p>[Textbook] 2.x</p></blockquote>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;[Textbook]: Computer Networking: A Top-Down Approach(7th Edition) by James F. Kurose, Keith W. Ross&lt;br&gt;搜索”#解题”查看所有计算题解题方法&lt;br&gt;
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Computer Network" scheme="https://Maxwell-lyu.github.io/tags/Computer-Network/"/>
    
  </entry>
  
  <entry>
    <title>DB-ALL</title>
    <link href="https://Maxwell-lyu.github.io/2019/09/02/Learn-DB-20190902-DB-ALL/"/>
    <id>https://Maxwell-lyu.github.io/2019/09/02/Learn-DB-20190902-DB-ALL/</id>
    <published>2019-09-02T02:15:09.000Z</published>
    <updated>2019-09-02T02:16:16.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="第一章"><a href="#第一章" class="headerlink" title="第一章:"></a>第一章:</h1>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;第一章&quot;&gt;&lt;a href=&quot;#第一章&quot; class=&quot;headerlink&quot; title=&quot;第一章:&quot;&gt;&lt;/a&gt;第一章:&lt;/h1&gt;
      
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Introduction to Database" scheme="https://Maxwell-lyu.github.io/tags/Introduction-to-Database/"/>
    
  </entry>
  
  <entry>
    <title>DB-KEY</title>
    <link href="https://Maxwell-lyu.github.io/2019/09/02/Learn-DB-20190902-DB-KEY/"/>
    <id>https://Maxwell-lyu.github.io/2019/09/02/Learn-DB-20190902-DB-KEY/</id>
    <published>2019-09-02T01:29:02.000Z</published>
    <updated>2019-12-26T11:24:25.267Z</updated>
    
    <content type="html"><![CDATA[<h1 id="关系代数"><a href="#关系代数" class="headerlink" title="关系代数"></a>关系代数</h1><h2 id="关系代数的应用解过程"><a href="#关系代数的应用解过程" class="headerlink" title="关系代数的应用解过程"></a>关系代数的应用解过程</h2><blockquote><p>关系代数: </p><ol><li>确定查询目标</li><li>明确查询条件</li><li>选择查找路径， 确定操作对象</li><li>关系的合并: 据3, 联结</li><li>元组的选择: 据2, 条件</li><li>属性的指定: 据1, 投影</li></ol></blockquote><h1 id="第八章"><a href="#第八章" class="headerlink" title="第八章"></a>第八章</h1><h2 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h2><ul><li>关系模式设计: 同一个关系数据库系统 有 多种不同的关系模式设计方案</li><li>好的设计方案: 既有合理的数据冗余度, 又没有插入和删除操作异常</li><li>不同设计结果有区别的原因: 函数依赖(属性间的语义相关性)不同</li><li>关系的规范化<ul><li>按照给定范式要求设计关系模式</li><li>范式: 对一个关系中允许存在的函数依赖的要求<h2 id="规范化理论"><a href="#规范化理论" class="headerlink" title="规范化理论"></a>规范化理论</h2><h3 id="函数依赖"><a href="#函数依赖" class="headerlink" title="函数依赖"></a>函数依赖</h3></li></ul></li><li>函数依赖: 一个关系中 两组属性之间的 取值约束<ul><li>表示: $X\to Y$: $Y$函数依赖于$X$</li><li>直观: 在关系$R$中, 每个$X$的值都有唯一的一个$Y$值与之对应</li><li>定义: 关系模式$R(U)$中, 关系$r$中元组$r_i$在$X$中的取值确定后, $Y$中取值必被确定, 则$X\to Y$</li><li>$X$决定因素, $Y$依赖因素</li></ul></li><li>发现函数依赖<ul><li>直接根据语义</li><li>根据取值对应关系<ul><li>一一对应: $X\to Y$, $Y\to X$</li><li>一多对应/多一对应: $Y\to X$, $X\to Y$</li><li>多多对应: 没有</li></ul></li></ul></li><li>平凡函数依赖<ul><li>非平凡函数依赖: $X\to Y, Y\not\subseteq X$, 默认是这个</li><li>平凡函数依赖: 反之</li></ul></li><li>完全函数依赖<ul><li>完全函数依赖: $X\to Y, \forall X’\subset X, X’\not\to Y$, 则$X\overset{f}{\to}Y$</li><li>部分函数依赖: $X\to Y, \exists X’\subset X, X’\to Y$, 则$X\overset{p}{\to}Y$</li></ul></li><li>传递函数依赖<ul><li>$X\to Y, Y\not\subset X, Y\not\to X, Y\to Z$, 则 $X\to Z$为传递函数依赖</li></ul></li><li>Armstrong公理系统<ul><li>基本规则<ul><li>自反规则: $Y\subseteq X$, 则$X\to Y$</li><li>增广规则: $X\to Y$, 则$XZ\to YZ$</li><li>传递规则: $X\to Y\wedge Y\to Z$, 则$X\to Z$</li></ul></li><li>扩充规则<ul><li>分解规则: $X\to YZ$, 则$X\to Y\wedge X\to Z$</li><li>合并规则: $X\to Y\wedge X\to Z$则$X\to YZ$</li><li>伪传递规则: $X\to Y\wedge WY\to Z$, 则$WX\to Z$</li></ul></li></ul></li><li>函数依赖的逻辑蕴含概念<ul><li>$F$为关系模式$R(U)$的一个函数依赖集</li><li>从已有的函数依赖出发, 利用公理系统可以推导出$X\to Y$, 则$F\vDash X\to Y$</li></ul></li><li>函数依赖集$F$的闭包$F^+$: $F^+=\{X\to Y|F\vDash X\to Y\}$</li><li>函数依赖集的等价<ul><li>可以互相推导出其中的函数依赖</li></ul></li><li>最小函数依赖集<ul><li>与$F$等价的, 最小的集合</li><li>[解题] 寻找最小依赖集<ul><li>首先得到题目中的所有函数依赖, 分解成右端只有一个的依赖</li><li>画箭头图, 用那堆公理尽可能减少集合大小</li><li>合并依赖</li></ul></li></ul></li><li>属性集$X$在函数依赖集$F^+$上的闭包$X_F^+$: $X_F^+=\{A|F\vDash X\to A\}$<ul><li>[解题] 计算闭包<ul><li>$X^+=X$</li><li>不断重复: 对每一个$F$中的依赖$Y\to Z$, 若$Y\subseteq X^+$, 则$X^+ = X^+ \cup Z$</li><li>直到不再变化</li></ul></li></ul></li><li>关键字<ul><li>若$K\subseteq U, K\overset{f}{\to}U$, 则$K$是$R$的关键字</li><li>主属性集: 所有关键字中的属性构成的集合</li><li>非主属性集: 不属于任何一个关键字的属性构成的集合</li><li>关键字与闭包: $K_F^+=U$, $\forall Z\subset F, Z_F^+\ne U$</li><li>[解题] 寻找关键字<ul><li>计算最小依赖集</li><li>不断重复从$U$中删除属性, 直到其闭包不等X于$U$</li><li>将得到一个关键字</li><li>技巧<ul><li>只在左边出现过的属性 属于 每一个关键字</li><li>只在右边出现过的属性 不属于 任何一个关键字</li><li>只需要对两边都有的属性尝试删除即可<h3 id="与函数依赖有关的范式"><a href="#与函数依赖有关的范式" class="headerlink" title="与函数依赖有关的范式"></a>与函数依赖有关的范式</h3></li></ul></li></ul></li></ul></li><li>模式分解<ul><li>分解结果: 子关系模式, 满足<ul><li>$\textrm{Head}(R)=\bigcup^n\textrm{Head}(R_i)$</li><li>$F_i=\{X\to Y|X\to Y\in F^+ \wedge (X\cup Y)\in \textrm{Head}(R_i)\}$</li></ul></li><li>分解方法<ul><li>找出所有不满足范式的依赖</li><li>选择一个依赖, 设$X\overset{f}{\to}Y$为这个依赖, 则将这个依赖所在的关系$R$分解为<ul><li>$R_1=\{X\cup Y, \{X\to Y\}\}$</li><li>$R_2=\{\textrm{Head}(R)-Y, F_2\}$</li><li>其中$F_2=\{A\to B|A\to B\in F^+\wedge (A\cup B)\subseteq \textrm{Head}(R_2)\}$</li></ul></li></ul></li></ul></li><li>1NF: 属性值不可分割, 全都满足</li><li>2NF: 满足1NF, 每个非主属性都完全依赖于关键字<ul><li>检查:<ul><li>找到所有非主属性 和 所有候选关键字</li><li>检查每一个非主属性$A$和每一个候选关键字$K$之间的函数依赖, 看看有没有部分依赖</li></ul></li></ul></li><li>3NF: 满足2NF, 每个非主属性都不传递依赖于关键字<ul><li>检查: 不满足3NF, 则必然存在下列情况之一, 其中$X\overset{f}{\to} Y$<ul><li>$X$是某个关键字的真子集</li><li>$X$不是关键字</li></ul></li></ul></li><li>BCNF: 满足1NF, 若$X\to Y$则$X$必含有该模式的关键字<ul><li>检查: 每个函数依赖, 是否满足$X$是关键字</li></ul></li><li>BCNF -&gt; 3NF<h3 id="多值依赖与第四范式"><a href="#多值依赖与第四范式" class="headerlink" title="多值依赖与第四范式"></a>多值依赖与第四范式</h3></li><li>多值依赖: $X\to\to Y$<ul><li>定义: 对$X$的一个取值, 存在一组$Y$与其对应; $Y$的取值与$U-X-Y$不相关</li><li>成因: 两个一对多关系$C\to T$, $C\to L$, 其合并后$T$与$L$就是多值依赖</li><li>平凡多值依赖<ul><li>非平凡多值依赖: $U-X-Y$不为空集</li><li>平凡多值依赖: 反之</li></ul></li></ul></li><li>多值依赖有关的推理规则(需要掌握)<ul><li>求补规则: 若$X\to Y$, 则$U-X-Y$</li><li>转换规则: 若$X\to Y$, 则$X\to\to Y$</li></ul></li><li>4NF<ul><li>定义: 若$X\to\to Y$是非平凡多值依赖, 则$X$必含有关键字</li><li>特点: 函数依赖需要满足BCNF; 不是函数依赖的多值依赖只有平凡多值依赖<h2 id="模式分解的研究"><a href="#模式分解的研究" class="headerlink" title="模式分解的研究"></a>模式分解的研究</h2></li></ul></li><li>无损联结性<ul><li>设$\rho=\{R_1,\cdots,R_k\}$是对$R$的一个分解</li><li>如果对每个满足$F$的关系实例$r$都满足$r=\pi_{R_1}(r)\Join\cdots\Join\pi_{R_k}(r)$</li><li>则$\rho$是无损联接分解</li><li>充要条件($\rho=\{R_1,R_2\}$)<ul><li>$R_1\cap R_2\to (R_1-R_2)$ 或 $R_1\cap R_2\to (R_2-R_1)$</li></ul></li></ul></li><li>依赖保持性<ul><li>表示$\pi_Z(F)=\{X\to Y|X\to Y\in F^+\wedge (X\cup Y)\subseteq Z\}$</li><li>$F^+=(\pi_{R_1}(F)\cup\cdots\cup\pi_{R_1}(F))^+$<h2 id="到3NF的分解方法"><a href="#到3NF的分解方法" class="headerlink" title="到3NF的分解方法"></a>到3NF的分解方法</h2></li></ul></li><li>计算最小依赖集, 代替$F$进行分解</li><li>$S=\emptyset$</li><li>对每一个函数$X\to Y$依赖进行<ul><li>若在$S$中找不到子关系模式$Z$, 使得$X\cup Y\subseteq\textrm{Head}(Z)$</li><li>$X$和$Y$合并成新的子关系模式, 加入$S$</li></ul></li><li>如果$R$中的每个候选关键字$K$均不在$S$中, 则任选一个关键字, 其属性单独构成一个子关系模式, 加入$S$</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;关系代数&quot;&gt;&lt;a href=&quot;#关系代数&quot; class=&quot;headerlink&quot; title=&quot;关系代数&quot;&gt;&lt;/a&gt;关系代数&lt;/h1&gt;&lt;h2 id=&quot;关系代数的应用解过程&quot;&gt;&lt;a href=&quot;#关系代数的应用解过程&quot; class=&quot;headerlink&quot; titl
      
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Introduction to Database" scheme="https://Maxwell-lyu.github.io/tags/Introduction-to-Database/"/>
    
  </entry>
  
  <entry>
    <title>JavaScript</title>
    <link href="https://Maxwell-lyu.github.io/2019/08/05/Tech-JS-20190805-JS/"/>
    <id>https://Maxwell-lyu.github.io/2019/08/05/Tech-JS-20190805-JS/</id>
    <published>2019-08-05T14:36:20.000Z</published>
    <updated>2019-10-13T12:48:29.426Z</updated>
    
    <content type="html"><![CDATA[<h1 id="Where-to-Insert-JavaScript"><a href="#Where-to-Insert-JavaScript" class="headerlink" title="Where to Insert JavaScript"></a>Where to Insert JavaScript</h1><ol><li><p>Header or Body, use <code>&lt;script&gt; ... &lt;/script&gt;</code></p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="undefined"></span></span><br><span class="line"><span class="undefined">  function myFunction() &#123;&#125;</span></span><br><span class="line"><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure></li><li><p>External File or URL, use <code>&lt;script src=&quot;...&quot;&gt;&lt;/script&gt;</code></p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"/js/myScript.js"</span>&gt;</span><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"https://www.dummy.com/js/myScript.js"</span>&gt;</span><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure></li></ol><h1 id="JavaScript-Output"><a href="#JavaScript-Output" class="headerlink" title="JavaScript Output"></a>JavaScript Output</h1><ol><li>to Document: <code>document.write(&quot;...&quot;)</code></li><li>to Element: <code>document.getElementById(&quot;elementName&quot;).innerHTML = ...</code></li><li>to Alert Window: <code>window.alert(...);</code> <code>alert(...)</code></li><li>to Console: <code>console.log(...)</code></li></ol><h1 id="JavaScript-Syntax"><a href="#JavaScript-Syntax" class="headerlink" title="JavaScript Syntax"></a>JavaScript Syntax</h1><p>I know C, so nothing new</p><h1 id="JavaScript-Statements"><a href="#JavaScript-Statements" class="headerlink" title="JavaScript Statements"></a>JavaScript Statements</h1><ol><li>“;” is not required, but recommended</li><li>line break after operator?????</li><li>use <code>function</code> as code blocks</li><li>keywords: <ol><li><code>break</code>, <code>continue</code>, <code>do ... while</code>, <code>for</code>, <code>if ... else</code>, <code>return</code>, <code>switch</code> similar to C</li><li><code>try ... catch</code> similar to java</li><li><code>debugger</code>: Stops the execution of JavaScript, and calls (if available) the debugging function</li><li><code>function</code>, <code>var</code> explained above</li></ol></li></ol><h1 id="JavaScript-Comments"><a href="#JavaScript-Comments" class="headerlink" title="JavaScript Comments"></a>JavaScript Comments</h1><p>Nothing new here</p><h1 id="JavaScript-Variables"><a href="#JavaScript-Variables" class="headerlink" title="JavaScript Variables"></a>JavaScript Variables</h1>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;Where-to-Insert-JavaScript&quot;&gt;&lt;a href=&quot;#Where-to-Insert-JavaScript&quot; class=&quot;headerlink&quot; title=&quot;Where to Insert JavaScript&quot;&gt;&lt;/a&gt;Where to
      
    
    </summary>
    
      <category term="Technique" scheme="https://Maxwell-lyu.github.io/categories/Technique/"/>
    
    
      <category term="JavaScript" scheme="https://Maxwell-lyu.github.io/tags/JavaScript/"/>
    
  </entry>
  
  <entry>
    <title>DB-PRE</title>
    <link href="https://Maxwell-lyu.github.io/2019/07/11/Learn-DB-20190711-DB-PRE/"/>
    <id>https://Maxwell-lyu.github.io/2019/07/11/Learn-DB-20190711-DB-PRE/</id>
    <published>2019-07-11T11:44:05.000Z</published>
    <updated>2019-12-27T02:45:54.643Z</updated>
    
    <content type="html"><![CDATA[<h1 id="第一章-数据库系统概述"><a href="#第一章-数据库系统概述" class="headerlink" title="第一章: 数据库系统概述"></a>第一章: 数据库系统概述</h1><h2 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h2><ul><li><strong>信息</strong>: 用于反映现实世界中事物的<strong>物理状态</strong>, 向人们提供一些已知的、客观存在的事实和知识</li><li><strong>数据</strong>: 是指具有一定的语义含义, 并且可以被记录下来的<strong>已知事实</strong>. 在计算机中, 数据被表示为具有一定格式（或结构）的<strong>符号串</strong>, 它是计算机软件中程序加工的原料与结果, 属于软件范畴</li><li>数据是信息的载体, 信息则是数据的内涵</li><li><p><strong>数据的特性</strong>  </p><ol><li>表现的多样性</li><li>可构造性: 型(数据类型, 数据结构, 数据模式), 值</li><li>挥发性/持久性</li><li>私有性/共享性</li><li>‘量’的表示: 少量/大量/海量</li></ol></li><li><p><strong>数据特性的变化</strong>  </p><ol><li>量: 少量-&gt;大量-&gt;海量</li><li>结构: 简单-&gt;复杂</li><li>服务范围: 私有-&gt;共享</li><li>在软件中的地位: 附属地位(程序是主体)-&gt;主导地位(数据为中心, 应用程序共享数据)</li></ol></li><li><p><strong>数据库应用系统</strong>DBAS: 利用数据库系统作应用开发所构成的集成化的独立运行系统</p><ul><li><strong>数据库系统</strong>DBS: 是一个以对海量的、具有复杂数据结构的、可以持久保存的、可供多 户共享的数据进行统一管理为目标的计算机系统<ul><li><strong>数据库</strong>DB: 是数据集合, 具有统一的结构形式并存放于统一的存储介质内, 它由多种应用数据集成, 并可被应用所共享</li><li><strong>数据库管理系统</strong>DBMS: <ul><li>是管理数据库的系统软件</li><li>特点: 管理持久性数据, 大量数据, 数据共享</li><li>作用: 数据库应用程序与数据库的接口, 安全可靠+简明方便</li><li>功能: 组织, 操纵, 维护, 控制及保护, 交换, 服务, 字典</li><li>数据子语言: (SQL语言的组成部分<ul><li>数据定义语言: DDL</li><li>数据操纵语言: DML</li><li>数据控制语言: DCL</li></ul></li><li>数据子语言的使用方式: 交互式命令(终端直接操作), 宿主型(嵌入到宿主语言中)</li></ul></li><li><strong>数据库管理员</strong>DBA: 对数据库进行规划、设计、维护、监视的专职人员</li><li><strong>软件平台</strong>: 操作系统, 语言, 数据库应用开发工具, 通用的数据库访问接口</li><li><strong>硬件平台</strong></li></ul></li><li><strong>应用软件</strong>, <strong>应用界面</strong></li><li><strong>数据库用户</strong><ul><li><strong>最终用户</strong>: 终端查询用户, 应用程序的使用者</li><li><strong>应用程序开发人员</strong></li><li><strong>数据库管理员</strong></li></ul></li></ul></li><li><p>数据库应用系统层次结构(9)</p><blockquote><p>硬件平台-&gt;操作系统-&gt;数据-&gt;数据库管理系统-&gt;数据交换与中间件-&gt;开发工具-&gt;应用软件-&gt;应用界面-&gt;用户</p></blockquote></li></ul><h2 id="数据库系统的发展及趋势"><a href="#数据库系统的发展及趋势" class="headerlink" title="数据库系统的发展及趋势"></a>数据库系统的发展及趋势</h2><ul><li>数据管理技术的发展历史<blockquote><p>人工管理-&gt;文件系统管理-&gt;数据库系统管理</p></blockquote></li><li>数据库管理系统的发展阶段<ul><li>层次/网状数据库: 20世纪60年代~70年代<ul><li>从无到有, 简单的共享数据读写</li></ul></li><li>关系数据库: 20世纪70年代~<ul><li>从有到大规模商业化应用</li><li>面向事务处理型引用OLTP</li></ul></li><li>数据仓库: 20世纪90年代~<ul><li>面向数据分析型婴童OLAP</li></ul></li><li>新型数据库管理系统: 21世纪<ul><li>NoSQL数据库/大数据管理系统</li></ul></li></ul></li><li>数据库系统的发展历史<ul><li><strong>文件系统阶段</strong>: 仅是数据库系统的雏形<ul><li>优点: 利用文件系统来参与数据管理, 向用户提供简单的数据管理和共享能力</li><li>缺点: 数据管理功能不完整不统一, 数据共享能力弱, 不利于数据库系统的移植</li></ul></li><li><strong>层次数据库与网状数据库</strong>: 是真正的数据库系统<ul><li>优点: 统一的数据管理工具, 数据共享能力</li><li>缺点: 受文件物理影响大, 数据构造繁琐</li></ul></li><li><strong>关系数据库</strong>: 80年代潮流<ul><li>优点: 结构简单、使用方便、逻辑性强、物理性少</li><li>缺点: 模型的描述能力不足, 数据操纵功能有待扩展</li><li>扩充: <strong>专用数据库系统</strong>: 专用性有余而通用性不足</li></ul></li><li><strong>通用数据库系统</strong>: 90年代重点<ul><li>面向对象数据库系统</li><li>知识库系统</li><li>关系数据库系统扩充</li></ul></li><li><strong>新一代数据库系统</strong>: 关系数据库系统的进一步扩充与改造<ul><li>对象关系数据库系统, 数据仓库(Data Warehouse), Web数据库, 安全数据库, (嵌入式数据库, 移动数据库, 实时数据库网格数据库, 传感器网络数据库</li></ul></li></ul></li></ul><h2 id="数据库系统的基本特点"><a href="#数据库系统的基本特点" class="headerlink" title="数据库系统的基本特点"></a>数据库系统的基本特点</h2><ul><li><strong>集成性</strong>: 集多种应用数据于一体<ul><li>统一的数据结构</li><li>全局统一的数据模式</li><li>根据应用需要构造局部模式</li></ul></li><li><strong>高共享性</strong>与<strong>低冗余性</strong><ul><li>数据共享<ul><li>多个应用程序使用, 可用于不同的目的</li><li>已有的数据库系统上开发新的应用程序</li><li>向外界提供信息服务功能</li></ul></li><li>数据冗余<ul><li>同一个数据在不同的地方重复存储</li></ul></li><li>减少不必要的存储空间, 避免数据的不一致性</li></ul></li><li><strong>独立性</strong><ul><li>数据或数据结构的改变不会导致对使用这些数据的应用程序的修改, 反之亦然</li><li>物理独立性: 物理结构（包括存储结构、存取方式等）的改变, 不影响数据库的逻辑结构, 不致引起应用程序的变化</li><li>逻辑独立性: 数据库总体逻辑结构的改变, 如修改数据模式、增加新的数据类型、改变数据间联系等, 不需要相应修改应用程序</li></ul></li><li><strong>数据的统一管理与控制</strong><ul><li>数据的完整性检查</li><li>数据的安全性保护</li><li>并发控制</li><li>数据库故障恢复</li></ul></li></ul><h2 id="数据库内部结构体系"><a href="#数据库内部结构体系" class="headerlink" title="数据库内部结构体系"></a>数据库内部结构体系</h2><ul><li><strong>数据库系统的三级模式</strong><ul><li><strong>概念模式</strong>简称<strong>模式</strong>-&gt;概念数据库<ul><li>整个数据库中数据的全局逻辑结构的描述</li><li>基于数据模型, 利用数据定义语言DDL描述</li><li>数据类型, 长度, 特征, 数据间联系, 安全性完整性的要求</li></ul></li><li><strong>外模式</strong>(<strong>子模式</strong>, <strong>用户模式</strong>)-&gt;用户数据库<ul><li>是关于某个用户所需数据的逻辑结构的描述</li><li>是概念模式的子集, 同一概念模式可有多个外模式, 针对用户</li><li>简化用户接口易用, 降低冗余, 利于安全保密</li></ul></li><li><strong>内模式</strong>(<strong>物理模式</strong>)-&gt;物理数据库<ul><li>是关于数据库中数据的物理存储结构和物理存取方法的描述</li></ul></li><li>物理数据库: 真实存在; 其他两种数据库由物理数据库通过数据库管理系统构造</li></ul></li><li><strong>数据库系统的两级映射</strong>: DBMS提供<ul><li><strong>概念模式到内模式</strong>: 物理独立性: 全局逻辑结构到数据的物理存储结构间的对应关系</li><li><strong>外模式到概念模式</strong>: 逻辑独立性: 一个概念模式中可以定义多个外模式, 而每个外模式是概念模式的一个基本视图</li><li>两级映射建立三级模式间的联系与转换, 保证了数据库系统中数据独立性的实现</li></ul></li></ul><h1 id="第二章-数据模型"><a href="#第二章-数据模型" class="headerlink" title="第二章: 数据模型"></a>第二章: 数据模型</h1><h2 id="数据模型的基本概念"><a href="#数据模型的基本概念" class="headerlink" title="数据模型的基本概念"></a>数据模型的基本概念</h2><ul><li><strong>数据</strong>: 现实世界中客体符号化抽象</li><li><strong>数据模型</strong>: 数据基本特征的抽象, 描述<strong>数据的结构</strong>, 定义在该数据结构上<strong>可以执行的操作</strong>以及数据之间必须满足的<strong>约束条件</strong><blockquote><p>数据模型应该能比较真实地模拟现实世界, 易于人理解, 便于在计算机上实现</p><ul><li><strong>数据结构</strong>: 数据的类型, 内容, 性质, 数据间联系</li><li><strong>数据操作</strong>: 操作类型, 操作方式</li><li><strong>数据约束</strong>: 数据结构内数据间的相互关系: 语法语义联系, 制约与依存, 动态变化规则</li></ul></blockquote></li><li>数据模型的<strong>类型</strong><blockquote><p>数据模型的核心是数据结构, 现实中数据及其关系到数据库, 有逐步转化的过程, 以数据模型表示其转化结果<br> 概念数据模型<ruby>–&gt;<rt>转化</rt></ruby>逻辑数据模型<ruby>–&gt;<rt>DBMS</rt></ruby>物理数据模型(可实现)</p><ul><li><strong>概念数据模型</strong>: 面向客观世界, 面向用户, 无关于数据库管理系统和计算机平台<br>种类: E-R模型, EE-R模型; 面向对象模型; 谓词模型<br>描述客观对象的数据特征及相互关系</li><li><strong>逻辑数据模型</strong>: 面向数据库系统, 着重于DBMS实现, 承上启下<br>种类: 层次, 网状模型; 关系, 面向对象, 谓词模型; 对象关系模型<br>描述事物及关系在选定的DBMS中的实现结构, 即据DBMS定义事物及关系的实现结构</li><li><strong>物理数据模型</strong>: 面向计算机物理表示, 给出数据模型在计算机上的物理表示<br>向用户提供与物理存储结构与存取方法相关的定义: 索引, 集簇, 存储区域的选择<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">客观世界                 用户1    ...   用户n</span><br><span class="line">  |                        |              |</span><br><span class="line">  |                        |              |</span><br><span class="line">  |                        |              |</span><br><span class="line">概念模型   +-----------&gt;外模式1   ...  外模式n</span><br><span class="line">  |       /                |              |</span><br><span class="line">  |      /                 |              |</span><br><span class="line">  |     /                  |              |</span><br><span class="line">逻辑模型---------------&gt;概念模式---------+</span><br><span class="line">  |                        |</span><br><span class="line">  |                        |</span><br><span class="line">  |                        |</span><br><span class="line">物理模型---------------&gt;内模式</span><br></pre></td></tr></table></figure></li></ul></blockquote></li></ul><h2 id="数据模型的四个世界"><a href="#数据模型的四个世界" class="headerlink" title="数据模型的四个世界"></a>数据模型的四个世界</h2><ul><li><strong>现实世界</strong>: 客观世界中, 据用户需求目标, 划定边界的应用环境<blockquote><p>用户需求: 数据需求, 处理要求<br>提供转换过程的: 客观基础, 启动环境</p></blockquote></li><li><strong>概念世界</strong>: 基于现实世界, 进一步的抽象而形成<blockquote><p>基本术语: (实体, 属性, 联系)E-R模型, (对象, 类, 方法, 继承)OO模型<br>无关于具体的DBMS和计算机</p></blockquote></li><li><strong>信息世界</strong>: 基于概念世界, 用特定的DBMS构造而成的逻辑数据模型<blockquote><p>用特定的DBMS所提供的工具来定义逻辑数据模型, 侧重于概念数据模型的细化和在数据库系统一级的实现<br>有关于具体的DBMS</p></blockquote></li><li><strong>计算机世界</strong>: 基于逻辑数据模型在计算机中的物理实现, 形成物理数据模型<blockquote><p>侧重于数据库物理存储结构的描述: 存储结构设计, 存取路径设计, 存储空间分配<br>DB的最终实现结构</p></blockquote></li></ul><h2 id="概念世界与概念模型"><a href="#概念世界与概念模型" class="headerlink" title="概念世界与概念模型"></a>概念世界与概念模型</h2><ul><li><strong>概念世界</strong>:  概念世界是一个较为抽象, 概念化的世界; 给出数据的概念化结构; 概念世界一般用概念模型表示</li><li>概念模型种类: 实体-联系(E-R), 扩充的实体-联系(EE-R), 面向对象, 谓词模型</li></ul><h3 id="E-R模型"><a href="#E-R模型" class="headerlink" title="E-R模型"></a>E-R模型</h3><ul><li>概念化模型: 现实世界的要求 转化成 实体, 联系, 属性 及 两种基本关系; 用E-R图表示</li><li><strong>实体</strong><ul><li>客观存在且又能相互区别的事物<blockquote><p>客观事物的抽象, 概念世界中的基本单位</p></blockquote></li><li><strong>实体集</strong>: 具有共性的实体所构成的集合</li></ul></li><li><strong>属性</strong><ul><li>实体所具有的某种特性或特征<blockquote><p>属性有值, 取值集合为<strong>值域</strong></p></blockquote></li><li>一个实体可有多个属性<blockquote><p>共性实体有相同的属性组成<br>不同实体在其属性取值上有区别</p></blockquote></li></ul></li><li><strong>联系</strong><ul><li>一个实体集中的实体与另一个实体集中的实体之间的对应关系</li><li>种类(与联系相关的实体集数): 二元联系, 多元联系, 内部联系</li><li>例子<ul><li>二元(隶属, 学习, 借阅)</li><li>多元(供应: 工厂, 产品, 用户)</li><li>内部(围棋比赛: 黑方, 白方)</li></ul></li><li>相同实体集之间的多种联系<ul><li>在同一组实体集之间可以存在多种联系</li></ul></li><li>联系的函数对应关系<ul><li>一一对应（one to one）</li><li>一多对应（one to many, 多一对应（many to one）</li><li>多多对应（many to many）</li></ul></li><li>联系所具有的特性<ul><li>因联系的发生而产生的特性可以通过<strong>联系上的属性</strong>来表示</li></ul></li></ul></li><li>基本概念之间的<strong>连接关系</strong><ol><li>实体集（联系）与属性间的连接关系</li><li>实体集与联系间的连接关系</li></ol><ul><li>实体(集), 属性及其连接关系的描述<ul><li>属性的描述: 属性名, 属性域</li><li>实体的描述: <ul><li>实体名</li><li>实体型: 实体名+一组属性名<blockquote><p>描述实体的组成结构信息</p></blockquote></li><li>实体值 <blockquote><p>所有属性值的集合称为实体值, 又称元组</p></blockquote></li></ul></li><li>实体集的描述<ul><li>属性集合+关键字<blockquote><p>关键字: 是可用于区分同一个实体集中不同实体的 ‘最小属性集合’</p></blockquote></li></ul></li></ul></li><li>联系及其与实体集之间的连接关系的描述<ul><li>联系名</li><li>属性: 联系拥有属性<blockquote><p>由一个‘联系名’ + 与该联系相关的‘实体集的名称’, 以及联系上的属性, 从而构成联系及其与实体集之间的连接关系的描述  </p></blockquote></li><li>函数对应关系</li></ul></li><li>E-R图<ul><li>基本概念表示: 图形内写名称<ul><li>实体集: 矩形框</li><li>属性: 椭圆</li><li>关键字: 椭圆, 属性名加下划线</li><li>联系: 菱形框</li></ul></li><li>联系表示: 无向线段<blockquote><p>每个属性只能隶属于一个实体集, 哪怕同名<br>实体集与联系的连线旁边, 用数字标明涉及的实体数量</p></blockquote></li></ul></li><li>设计E-R模型<ul><li>实体 or 属性<blockquote><p>考虑取值, 若某一性质仅有一个重要的信息, 则作为属性, 如仅使用身份证号码的身份证; 若有多个重要信息, 则作为实体, 这些信息作为属性, 如身份证与其号码, 有效期, 签发机关等</p></blockquote></li><li>实体 or 联系<blockquote><p>与多个对象有关, 往往是联系; 一些事件有相关的物品, 例如交易与其合同, 交易可作为关系, 也可用合同表示为实体</p></blockquote></li><li>二元 or 多元<blockquote><p>只需考虑两两关系且无歧义时, 多元可转化为多个二元  </p></blockquote></li><li>属性依附对象<blockquote><p>实体的属性: 内在特征, 与联系无关; 联系的属性: 联系消失则消失的属性</p></blockquote></li></ul></li></ul></li></ul><h3 id="EE-R模型"><a href="#EE-R模型" class="headerlink" title="EE-R模型"></a>EE-R模型</h3><ul><li>扩充的内容<ul><li>IS_A联系 (Generalization Hierarchies): 继承, 即超(实体)集与子(实体)集关系<blockquote><p>用子集到超集的有向箭头表示, 书中箭头带圈</p><ul><li>继承性: 子集继承超集中的所有属性, 亦可有自己专有的属性; 超集关键字也是子集关键字</li><li>传递性</li><li>优点: 更好地映射到面向对象方法; 统一共性, 又能体现差异, 更好地模拟现实世界</li><li>覆盖约束: 所有子集的并集等价于超集, 一个实体至少属于一个子集</li><li>不相交约束: 子集互不相交, 一个实体至多属于一个子集</li></ul></blockquote></li><li>弱实体(Weak Entity): 某个实体依附于其他实体的存在<blockquote><p>用从弱实体集到联系的有向箭头表示</p></blockquote></li><li>属性的划分<ul><li>Identifier（标识符）: 又称关键字</li><li>Descriptor（描述符）</li><li>a composite attribute（组合属性）: 一组简单属性, 组合为一个组合属性, 描述一个性质, 例如姓名=名+姓</li><li>a multi-valued attribute（多值属性）: 一个实体在一个属性有多个值</li></ul></li><li>属性基数 (Cardinality of Attributes): 二元组表示属性取值数量特征<blockquote><p>标注在属性到实体集的连线上 </p><ul><li>(0,?): 可取空值, 不加限制</li><li>(1,?): 不可空值</li><li>(?,1): 单值属性</li><li>(?,N): 可取空值, 至多N值</li></ul></blockquote></li><li>实体在一个联系中的参与基数(Cardinality of Entity Participation in a Relationship)<blockquote><p>标注在联系到实体集的连线上</p><ul><li>card(E,R) = (min-card(E,R), max-card(E,R)), 实体集E中一个实体, 通过联系R连接到实体集F中, 所能连接的实体数量范围<ul><li>单值参与: max = 1; 否则多值参与</li><li>可选参与: min = 0; 否则强制参与</li></ul></li><li>用“参与方式”代替函数对应关系,  描述实体在联系中的数量对应关系</li><li>[解题技巧] 观察每个实体连了几根线, 这个数值的范围就是参与基数</li></ul></blockquote></li></ul></li><li>| Classification | Description |<br>| :-: | - |<br>| Entity | A collection of distinguishable real-world objects with common properties. |<br>| Attribute | A data item that describes a property of an entity or a relationship. |<br>| Identifier | (set of attributes) | Uniquely identifies an entity instance or relationship occurrence. |<br>| Descriptor | Non-key attribute, describing an entity or relationship. |<br>| Composite attribute | A group of simple attributes that together describe a property of an object. |<br>| Multi-valued attribute | An entity attribute that takes on multiple values for a single entity instance. |<br>| Relationship | Named set of m-tuples, identifies subset of the Cartesian product E1×E2×…×Em |<br>| Binary relationship | A relationship on two distinct entities |<br>| Ring, recursive relationship | A relationship relating an entity to itself |<br>| N-ary (N&gt;2) relationship | A relationship on more than two entities |</li></ul><h3 id="面向对象模型"><a href="#面向对象模型" class="headerlink" title="面向对象模型"></a>面向对象模型</h3><ul><li>概念<ul><li>面向对象技术引入到数据库领域, 借鉴面向对象的设计方法而发展起来的一种新的数据模型</li><li>采用了面向对象方法中的基本概念和方法来构造数据库的数据模型</li><li>提升了模型的表达能力, 特别是在表示非传统的、复杂数据关系方面具有极强的表达力</li></ul></li><li>对象<ul><li>客观世界中能够相互区别开来的事物(同E-R模型中实体定义)</li><li>区别<br>| | 对象 | 实体 |<br>| - | - | - |<br>| 描述特征 | 属性组成+行为特征 | 属性取值 |<br>| 区分实体 | 对象标识符 | 属性取值 |</li><li>组成<ul><li>标识符: OID: 每对象仅有一个, 用以相互区别</li><li>静态特征: 属性, 反应状态与特性</li><li>动态特性: 方法, 施加在对象上的程序, 可审视或改变属性值</li></ul></li><li>特点<ul><li>封装<ul><li>[属性+方法]合为整体</li><li>封装产生划分:<ul><li>内部表示: 属性的组成, 方法的实现</li><li>外部表示: 方法的调用接口, 亦称对象界面</li></ul></li><li>优点: 利于保护, 力与维护, 提高可靠性和重用性</li></ul></li><li>标识符的独立性<ul><li>独立于属性, 由系统定义并赋值, 唯一标识一个对象</li><li>特性: 唯一性, 持久性, 不可重用性</li></ul></li><li>属性值的多值性<ul><li>可以是: 单值, 值的集合, 另一个对象</li></ul></li></ul></li></ul></li><li>类(class)<ul><li>具有相同属性, 方法的对象集合</li><li>定义类, 以描述其中对象的静态特性和动态特性</li><li>实例: 类抽象为”类对象”, 而类的对象称为”实例”</li><li>元类: 由所有类对象构成的对象集合</li><li>类间关系<ul><li>继承: IS-A<ul><li>单向不循环的层次结构, 共享实现和定义</li><li>普化: 子类到超类, 对象集合合并</li><li>特化: 超类到子类, 对象集合分解</li><li>单继承: 每个子类只有唯一的直接超类</li><li>多继承: 每个子类可有多个直接超类</li><li>继承的作用: 支持共享与重用, 有助于扩充</li><li>问题<ul><li>重载: 解决在继承过程中, 超类与子类（或超类与超类）之间的冲突</li><li>冲突: 方法或属性的名字相同但语义或实现不同</li></ul></li></ul></li><li>聚合与分解: IS-PART-OF<ul><li>聚合: 若干个简单类聚合成一个复杂的类的过程</li><li>分解: 复杂类分解成若干层次上的简单类的过程</li><li>语义: 组成语义, 嵌套语义, 联系语义 </li></ul></li><li>两种联系来构成类的层次结构, 描述复杂的数据关系, 以它们为主要手段来构造面向对象的数据模型</li></ul></li></ul></li><li>消息<ul><li>对象协作机制</li><li>发送消息以调用其他对象中的方法</li><li>仅作用于对象界面</li><li>用户操作也可看成消息<ul><li>消息组成: (type) A.Op(O1, O2, …, On) (形同函数调用)</li><li>消息与方法: 方法是内部操作(接口+实现), 消息是跨对象的操作</li></ul></li></ul></li><li>C++与OODB<br>| C++ | OODB |<br>| - | - |<br>| - | 有OID |<br>| 管理对象 | 管理类 |<br>| 关心继承 | 关心继承和合成 |<br>| 挥发性 | 持久性 |<br>| - | 重视安全, 完整, 并发和故障恢复 |</li></ul><h3 id="谓词模型"><a href="#谓词模型" class="headerlink" title="谓词模型"></a>谓词模型</h3><ul><li>概念<ul><li>谓词模型又称谓词逻辑模型, 使用一阶谓词演算公式表示数据模型</li><li>用于构建: 概念数据模型 和 逻辑数据模型</li></ul></li><li>实体集<ul><li>谓词: 标识符号+若干变元, 变元取值, 判断是否成立</li><li>n个属性的实体集, 用含n个变元的谓词表示该实体集</li><li>在此实体集中的元组, 使此谓词为真, 不在则为假</li></ul></li><li>属性<ul><li>用变元取值表示属性</li><li>属性的域也可用谓词表示</li><li>对变元的约束可用统一的约束谓词表示</li><li>n属性的实体集有此表示: $P(x_1,x_2,\cdots,x_n)\wedge C(x_1)\wedge C(x_2)\wedge\cdots\wedge C(x_n)$</li></ul></li><li>联系<ul><li>谓词来表示联系, 谓词中的变元由参与该联系的实体（通常用实体的关键字属性代替）以及联系本身所具有的属性组成</li></ul></li><li>操作<ul><li>$x_i$为操作对象, $X$为结果: $Op(x_1,x_2,\cdots,x_n, X)$</li></ul></li><li>完整性约束<ul><li>谓词或谓词公式来表示属性间的完整性约束条件</li></ul></li></ul><h2 id="信息世界与逻辑模型"><a href="#信息世界与逻辑模型" class="headerlink" title="信息世界与逻辑模型"></a>信息世界与逻辑模型</h2><ul><li>信息世界是数据库的世界, 它着重于数据模型在数据库系统一级的构造与操作<ul><li>信息世界用逻辑数据模型来进行描述</li></ul></li></ul><h3 id="逻辑模型的分类"><a href="#逻辑模型的分类" class="headerlink" title="逻辑模型的分类"></a>逻辑模型的分类</h3><ul><li>层次模型和网状模型</li><li>关系模型和对象关系模型</li><li>面向对象模型</li><li>谓词模型</li></ul><h3 id="简史"><a href="#简史" class="headerlink" title="简史"></a>简史</h3><ul><li>The ’60s: 数据库技术的萌芽阶段</li><li>1961: IDS (Integrated Data Store)网络数据模型</li><li>1965-1970: IMS (Information Management System)层次数据模型, 多用户</li><li>1970: 关系数据模型 </li><li>1975: 著名的国际会议<ul><li>SIGMOD: ACM Special Interest Group on Management Of Data</li><li>VLDB: Very Large Data Bases</li><li>ICDE: IEEE International Conference on Data Engineering</li></ul></li><li>1976: Entity-Relationship (ER) model</li><li>The ’80s: 商用关系数据库管理系统的兴起</li><li>The ’90s<ul><li>专用数据库系统</li><li>商用面向对象数据库管理系统</li><li>对象关系数据库管理系统</li></ul></li><li>新世纪以来<ul><li>数据仓库, 安全数据库, XML数据库, 嵌入式、移动、实时、内存, NoSQL ……</li></ul></li><li>早期有影响的研究工作<ul><li>System R (IBM)</li><li>INGRES (University of California, Berkeley)</li><li>System 2000 (University of Texas, Austin)</li><li>Socrate Project (University of Grenoble, France)</li><li>ADABAS (Technical University of Darmstadt, W. Germany)</li></ul></li><li>数据库语言<ul><li>SQUARE, SEQUEL (SQL), QBE, QUEL</li></ul></li><li>其它方向: <ul><li>Expert Database Systems</li><li>Object-oriented DBMSs</li></ul></li><li>概念模型与逻辑模型对应关系表<br>| 概念模型 | E-R模型 | EE-R模型 | 面型对象模型 | 谓词模型 |<br>| - | - | - | - | - |<br>| 逻辑模型 | 层次模型, 网状模型, 关系模型 | 对象关系模型 | 面型对象模型 | 谓词模型 |</li></ul><h3 id="关系模型"><a href="#关系模型" class="headerlink" title="关系模型"></a>关系模型</h3><ul><li>概念: 关系模型是一种新的逻辑模型</li><li>基本数据结构: 二维表(简称表)</li><li>数据操纵: 表查询, 表的删除插入修改</li><li>二维表<ul><li>二维表由表框架与元组所组成, 表框架由若干个属性组成</li><li>存放于框架内的每‘一行数据’都被称为 ‘一个元组’ (Tuple), 或称‘行’(Row)</li><li>一张二维表是由一个有n个属性的框架及m个元组组成</li></ul></li><li>关系<ul><li>由行和列组成的二维表格</li><li>关系的约束<ul><li>同一表中的属性名各不相同</li><li>表中的属性与属性的排放次序无关</li><li>表中的元组均不相同</li><li>表中的元组与元组的排列次序无关</li><li>表中的每一分量必须是一个不可分割的基本数据项</li></ul></li><li>概念<ul><li>关系模式: 一个关系的关系名及其属性名的集合构成该关系的关系模式</li><li>关系数据库模式: 该关系数据库中所有关系的关系模式的集合</li><li>元组: 关系中的每一行</li><li>关键字<ul><li>一个属性集的值能唯一标识关系中的一个元组, 且又不含多余的属性值</li><li>每一个关系都有关键字</li><li>一个关系也可以有多个关键字, 所以关键字也被称为‘候选关键字’</li><li>主关键字: 关系的候选关键字中选取一个</li><li>外关键字: 设关系R中的属性集F, 其取值来自于关系S中的主关键字K, 则称属性集F是关系R的外关键字(取值来自外部关键字 的 属性集)</li></ul></li></ul></li><li>关系模型上的数据操作<ul><li>关系模型数据操作的对象是‘关系’；</li><li>关系模型数据操作的结果也是一个‘关系’；</li><li>关系模型的五种基本操作: 属性指定, 元组选择, 关系的合并, 元组插入, 元组删除</li></ul></li></ul></li></ul><h2 id="计算机世界与物理模型"><a href="#计算机世界与物理模型" class="headerlink" title="计算机世界与物理模型"></a>计算机世界与物理模型</h2><ul><li>物理模型是面向计算机的模型, 它构作数据库系统的物理实现: 操作系统级文件组织, 硬件级数据组织</li></ul><h3 id="文件系统的组成"><a href="#文件系统的组成" class="headerlink" title="文件系统的组成"></a>文件系统的组成</h3><ul><li>文件系统的组成<ul><li>项 (Item) : 文件系统中最小基本单位, 项内符号是不能继续分割的</li><li>记录 (Record): 由若干项组成, 记录内的各项间有内在语义联系<ul><li>记录有型与值的区别</li></ul></li><li>文件 (file): 记录的集合<ul><li>一般讲, 一个文件所包含的记录都是同型的</li></ul></li><li>文件集 (file set): 由若干个文件构成</li></ul></li><li>提高文件读写操作效率的方法<ul><li>索引(Index)<ul><li>将文件中的记录与其物理地址(即磁盘块)间建立一张对应关系表以便于快速查找, 这就是索引</li><li>索引一般也是一个文件. 当数据文件中的记录数很大时, 索引文件本身也还需要建立索引, 这叫二级索引</li><li>依此类推, 可以建立多级索引</li><li>B+树是关系数据库的物理实现中最常用的一种多级索引技术</li></ul></li><li>hash法<ul><li>一种函数转换法, 其主要思想是: 通过一个hash函数将要查找的记录转换成该记录所在的物理地址, 然后可以直接进行记录的定位读取操作</li></ul></li><li>集簇(Cluster)<ul><li>在记录查找中往往需要按某项的项值查找, 将具有相同或相邻项值的记录聚集在相同磁盘块内或圆柱体内以减少读盘次数, 提高查找速度, 这被称为集簇</li></ul></li></ul></li></ul><h1 id="第三章-关系数据库系统"><a href="#第三章-关系数据库系统" class="headerlink" title="第三章: 关系数据库系统"></a>第三章: 关系数据库系统</h1><h2 id="关系数据库系统概述"><a href="#关系数据库系统概述" class="headerlink" title="关系数据库系统概述"></a>关系数据库系统概述</h2><h3 id="关系数据库系统的优点"><a href="#关系数据库系统的优点" class="headerlink" title="关系数据库系统的优点"></a>关系数据库系统的优点</h3><ol><li>数据结构简单<ul><li>二维表: 记录-字段</li></ul></li><li>使用方便<ul><li>不涉及物理结构, 非过程性数据子语言</li></ul></li><li>功能强<ul><li>表达能力强, 便于修改数据间联系, 灵活选取数据存取路径, 高级的数据操纵语言</li></ul></li><li>数据独立性高<ul><li>不涉及物理因素, 操作非过程性</li></ul></li><li>理论基础深<ul><li>关系代数+关系演算理论-&gt;系统实现</li></ul></li><li>可移植性好</li><li>标准化程度高<ul><li>数据子语言的标准化: SQL语言标准</li></ul></li><li>分布式功能<ul><li>Client/Server(C/S); Browser/Server(B/S); 分布式数据库</li></ul></li><li>开放性<ul><li>数据访问接口实现与其它系统的互连: OBDC, JDBC</li></ul></li><li>其它方面的功能扩展</li></ol><h2 id="关系数据库系统衡量准则"><a href="#关系数据库系统衡量准则" class="headerlink" title="关系数据库系统衡量准则"></a>关系数据库系统衡量准则</h2><h3 id="六条准则1974"><a href="#六条准则1974" class="headerlink" title="六条准则1974"></a>六条准则1974</h3><p>提供高度的数据独立性<br>提供严格的数据视图<br>减轻DBA的工作<br>建立理论基础<br>事务管理与文件管理相结合: 为商业及其它行业的服务作准备<br>操作对象是记录集合, 而不是单个记录  </p><h3 id="完全关系型的12条严格标准1985"><a href="#完全关系型的12条严格标准1985" class="headerlink" title="完全关系型的12条严格标准1985"></a>完全关系型的12条严格标准1985</h3><ol><li>信息准则: 逻辑一级<ul><li>所有信息 -&gt; 表中的值, 唯一且显式地表示</li><li>结构描述信息 -&gt; 组织成关系形式</li></ul></li><li>确保访问准则<ul><li>表名+关键字值+列名 -&gt; 访问到每一个原子数据</li></ul></li><li>空值的关系处理准则<ul><li>空值: 无意义/当前未知</li><li>系统应当可以处理有空值参与的: 比较运算, 表达式运算, 统计运算</li></ul></li><li>基于资源管理的动态联机目录<ul><li>数据库的描述信息(数据字典) 与 用户数据 有 相同的表示形式和操作方式</li><li>被授权用户可对 数据库的描述信息 进行 查询与扩充</li></ul></li><li>统一易用的数据子语言: 至少一种子语言支持以下功能<ul><li>数据定义</li><li>视图(view)定义</li><li>数据操纵</li><li>完整性约束能力</li><li>授权机制</li><li>事务处理能力</li></ul></li><li>视图更新准则: 视图除查询外, 还可增加, 删除, 修改数据</li><li>高级的插入、删除及修改操作: 一条命令可以插入、删除及修改操作多条元组</li><li>物理数据独立性</li><li>逻辑数据独立性</li><li>数据完整性准则: 提供三类数据完整性约束的定义功能</li><li>分布独立性: 数据分布的改变不影响原有的应用程序</li><li>无损害原则: 对提供低级数据子语言的要求</li></ol><h3 id="关系数据库产品的类别划分"><a href="#关系数据库产品的类别划分" class="headerlink" title="关系数据库产品的类别划分"></a>关系数据库产品的类别划分</h3><ul><li>半关系型系统<ul><li>基本数据结构: 关系</li><li>满足12条准则中的 少量要求</li></ul></li><li>基本关系型系统<ul><li>基本数据结构: 关系</li><li>满足12条准则中的 大部分要求</li></ul></li><li>完全关系型系统<ul><li>严格符合 上述的12条准则</li></ul></li></ul><h2 id="关系模型数学理论-—-关系代数"><a href="#关系模型数学理论-—-关系代数" class="headerlink" title="关系模型数学理论 — 关系代数"></a>关系模型数学理论 — 关系代数</h2><h3 id="关系模型-1"><a href="#关系模型-1" class="headerlink" title="关系模型"></a>关系模型</h3><h4 id="关系数据结构"><a href="#关系数据结构" class="headerlink" title="关系数据结构"></a>关系数据结构</h4><ul><li>术语对应关系<br>| 关系模型 | DBMS(SQL) | 文件系统 |<br>| - | - | - |<br>| Relation 关系 | Table 表 | File of Records |<br>| Attribute 属性 | Column 列 | Field |<br>| Tuple 元组 | Row 行 | Record |<br>| Schema 模式 | Table Heading 表头 | Type of Record | </li><li>表结构<br>表 = n元表框架 + m个元组<ul><li>表框架<br>属性组成表框架; n个属性 - 表的元数; 属性取值范围 - 值域</li><li>元组<br>行 - 元组; n元表 - 元组n个分量; m行 - 表的基数 - 元组数量</li></ul></li><li>关系<ul><li>被称为关系的二维表必须满足的性质<ul><li>元组: 个数有限, 唯一, 次序无关, 分量原子性, 分量值域同一</li><li>属性: 名称唯一, 次序无关</li></ul></li><li>满足以上关系的二维表, 所建立的模型称为关系模型</li><li>二维表 –(抽象)–&gt; 关系; n个属性 - n元关系</li><li>关系 - 关系名; 属性 - 属性名; 关系名($R$) + n*属性名($A_1, \cdots, A_n$) = 关系框架($R(A_1, \cdots, A_n)$)</li></ul></li><li>键<ul><li>键: 唯一最小标识元组的属性集, 每张表至少一个</li><li>主键: 被选中的键; 候选键: 其他</li><li>超键: 唯一标识元组的属性集(键是极小超键, 其任意子集均不能标识元组)</li><li>外键: 如果表A中的属性集F是表B的键, 则称该属性集F为表A的外键</li></ul></li></ul><h4 id="关系操纵"><a href="#关系操纵" class="headerlink" title="关系操纵"></a>关系操纵</h4><ul><li>查询<ul><li>单张表内<ul><li>目标: 某(行 - 元组)的(属性值 - 元组分量)</li><li>过程: (纵向定位 - 行选择)选符合条件的元组 -&gt; (横向定位 - 列指定)指定属性</li></ul></li><li>多张表<ul><li>先合并-&gt;单张表查询</li></ul></li></ul></li><li>删除<ul><li>基本单位: 元组</li><li>过程<ul><li>确定被删除的元组: 单个关系内的选择操作来确定</li><li>删除操作: 一次操作只能删除一个关系内的元组</li></ul></li></ul></li><li>插入<ul><li>一条操作只能向一个关系中增加新的元组</li></ul></li><li>修改<ul><li>修改不是基本操作, 修改 = 删除(旧元组) + 插入(修改后的新元组)</li></ul></li><li>小结: 关系-(操纵)-&gt;(新)关系</li><li>五种基本操作<ul><li>元组选择: 选择满足条件的元组</li><li>属性指定: 选择结果需要的属性</li><li>关系合并: 多个关系两两合并, 最终合并为一个关系</li><li>元组插入</li><li>元组删除</li></ul></li><li>空值处理<ul><li>数据完整性约束: 主键不允许空值</li><li>空值运算<ul><li>算数表达式中有空值, 则结果为空值</li><li>逻辑表达式中有空值, 则结果为逻辑假</li><li>统计计算:<ul><li>集合中的空值元素不计算在内: SUM, AVG, MAX, MIN, COUNT</li><li>空集: [ SUM, AVG, MAX, MIN ] = 空元素; [ COUNT ] = 0</li></ul></li></ul></li></ul></li></ul><h4 id="关系中的数据约束"><a href="#关系中的数据约束" class="headerlink" title="关系中的数据约束"></a>关系中的数据约束</h4><ul><li>三类数据完整性约束<ul><li>实体完整性约束: 属性不为空值</li><li>参照完整性约束: 外键要么取空值, 要么是被引用表中的主键值</li><li>用户定义的完整性: 用户自己定义的属性取值约束</li></ul></li><li>关系代数<ul><li>关系的表示 </li><li>关系操纵的表示</li><li>关系代数与关系模型</li><li>关系代数的扩充运算</li></ul></li></ul><h3 id="关系的表示"><a href="#关系的表示" class="headerlink" title="关系的表示"></a>关系的表示</h3><ul><li>笛卡尔积<br>$D_1, D_2, \cdots, D_n$是$n$个集合<br>$D_1\times D_2\times\cdots\times D_n=\{(d_1, d_2, \cdots, d_n): d_i\in D_i, i\in (1, 2, \cdots, n)\}$<br>$|D_1\times D_2\times\cdots\times D_n| = \prod_{i=1}^n |D_i|$  </li><li>关系<br>设属性域为$D_1, D_2, \cdots, D_n$<br>关系$R\subseteq D_1\times D_2\times\cdots\times D_n$  </li></ul><h3 id="关系操纵的表示"><a href="#关系操纵的表示" class="headerlink" title="关系操纵的表示"></a>关系操纵的表示</h3><ul><li>对应关系<br>| 关系基本操作 | 关系代数运算 |<br>| :-: | :-: |<br>| 元组选择 | 选择运算 |<br>| 属性指定 | 投影运算 |<br>| 关系合并 | 笛卡尔积 |<br>| 元组插入 | 并运算 |<br>| 元组删除 | 差运算 |<br>注意运算的: 执行条件, 执行结果</li><li>相容表/同类关系: 相同的表头: 同数量, 同名, 同值域</li><li>关系运算<ul><li>交运算: 同类关系<ul><li>用$R\cap S = R-(R-S)$代替, 不是基本运算</li></ul></li><li>并运算: 同类关系: 交换律, 结合律<ul><li>关系模式不变, 属于$R$或者$S$</li></ul></li><li>差运算: 同类关系: 无交换律, 无结合律<ul><li>关系模式不变, 属于$R$且不属于$S$</li></ul></li><li>投影运算: $\pi_A(R)$: 无交换律<ul><li>略去某些列, 重排剩余列的次序<br>关系$R$有属性$\{A_1,A_2, \cdots, A_n\}$, 在其中$m$个属性上的投影运算如下<br>$\pi_{B_1, B_2, \cdots, B_n}(R), B_i\in\{A_1,A_2, \cdots, A_n\}$  </li><li>注意消除可能出现的重复元组</li></ul></li><li>选择运算: $\sigma_F(R)$: 交换律<ul><li>关系模式不变, 由属于$R$且满足条件$F$的元组构成</li></ul></li><li>笛卡尔乘积 - 关系的合并: 交换律, 结合律<ul><li>若有相同的属性名, 必须在结果关系中对其中一个换名</li></ul></li></ul></li><li>关系操作<ul><li>插入: $R^*=R\cup R_{new}$</li><li>删除: $R^* = R-R_{old}$</li><li>修改: $R^* = (R-R_{old})\cup R_{new}$</li><li>查询: $\pi_A(\sigma_B(R))$简写为$\pi_A\sigma_B(R)$: 不能交换位置</li></ul></li></ul><h3 id="关系模型与关系代数"><a href="#关系模型与关系代数" class="headerlink" title="关系模型与关系代数"></a>关系模型与关系代数</h3><ul><li>关系: $n$元有序组的集合</li><li>关系操纵: 关系上的集合运算</li><li>关系代数: 关系集合$A$及5种基运算构成的代数</li><li>关系模型<ul><li>关系模型的数据结构</li><li>关系模型上的数据操纵</li><li>关系模型上的数据约束</li></ul></li></ul><h3 id="关系代数中的扩充运算"><a href="#关系代数中的扩充运算" class="headerlink" title="关系代数中的扩充运算"></a>关系代数中的扩充运算</h3><ul><li>交运算: 同类关系: 交换律, 结合律<ul><li>关系模式不变, 既属于$R$也属于$S$的元组组成的集合</li><li>可由差运算实现: $R\cap S=R-(R-S)=S-(S-R)$</li></ul></li><li>除运算: $\textrm{Head}(S)\subset \textrm{Head}(R)$<ul><li>关系模式: $\textrm{Head}(T)=\textrm{Head}(R) - \textrm{Head}(S)$</li><li>设$x\in T$, 则$\forall y\in S$, $(x,y)\in R$, 所有满足条件的$x$构成结果</li><li>如果$R=T\times S$, 则$T=R\div S$, $S=R\div T$; 如果$T=R\div S$, 则$T\times S\subseteq R$</li><li>$R\div S=\pi_{A_1,\cdots A_n}(R)-\pi_{A_1,\cdots A_n}((\pi_{A_1,\cdots A_n}(R)\times S)-R)$</li></ul></li><li>联接运算<ul><li>根据联接条件合并: $R\bowtie_F S=\sigma_F(R\times S)$</li><li>自然联接: $R\bowtie S$所有同名属性上的取值都一样, 就联接元组, 同名属性保留一份</li><li>外联接: 有”外”的一侧, 其所有元组均出现, 另一侧无匹配元组就用null代替</li></ul></li></ul><h3 id="关系代数实例"><a href="#关系代数实例" class="headerlink" title="关系代数实例"></a>关系代数实例</h3><h4 id="解题技巧"><a href="#解题技巧" class="headerlink" title="解题技巧"></a>解题技巧</h4><ul><li>“所有A都…的B”, 用除法, 被除的对象应当先投影, 以免遗漏</li><li>用公共属性查私有属性, 先笛卡尔积, 之后用选择, 条件设为同名属性取值相等, 最后投影</li><li>正面难构造, 就构造反面, 然后用笛卡尔积减去反面</li><li>最大值最小值, 例子: 取C中最大, C为key-value对<br>$$D\coloneqq C$$<br>$$M = C - \pi_{C.key,C.val}\sigma_{C.val &lt; D.val}(C\times D)$$<br>原理: 每取值跟所有取值比较, 存在更大就会保留, 找出所有的非最大值, 之后减去</li><li>同时满足多个条件, 则取交; 满足多个条件中的一个, 则取并</li><li>联接可以实现”之一”的效果, 也可以实现相等关系</li></ul><h4 id="解题步骤"><a href="#解题步骤" class="headerlink" title="解题步骤"></a>解题步骤</h4><ul><li>确定查询目标（结果关系中的属性）</li><li>明确查询条件</li><li>选择从条件到目标的查找路径，并据此确定操作对象，即: <ul><li>在操作过程中需要使用到那些关系?</li><li>这些关系又是如何被联接成一个关系的?</li></ul></li><li>关系的合并<ul><li>根据步骤 3) 的分析结果进行关系的联接</li></ul></li><li>元组的选择<ul><li>根据步骤 2) 的分析结果(查询条件)进行元组的选择</li></ul></li><li>属性的指定<ul><li>根据步骤 1) 的分析结果执行投影操作</li></ul></li></ul><h4 id="更多技巧"><a href="#更多技巧" class="headerlink" title="更多技巧"></a>更多技巧</h4><ul><li>差运算<ul><li>当查询条件带有‘否定’语义，或者具有明显的‘排它性’的时候，通常需要使用两个子查询之间的‘差’运算</li><li>‘差’运算的运算对象（关系）中，通常需要包含其关键字</li></ul></li><li><p>“笛卡尔积/θ-连接/自然连接”的使用方法</p><ul><li>都是关系的合并运算<ul><li>笛卡尔积是基本运算，θ-连接和自然连接则是扩充运算, 请注意三者的结果关系的关系模式之间的区别</li></ul></li><li>笛卡尔积<ul><li>是实现跨不同关系表进行数据访问的基础, 在笛卡尔积的结果关系中，存在着很多无意义的结果元组，通常需要通过后续的选择运算过滤掉</li></ul></li><li>θ-连接<ul><li><strong>相邻的“笛卡尔积+选择运算”可以合并为一个θ-连接</strong></li></ul></li><li>自然连接<ul><li>如果连接条件是基于“两张表中的所有同名属性的相等比较”，可以将θ-连接进一步简写为自然连接</li></ul></li><li>一般方法: 笛卡尔积+选择  or  θ-连接<ul><li>不存在同名属性，或者连接条件不是基于同名属性的相等比较</li><li>在结果关系中可能存在同名属性，需要加以区别</li></ul></li><li>常用方法: 自然连接<ul><li>连接条件是隐含的（所有同名属性的相等比较）</li><li>如果在两个关系之间存在多对‘同名属性’，而本次查询又不需要‘所有’的同名属性都相等，此时有两种选择: </li><li>采用前述的一般方法来实现关系的合并</li><li><strong>先对其中的一个关系执行投影运算</strong>，过滤掉其中不需要相等的那些同名属性，然后再使用自然连接运算</li></ul></li><li>难点: 关系的自连接<ul><li>使用<strong>赋值运算定义‘同质不同名’的两个中间关系</strong>(元组集合相同，但关系名不同)，当然也可以对中间关系中的属性进行重命名</li><li>然后再使用前述的一般方法实现两个中间关系的合并</li></ul></li></ul></li><li><p>除</p><ul><li>‘除’ 运算与‘联接’运算的区别</li><li>我们将查询的结果关系称为‘目标对象’，用于定义查询条件的关系称为‘条件对象’</li><li>在决定某个元组t是否属于结果关系时，<ul><li>如果只需要从条件对象中找到<strong>一个元组</strong>c并使得查询条件成立，那么就直接使用‘联接’运算（包括笛卡尔积、θ-连接和自然连接）</li><li>如果需要条件对象集中的<strong>所有元组</strong>都能使得查询条件成立，那么就使用‘除’运算</li></ul></li><li>‘除’ 运算表达式的表示方法<ul><li>被除数关系中必须包含目标对象和条件对象的<strong>关键字</strong></li><li>除数关系中只含条件对象的关键字</li><li>被除数和除数关系中<strong>不能含其它‘不必要’的多余属性</strong>, 先投影再除</li></ul></li></ul></li></ul><h2 id="关系演算"><a href="#关系演算" class="headerlink" title="关系演算"></a>关系演算</h2><h3 id="一阶谓词演算"><a href="#一阶谓词演算" class="headerlink" title="一阶谓词演算"></a>一阶谓词演算</h3><ul><li>命题:  可以判断真假的语句<ul><li>个体词: 可以独立存在的客体<ul><li>个体常量: $a,b,c,\cdots$: 具体特定</li><li>个体变元: $x,y,z,\cdots$: 抽象泛指</li><li>个体域: 指个体变元的取值范围</li><li>全总个体域: 由宇宙间的一切事物组成</li></ul></li><li>谓词: 个体性质或个体间关系: $P(x_1,x_2,\cdots,x_n)$<ul><li>常项/变项: 具体性质或关系/抽象泛指的性质或关系</li><li>n/0元谓词: 含n个/不含个体变元的谓词</li><li>根据变元的取值来判断其是否成立</li></ul></li></ul></li><li>指派: $(v_1,v_2,\cdots,v_n)$为$P(x_1,x_2,\cdots,x_n)$的指派, $x_i$取值$v_i$<ul><li>成真指派/成假指派: $P(v_1,v_2,\cdots,v_n)$为逻辑真/假</li></ul></li><li>量词: 个体常量或个体变元之间数量关系<ul><li>全称/存在量词: 每一个/至少有一个 个体域中的个体满足谓词</li><li>约束/自由变元: 受到/不受量词约束的变元</li><li>顺序: 既有全称量词也有存在量词，那么它们的书写顺序是相关的, 无括号则从左到右依次处理</li><li>指派: 只对自由变元取值</li></ul></li><li>连接符<ul><li>非, 与, 或, 蕴含</li></ul></li></ul><h3 id="关系的表示-1"><a href="#关系的表示-1" class="headerlink" title="关系的表示"></a>关系的表示</h3><p>关系-&gt;谓词<br>关系操作-&gt;关系演算公式</p><ul><li>关系演算系统<ul><li>元组关系演算: 变元取值为元组, 元组变量<br>$n$元关系$R$-&gt;谓词$R(t)$, $t$为元组变量, $t(i)$为关系$R$中第$i$属性</li><li>域关系演算: 变元取值为单个属性值, 域变量<br>$n$元关系$R$-&gt;$n$元谓词$R(x_1,x_2,\cdots,x_n)$, $x_i$为属性变量, 为关系$R$中第$i$属性</li></ul></li><li>关系表示<ul><li>关系$R$中的每个元组都是成真指派, 其他不出现在$R$中的任何元组都是成假指派</li><li>元组关系演算: $R=\{t|P(t)\}$</li><li>域关系演算: $R=\{&lt;x_1,x_2,\cdots,x_n&gt;|P(x_1,x_2,\cdots,x_n)\}$</li></ul></li></ul><h3 id="关系操纵的表示-1"><a href="#关系操纵的表示-1" class="headerlink" title="关系操纵的表示"></a>关系操纵的表示</h3><ul><li>并<br>$$R\cup S=\{t|R(t)\vee S(t)\}$$</li><li>差<br>$$R-S=\{t|R(t)\wedge \neg S(t)\}$$</li><li>选择<br>$$\sigma_F(R)=\{t|R(t)\wedge F\}$$</li><li>投影<br>$$\pi_{A_{i_1},A_{i_2},\cdots,A_{i_k}}(R)=\{u^{(k)}|\exists t, (R(t)\wedge \bigwedge^ku(k)=t(i_k))\}$$</li><li>笛卡尔积<br>$$R\times S=\{t^{(m+n)}|\exists u\exists v, (R(u)\wedge S(v)\wedge\bigwedge_{i=1}^m t(i) = u(i)\wedge \bigwedge_{j=1}^n t(m+j)=v(j))\}$$</li><li>关系演算表达式<br>$\{t|\phi(t)\}$, 简写为$\phi(t)$</li><li>公式, 原子公式: 见数理逻辑</li><li>优先顺序<ul><li>比较运算符&gt;量词&gt;否定操作&gt;逻辑运算符, 有括号的优先</li></ul></li></ul><h3 id="关系演算的例子"><a href="#关系演算的例子" class="headerlink" title="关系演算的例子"></a>关系演算的例子</h3><ul><li>投影<br>$$\pi_{A_{1},A_{2},\cdots,A_{k}}(R)=\exists x_{k+1},x_{k+2},\cdots ,x_n(R(x_1,x_2,\cdots,x_n))$$</li><li>选择<br>$$\sigma_F(R)=R(x_1,x_2,\cdots,x_n)\wedge F$$<ul><li>相等比较可以直接用常量代替: $\sigma_{x_1=’a’}(R)=R(‘a’,x_2,\cdots,x_n)\wedge F$</li></ul></li><li>笛卡尔积<br>$$R\times S = R(p)\wedge S(q)$$</li><li>$\theta$-联接<br>$$R\underset{F}{\bowtie} S = R(p)\wedge S(q)\wedge F$$</li><li>自然联接<br>$$R\bowtie S = R(x,y,z)\wedge S(t,u,v)$$</li><li>自联接, 重命名<br>$$R(x, g_1)\wedge R(x, g_2)$$</li><li>除法<br>$$R\div S=\forall y(S(y)\rightarrow R(x,y))$$</li><li>删除<br>$$R-S = R(u)\wedge \neg S$$</li><li>插入<br>$$R\cup S = R(t)\vee S(t)$$</li><li>修改 = 删除再插入</li></ul><h3 id="关系演算的安全限制"><a href="#关系演算的安全限制" class="headerlink" title="关系演算的安全限制"></a>关系演算的安全限制</h3><ul><li>无限性问题<ul><li>无限关系: 无限个元组</li><li>无穷验证: 量词引发无穷验证</li></ul></li><li>安全公式: 不产生无限性问题的公式</li><li>约束集: $\text{DOM}(\phi)$<ul><li>构成: 公式中出现的关系中的某些分量, 公式中显式出现的常量符号</li><li>以公式$\phi$作特性可以构造出一个元组集合，其中的每个元组只能由出现在$\text{DOM}(\phi)$中的符号构成，则这样的公式$\phi$是安全的</li></ul></li><li>判定条件<ul><li>如$t$满足公式$\phi$，则$t$的每个分量必定是$\text{DOM}(\phi)$的元素<br>不产生无限关系</li><li>对$\phi$中每一个形为$\exists t(W(t))$的子公式，若 t满足 W, 则$t$的每个分量一定属于$\text{DOM}(\phi)$<br>不因为量词$\exists$而无穷验证</li><li>对$\phi$中每一形为$\forall t(W(t))$的子公式，如果t 的任一分量不在 $\text{DOM}(\phi)$中，则$t$必定满足W<br>不因为量词$\forall$而无穷验证</li></ul></li></ul><h3 id="关系代数与关系演算"><a href="#关系代数与关系演算" class="headerlink" title="关系代数与关系演算"></a>关系代数与关系演算</h3><ul><li>‘关系代数’  等价于  ‘安全的关系演算’<ul><li>用关系演算表达式可以表示关系代数中的五种基本运算</li><li>用关系代数表达式可以表示安全的关系演算<ul><li>可以将一个安全的关系演算公式转换成等价的一个关系代数表达式</li><li>关系演算公式的构成方式: 原子公式, 原子公式的量词和演算</li><li>原子公式的表示: 量词/属性间比较/属性与常量比较</li></ul></li></ul></li><li>公式的表示<ul><li>$\phi_1\wedge\phi_2$<ul><li>有公共变元, 等价于自然联接$R_1\bowtie R_2$</li><li>无公共变元, 等价于笛卡尔乘积$R_1\times R_2$</li></ul></li><li>$\phi_1\vee\phi_2$: $R_1\cup R_2$</li><li>$\phi_1\rightarrow\phi_2$: $R_2\div R_1$</li><li>$\neg\phi$: $(\prod^nD_i)-R$, $D_i$为第$i$个自由变元的值域</li><li>$\exists r(\phi)$: $\pi_{A_1,A_2,\cdots,A_k}(R)$</li><li>$\forall r(\phi)$: $R\div S$</li></ul></li><li>完备系统<ul><li>能够提供关系代数的五种基本运算功能的关系模型系统</li><li>具有安全的关系演算功能的关系模型系统</li></ul></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;第一章-数据库系统概述&quot;&gt;&lt;a href=&quot;#第一章-数据库系统概述&quot; class=&quot;headerlink&quot; title=&quot;第一章: 数据库系统概述&quot;&gt;&lt;/a&gt;第一章: 数据库系统概述&lt;/h1&gt;&lt;h2 id=&quot;基本概念&quot;&gt;&lt;a href=&quot;#基本概念&quot; class
      
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Introduction to Database" scheme="https://Maxwell-lyu.github.io/tags/Introduction-to-Database/"/>
    
  </entry>
  
  <entry>
    <title>Problem Solving IV Note 07</title>
    <link href="https://Maxwell-lyu.github.io/2019/06/16/Learn-PS-20190616-PS-IV-07/"/>
    <id>https://Maxwell-lyu.github.io/2019/06/16/Learn-PS-20190616-PS-IV-07/</id>
    <published>2019-06-16T12:41:25.000Z</published>
    <updated>2019-06-16T12:47:30.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="Chapter-31-数论算法"><a href="#Chapter-31-数论算法" class="headerlink" title="Chapter 31: 数论算法"></a>Chapter 31: 数论算法</h1><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">exgcd</span> <span class="params">(<span class="keyword">int</span> a, <span class="keyword">int</span> b, <span class="keyword">int</span> &amp;x, <span class="keyword">int</span> &amp;y)</span> </span>&#123;</span><br><span class="line">  <span class="keyword">if</span> (!b) &#123;</span><br><span class="line">      x = <span class="number">1</span>, y = <span class="number">0</span>;</span><br><span class="line">      <span class="keyword">return</span> a;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">int</span> ans = exgcd (b, a % b, y, x);</span><br><span class="line">  y -= a / b * x;</span><br><span class="line">  <span class="keyword">return</span> ans;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;Chapter-31-数论算法&quot;&gt;&lt;a href=&quot;#Chapter-31-数论算法&quot; class=&quot;headerlink&quot; title=&quot;Chapter 31: 数论算法&quot;&gt;&lt;/a&gt;Chapter 31: 数论算法&lt;/h1&gt;&lt;figure class=&quot;high
      
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Problem Solving" scheme="https://Maxwell-lyu.github.io/tags/Problem-Solving/"/>
    
      <category term="Introduction to Algorithms" scheme="https://Maxwell-lyu.github.io/tags/Introduction-to-Algorithms/"/>
    
  </entry>
  
  <entry>
    <title>Probability Ch8</title>
    <link href="https://Maxwell-lyu.github.io/2019/06/11/Learn-PMS-20190611-PMS-08/"/>
    <id>https://Maxwell-lyu.github.io/2019/06/11/Learn-PMS-20190611-PMS-08/</id>
    <published>2019-06-11T02:57:16.000Z</published>
    <updated>2019-06-16T08:14:36.000Z</updated>
    
    <content type="html"><![CDATA[<p>Probability Course in 2019 Spring<br><a id="more"></a> </p><h1 id="假设检验"><a href="#假设检验" class="headerlink" title="假设检验"></a>假设检验</h1><h2 id="u-检验"><a href="#u-检验" class="headerlink" title="$u$检验"></a>$u$检验</h2><p>$$\frac{\bar{X}{}$$ </p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Probability Course in 2019 Spring&lt;br&gt;
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Probability and Mathematical Statistics" scheme="https://Maxwell-lyu.github.io/tags/Probability-and-Mathematical-Statistics/"/>
    
  </entry>
  
  <entry>
    <title>Data Communication Final</title>
    <link href="https://Maxwell-lyu.github.io/2019/06/04/Learn-DC-20190604-DC-FIN/"/>
    <id>https://Maxwell-lyu.github.io/2019/06/04/Learn-DC-20190604-DC-FIN/</id>
    <published>2019-06-04T07:28:33.000Z</published>
    <updated>2019-10-13T12:48:21.387Z</updated>
    
    <content type="html"><![CDATA[<p>数据通信: 期末复习<br><a id="more"></a>  </p><h1 id="第二章：网络体系结构"><a href="#第二章：网络体系结构" class="headerlink" title="第二章：网络体系结构"></a>第二章：网络体系结构</h1><ul><li>通信模型<ul><li>源系统（源点，发送器），传输系统，目的系统（接收器，终点)</li></ul></li><li>传输方式<ul><li>单工：一个信道，只能单向</li><li>半双工：一个信道，同一时间只能上/下行，有选择器</li><li>全双工：两个信道，同时上下行</li></ul></li><li>数字通信与模拟通信<ul><li>数字系统：数字-数字编码，模拟-数字编码</li><li>模拟系统：模拟信号以固有频率基带传输（不编码），频谱搬移后传输（模拟-模拟编码）</li><li>混成系统：同一系统既包含模拟也包含数字</li></ul></li><li>网络体系结构：TCP/IP<ul><li>应用层，传输层，网际层，数据链路层，物理层</li></ul></li><li>套接字及其类型<ul><li>流套接字：TCP：可靠，按时</li><li>数据包套接字：UDP：快速乱序无保证</li><li>原始套接字：IP：直接访问底层</li></ul></li></ul><h1 id="第三章：数据传输"><a href="#第三章：数据传输" class="headerlink" title="第三章：数据传输"></a>第三章：数据传输</h1><ul><li>概念与术语<ul><li>导向媒体：电磁波沿某一物理路径前进（光纤，双绞线，同轴电缆<ul><li>点对点：直连链路</li><li>多点：共享</li></ul></li><li>非导向媒体：无线传输，不引导传输方向（空气，真空，海水</li></ul></li><li>数据与信号<ul><li>数据：信源产生，可能为模拟或数字</li><li>信号：经过调制，电磁信号居多</li></ul></li><li>周期信号的傅里叶级数表示<ul><li>傅里叶表示：<br>$$x(t)=\frac{A_0}{2}+\sum_{n=1}^{\infty}(A_n\cos(2\pi nf_0t)+B_n\sin(2\pi nf_0t))$$<br>$$A_n = \frac{2}{T}\int_{0}^{T}x(t)\cos(2\pi nf_0t)dt$$<br>$$B_n = \frac{2}{T}\int_{0}^{T}x(t)\sin(2\pi nf_0t)dt$$</li><li>方波的傅里叶表示<br>$$f(x)=\frac{4}{\pi}\sum_{n=2k-1}^\infty \frac{1}{n}\sin(\frac{n\pi x}{L})$$</li></ul></li><li>信号功率计算<ul><li>任意时段功率：<br>$$P_x=\frac{1}{t_2-t_1}\int_{t_1}^{t_2}|x(t)|^2dt$$</li><li>周期平均功率<br>$$P=\frac{1}{T}\int_{0}^{T}|x(t)|^2dt$$   </li></ul></li><li>信号的频谱与带宽<ul><li>频谱：信号的频率范围</li><li>绝对带宽：频谱宽度，最大减最小</li><li>有效带宽：包含绝大多数能量的带宽，某频率区间的功率积分是总功率的一半（-3dB）</li><li>直流分量：频率为0的部分</li></ul></li><li>方波数据率与带宽的关系<ul><li>$R_b=2f$，$R_b$数据率，$f$方波频率</li></ul></li><li>模拟/数字数据与模拟/数字传输<ul><li>模拟信号：放大器</li><li>数字信号：转发器</li></ul></li><li>数字信号传输的优势<ul><li>大规模集成电路</li><li>数据完整性</li><li>容量利用率</li><li>安全和保密</li><li>综合性、存储</li></ul></li><li>传输损伤<ul><li>衰减：放大器与转发器解决<ul><li>要求: 接收到的信号足够强, 信号电平高于噪声电平</li></ul></li><li>失真<ul><li>衰减失真：高频失真多，衰减均衡和高频高倍放大解决</li><li>时延失真：中心频率附近传输快，仅限数字信号，码间串扰</li></ul></li><li>噪声<ul><li>信噪比：$SNR_{db}=\lg{\frac{S}{N}}$</li><li>热噪声：$N_0=kT$，$k$玻尔兹曼常量，$T$热力学温度, 每赫兹噪声, 计算时$N=BN_0$</li><li>互调噪声、串扰（双绞线扭绞）、冲激噪声</li></ul></li></ul></li><li>信道容量：最大数据传输速率<ul><li>数据率bps，带宽Hz，噪声，误码率</li><li>奈奎斯特带宽：信道无噪声时：$C=2B\log_2{M}$，$M$指信号的电平数</li><li>香农容量公式：只有热噪声时：$C=B\log_2(1+SNR)$，$SNR=10^{0.1SNR_{db}}$为信噪比</li></ul></li></ul><h1 id="第四章：传输媒体"><a href="#第四章：传输媒体" class="headerlink" title="第四章：传输媒体"></a>第四章：传输媒体</h1><ul><li>光纤<ul><li>优势：容量大，体积小，衰减小，电磁隔离，转发器间隔远</li><li>折射率分类：<ul><li>阶跃型：折射率阶跃，会有失真</li><li>渐变型：光路周期性汇聚</li></ul></li><li>模式分类<ul><li>单模、多模</li></ul></li></ul></li><li>无线传播：高频天线小<ul><li>地波：-2MHz</li><li>天波：2MHz-30MHz</li><li>视距传播：30MHz-</li></ul></li><li>视距传播损伤<ul><li>自由空间损耗模型<br>$$L=10\lg(\frac{4\pi d}{\lambda})^2dB$$</li></ul></li></ul><h1 id="第五章：信号编码技术"><a href="#第五章：信号编码技术" class="headerlink" title="第五章：信号编码技术"></a>第五章：信号编码技术</h1><ul><li>编码与调制技术<ul><li>数字信号传输：数字或模拟数据-&gt;(编码器)-&gt;数字信号-&gt;(解码器)-&gt;原数据</li><li>模拟信号传输：数字或模拟基带信号<->(调制解调器)<->模拟信号</-></-></li></ul></li><li>数字信号编码格式<ul><li>NRZ-L：高电平0，低电平1</li><li>NRZI：区间起始无变化0，区间起始有变化1</li><li>双极性AMI：零电平0，正电平负电平1交替出现</li><li>伪三进制：正电平负电平0交替出现，零点平1</li><li>曼彻斯特：区间正中高到低0，低到高1</li><li>差分曼彻斯特：区间正中总是变化，区间起始变化0，区间起始不变1</li></ul></li><li>扰码<ul><li>扰码产生替代连续电压的序列</li><li>填充序列：提供足够的信息用于同步，可被识别替换还原，长度相同</li><li>目标：不含直流，定时信息丰富，不降低数据率，可检错，易于判断还原</li></ul></li><li>HDB3：会给出编码方式  </li></ul><table><thead><tr><th style="text-align:center"></th><th style="text-align:center">自上一次替换后双极性</th><th style="text-align:center">脉冲（比特1）数</th></tr></thead><tbody><tr><td style="text-align:center">前面脉冲的极性</td><td style="text-align:center">奇数</td><td style="text-align:center">偶数</td></tr><tr><td style="text-align:center">-</td><td style="text-align:center">000-</td><td style="text-align:center">+00+</td></tr><tr><td style="text-align:center">+</td><td style="text-align:center">000+</td><td style="text-align:center">-00-</td></tr></tbody></table><ul><li>调制技术：开关键控载波<ul><li>振幅ASK：01由振幅表示<ul><li>相干解调：乘上同周期的信号，低通滤波</li></ul></li><li>频移FSK：不同频率表示01<ul><li>应用：话音，高频无线电（天波，同轴电缆局域网</li></ul></li><li>相移PSK：不同相位表示信息<ul><li>二进制相移键控：$0,\pi$</li><li>QPSK：四个相位，$\pm\frac{\pi}{4},\pm\frac{3\pi}{4}$</li></ul></li><li>正交调幅QAM：两个载波正交（差90相位，分别ASK，两个独立信号</li><li>补点公式：<ul><li>ASK，PSK<br>$$B_T=(1+r)R$$</li><li>FSK<br>$$B_T=2\Delta f+(1+r)R$$</li><li>MPSK<br>$$B_T=\frac{1+r}{\log_2M}R$$</li><li>MFSK<br>$$B_T=\frac{(1+r)M}{\log_2M}R$$</li></ul></li></ul></li><li>模拟数据数字化<ul><li>脉码调制PCM<ul><li>定时采样，每次采样有几个bit进行量化</li><li>压扩函数：非线性编码，振幅低的地方密集</li></ul></li><li>增量调制DM<ul><li>近似信号的导数，有过载噪声</li></ul></li></ul></li><li>模拟调制系统<ul><li>模拟数据加载到载波，利于传输，允许频分复用，扩展带宽，抗干扰</li><li>调幅AM<ul><li>数据与载波相加<br>$$s_{AM}=[A_0+m(t)]\cos\omega_ct$$<br>归一化，小于1时可以包络解调，否则只能正交解调<br>$$s(t)=[1+n_ax(t)]\cos2\pi f_ct, n_a&lt;1$$</li></ul></li><li>调频FM<br>$$s(t)=A_c\cos[2\pi f_c+\varphi(t)],\varphi’(t)=n_fm(t)$$</li><li>调相PM<br>$$s(t)=A_c\cos[2\pi f_c+\varphi(t)],\varphi(t)=n_pm(t)$$<br>与FM转化：频率可定义为相位变化率，因此将PM后面的积分即可得到FM</li></ul></li></ul><h1 id="第六章：差错检测与矫正"><a href="#第六章：差错检测与矫正" class="headerlink" title="第六章：差错检测与矫正"></a>第六章：差错检测与矫正</h1><ul><li>奇偶校验<ul><li>偶校验：末尾加校验比特，整个字符中的1的个数为偶数</li></ul></li><li>因特网校验和<ul><li>两个数字视为无符号二进制整数，相加，高位进位就在最低位加1</li></ul></li><li>循环冗余检验CRC<ul><li>k位信息，生成n-k位比特，作为检验序列（会给出公式，公式最高位$X^{n-k}$</li></ul></li><li>块码原理<ul><li>2k+1的距离，最多检2k=$d_{min}-1$，最多纠k=$\lfloor\frac{d_{min}-1}{2}\rfloor$</li><li>冗余度：(n-k)/k，码字共n位，k个信息位</li><li>编码率：k/n</li></ul></li></ul><h1 id="第七章-数据链路控制协议"><a href="#第七章-数据链路控制协议" class="headerlink" title="第七章: 数据链路控制协议"></a>第七章: 数据链路控制协议</h1><h2 id="帧传输模型"><a href="#帧传输模型" class="headerlink" title="帧传输模型"></a>帧传输模型</h2><h2 id="性能指标"><a href="#性能指标" class="headerlink" title="性能指标"></a>性能指标</h2><table><thead><tr><th>名称</th><th>描述</th><th>详述</th></tr></thead><tbody><tr><td>传输时延</td><td>数据量 ÷ 数据率</td><td>emit <strong>all bits</strong> into medium</td></tr><tr><td>传播时延</td><td>介质一段到另一端</td><td><strong>a bit</strong> to traverse the link</td></tr><tr><td>处理时延</td><td>单节点时延 × 途径节点数</td><td>the recipient or intermediate <strong>node</strong> processing</td></tr><tr><td>排队时延</td><td>Σ此前耗时</td><td>waiting time at the <strong>queue</strong></td></tr></tbody></table><h2 id="流量控制"><a href="#流量控制" class="headerlink" title="流量控制"></a>流量控制</h2><h3 id="停止等待流量控制"><a href="#停止等待流量控制" class="headerlink" title="停止等待流量控制"></a>停止等待流量控制</h3><ul><li><p>流程  </p><ol><li>源点<strong>发送帧</strong></li><li>终点<strong>收到帧</strong>, 回复<strong>ACK</strong></li><li>原点收到<strong>ACK</strong>, 发送<strong>下一帧</strong></li><li>终点不发ACK终止流</li></ol></li><li><p>数据切分成小数据块传输  </p><ol><li>接收方<strong>缓存有限</strong></li><li>便于<strong>错误重传</strong></li><li>避免一个站点<strong>长时间占用传输媒体</strong></li></ol></li><li><p>计算题  </p><ul><li>链路比特长度<br>数据率$R/bps$, 距离$d/m$, 传播速度$v/ms^{-1}$<br>$$B=R\times\frac{d}{v}$$  </li><li>传播时延(归一化值)<br>链路比特长度$B/b$, 帧长度$L/b$<br>$$a=\frac{t_{prop}}{t_{frame}}=\frac{d/v}{L/R}=\frac{B}{L}$$</li><li>链路利用率<br>传播时延(归一化值)$a$<br>$$U=\frac{t_{frame}}{t_{all}}=\frac{t_{frame}}{2t_{prop}+t_{frame}}=\frac{1}{1+2a}$$</li></ul></li></ul><h3 id="滑动窗口流量控制"><a href="#滑动窗口流量控制" class="headerlink" title="滑动窗口流量控制"></a>滑动窗口流量控制</h3><ul><li><p>流程<br>接收端缓存大小 W<br>发送端在没有收到ACK前可以发送W个帧<br>每个帧通过序号来标识, 序号大小受字段长度限制(k bits)帧以 2 k 为模编号($0\to 2^{k}-1$)<br>ACK(RRx)包含<strong>下一个期望收到的帧</strong>编号x  </p></li><li><p>优化  </p><ol><li>接收端可发送RNR, 切断对方的帧流</li><li>之后, 接收端必须通过一个正常的确认帧来重启</li><li>双向链路捎带: 没数据有确认就单发ACK, 有数据有确认就捎带, 有数据没确认就发重复的确认</li></ol></li><li><p>计算题  </p><ul><li>链路利用率<br>窗口宽度$W$, 传播时延(归一化值)$a$<br>$$U=\begin{cases}<br>1 &amp; W \geq 2a + 1\\<br>\frac{W}{2a + 1} &amp; W &lt; 2a + 1<br>\end{cases}$$</li></ul></li></ul><h2 id="差错控制"><a href="#差错控制" class="headerlink" title="差错控制"></a>差错控制</h2><ul><li>自动请求重传ARQ<br>差错检测 肯定确认 超时重传 否定重传</li></ul><h3 id="停止等待ARQ-Stop-and-Wait"><a href="#停止等待ARQ-Stop-and-Wait" class="headerlink" title="停止等待ARQ Stop and Wait"></a>停止等待ARQ Stop and Wait</h3><ul><li>基于停止等待流量控制</li><li>保持一个发送帧的拷贝, 在终点确认返回前, 源点不发送其他帧</li><li>帧损伤<ul><li>接收端检测到差错, 丢弃该帧？</li><li>发送端超时重传</li></ul></li><li>ACK 损伤<ul><li>发送端超时重传</li><li>接收端收到用两份相同编号的帧</li></ul></li></ul><h3 id="Go-Back-N-ARQ"><a href="#Go-Back-N-ARQ" class="headerlink" title="Go-Back-N ARQ"></a>Go-Back-N ARQ</h3><ul><li>基于滑动窗口流控机制, 没有收到确认的帧的最大数目取决于窗口大小</li><li>无错误: ACKx表示准备接收x号帧</li><li>有错误: REJx表示x号帧错误, 重传x及其后的所有帧</li><li>ACK(RR) 损伤: 下一个ACK可能在超时前到来, 那么无影响; 否则发送”ACK with P bit set”重置</li><li>REJ 损伤: 接收端将其作为丢失帧, 计算超时</li></ul><h3 id="选择拒绝ARQ-Selective-Reject"><a href="#选择拒绝ARQ-Selective-Reject" class="headerlink" title="选择拒绝ARQ Selective Reject"></a>选择拒绝ARQ Selective Reject</h3><ul><li>仅重传拒绝帧或超时帧, 后续帧被接收端接收并缓存起来</li></ul><h3 id="对比"><a href="#对比" class="headerlink" title="对比"></a>对比</h3><table><thead><tr><th>ARQ</th><th>最大窗口大小(n bit 序号)</th><th>发送端缓存大小</th><th>接收端缓存大小</th></tr></thead><tbody><tr><td>Stop-Wait</td><td>无窗口, 无序号</td><td>无</td><td>无</td></tr><tr><td>Go-Back-N</td><td>$2^n-1$</td><td>窗口大小</td><td>无</td></tr><tr><td>Sel-Rej</td><td>$2^{n-1}$</td><td>窗口大小</td><td>窗口大小</td></tr></tbody></table><h2 id="HDLC"><a href="#HDLC" class="headerlink" title="HDLC"></a>HDLC</h2><ul><li>站点类型<ul><li>主站: 负责链路控制操 命令</li><li>从站: 在主站的控制下操作 响应</li><li>混合站: 结合了主站和从站的特点</li></ul></li><li>链路设置<ul><li>非平衡设置 1 个主站, 多个从站</li><li>平衡设置 2 个混合站组成</li></ul></li><li>数据传送方式</li></ul><table><thead><tr><th>数据传送方式</th><th>链路设置</th><th>传输发起</th></tr></thead><tbody><tr><td>正常相应方式NRM</td><td>非平衡设置</td><td>主站发起, 从站收到主站命令才能传输</td></tr><tr><td>异步平衡方式ABM</td><td>平衡设置</td><td>混合站均可发起, 应用最广泛</td></tr></tbody></table><ul><li>帧结构<br>同步传输, 以帧的形式进行, 一个帧格式满足控制和交换 </li></ul><table><thead><tr><th style="text-align:center">Flag</th><th style="text-align:center">Address</th><th style="text-align:center">Control</th><th style="text-align:center">Information</th><th style="text-align:center">FCS</th><th style="text-align:center">Flag</th></tr></thead><tbody><tr><td style="text-align:center">8 bit</td><td style="text-align:center">8 bit extendable</td><td style="text-align:center">8 or 16 bit</td><td style="text-align:center">variable</td><td style="text-align:center">16 or 32 bit</td><td style="text-align:center">8 bit</td></tr></tbody></table><h1 id="第八章-复用"><a href="#第八章-复用" class="headerlink" title="第八章: 复用"></a>第八章: 复用</h1><h2 id="FDM-频分复用"><a href="#FDM-频分复用" class="headerlink" title="FDM 频分复用"></a>FDM 频分复用</h2><ul><li>概念: 多个信号调制到不同的载波频率上, 且有足够间隙防止其带宽重叠, 以同时运载  </li><li>信道: 每个信号占有的频率范围  </li><li>防护频带: 载波频率中, 信道之间未被占用的部分  </li><li>流程<br>载波$m_i(t)$ <ruby>—&gt;<rt>调制器$f_i$</rt></ruby> 副载波$s_i(t)$ <ruby>—&gt;<rt>叠加$\sum$</rt></ruby> 基带$m_b(t)$ <ruby>—&gt;<rt>发送器$f_c$</rt></ruby> FDM信号$s(t)$<br>FDM信号$s(t)$ <ruby>—&gt;<rt>接收器</rt></ruby> 复合基带$m_b(t)$ <ruby>—&gt;<rt>滤波器$f_i$</rt></ruby> 副载波$s_i(t)$ <ruby>—&gt;<rt>解调器$f_i$</rt></ruby> 载波$m_i(t)$ </li><li>WDM 波分复用</li></ul><table><thead><tr><th>复用类型</th><th>关键设备</th><th>复用原理</th><th>介质</th></tr></thead><tbody><tr><td>FDM 频分复用</td><td>调制解调器</td><td>载波频率</td><td></td></tr><tr><td>WDM 波分复用</td><td>棱镜</td><td>光波长</td><td>光纤</td></tr></tbody></table><h2 id="Synchronous-TDM-同步时分复用"><a href="#Synchronous-TDM-同步时分复用" class="headerlink" title="Synchronous TDM 同步时分复用"></a>Synchronous TDM 同步时分复用</h2><ul><li>概念<ul><li>可以用于<strong>数字信号</strong>或<strong>模拟信号传输数字数据</strong></li><li>数据被组织成”<strong>帧</strong>“: 每帧包含一组循环使用的<strong>时隙</strong>; </li><li>每个数据源可以被分配一个或多个时隙(较快的设备), 在扫描时分配</li><li>间隔可以是比特级. 也可以是字符级或更大的粒度</li><li>同步时分复用中同步是指时隙被<strong>提前分配给数据源</strong>, 且是固定的</li></ul></li><li>流程<br>数据$m_i(t)$ <ruby>—&gt;<rt>缓存</rt></ruby> 数据$m_i(t)$ <ruby>—&gt;<rt>扫描操作</rt></ruby> TDM流$m_c(t)$ <ruby>—&gt;<rt>调制解调</rt></ruby> 经调制的TDM流$s(t)$<br>经调制的TDM流$s(t)$ <ruby>—&gt;<rt>调制解调</rt></ruby> TDM流$m_c(t)$ <ruby>—&gt;<rt>扫描操作</rt></ruby> 数据$m_i(t)$ <ruby>—&gt;<rt>缓存</rt></ruby> 数据$m_i(t)$   </li><li>链路控制<ul><li>不需要链路控制, 数据流无头尾</li><li>数据率是固定的, 没有信息将发送空时隙</li></ul></li><li>差错控制: 基于单信道的差错控制</li><li>组帧<ul><li>无需为帧定界, 但需源宿同步</li><li>增加数字组帧: 每个TDM帧附加一个控制比特</li><li>同步搜索模式：接收器将接收到的帧中的比特位与预期的模式相比较, 直到这个模式在多个帧里持续传输</li><li>脉冲填充: 同步不同数据率的源</li></ul></li><li>数字载波系统<ul><li>E体系: 2.048Mbps</li><li>T体系: 1.544Mbps</li><li><h2 id="Statistical-TDM-统计时分复用"><a href="#Statistical-TDM-统计时分复用" class="headerlink" title="Statistical TDM 统计时分复用"></a>Statistical TDM 统计时分复用</h2></li></ul></li><li>概念<ul><li>每一源有一缓存, 填满时作为一帧发送</li><li>根据需求分配时隙, 解决空时隙和浪费问题</li></ul></li><li>电缆调制解调器<ul><li>有线电视网访问Internet</li><li>信道  </li></ul></li></ul><table><thead><tr><th>用户到网络数据</th><th>电视节目</th><th>网络到用户数据</th></tr></thead><tbody><tr><td>5-40MHz</td><td>50-550MHz</td><td>550-750MHz</td></tr></tbody></table><ul><li>每个信道被多个用户共享<h2 id="ADSL-非对称用户数字线路"><a href="#ADSL-非对称用户数字线路" class="headerlink" title="ADSL 非对称用户数字线路"></a>ADSL 非对称用户数字线路</h2><ul><li>用户与广域网之间的线路, 用双绞线或电话线, 下行大于上行</li><li>使用频分复用, 低25kHz用于话音, 使用回声抵消或FDM双向传输</li><li>FDM</li></ul></li></ul><table><thead><tr><th>话音POTS</th><th>上行流</th><th>下行流</th></tr></thead><tbody><tr><td>0-20kHz</td><td>25-200kHz</td><td>250-1000kHz</td></tr></tbody></table><ul><li>更多xDSL<ul><li>HDSL: 高数据率数字用户线路, 两根双绞线</li><li>SDSL：单线数字用户线路</li><li>VDSL：甚高数据率数字用户线路</li></ul></li></ul><h1 id="第九章-交换"><a href="#第九章-交换" class="headerlink" title="第九章: 交换"></a>第九章: 交换</h1><h2 id="电路交换"><a href="#电路交换" class="headerlink" title="电路交换"></a>电路交换</h2><ul><li>概念<ul><li>公共电话网PSTN, 为话音通话开发, 也能处理数字数据</li></ul></li><li>流程<ul><li>建立通路, 通信, 断开通路</li></ul></li></ul><h3 id="空分交换"><a href="#空分交换" class="headerlink" title="空分交换"></a>空分交换</h3><ul><li>Crossbar Switch Fabric<ul><li>两两交叉, $n$入$n$出, 将有$n^2$个交叉点, 而至多用$n$个交叉点</li><li>非阻塞</li></ul></li><li>3-Stage Space Division Switching</li></ul><table><thead><tr><th>第一级</th><th>第二级</th><th>第三级</th></tr></thead><tbody><tr><td>$\frac{N}{n}$个$n\times m$单元</td><td>$m$个$n\times n$单元</td><td>$\frac{N}{n}$个$N\times m$单元</td></tr></tbody></table><ul><li><p>$m\geq 2n - 1$时非阻塞, 否则阻塞</p></li><li><p>Banyan Switch<br><img src="BanyanSwitch.jpg" alt="BanYan Switch"></p><ul><li>利用输入端的二进制编码来构建多层空分交换, $N = 2^k$, 则共有$k$层, 每层$2^{k-1}=N/2$个$2\times 2$单元</li><li>每层接线按照输入端二进制编号的各位连接</li><li>$N=8$, 是三级空分交换, 此时算得非阻塞</li></ul></li></ul><h2 id="分组交换"><a href="#分组交换" class="headerlink" title="分组交换"></a>分组交换</h2><ul><li>概念<ul><li>数据交换, 大数据段分为较小的数据包, 数据包包括用户数据和控制信息</li><li>包途径多个节点, 在节点处被缓存, 链路可用将被发送</li></ul></li></ul><h3 id="数据报交换"><a href="#数据报交换" class="headerlink" title="数据报交换"></a>数据报交换</h3><ul><li>概念<ul><li>每个数据包被当作单独的数据包对待, 独自寻路, 不受此前包的影响</li></ul></li><li>特性<ul><li>无建立时间</li><li>灵活</li><li>可靠</li></ul></li></ul><h3 id="虚电路交换"><a href="#虚电路交换" class="headerlink" title="虚电路交换"></a>虚电路交换</h3><ul><li>概念<ul><li>先建立路径(虚拟), 此后发送数据包均按此路径发送</li></ul></li><li>特性<ul><li>网络可提供排序和错误控制(包按序发送)</li><li>传送速度更快(无需选择路由)</li><li>较不可靠</li></ul></li></ul><h2 id="异步传输模式ATM"><a href="#异步传输模式ATM" class="headerlink" title="异步传输模式ATM"></a>异步传输模式ATM</h2><ul><li>概念<ul><li>信源: 小的, 固定长度的分组, 减小时延</li><li>面向连接的分组交换技术: 提供类似电路交换网络的性能, 同时有提供分组交换的灵活性和效率</li><li>数据率: 高</li><li>支持数据, 话音, 视频</li><li>传输: 基于优先级和QoS(服务质量), 用户可选择服务等级</li></ul></li><li>ATM逻辑连接<ul><li>虚通路: VCC, 类似虚电路, 速率可变, 全双工, 定长信源流</li><li>虚通道连接: VPC, 一群具有相同端点的虚通路</li><li><h2 id="本章习题"><a href="#本章习题" class="headerlink" title="本章习题"></a>本章习题</h2></li></ul></li><li>性能分析</li></ul><table><thead><tr><th>交换方式</th><th>建立时间$t_{build}$</th><th>实际传输的数据$L’$</th><th>传输时间$t_{trans}$</th><th>节点延迟$t_{delay}$</th><th>总时间$t$</th></tr></thead><tbody><tr><td>电路交换</td><td>$S$</td><td>$L$</td><td>$\frac{L}{B}$</td><td>$DN$</td><td>$S + DN + \frac{L}{B}$</td></tr><tr><td>数据报交换</td><td>$0$</td><td>$P\lceil\frac{L}{P-H}\rceil$</td><td>$P\lceil\frac{L}{P-H}\rceil/B$</td><td>$DN$</td><td>$DN + P\lceil\frac{L}{P-H}\rceil/B$</td></tr><tr><td>虚电路交换</td><td>$S$</td><td>$P\lceil\frac{L}{P-H}\rceil$</td><td>$P\lceil\frac{L}{P-H}\rceil/B$</td><td>$DN$</td><td>$S + DN + P\lceil\frac{L}{P-H}\rceil/B$</td></tr></tbody></table><h1 id="第十章-蜂窝无线网络"><a href="#第十章-蜂窝无线网络" class="headerlink" title="第十章: 蜂窝无线网络"></a>第十章: 蜂窝无线网络</h1><h2 id="蜂窝无线网络的概念"><a href="#蜂窝无线网络的概念" class="headerlink" title="蜂窝无线网络的概念"></a>蜂窝无线网络的概念</h2><ul><li>蜂窝构成<ul><li>区域被分为蜂窝</li><li>蜂窝使用低功率发送器: 100W以下, 控制功率防止频率逃逸</li><li>每个蜂窝一个基站: 发送, 接收, 控制单元</li><li>相邻蜂窝频率不同: 防止干扰</li><li>蜂窝形状为六边形: 蜂窝半径为$R$, 则相邻蜂窝中心距离$\sqrt{3}R$</li></ul></li><li>频率重用<ul><li>$D$: 使用相同频率的蜂窝(同波道)中心之间的距离</li><li>$R$: 蜂窝半径</li><li>$d$: 相邻蜂窝中心之间的距离</li><li>$N$: 重复模式中的蜂窝数量, 重用系数, 其可能值仅有这些<br>$$N=I^2+J^2+(I\times J)\quad I,J\in\mathbb{N}$$</li><li>有以下关系式<br>$$\frac{D}{R}=\sqrt{3N}$$</li></ul></li><li>增大容量<ul><li>添加新信道: 建立时不会用完全部的信道, 添加新信道满足扩张</li><li>频率借用: 拥塞的蜂窝可以从邻近的空闲蜂窝借用频率, 也可动态指派频率给各个蜂窝</li><li>蜂窝分裂: 大蜂窝在使用率高的地区分裂为小蜂窝, 其功率低覆盖面积小</li><li>蜂窝扇区化: 定向天线, 蜂窝被划分为楔形扇区, 指派蜂窝频率的一个真子集</li><li>微蜂窝: 功率和覆盖范围超小的蜂窝, 建筑物内, 公路旁, 城市街道等\</li></ul></li></ul><h2 id="蜂窝系统的操作"><a href="#蜂窝系统的操作" class="headerlink" title="蜂窝系统的操作"></a>蜂窝系统的操作</h2><ul><li>信道<ul><li>控制信道: 交换 建立与维持呼叫的信息</li><li>业务信道: 承载用户之间话音或数据的连接</li></ul></li><li>呼叫典型步骤 MTSO</li></ul><table><thead><tr><th>功能</th><th>描述</th></tr></thead><tbody><tr><td>移动单元初始化</td><td>定期扫描, 选择使用最强的基站建立控制信道, 并与控制该蜂窝的MTSO握手, 之后监听是否有寻呼</td></tr><tr><td>移动台发起的呼叫</td><td>移动单元通过在已选的建立信道上, 若信道空闲, 发送被叫单元的号码来发起呼叫</td></tr><tr><td>寻呼</td><td>MTSO根据被叫号码, 向某些基站发送寻呼信息</td></tr><tr><td>呼叫接收</td><td>被叫单元识别寻呼, 向基站发通知 -&gt; 基站向MTSO发通知 -&gt; MTSO建立电路, 选两个业务信道, 通知两个基站 -&gt; 基站通知单元</td></tr><tr><td>呼叫进行中</td><td>话音或数据信号: 单元 <-> 基站  <-> MTSO <-> 基站 <-> 单元</-></-></-></-></td></tr><tr><td>切换</td><td>移动单元跨蜂窝移动, 业务信道切换到指派给新蜂窝的业务信道, 不警告用户</td></tr><tr><td>呼叫阻塞</td><td>没有空闲业务信道, 将重试数次, 耗尽次数返回忙音</td></tr><tr><td>呼叫终止</td><td>用户挂机, MTSO得到通知, 释放业务信道</td></tr><tr><td>呼叫掉线</td><td>信号强度低于最小信号强度, MTSO将得到通知, 释放信道</td></tr><tr><td>连接固定用户</td><td>MTSO与公用电话交换网络连接</td></tr><tr><td>连接远程用户</td><td>MTSO通过电话网或专用线路, 与远程MTSO连接, 并为二者用户建立连接</td></tr></tbody></table><h2 id="移动无线电传播效应"><a href="#移动无线电传播效应" class="headerlink" title="移动无线电传播效应"></a>移动无线电传播效应</h2><ul><li>信号强度<ul><li>太强: 同信道干扰</li><li>太弱: 不足以维持连接</li></ul></li><li>衰落</li></ul><h2 id="移动环境中的衰落"><a href="#移动环境中的衰落" class="headerlink" title="移动环境中的衰落"></a>移动环境中的衰落</h2><ul><li>三种重要的传播机制<ul><li>反射</li><li>衍射</li><li>散射</li></ul></li><li>多径传播效应<ul><li>主脉冲 -&gt; 主脉冲+多个副脉冲: 相当于噪声</li></ul></li><li>衰落的类型</li></ul><table><thead><tr><th>类型</th><th>描述</th></tr></thead><tbody><tr><td>快衰落</td><td>振幅的变化也高达20一30dB这种类型的迅速衰落变化</td></tr><tr><td>慢衰落</td><td>接收功率除了出现快速波动之外, 接收到的平均功率水平也会变化</td></tr><tr><td>平坦衰落</td><td>接收信号的所有频率成分的波动是同时的且成相同比例的</td></tr><tr><td>选择性衰落</td><td>对一个无线电信号的不同頻谱成分的影响是不同的</td></tr></tbody></table><h2 id="四代蜂窝网络"><a href="#四代蜂窝网络" class="headerlink" title="四代蜂窝网络"></a>四代蜂窝网络</h2><table><thead><tr><th>技术</th><th>最初设计时间</th><th>应用时间</th><th>服务</th><th>数据率</th><th>复用技术</th><th>核心网络</th><th>更多</th></tr></thead><tbody><tr><td>1G</td><td>1970</td><td>1984</td><td>模拟话音</td><td>1.9kbps</td><td>FDMA</td><td>PSTN</td></tr><tr><td>2G</td><td>1980</td><td>1991</td><td>数字话音</td><td>9.6kbps-14.4kbps</td><td>(GSM)TDMA, CDMA</td><td>PSTN</td><td>EDGE, 均衡, 交织, RAKE接收, 功率控制</td></tr><tr><td>2.5G</td><td>1985</td><td>1999</td><td>大容量分组化数据</td><td>384kbps-2Mbps</td><td>TDMA,CDMA</td><td>PSTN, 分组网络</td><td>多用户检测, 智能天线,  Turbo 编码, 多媒体数据</td></tr><tr><td>4G</td><td>2000</td><td>2012</td><td>完全基于IP</td><td>20~100Mbps-1Gbps</td><td>OFDMA, SC-FDMA</td><td>IP干线网</td><td>自适应调制编码, 混合自动重传, MIMO</td></tr></tbody></table><h2 id="LTE-Advanced-传输特性"><a href="#LTE-Advanced-传输特性" class="headerlink" title="LTE-Advanced 传输特性"></a>LTE-Advanced 传输特性</h2><ul><li>FDD与TDD<ul><li>FDD: 成对的上下行信道, 中间有保护频带</li><li>TDD: 同一频带, 时域上交替</li></ul></li><li>载波聚合<ul><li>带内连续: 相邻的信道被看作被放大的信道</li><li>带内不连续: 多个分量载波CC在带内不连续, 需要多个收发器</li><li>带间不连续: 多个收发器</li></ul></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;数据通信: 期末复习&lt;br&gt;
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Data Communication" scheme="https://Maxwell-lyu.github.io/tags/Data-Communication/"/>
    
  </entry>
  
  <entry>
    <title>Probability Ch7</title>
    <link href="https://Maxwell-lyu.github.io/2019/05/23/Learn-PMS-20190523-PMS-07/"/>
    <id>https://Maxwell-lyu.github.io/2019/05/23/Learn-PMS-20190523-PMS-07/</id>
    <published>2019-05-23T00:45:09.000Z</published>
    <updated>2019-06-13T01:06:32.000Z</updated>
    
    <content type="html"><![CDATA[<p>Probability Course in 2019 Spring<br><a id="more"></a> </p><h1 id="参数估计"><a href="#参数估计" class="headerlink" title="参数估计"></a>参数估计</h1><h2 id="矩估计"><a href="#矩估计" class="headerlink" title="矩估计"></a>矩估计</h2><ul><li><strong>计算步骤</strong><ol><li>求总体的各阶原点矩，用参数表示<br>$$\mu_i=g_i(\theta_1,\theta_2,\cdots,\theta_k)$$</li><li>解方程组，用总体矩表示参数<br>$$\theta_i=h_i(\mu_1,\mu_2,\cdots,\mu_k)$$</li><li>用样本的矩代替总体矩，得到参数的表示<br>$$\theta_i=h_i(\mu_1,\mu_2,\cdots,\mu_k)$$  </li></ol></li></ul><h2 id="极大似然估计"><a href="#极大似然估计" class="headerlink" title="极大似然估计"></a>极大似然估计</h2><ul><li><strong>计算步骤</strong><ol><li>列出以下式子<br>$$L(x_1,x_2,\cdots,x_n;\hat{\theta})=\max_{\theta\in\Theta}L(x_1,x_2,\cdots,x_n;\theta)=\prod_{i=1}^np(x_i;\theta)$$</li><li>上式取对数, 得到似然方程组<br>$$\frac{\partial\ln L(\theta)}{\partial\theta}=\sum_{i=1}^n\frac{\partial\ln p(x_i;\theta)}{\partial\theta}=0$$</li><li>解出参数，注意参数本身的范围</li></ol></li></ul><h2 id="估计量的评价标准"><a href="#估计量的评价标准" class="headerlink" title="估计量的评价标准"></a>估计量的评价标准</h2><ol><li>无偏性<br>$$E[\hat{\theta}(X_1,X_2,\cdots,X_n)]=\theta$$</li><li>均方误差<br>$$M(\hat{\theta},\theta)=E(\hat{\theta}-\theta)^2=D(\hat{\theta})+(E\hat{\theta}-\theta)^2$$</li><li>一致性<br>$$\hat{\theta}_n\stackrel{P}{\to}\theta$$<ol><li>无偏, 方差极限为0</li></ol></li></ol><h2 id="区间估计"><a href="#区间估计" class="headerlink" title="区间估计"></a>区间估计</h2><ol><li><p>基本概念与枢纽变量法</p><ul><li><strong>区间估计</strong><br>$$P(\hat{\theta}_1&lt;\theta&lt;\hat{\theta}_1)=1-\alpha$$<br>分别为置信下限, 置信上限, 置信系数</li><li><strong>计算方法</strong><ol><li>找一个样本函数, 包含待估参数, 并且分布已知</li><li>根据此分布, 找到常数$a$, $b$, 使得<br>$$P(a&lt;U&lt;b)=1-\alpha$$</li><li>利用不等式解出$\theta$范围</li></ol></li><li><strong>双边与单边</strong><ol><li>置信度$1-\alpha$</li><li>双边需要取$\alpha/2$或$1-\alpha/2$</li><li>单边直接用$\alpha$或$1-\alpha$</li></ol></li></ul></li><li><p>正态总体$N(\mu, \sigma^2)$中均值$\mu$的置信区间  </p><ul><li>$\sigma^2$已知<br>$$\bar{X}\pm u_{\alpha/2}\frac{\sigma}{\sqrt{n}}$$</li><li>$\sigma^2$未知<br>$$\bar{X}\pm t_{\alpha/2}(n-1)\times\frac{S}{\sqrt{n}}$$</li></ul></li><li>正态总体$N(\mu, \sigma^2)$中方差$\sigma^2$的置信区间<br>$$(\frac{(n-1)S^2}{\chi^2_{\alpha/2}(n-1)},\frac{(n-1)S^2}{\chi^2_{1-\alpha/2}(n-1)})$$</li><li>两个正态总体$N(\mu_1, \sigma_1^2)$, $N(\mu_2, \sigma_2^2)$中均值差$\mu_1-\mu_2$的置信区间<ul><li>$\sigma_i^2$已知<br>$$\bar{X}-\bar{Y}\pm u_{\alpha/2}\sqrt{\frac{\sigma_1^2}{n_1}+\frac{\sigma_2^2}{n_2}}$$</li><li>$\sigma_i^2$未知<br>$$\bar{X}-\bar{Y}\pm t_{\alpha/2}(n_1+n_2-2)\times S_w\sqrt{\frac{1}{n_1}+\frac{1}{n_2}}$$<br>$$S_w=\sqrt{\frac{(n_1-1)S_1^2+(n_2-1)S_2^2}{n_1-n_2-2}}$$</li></ul></li><li>两个正态总体$N(\mu_1, \sigma_1^2)$, $N(\mu_2, \sigma_2^2)$方差比$\sigma_1^2/\sigma_2^2$的置信区间<br>$$(\frac{S_1^2}{S_2^2}\frac{1}{F_{\alpha/2}(n_1-1,n_2-1)}, \frac{S_1^2}{S_2^2}\frac{1}{F_{1-\alpha/2}(n_1-1,n_2-1)})$$</li></ol>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Probability Course in 2019 Spring&lt;br&gt;
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Probability and Mathematical Statistics" scheme="https://Maxwell-lyu.github.io/tags/Probability-and-Mathematical-Statistics/"/>
    
  </entry>
  
  <entry>
    <title>Probability Ch6</title>
    <link href="https://Maxwell-lyu.github.io/2019/05/09/Learn-PMS-20190509-PMS-06/"/>
    <id>https://Maxwell-lyu.github.io/2019/05/09/Learn-PMS-20190509-PMS-06/</id>
    <published>2019-05-09T01:14:19.000Z</published>
    <updated>2019-06-17T01:18:52.000Z</updated>
    
    <content type="html"><![CDATA[<p>Probability Course in 2019 Spring<br><a id="more"></a> </p><h1 id="统计量与抽样分布"><a href="#统计量与抽样分布" class="headerlink" title="统计量与抽样分布"></a>统计量与抽样分布</h1><h2 id="总体与样本"><a href="#总体与样本" class="headerlink" title="总体与样本"></a>总体与样本</h2><h3 id="总体与个体"><a href="#总体与个体" class="headerlink" title="总体与个体"></a>总体与个体</h3><ul><li><strong>总体</strong>  所研究的对象的全体</li><li><strong>个体</strong>  总体当中的每个元素</li></ul><h3 id="样本"><a href="#样本" class="headerlink" title="样本"></a>样本</h3><ul><li><strong>样本</strong>  为了对总体$X$进行研究, 通常要从总体中随机地抽取一些个体, 这些个体就成为样本</li><li><strong>抽样</strong>  抽得样本的过程</li><li><strong>样本容量</strong>  样本中个体的数量称为样本容量</li><li><strong>样本值</strong>  设对总体进行了$n$次观测, 得到一组数据$(x_1,x_2,\cdots,x_n)$</li><li><strong>随机抽样的要求: 简单随机样本</strong><ol><li>代表性</li><li>独立性</li><li>分布函数<br>$$p(x_1,x_2,\cdots,x_n)=\prod_{i=1}^np(x_i)$$</li></ol></li></ul><h2 id="统计量与抽样分布-1"><a href="#统计量与抽样分布-1" class="headerlink" title="统计量与抽样分布"></a>统计量与抽样分布</h2><ul><li><p><strong>定义6.1</strong><br>设$(X_1,X_2,\cdots,X_n)$为总体$X$的一个样本, $T(x_1,x_2,\cdots,x_n)$为不含任何未知参数的函数, 则称$T(x_1,x_2,\cdots,x_n)$为一个统计量</p></li><li><p><strong>样本均值</strong><br>$$\bar{X}=\frac{1}{n}\sum_{i-1}^nX_i$$</p></li><li><p><strong>样本方差</strong><br>$$S^2=\frac{1}{n-1}\sum_{i=1}^n(X_i-\bar{X})^2$$<br>$$S^{*2}=\frac{1}{n}\sum_{i=1}^n(X_i-\bar{X})^2=\frac{1}{n}\sum_{i=1}^nX_i^2-\bar{X}^2$$</p></li><li><p><strong>样本标准差</strong><br>$$S=\sqrt{S^2}$$</p></li></ul><h2 id="正态总体"><a href="#正态总体" class="headerlink" title="正态总体"></a>正态总体</h2><ol><li>$\chi^2$分布<br>$X_i\sim N(0,1)$<br>$$\chi^2=\sum_{i=1}^nX_i^2\sim \chi^2(n)$$</li><li>$t$分布<br>$X\sim N(0,1), Y\sim\chi^2(n)$<br>$$T=\frac{X}{\sqrt{Y/n}}\sim t(n)$$</li><li>$F$分布<br>$U\sim\chi^2(n_1),V\sim\chi^2(n_2)$<br>$$F=\frac{U/n_1}{V/n_2}\sim F(n_1,n_2)$$</li><li>上$\alpha$分位点$\lambda_\alpha$<br>$$P(X&gt;\lambda_\alpha)=\alpha$$</li><li>要记忆的式子  <ul><li>$$\bar{X}\sim N(\mu, \frac{\sigma^2}{n})$$</li><li>$$\frac{(n-1)S_{n-1}^2}{\sigma^2}=\sum_{i=1}^n(\frac{X_i-\bar{X}}{\sigma})\sim\chi^2(n-1)$$</li><li>$$\sum_{i=1}^n(\frac{X_i-\mu}{\sigma})\sim\chi^2(n)$$</li><li>$\bar{X}$与$S_{n-1}^2$相互独立</li><li>$$T=\frac{\sqrt{n}(\bar{X}-\mu)}{S_{n-1}}\sim t(n-1)$$</li><li>$$T’=\frac{\sqrt{n-1}(\bar{X}-\mu)}{S_{n}}\sim t(n-1)$$</li><li>$$F=\frac{S_1^2/\sigma_1^2}{S_2^2/\sigma_2^2}\sim F(n_1-1, n_2-1)$$</li><li>$$U=\frac{(\bar{X}-\bar{Y})-(\mu_1-\mu_2)}{\sqrt{\frac{\sigma_1^2}{n_1}+\frac{\sigma_2^2}{n_2}}}\sim N(0,1)$$</li></ul></li></ol><ul><li><strong>定理6.2</strong><ol><li>$\bar{X}\sim N(\mu, \frac{\sigma^2}{n})$</li><li>$(n-1)\frac{S^2}{\sigma^2}\sim \chi^2(n-1)$</li><li>$\bar{X}$与$S^2$相互独立</li></ol></li><li><strong>推论6.1</strong><br>$$T=\frac{\sqrt{n}(\bar{X}-\mu)}{S}\sim t(n-1)$$</li><li><strong>推论6.2</strong><br>$$F=\frac{S_1^2/\sigma_1^2}{S_2^2/\sigma_2^2}\sim F(n_1-1,n_2-1)$$</li><li><strong>推论6.3</strong><br>$$T=\sqrt{\frac{n_1+n_2-2}{\frac{1}{n_1}+\frac{1}{n_2}}}\frac{(\bar{X}-\bar{Y})-(\mu_1-\mu_2)}{\sqrt{(n_1-1)S_1^2+(n_2-1)S_2^2}}\sim t(n_1+n_2-2)$$</li></ul>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Probability Course in 2019 Spring&lt;br&gt;
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Probability and Mathematical Statistics" scheme="https://Maxwell-lyu.github.io/tags/Probability-and-Mathematical-Statistics/"/>
    
  </entry>
  
  <entry>
    <title>Data Communication Mid-Term</title>
    <link href="https://Maxwell-lyu.github.io/2019/04/29/Learn-DC-20190429-DC-MID/"/>
    <id>https://Maxwell-lyu.github.io/2019/04/29/Learn-DC-20190429-DC-MID/</id>
    <published>2019-04-29T03:37:44.000Z</published>
    <updated>2019-09-02T01:28:16.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="数据通信：期中复习"><a href="#数据通信：期中复习" class="headerlink" title="数据通信：期中复习"></a>数据通信：期中复习</h1><h2 id="第二章：网络体系结构"><a href="#第二章：网络体系结构" class="headerlink" title="第二章：网络体系结构"></a>第二章：网络体系结构</h2><ul><li>通信模型<ul><li>源系统（源点，发送器），传输系统，目的系统（接收器，终点)</li></ul></li><li>传输方式<ul><li>单工：一个信道，只能单向</li><li>半双工：一个信道，同一时间只能上/下行，有选择器</li><li>全双工：两个信道，同时上下行</li></ul></li><li>数字通信与模拟通信<ul><li>数字系统：数字-数字编码，模拟-数字编码</li><li>模拟系统：模拟信号以固有频率基带传输（不编码），频谱搬移后传输（模拟-模拟编码）</li><li>混成系统：同一系统既包含模拟也包含数字</li></ul></li><li>网络体系结构：TCP/IP<ul><li>应用层，传输层，网际层，数据链路层，物理层</li></ul></li><li>套接字及其类型<ul><li>流套接字：TCP：可靠，按时</li><li>数据包套接字：UDP：快速乱序无保证</li><li>原始套接字：IP：直接访问底层</li></ul></li></ul><h2 id="第三章：数据传输"><a href="#第三章：数据传输" class="headerlink" title="第三章：数据传输"></a>第三章：数据传输</h2><ul><li>概念与术语<ul><li>导向媒体：电磁波沿某一物理路径前进（光纤，双绞线，同轴电缆<ul><li>点对点：直连链路</li><li>多点：共享</li></ul></li><li>非导向媒体：无线传输，不引导传输方向（空气，真空，海水</li></ul></li><li>数据与信号<ul><li>数据：信源产生，可能为模拟或数字</li><li>信号：经过调制，电磁信号居多</li></ul></li><li>周期信号的傅里叶级数表示<ul><li>傅里叶表示：<br>$$x(t)=\frac{A_0}{2}+\sum_{n=1}^{\infty}(A_n\cos(2\pi nf_0t)+B_n\sin(2\pi nf_0t))$$<br>$$A_n = \frac{2}{T}\int_{0}^{T}x(t)\cos(2\pi nf_0t)dt$$<br>$$B_n = \frac{2}{T}\int_{0}^{T}x(t)\sin(2\pi nf_0t)dt$$</li><li>方波的傅里叶表示<br>$$f(x)=\frac{4}{\pi}\sum_{n=2k-1}^\infty \frac{1}{n}\sin(\frac{n\pi x}{L})$$</li></ul></li><li>信号功率计算<ul><li>任意时段功率：<br>$$P_x=\frac{1}{t_2-t_1}\int_{t_1}^{t_2}|x(t)|^2dt$$</li><li>周期平均功率<br>$$P=\frac{1}{T}\int_{0}^{T}|x(t)|^2dt$$   </li></ul></li><li>信号的频谱与带宽<ul><li>频谱：信号的频率范围</li><li>绝对带宽：频谱宽度，最大减最小</li><li>有效带宽：包含绝大多数能量的带宽，某频率区间的功率积分是总功率的一半（-3dB）</li><li>直流分量：频率为0的部分</li></ul></li><li>数据率与带宽的关系<ul><li>$R_b=2f$，$R_b$数据率，$f$带宽</li></ul></li><li>模拟/数字数据与模拟/数字传输<ul><li>模拟信号：放大器</li><li>数字信号：转发器</li></ul></li><li>数字信号传输的优势<ul><li>大规模集成电路</li><li>数据完整性</li><li>容量利用率</li><li>安全和保密</li><li>综合性、存储</li></ul></li><li>传输损伤<ul><li>衰减：放大器与转发器解决</li><li>失真<ul><li>衰减失真：高频失真多，衰减均衡和高频高倍放大解决</li><li>时延失真：中心频率附近传输快，仅限数字信号，码间串扰</li></ul></li><li>噪声<ul><li>信噪比：$SNR_{db}=1o\lg{\frac{S}{N}}$</li><li>热噪声：$N_0=kT$，$k$玻尔兹曼常量，$T$热力学温度</li><li>互调噪声、串扰（双绞线扭绞）、冲激噪声</li></ul></li></ul></li><li>信道容量：最大数据传输速率<ul><li>数据率bps，带宽Hz，噪声，误码率</li><li>奈奎斯特带宽：信道无噪声时：$C=2B\log_2{M}$，$M$指信号的电平数</li><li>香农容量公式：只有热噪声时：$C=B\log_2(1+SNR)$，$SNR=10^{0.1SNR_{db}}$为信噪比</li></ul></li></ul><h2 id="第四章：传输媒体"><a href="#第四章：传输媒体" class="headerlink" title="第四章：传输媒体"></a>第四章：传输媒体</h2><ul><li>光纤<ul><li>优势：容量大，体积小，衰减小，电磁隔离，转发器间隔远</li><li>折射率分类：<ul><li>阶跃型：折射率阶跃，会有失真</li><li>渐变型：光路周期性汇聚</li></ul></li><li>模式分类<ul><li>单模、多模</li></ul></li></ul></li><li>无线传播：高频天线小<ul><li>地波：-2MHz</li><li>天波：2MHz-30MHz</li><li>视距传播：30MHz-</li></ul></li><li>视距传播损伤<ul><li>自由空间损耗模型<br>$$L=10\lg(\frac{4\pi d}{\lambda})^2dB$$</li></ul></li></ul><h2 id="第五章：信号编码技术"><a href="#第五章：信号编码技术" class="headerlink" title="第五章：信号编码技术"></a>第五章：信号编码技术</h2><ul><li>编码与调制技术<ul><li>数字信号传输：数字或模拟数据-&gt;(编码器)-&gt;数字信号-&gt;(解码器)-&gt;原数据</li><li>模拟信号传输：数字或模拟基带信号<->(调制解调器)<->模拟信号</-></-></li></ul></li><li>数字信号编码格式<ul><li>NRZ-L：高电平0，低电平1</li><li>NRZI：区间起始无变化0，区间起始有变化1</li><li>双极性AMI：零电平0，正电平负电平1交替出现</li><li>伪三进制：正电平负电平0交替出现，零点平1</li><li>曼彻斯特：区间正中高到低0，低到高1</li><li>差分曼彻斯特：区间正中总是变化，区间起始变化0，区间起始不变1</li></ul></li><li>扰码<ul><li>扰码产生替代连续电压的序列</li><li>填充序列：提供足够的信息用于同步，可被识别替换还原，长度相同</li><li>目标：不含直流，定时信息丰富，不降低数据率，可检错，易于判断还原</li></ul></li><li>HDB3：会给出编码方式  </li></ul><table><thead><tr><th style="text-align:center"></th><th style="text-align:center">自上一次替换后双极性</th><th style="text-align:center">脉冲（比特1）数</th></tr></thead><tbody><tr><td style="text-align:center">前面脉冲的极性</td><td style="text-align:center">奇数</td><td style="text-align:center">偶数</td></tr><tr><td style="text-align:center">-</td><td style="text-align:center">000-</td><td style="text-align:center">+00+</td></tr><tr><td style="text-align:center">+</td><td style="text-align:center">000+</td><td style="text-align:center">-00-</td></tr></tbody></table><ul><li>调制技术：开关键控载波<ul><li>振幅ASK：01由振幅表示<ul><li>相干解调：乘上同周期的信号，低通滤波</li></ul></li><li>频移FSK：不同频率表示01<ul><li>应用：话音，高频无线电（天波，同轴电缆局域网</li></ul></li><li>相移PSK：不同相位表示信息<ul><li>二进制相移键控：$0,\pi$</li><li>QPSK：四个相位，$\pm\frac{\pi}{4},\pm\frac{3\pi}{4}$</li></ul></li><li>正交调幅QAM：两个载波正交（差90相位，分别ASK，两个独立信号</li><li>补点公式：<ul><li>ASK，PSK<br>$$B_T=(1+r)R$$</li><li>FSK<br>$$B_T=2\Delta f+(1+r)R$$</li><li>MPSK<br>$$B_T=\frac{1+r}{\log_2M}R$$</li><li>MFSK<br>$$B_T=\frac{(1+r)M}{\log_2M}R$$</li></ul></li></ul></li><li>模拟数据数字化<ul><li>脉码调制PCM<ul><li>定时采样，每次采样有几个bit进行量化</li><li>压扩函数：非线性编码，振幅低的地方密集</li></ul></li><li>增量调制DM<ul><li>近似信号的导数，有过载噪声</li></ul></li></ul></li><li>模拟调制系统<ul><li>模拟数据加载到载波，利于传输，允许频分复用，扩展带宽，抗干扰</li><li>调幅AM<ul><li>数据与载波相加<br>$$s_{AM}=[A_0+m(t)]\cos\omega_ct$$<br>归一化，小于1时可以包络解调，否则只能正交解调<br>$$s(t)=[1+n_ax(t)]\cos2\pi f_ct, n_a&lt;1$$</li></ul></li><li>调频FM<br>$$s(t)=A_c\cos[2\pi f_c+\varphi(t)],\varphi’(t)=n_fm(t)$$</li><li>调相PM<br>$$s(t)=A_c\cos[2\pi f_c+\varphi(t)],\varphi(t)=n_pm(t)$$<br>与FM转化：频率可定义为相位变化率，因此将PM后面的积分即可得到FM</li></ul></li></ul><h2 id="第六章：差错检测与矫正"><a href="#第六章：差错检测与矫正" class="headerlink" title="第六章：差错检测与矫正"></a>第六章：差错检测与矫正</h2><ul><li>奇偶校验<ul><li>偶校验：末尾加校验比特，整个字符中的1的个数为偶数</li></ul></li><li>因特网校验和<ul><li>两个数字视为无符号二进制整数，相加，高位进位就在最低位加1</li></ul></li><li>循环冗余检验CRC<ul><li>k位信息，生成n-k位比特，作为检验序列（会给出公式，公式最高位$X^{n-k}$</li></ul></li><li>块码原理<ul><li>2k+1的距离，最多检2k=$d_{min}-1$，最多纠k=$\lfloor\frac{d_{min}-1}{2}\rfloor$</li><li>冗余度：(n-k)/k，码字共n位，k个信息位</li><li>编码率：k/n</li></ul></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;数据通信：期中复习&quot;&gt;&lt;a href=&quot;#数据通信：期中复习&quot; class=&quot;headerlink&quot; title=&quot;数据通信：期中复习&quot;&gt;&lt;/a&gt;数据通信：期中复习&lt;/h1&gt;&lt;h2 id=&quot;第二章：网络体系结构&quot;&gt;&lt;a href=&quot;#第二章：网络体系结构&quot; cla
      
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Data Communication" scheme="https://Maxwell-lyu.github.io/tags/Data-Communication/"/>
    
  </entry>
  
  <entry>
    <title>Probability Ch5</title>
    <link href="https://Maxwell-lyu.github.io/2019/04/28/Learn-PMS-20190428-PMS-05/"/>
    <id>https://Maxwell-lyu.github.io/2019/04/28/Learn-PMS-20190428-PMS-05/</id>
    <published>2019-04-28T00:01:48.000Z</published>
    <updated>2019-06-16T02:21:06.000Z</updated>
    
    <content type="html"><![CDATA[<p>Probability Course in 2019 Spring<br><a id="more"></a> </p><h1 id="极限理论"><a href="#极限理论" class="headerlink" title="极限理论"></a>极限理论</h1><h2 id="大数定律"><a href="#大数定律" class="headerlink" title="大数定律"></a>大数定律</h2><ul><li><strong>定义5.1</strong><br>设$X_1,X_2,\cdots, X_n$为一列随机变量, 若存在随机变量$X$, 使得任意给定的$\epsilon&gt;0$,<br>$$-$$<br>$$\lim_{n\to\infty}P(|\frac{1}{n}\sum_{k=1}^nX_k - \frac{1}{n}\sum_{k=1}^nEX_k|\geq\epsilon)=0$$<br>则称随机变量序列$\{X_n\}$依概率收敛于随机变量$X$, 记为$X_n\stackrel{P}{\to}X$</li><li><strong>定义5.2</strong><br>大数定律: 变量平均值依概率收敛于期望平均值<br>$$\frac{1}{n}\sum_{k=1}^nX_k\stackrel{P}{\to}\frac{1}{n}\sum_{k=1}^nEX_k$$</li><li><strong>马尔可夫大数定律</strong><br>$$\lim_{n\to\infty}\frac{1}{n^2}D(\sum_{k=1}^nX_k)\to 0$$</li><li><strong>切比雪夫大数定律</strong><br>$$\exists C, \forall k, D(X_k)\leq C$$</li><li><strong>独立同分布大数定律</strong><br>$$X_k\textrm{独立同分布},EX_k=\mu,D(X_k)=\sigma^2&lt;\infty$$</li><li><strong>贝努里大数定律</strong><br>事件$A$发生的频率依概率收敛到事件$A$发生的概率<br>$$\frac{\mu_n}{n}\stackrel{P}{\to}p$$</li></ul><h2 id="中心极限定理"><a href="#中心极限定理" class="headerlink" title="中心极限定理"></a>中心极限定理</h2><ol><li>$\{X\}$独立同分布, 则$\sum_{k=1}^nX_k$近似服从正态分布</li><li>$X$服从二项分布, $n$足够大, 则$X$近似服从正态分布</li><li>$X$服从泊松分布, $n$足够大, 则$X$近似服从正态分布</li><li>分布的标准化: $Y=\frac{X-\mu}{\sigma}$</li></ol>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Probability Course in 2019 Spring&lt;br&gt;
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Probability and Mathematical Statistics" scheme="https://Maxwell-lyu.github.io/tags/Probability-and-Mathematical-Statistics/"/>
    
  </entry>
  
  <entry>
    <title>Problem Solving IV 10</title>
    <link href="https://Maxwell-lyu.github.io/2019/04/27/Learn-PS-20190427-PS-IV-10/"/>
    <id>https://Maxwell-lyu.github.io/2019/04/27/Learn-PS-20190427-PS-IV-10/</id>
    <published>2019-04-27T11:10:38.000Z</published>
    <updated>2019-04-27T12:34:22.000Z</updated>
    
    <content type="html"><![CDATA[<p>Key definitions and theorems in Ch2.3 in Algorithms for Hard Problems.<br><a id="more"></a> </p><h1 id="Chapter-2-Elementary-Fundamentals"><a href="#Chapter-2-Elementary-Fundamentals" class="headerlink" title="Chapter 2: Elementary Fundamentals"></a>Chapter 2: Elementary Fundamentals</h1><h2 id="Fundamentals-of-Algorithmics"><a href="#Fundamentals-of-Algorithmics" class="headerlink" title="Fundamentals of Algorithmics"></a>Fundamentals of Algorithmics</h2><h3 id="Alphabets-Words-and-Languages"><a href="#Alphabets-Words-and-Languages" class="headerlink" title="Alphabets, Words, and Languages"></a>Alphabets, Words, and Languages</h3><ul><li><strong>Alphabet</strong>: Any non-empty, finite set is called an alphabet.   </li><li><strong>Symbol</strong>: Every element of an alphabet $\Sigma$ is called a symbol of $\Sigma$.  </li><li><strong>Word</strong>: A word over $\Sigma$ is any finite sequence of symbols of $\Sigma$.  </li><li><strong>Empty Word</strong>: The empty word $\lambda$ is the only word consisting of zero symbols.  </li><li>The set of all words over the alphabet $\Sigma$ is denoted by $\Sigma^*$.</li><li><strong>Length</strong>: The length of a word $w$ over an alphabet $\Sigma$, denoted by $|w|$, is the number of symbols in $w$ (i.e., the length of $w$ as a sequence).</li><li><p>For every word $w\in\Sigma^*$, and every symbol $a\in\Sigma$, $#_a (w)$ is the number of occurrences of the symbol $a$ in the word $w$.  </p></li><li><p>More to be added</p></li><li><p><strong>Canonical Ordering</strong>: We define the canonical ordering on $\Sigma^<em>$ as follows. For all $u, v\in\Sigma^</em>$, $u &lt; v$ if $|u| &lt; |v|$ or $|u| = |v|$, $u = xs_iu’$, and $v = xs_jv’$ for some $x,u’,v’ \in\Sigma^*$, and $i &lt; j$.  </p></li></ul><h3 id="Algorithmic-Problems"><a href="#Algorithmic-Problems" class="headerlink" title="Algorithmic Problems"></a>Algorithmic Problems</h3><ul><li><strong>Decision Problem</strong><br>A decision problem is a triple $(L, U, \Sigma)$ where $\Sigma$ is an alphabet and $L \subseteq U \subseteq \Sigma^*$. An algorithm $A$ solves (decides) the decision problem $(L, U, \Sigma)$ if, for every $x \in U$,<ol><li>$A ( x) = 1$ if $x \in L$, and</li><li>$A(x) = 0$ if $x \in U - L (x \notin L)$.</li></ol><ul><li><strong>PRIM</strong>: PRIMALITY TESTING: 质数检验</li><li><strong>EQ-POL</strong>: EQUIVALENCE PROBLEM FOR POLYNOMIALS: 多项式等价问题</li><li><strong>EQ-IBP</strong>: EQUIVALENCE PROBLEM FOR ONE-TIME-ONLY BRANCHING PROGRAMS: 分支程序等价性</li><li><strong>SAT</strong>: SATISFIABILITY PROBLEM: 合取范式是否可满足</li><li><strong>kSAT</strong>: 只有k个子式的合取范式是否可满足</li><li><strong>CLIQUE</strong>: CLIQUE PROBLEM: 给定图是否有子图为k阶完全图</li><li><strong>VCP</strong>: VERTEX COVER PROBLEM: k点覆盖问题</li><li><strong>HC</strong>: HAMILTONIAN CYCLE PROBLEM: 是否有哈密顿回路</li><li><strong>SOL-IP</strong>: EXISTENCE PROBLEMS IN LINEAR INTEGER PROGRAMMING: 整数线性规划有解问题</li><li><strong>SOL-0/1-IP</strong>: 01线性规划有解问题</li><li><strong>SOL-IP$_p$</strong>: 模p线性规划有解问题</li></ul></li><li><strong>Optimization Problem</strong> 7-tuple $U=(\Sigma_I,\Sigma_O,L,L_I,\mathcal{M}, cost, goal)$<ul><li><strong>TSP</strong>: TRAVELING SALESPERSON PROBLEM: 旅行商问题</li><li><strong>MS</strong>: MAKESPAN SCHEDULING PROBLEM: 生产计划问题</li><li><strong>MIN-VCP</strong>: 最小点覆盖问题</li><li><strong>SCP</strong>: SET COVER PROBLEM: 集合覆盖问题</li><li><strong>WEIGHT-VCP</strong>: 带权重的点覆盖问题: 点覆盖权之和最小</li><li><strong>MAX-CL</strong>: MAXIMUM CLIQUE PROBLEM: 给定图所含的最大完全子图的阶</li><li><strong>MAX-CUT</strong>, <strong>MIN-CUP</strong>: 最大割最小割</li><li><strong>SKP</strong>: SIMPLE KNAPSACK PROBLEM: 简单背包: 物品重量不超, 最多能带的重量</li><li><strong>KP</strong>: 背包问题: 物品重量不超, 最多能带的价值总和</li><li><strong>BIN-P</strong>: 装箱问题: 用最少的箱子装完物品, 容积不超箱子大小</li><li><strong>MAX-SAT</strong>:</li><li><strong>LP</strong>, <strong>IP</strong>, <strong>MAX-LINMODK</strong></li></ul></li></ul><h3 id="Complexity-Theory"><a href="#Complexity-Theory" class="headerlink" title="Complexity Theory"></a>Complexity Theory</h3><ul><li><strong>Tractable</strong>: 多项式时间可解</li><li><strong>Verifier</strong>: 检验器</li></ul>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Key definitions and theorems in Ch2.3 in Algorithms for Hard Problems.&lt;br&gt;
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Problem Solving" scheme="https://Maxwell-lyu.github.io/tags/Problem-Solving/"/>
    
      <category term="Abstract Algebra" scheme="https://Maxwell-lyu.github.io/tags/Abstract-Algebra/"/>
    
  </entry>
  
  <entry>
    <title>Problem Solving IV 09</title>
    <link href="https://Maxwell-lyu.github.io/2019/04/21/Learn-PS-20190421-PS-IV-09/"/>
    <id>https://Maxwell-lyu.github.io/2019/04/21/Learn-PS-20190421-PS-IV-09/</id>
    <published>2019-04-21T02:47:45.000Z</published>
    <updated>2019-04-21T13:42:30.000Z</updated>
    
    <content type="html"><![CDATA[<p>My note when <ruby> previewing<rt> Copying the Textbook of</rt> </ruby>  abstract algebra.<br><a id="more"></a><br><em>Form now on, only the theorems that is new to me are included in my note</em></p><h1 id="Chapter-8-Maximum-Likelihood-Decoding"><a href="#Chapter-8-Maximum-Likelihood-Decoding" class="headerlink" title="Chapter 8: Maximum-Likelihood Decoding"></a>Chapter 8: Maximum-Likelihood Decoding</h1><h2 id="Error-Detecting-and-Correcting-Codes"><a href="#Error-Detecting-and-Correcting-Codes" class="headerlink" title="Error-Detecting and Correcting Codes"></a>Error-Detecting and Correcting Codes</h2><ul><li><strong>Theorem 8.13</strong>  <blockquote><p>$d_{min}=2n+1$ means correcting $n$ or fewer errors or detecting $2n$ or fewer errors.</p></blockquote></li></ul><h2 id="Linear-Codes"><a href="#Linear-Codes" class="headerlink" title="Linear Codes"></a>Linear Codes</h2><ul><li><p><strong>Group Code</strong>  </p><blockquote><p>A code that is a subgroup of $\mathbb{Z}_2^n$  </p></blockquote></li><li><p><strong>Lemma 8.17</strong></p><blockquote><p>$w(\mathbf{x}+\mathbf{y})=d(\mathbf{x},\mathbf{y})$</p></blockquote></li><li><p><strong>Theorem 8.18</strong>  </p><blockquote><p>$d_{min}=\min\{w(\mathbf{x}):\mathbf{x}\ne 0\}$</p></blockquote></li><li><p><strong>Theorem 8.21</strong></p><blockquote><p>$H\in\mathbb{M}_{m\times n}(\mathbb{Z}_2)$, then $\mathrm{null}(H)$ is a group code</p></blockquote></li></ul><h2 id="Parity-Check-and-Generator-Matrices"><a href="#Parity-Check-and-Generator-Matrices" class="headerlink" title="Parity-Check and Generator Matrices"></a>Parity-Check and Generator Matrices</h2><ul><li><p><strong>Canonical Parity-Check Matrix</strong></p><blockquote><p>$H=(A|I_m)$, $A\in\mathbb{M}_{m\times (n-m)}(\mathbb{Z}_2)$</p></blockquote></li><li><p><strong>Generator Matrix</strong></p><blockquote><p>$G=(\frac{I_{n-m}}{A})$</p></blockquote></li><li><p><strong>Theorem 8.25</strong></p><ol><li>If $H\in\mathbb{M}_{m\times n}(\mathbb{Z}_2)$ is a canonical parity-check matrix  </li><li>then Null(H) consists of all $\mathbf{x}\in\mathbb{Z}_2$ whose first $n-m$ bits are arbitrary but whose last $m$ bits are determined by $H\mathbf{x} = 0$.   </li><li>Each of the last $m$ bits serves as an even parity check bit for some of the first $n-m$ bits.   </li><li>Hence, $H$ gives rise to an $(n, n - m)$-block code.</li></ol></li><li><p><strong>Theorem 8.26</strong></p><ol><li>Suppose that $G$ is an $n \times k$ standard generator matrix.   </li><li>Then $C = \{\mathbf{y} : G\mathbf{x} = \mathbf{y}\ for\ \mathbf{x} \in \mathbb{Z}_2^k\}$ is an $(n, k)$-block code.   </li><li>More specifically, $C$ is a group code.</li></ol></li><li><p><strong>Theorem 8.31</strong></p><blockquote><p>Then the null space of $H$ is a single error-detecting code if and only if no column of $H$ consists entirely of zeros.</p></blockquote></li><li><p><strong>Theorem 8.34</strong></p><blockquote><p>Let H be a binary matrix. The null space of $H$ is a single error-correcting code if and only if $H$ does not contain any zero columns and no two columns of $H$ are identical.</p></blockquote></li></ul><h2 id="Efficient-Decoding"><a href="#Efficient-Decoding" class="headerlink" title="Efficient Decoding"></a>Efficient Decoding</h2><ul><li><p><strong>Syndrome</strong></p><blockquote><p>$H\mathbf{x}$, where $H$ is an $n\times m$-matrix, and $\mathbf{x}\in\mathbb{Z}_2^k$</p></blockquote></li><li><p><strong>Proposition 8.36</strong></p><blockquote><p>$\mathbf{x}=\mathbf{c}+\mathbf{e}$, $\mathbf{x}$ is the code received, $\mathbf{c}$ is the codeword, $\mathbf{e}$ is the transmission error. Then $H\mathbf{x}=H\mathbf{e}$</p></blockquote></li><li><p><strong>Theorem 8.37</strong></p><ol><li>Let $H\in\mathbb{M}_{m\times n}(\mathbb{Z}_2)$ and suppose that the linear code corresponding to $H$ is single error-correcting. </li><li>Let $\mathbf{r}$ be a received $n$-tuple that was transmitted with at most one error. </li><li>If the syndrome of $\mathbf{r}$ is $0$, then no error has occurred; </li><li>Otherwise, if the syndrome of $\mathbf{r}$ is equal to some column of H, say the $i$-th column, then the error has occurred in the $i$-th bit.</li></ol></li><li><p><strong>Coset Decoding</strong></p><blockquote><p>Coset or standard decoding uses the cosets of $C$ in $\mathbb{Z}_2^n$ to implement maximum-likelihood decoding.</p></blockquote></li><li><p><strong>Proposition 8.43</strong></p><ol><li>Let $C$ be an $(n,k)$-linear code given by the matrix $H$ and suppose that $\mathbf{x}$ and $\mathbf{y}$ are in $\mathbb{Z}_2^n$ . </li><li>Then $\mathbf{x}$ and $\mathbf{y}$ are in the same coset of $C$ if and only if $H\mathbf{x} = H\mathbf{y}$. </li><li>That is, two n-tuples are in the same coset if and only if their syndromes are the same.</li></ol></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;My note when &lt;ruby&gt; previewing&lt;rt&gt; Copying the Textbook of&lt;/rt&gt; &lt;/ruby&gt;  abstract algebra.&lt;br&gt;
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Problem Solving" scheme="https://Maxwell-lyu.github.io/tags/Problem-Solving/"/>
    
      <category term="Abstract Algebra" scheme="https://Maxwell-lyu.github.io/tags/Abstract-Algebra/"/>
    
  </entry>
  
  <entry>
    <title>Probability Ch4</title>
    <link href="https://Maxwell-lyu.github.io/2019/04/20/Learn-PMS-20190420-PMS-04/"/>
    <id>https://Maxwell-lyu.github.io/2019/04/20/Learn-PMS-20190420-PMS-04/</id>
    <published>2019-04-20T02:44:15.000Z</published>
    <updated>2019-06-16T09:22:44.000Z</updated>
    
    <content type="html"><![CDATA[<p>Probability Course in 2019 Spring<br><a id="more"></a> </p><h1 id="随机变量的数字特征"><a href="#随机变量的数字特征" class="headerlink" title="随机变量的数字特征"></a>随机变量的数字特征</h1><h2 id="数学期望"><a href="#数学期望" class="headerlink" title="数学期望"></a>数学期望</h2><h3 id="数学期望的定义"><a href="#数学期望的定义" class="headerlink" title="数学期望的定义"></a>数学期望的定义</h3><ul><li><strong>定义4.1</strong>  离散型<br>设离散型随机变量$X$的分布律为$P(X=x_i)=p_i,i=1,2,\cdots$, 若级数$\sum_{i=1}^{+\infty}|x_i|p_i$收敛, 则<br>$$EX=\sum_{i=1}^{+\infty}x_ip_i$$  </li><li><strong>定义4.2</strong>  连续型<br>设连续型随机变量$X$的密度为$p(x)$, 若积分$\int_{-\infty}^{+\infty}|x|p(x)dx&lt;\infty$, 则<br>$$EX=\int_{-\infty}^{+\infty}xp(x)dx$$</li></ul><h3 id="随机变量函数的数学期望"><a href="#随机变量函数的数学期望" class="headerlink" title="随机变量函数的数学期望"></a>随机变量函数的数学期望</h3><ul><li><strong>定理4.1</strong> 随机变量函数的期望  <ol><li>离散型<br>$$EY=E[g(X)]=\sum_{k=1}^{+\infty}g(x_k)p_k$$</li><li>连续型<br>$$EY=E[g(X)]=\int_{-\infty}^{+\infty}g(x)p(x)dx$$  </li></ol></li></ul><ul><li><strong>定理4.2</strong> 随机向量函数的期望  <ol><li>离散型<br>$$EZ=E[g(X,Y)]=\sum_{i=1}^{+\infty}\sum_{j=1}^{+\infty}g(x_i,y_j)p_{ij}$$</li><li>连续型<br>$$EZ=E[g(X,Y)]=\int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty}g(x,y)p(x,y)dxdy$$</li></ol></li></ul><h3 id="数学期望的性质"><a href="#数学期望的性质" class="headerlink" title="数学期望的性质"></a>数学期望的性质</h3><ol><li>对常数$a,b$, 若$a\leq X\leq b$, 则$a\leq EX\leq b$; 特别地, 当$X\geq 0$时, $EX\geq 0$</li><li>线性性质<br>$$E(\sum_ic_iX_i)=\sum_ic_iEX_i$$</li><li>独立变量的期望<br>$$E(\prod_iX_i)=\prod_iEX_i$$</li></ol><h2 id="方差"><a href="#方差" class="headerlink" title="方差"></a>方差</h2><h3 id="方差的定义"><a href="#方差的定义" class="headerlink" title="方差的定义"></a>方差的定义</h3><ul><li><strong>定义4.4</strong> 方差<ol><li>离散型<br>$$D(X)=E(X-EX)^2=\sum_{i=1}^{+\infty}(x_k-EX)^2p_k$$</li><li>连续型<br>$$D(X)=E(X-EX)^2=\int_{-\infty}^{+\infty}(x-EX)^2p(x)dx$$</li></ol></li></ul><h3 id="方差的性质"><a href="#方差的性质" class="headerlink" title="方差的性质"></a>方差的性质</h3><ol><li>$$EX^2&lt;+\infty\quad\quad D(X)=EX^2-(EX)^2$$</li><li>被变量的分布唯一确定</li><li>$$D(X)=0\Leftrightarrow P(X=EX)=1$$</li><li>$$D(aX+b)=a^2D(X)$$</li><li>$$D(X\pm Y)=D(X)+D(Y)\pm 2E[(X-EX)(Y-EY)]$$</li><li>独立变量和的方差<br>$$D(\sum_iX_i)=\sum_iD(X_i)$$</li><li>切比雪夫不等式$\forall \epsilon&gt;0$<br>$$P(|X-EX|\geq\epsilon)\leq\frac{D(X)}{\epsilon^2}$$</li></ol><h3 id="矩"><a href="#矩" class="headerlink" title="矩"></a>矩</h3><ul><li><strong>定义4.5</strong><br>$EX^k$为$X$的 <strong>$k$阶原点矩</strong>, $E(X-EX)^k$为$X$的 <strong>$k$阶中心矩</strong><br>$EX^2=D(x)+(EX)^2$</li></ul><h2 id="协方差与相关系数"><a href="#协方差与相关系数" class="headerlink" title="协方差与相关系数"></a>协方差与相关系数</h2><ul><li><strong>定义4.6</strong> 协方差<br>$$\mathrm{cov}(X,Y)=E[(X-EX)(Y-EY)]$$<br>$$\mathrm{cov}(X,Y)=E(XY)-EX\cdot EY$$<br>$$D(\sum_{k=1}^nX_k)=\sum_{k=1}^nD(X_k)+2\sum_{1\leq i&lt;j\leq n}\mathrm{cov}(X_i,Y_j)$$</li><li><p><strong>协方差性质</strong></p><ol><li>若$X$和$Y$独立, 则$\mathrm{cov}(X,Y)=0$</li><li>$\mathrm{cov}(X,X)=D(X)$</li><li>对称性$\mathrm{cov}(X,Y)=\mathrm{cov}(Y,X)$</li><li>$\mathrm{cov}(aX+c_1,bY+c_2)=ab\mathrm{cov}(X,Y)$</li><li>$\mathrm{cov}(X_1+X_2,Y)=\mathrm{cov}(X_1,Y)+\mathrm{cov}(X_2,Y)$</li></ol></li><li><p><strong>定理4.3</strong> Cauchy-Schowarz不等式<br>$$[\mathrm{cov}(X,Y)]^2\leq D(X)D(Y)$$</p></li><li><strong>定义4.7</strong>  相关系数<br>$$\rho_{XY}=\mathrm{Corr}(X,Y)=\frac{\mathrm{cov}(X,Y)}{\sqrt{D(X)D(Y)}}$$</li><li><strong>相关系数性质</strong><ol><li>$|\rho_{XY}|\leq 1$</li><li>$|\rho_{XY}|=1\Leftrightarrow D(X)&gt;0,D(Y)&gt;0,P(cX+aY=b)=1$, 即$X$与$Y$以概率$1$具有线性关系</li></ol></li></ul><h1 id="随机变量一网打尽"><a href="#随机变量一网打尽" class="headerlink" title="随机变量一网打尽"></a>随机变量一网打尽</h1><table><thead><tr><th style="text-align:center">名称</th><th style="text-align:center">参数</th><th style="text-align:center">分布律或概率密度</th><th style="text-align:center">数学期望</th><th style="text-align:center">方差</th></tr></thead><tbody><tr><td style="text-align:center">0-1分布</td><td style="text-align:center">$B(x,p)$</td><td style="text-align:center">$P(X=k)=p^k(1-p)^{1-k}$</td><td style="text-align:center">$p$</td><td style="text-align:center">$p(1-p)$</td></tr><tr><td style="text-align:center">二项分布</td><td style="text-align:center">$B(n,p)$</td><td style="text-align:center">$P(X=k)=C_n^kp^k(1-p)^{n-k}$</td><td style="text-align:center">$np$</td><td style="text-align:center">$np(1-p)$</td></tr><tr><td style="text-align:center">负二项分布</td><td style="text-align:center">$NB(r,p)$</td><td style="text-align:center">$P(X=k)=C_{k-1}^{r-1}p^r(1-p)^{k-r}$</td><td style="text-align:center">$\frac{r}{p}$</td><td style="text-align:center">$\frac{r(1-p)}{p^2}$</td></tr><tr><td style="text-align:center">几何分布</td><td style="text-align:center">$G(p)$</td><td style="text-align:center">$P(X=k)=p(1-p)^{k-1}$</td><td style="text-align:center">$\frac{1}{p}$</td><td style="text-align:center">$\frac{(1-p)}{p^2}$</td></tr><tr><td style="text-align:center">超几何分布</td><td style="text-align:center">$H(n,M,N)$</td><td style="text-align:center">$P(X=k)=\frac{C_M^kC_{N-M}^{n-m}}{C_N^n}$</td><td style="text-align:center">$\frac{nM}{N}$</td><td style="text-align:center">$\frac{nM}{N}(1-\frac{M}{N})(\frac{N-n}{N-1})$</td></tr><tr><td style="text-align:center">泊松分布</td><td style="text-align:center">$P(\lambda)$</td><td style="text-align:center">$P(X=k)=\frac{\lambda^k}{k!}e^{-\lambda}$</td><td style="text-align:center">$\lambda$</td><td style="text-align:center">$\lambda$</td></tr><tr><td style="text-align:center">均匀分布</td><td style="text-align:center">$U[a,b]$</td><td style="text-align:center">$P_{[a,b]}\equiv\frac{1}{b-a}$</td><td style="text-align:center">$\frac{a+b}{2}$</td><td style="text-align:center">$\frac{(b-a)^2}{12}$</td></tr><tr><td style="text-align:center">正态分布</td><td style="text-align:center">$N(\mu,\sigma^2)$</td><td style="text-align:center">$p(x)=\frac{1}{\sqrt{2\pi}\sigma}e^{-\frac{(x-\mu)^2}{2\sigma^2}}$</td><td style="text-align:center">$\mu$</td><td style="text-align:center">$\sigma^2$</td></tr><tr><td style="text-align:center"><del>$\Gamma$分布</del></td><td style="text-align:center">$G(\lambda,r)$</td><td style="text-align:center">$p(x)_{x&gt;0}=\frac{\lambda^r}{\Gamma(r)}x^{r-1}e^{-\lambda x}$</td><td style="text-align:center">$\frac{r}{\lambda}$</td><td style="text-align:center">$\frac{r}{\lambda^2}$</td></tr><tr><td style="text-align:center">指数分布</td><td style="text-align:center">$e(\theta)$</td><td style="text-align:center">$p(x)_{x&gt;0}=\frac{1}{\theta}e^{-\frac{x}{\theta}}$</td><td style="text-align:center">$\theta$</td><td style="text-align:center">$\theta^2$</td></tr><tr><td style="text-align:center">柯西分布</td><td style="text-align:center">$C(\lambda, \alpha)$</td><td style="text-align:center">$p(x)=\frac{1}{\pi}\frac{1}{\lambda^2+(x-\alpha)^2}$</td><td style="text-align:center">$\nexists$</td><td style="text-align:center">$\nexists$</td></tr><tr><td style="text-align:center"></td><td style="text-align:center">$$</td><td style="text-align:center">$$</td><td style="text-align:center">$$</td><td style="text-align:center">$$</td></tr><tr><td style="text-align:center"></td><td style="text-align:center">$$</td><td style="text-align:center">$$</td><td style="text-align:center">$$</td><td style="text-align:center">$$</td></tr><tr><td style="text-align:center"></td><td style="text-align:center">$$</td><td style="text-align:center">$$</td><td style="text-align:center">$$</td><td style="text-align:center">$$</td></tr></tbody></table>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Probability Course in 2019 Spring&lt;br&gt;
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Probability and Mathematical Statistics" scheme="https://Maxwell-lyu.github.io/tags/Probability-and-Mathematical-Statistics/"/>
    
  </entry>
  
  <entry>
    <title>Problem Solving IV 08</title>
    <link href="https://Maxwell-lyu.github.io/2019/04/14/Learn-PS-20190414-PS-IV-08/"/>
    <id>https://Maxwell-lyu.github.io/2019/04/14/Learn-PS-20190414-PS-IV-08/</id>
    <published>2019-04-14T08:02:41.000Z</published>
    <updated>2019-04-14T08:57:10.000Z</updated>
    
    <content type="html"><![CDATA[<p>My note when <ruby> previewing<rt> Copying the Textbook of</rt> </ruby>  abstract algebra.<br><a id="more"></a> </p><h1 id="Chapter-7-Introduction-to-Cryptography"><a href="#Chapter-7-Introduction-to-Cryptography" class="headerlink" title="Chapter 7: Introduction to Cryptography"></a>Chapter 7: Introduction to Cryptography</h1><ul><li><strong>Plaintext</strong> (明文)  </li><li><strong>Ciphertext</strong> (密文)   </li><li><strong>Cryptosystem</strong> or <strong>Cipher</strong> (密码)  </li><li><strong>Encryption</strong> and <strong>Decryption</strong> (加密&amp;解密)  </li><li><strong>Key</strong> (密钥)  </li></ul><h2 id="Private-Key-Cryptography"><a href="#Private-Key-Cryptography" class="headerlink" title="Private Key Cryptography"></a>Private Key Cryptography</h2><ul><li><p><strong>Private Key Cryptography</strong> (单钥/私钥加密)  </p><blockquote><p>The same key is used for both encrypting and decrypting messages  </p></blockquote></li><li><p><strong>Monoalphabetic Cryptosystems</strong> (单字母密码系统/移位码)</p><blockquote><p>A character in the enciphered message represents exactly one character in the original message.</p></blockquote></li><li><p><strong>Simple Shift Code</strong> (简单移位码)</p><blockquote><p>$$f(p)=p+b\textrm{ mod } 26$$</p></blockquote></li><li><p><strong>Affine Cryptosystem</strong> (仿射密码系统)</p><blockquote><p>$\textrm{gcd}(a,26)=1$:<br>$$f(p) = ap+b\textrm{ mod } 26$$</p></blockquote></li><li><strong>Polyalphabetic Cryptosystem</strong> (多字母密码系统)<blockquote><p>A ciphertext letter could represent more than one plaintext letter<br>$\mathrm{A}\in\mathrm{M}_{2\times 2}$:<br>$$f(\vec{p})=\mathrm{A}\vec{p}+\vec{b}$$</p></blockquote></li></ul><h2 id="Public-Key-Cryptography"><a href="#Public-Key-Cryptography" class="headerlink" title="Public Key Cryptography"></a>Public Key Cryptography</h2><h3 id="The-RSA-Cryptosystem"><a href="#The-RSA-Cryptosystem" class="headerlink" title="The RSA Cryptosystem"></a>The RSA Cryptosystem</h3><ul><li><p><strong>RSA Cryptosystem</strong></p><ol><li>Find BIG primes $p$ and $q$</li><li>$n=pq$ and $m=(p-1)(q-1)=\phi(n)$</li><li>$\textrm{gcd}(E,m)=1$ for randomly selected $E$</li><li>Find $D$ using Euclidean Algorithm that $DE\equiv 1(\textrm{mod }m)$</li><li>$n$ and $E$ are public</li></ol></li><li><p><strong>RSA Encryption &amp; Decryption</strong>  </p><ol><li>Message is encoded and splitted into $x&lt;n$</li><li>Encrypted message is $y=x^E$</li><li>Decrypted message is $x=y^D\textrm{ mod }n$</li></ol></li></ul><h3 id="Message-Verification"><a href="#Message-Verification" class="headerlink" title="Message Verification"></a>Message Verification</h3><ul><li><strong>How it work</strong>  <ol><li>Alice: $(n,E,D)$  </li><li>Bob: $(n’,E’,D’)$  </li><li>$x’=x^{D’}\textrm{ mod }n’$<ul><li>A message that anyone can decrypt by encrypting it with $E’$    </li><li>Can only be generated by Bob   </li></ul></li><li>$y’=x’^{E}\textrm{ mod }n$<ul><li>A message only Alice can decrypt</li><li>The message to be sent to Alice</li><li>Alice  can read it with Bob’s Public key, and be sure of that it is sent by Bob</li></ul></li></ol></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;My note when &lt;ruby&gt; previewing&lt;rt&gt; Copying the Textbook of&lt;/rt&gt; &lt;/ruby&gt;  abstract algebra.&lt;br&gt;
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Problem Solving" scheme="https://Maxwell-lyu.github.io/tags/Problem-Solving/"/>
    
      <category term="Abstract Algebra" scheme="https://Maxwell-lyu.github.io/tags/Abstract-Algebra/"/>
    
  </entry>
  
  <entry>
    <title>Anki</title>
    <link href="https://Maxwell-lyu.github.io/2019/03/30/Tech-20190330-Anki/"/>
    <id>https://Maxwell-lyu.github.io/2019/03/30/Tech-20190330-Anki/</id>
    <published>2019-03-30T09:46:58.000Z</published>
    <updated>2019-04-01T12:20:46.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="Anki背诵和记忆任何东西"><a href="#Anki背诵和记忆任何东西" class="headerlink" title="Anki背诵和记忆任何东西"></a>Anki背诵和记忆任何东西</h1><h2 id="官方网站"><a href="#官方网站" class="headerlink" title="官方网站"></a>官方网站</h2><p>下载地址在官网，有Windows，Mac，Linux，iPhone/Android等版本<br><a href="http://www.ankichina.net/" target="_blank" rel="noopener">中文官网</a><br><a href="https://apps.ankiweb.net/index.html" target="_blank" rel="noopener">英文官网</a>  </p><h2 id="Anki是什么"><a href="#Anki是什么" class="headerlink" title="Anki是什么"></a>Anki是什么</h2><figure class="image-bubble">                <div class="img-lightbox">                    <div class="overlay"></div>                    <img src="01.png" alt="暗杀教室" title>                </div>                <div class="image-caption">暗杀教室</div>            </figure><p>Anki是日语“<ruby>暗<rt>あん</rt></ruby><ruby>記<rt>き</rt></ruby>”的罗马音，意为背诵，是目前世界最流行的记忆软件之一。这个软件在形式上类似“百词斩”等卡片式背单词软件，但功能却多出一个数量级。</p><h2 id="为什么是Anki"><a href="#为什么是Anki" class="headerlink" title="为什么是Anki"></a>为什么是Anki</h2><p>我在使用Anki的时候，对这一软件的以下功能有所尝试：  </p><ul><li>跨平台<br>Anki支持Windows（Win32和UWP都有），Linux，Mac，IOS，Android，而且这是一个开源软件，如果有必要，你甚至可以开发编译自己的版本</li><li>同步<br>借助AnkiWeb，跨设备同步记忆卡片组和学习进度。Github上还有搭建 自己的同步服务器的开源项目，B站也有相应的视频教程。此外，OneDrive也是可选的同步方式</li><li>灵活的卡片形式  <ol><li>普通的询问式卡片，选择题，填空题</li><li>支持LaTex(PC端可编辑和渲染源码，移动端仅支持查看图片缓存)</li><li>允许插入图片</li><li>允许插入音频甚至是视频（较大的媒体文件将会耗费大量时间同步）</li><li>允许打包分享卡片，网络上可以购买到现成的影音英语学习卡组</li></ol></li><li>自动化<br>很多优秀的脚本可以让你一键生成卡组，例如为英文单词列表自动查询字典，并匹配相应的中文释义，例句和发音，支持百度翻译，灵格斯自定义词典文件等<br>英语读写课给的英文单词表，一个脚本即可匹配牛津词典的释义和例句，3分钟不到就可以开始学习</li><li>科学的记忆<br>符合记忆规律，根据错误次数自动计算最合适的复习时间点，从几分钟到数年之后不等（最短的小于一分钟，我见过最长的是2年后）</li></ul><h2 id="怎么用？RTFM！"><a href="#怎么用？RTFM！" class="headerlink" title="怎么用？RTFM！"></a>怎么用？RTFM！</h2><p>这个软件提供了及其详细的手册！大家自己看吧。入门请不要使用移动版（iPhone/Android），因为功能不全<br><a href="http://www.ankichina.net/Index/ankishouce" target="_blank" rel="noopener">中文手册(翻译中)</a><br><a href="https://apps.an kiweb.net/docs/manual.html" target="_blank" rel="noopener">英文手册</a>    </p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;Anki背诵和记忆任何东西&quot;&gt;&lt;a href=&quot;#Anki背诵和记忆任何东西&quot; class=&quot;headerlink&quot; title=&quot;Anki背诵和记忆任何东西&quot;&gt;&lt;/a&gt;Anki背诵和记忆任何东西&lt;/h1&gt;&lt;h2 id=&quot;官方网站&quot;&gt;&lt;a href=&quot;#官方网站&quot;
      
    
    </summary>
    
      <category term="Technique" scheme="https://Maxwell-lyu.github.io/categories/Technique/"/>
    
    
      <category term="Utility" scheme="https://Maxwell-lyu.github.io/tags/Utility/"/>
    
  </entry>
  
  <entry>
    <title>PanDownload</title>
    <link href="https://Maxwell-lyu.github.io/2019/03/30/Tech-20190330-PanDownload/"/>
    <id>https://Maxwell-lyu.github.io/2019/03/30/Tech-20190330-PanDownload/</id>
    <published>2019-03-30T08:45:52.000Z</published>
    <updated>2019-04-01T12:20:36.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="PanDownload-百度云提速下载工具"><a href="#PanDownload-百度云提速下载工具" class="headerlink" title="PanDownload 百度云提速下载工具"></a>PanDownload 百度云提速下载工具</h1><h2 id="下载地址"><a href="#下载地址" class="headerlink" title="下载地址"></a>下载地址</h2><p><a href="http://pandownload.com/" target="_blank" rel="noopener">官方网站</a><br>网站亦包含详细使用说明，不过主要是针对旧版本，以下使用说明主要面向新版本变化较大的功能进行</p><h2 id="为什么是PanDownload"><a href="#为什么是PanDownload" class="headerlink" title="为什么是PanDownload"></a>为什么是PanDownload</h2><ul><li><strong>多线程</strong><br>百度网盘的限速机制大致为80kB/s~100kB/s每线程，PanDownload最大支持128线程下载  </li><li><strong>自动更新脚本</strong><br>百度网盘并非直链下载，需要解析，解析脚本时常需要更新。PanDownload提供自动更新脚本的功能  </li><li><strong>支持多账号登陆</strong><br>我个人使用过多种百度盘第三方客户端，有一些客户端无法下载自己网盘里的文件，需要每个文件创建分享链接才能下，而支持账号登陆，批量下载自己网盘文件的客户端更是难得  </li><li><strong>附加功能多</strong><br>我知道你们都是冲着新番资源来的，怎么用看下文  </li></ul><h2 id="使用说明"><a href="#使用说明" class="headerlink" title="使用说明"></a>使用说明</h2><h3 id="标签页"><a href="#标签页" class="headerlink" title="标签页"></a>标签页</h3><p>新版本加入的多标签功能，允许一个PanDownload客户端登陆多个网盘账号，或是打开多个连接。由于百度网盘单个账号的容量偏小，多个账号可以让你存更多资♂源。已登录的账号会在每次开启时自动打开一个标签页，显示此账号下的文件。<br>新建标签页，请点击标签页栏的<code>+</code>号<br><img src="01.png" alt>  </p><h3 id="新番下载"><a href="#新番下载" class="headerlink" title="新番下载"></a>新番下载</h3><p><code>更多功能-新番下载</code><br>按照更新日分类，正在播出的新番基本都有，比B站，爱奇艺的会员慢<code>10分钟</code>左右<br>选择相应的番剧，会打开一个分享目录，右键你想要的那一集，点击下载即可享用<br>如果显示出来源为<code>AGE动漫</code>，却没有下载链接显示，多数情况下是来源站正在维护或GG了，请尝试直接前往来源站（ping一下也行）：<br><a href="http://donghua.agefans.com/" target="_blank" rel="noopener">AGE动漫</a><br>PS：我记得以前还有嘀哩嘀哩的来源的，好像D站被B站干了，就剩AGE独苗一根<br>PPS：这里的资源大多数是720P AVC（x264）格式，动作一多就是马赛克，对画质有要求的还是老老实实大会员吧（上次看刀剑神域一段UGO变剑，搞得满屏马赛克，最高祭司都不用打码了  </p><h3 id="资源搜索"><a href="#资源搜索" class="headerlink" title="资源搜索"></a>资源搜索</h3><p><code>更多功能-资源搜索</code><br>绝对的找资源神器，大量的百度盘资源随你选，除了黄赌毒基本上都能搜到  </p><h2 id="老规矩"><a href="#老规矩" class="headerlink" title="老规矩"></a>老规矩</h2><p>所有下载的资源建议<ruby>24小时内<rt>啊呀，谁知道呢</rt></ruby>删除，资源本身与软件作者和本介绍作者无关<br>看番还是建议正版，除了画质，其实<ruby>弹幕<rt>养肥再看</rt></ruby>才是本体<br>我不保证你用了就会快到吃满带宽，因为我也不能<ruby>钦点<rt>打包票</rt></ruby>的<br>，但是你问我<ruby>支不支持<rt>有没有可能性</rt></ruby>那我肯定是支持的   </p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;PanDownload-百度云提速下载工具&quot;&gt;&lt;a href=&quot;#PanDownload-百度云提速下载工具&quot; class=&quot;headerlink&quot; title=&quot;PanDownload 百度云提速下载工具&quot;&gt;&lt;/a&gt;PanDownload 百度云提速下载工具&lt;/
      
    
    </summary>
    
      <category term="Technique" scheme="https://Maxwell-lyu.github.io/categories/Technique/"/>
    
    
      <category term="Utility" scheme="https://Maxwell-lyu.github.io/tags/Utility/"/>
    
  </entry>
  
  <entry>
    <title>Probability Ch3</title>
    <link href="https://Maxwell-lyu.github.io/2019/03/21/Learn-PMS-20190321-PMS-03/"/>
    <id>https://Maxwell-lyu.github.io/2019/03/21/Learn-PMS-20190321-PMS-03/</id>
    <published>2019-03-21T00:13:03.000Z</published>
    <updated>2019-06-16T09:17:02.000Z</updated>
    
    <content type="html"><![CDATA[<p>Probability Course in 2019 Spring<br><a id="more"></a> </p><h1 id="随机向量及其分布"><a href="#随机向量及其分布" class="headerlink" title="随机向量及其分布"></a>随机向量及其分布</h1><ul><li><strong>定义3.1</strong><br>若随机变量$X_1,X_2,\cdots, X_n$定义在同一个样本空间$\varOmega$上, 则称$(X_1,X_2.\cdots,X_n)$为一个$n$<strong>维随机向量</strong>或$n$<strong>维随机变量</strong>  </li></ul><h2 id="二位随机向量及其分布函数"><a href="#二位随机向量及其分布函数" class="headerlink" title="二位随机向量及其分布函数"></a>二位随机向量及其分布函数</h2><h3 id="二维离散型随机向量"><a href="#二维离散型随机向量" class="headerlink" title="二维离散型随机向量"></a>二维离散型随机向量</h3><ul><li><strong>定义3.2</strong><br>若二位随机向量$(X,Y)$的每个分量都是离散型的随机变量, 则称$(X,Y)$为一个<strong>二维离散型随机向量</strong></li><li><p><strong>定义3.3</strong><br>设随机向量$(X,Y)$的所有可能取值为$(x_i,y_i)$, $i,j=1,2,\cdots$, 假设当$i\ne k, j\ne l$时, $x_i\ne x_k, y_j\ne y_l$, 则$P(X=x_i, Y=y_i)=p_{ij}$, $i=1,2,\cdots$称为随机向量$(X,Y)$的<strong>联合分布率</strong>或$X$和$Y$的<strong>联合概率分布</strong><br>由分布律的定义可以得到联合分布率$\{p_{ij}\}$具有下列性质:  </p><ol><li>$p_{ij}\geq 0, i,j=1,2,\cdots$</li><li>$\sum_{i=1}^{+\infty}\sum_{j=1}^{+\infty}p_{ij}=1$</li></ol></li><li><p><strong>多项分布</strong><br>在$n$次独立重复实验中, 已知每次试验由三种不同的可能结果$A_1,A_2,A_3$, 且$P(A_i)=p_i$, $i=1,2,3$, $p_1+p_2+p_3=1$. 若以$X_1, X_2$分别记结果$A_1,A_2,A_3$出现的次数, 则任意的$k_i\in[0,n]\cap\mathbb{N}$, $i=1,2$<br>$$P(X_1=k_1,X_2=k_2)=\frac{n!}{k_1!k_2!(n-k_1-k_2)!}p_1^{k_1}p_2^{k_2}(1-p_1-p_2)^{n-k_1-k_2}$$<br>记为<br>$$(X_1,X_2)\sim M(n;p_1,p_2,p_3)$$  </p></li><li><p><strong>多元超几何分布</strong><br>设一个袋中分别标有1, 2或3的球, 设$i$号球有$N_i$只, $i=1,2,3$, 且$N_1+N_2+N_3=N$. 从中不放回地随机摸出$n$只, $n\leq N$, 若以$X_1$, $X_2$分别记1, 2号球的出现次数, 则$(X_1,X_2)$的联合概率分布为<br>$$P(X_1=n_1,X_2=n_2)=\frac{C_{N_1}^{n_1}C_{N_2}^{n_2}C_{N_3}^{n_3}}{C_N^n}$$  </p></li><li><p><strong>定义3.4</strong><br>对任意的实数$x,y$, 称二元函数$F(x,y)=P(X\leq x, Y\leq y)$为随机向量$(X,Y)$的 <strong>(联合)分布函数</strong>, 记为$(X,Y)\sim F(x,y)$<br>若$(X,Y)$的分布律为$\{p_{ij}\}$, 则它的分布函数可由它的分布律表示:<br>$$F(x,y)=\sum_{x_i\leq x, y_i\leq y}p_{ij}$$  </p></li><li><p><strong>边缘分布函数</strong><br>$$F_X(x)=P(X\leq x)=P(X\leq x, y\leq +\infty)=\lim_{y\to+\infty}P(X\leq x,Y\leq y)\eqqcolon F(x,+\infty)$$<br>$$F_Y(y)=F(+\infty, y)=\lim_{x\to +\infty}F(x,y)$$  </p></li></ul><h3 id="二维连续型随机向量"><a href="#二维连续型随机向量" class="headerlink" title="二维连续型随机向量"></a>二维连续型随机向量</h3><ul><li><p><strong>定义3.5</strong><br>设二维随机向量$(X,Y)$的分布函数为$F(x,y)$, 若存在非负可积二元函数$p(X,Y)$, 对任意的$x,y\in \mathbb{R}$, 有<br>$$F(x,y)=\int_{-\infty}^x\int_{-\infty}^{y}p(u,v)dudv$$<br>则称$(X,Y)$为<strong>二维连续型随机向量</strong>, 而称$p(X,Y)$为$(X,Y)$的一个<strong>联合概率密度函数</strong>, 简称为<strong>联合密度</strong><br>由分布律的定义可以得到联合概率密度函数$\{p(x,y)\}$具有下列性质:  </p><ol><li>$p(x,y)\geq 0$</li><li>$\int_{-\infty}^{+\infty}\int_{-\infty}^{+\infty}p(x,y)dxdy=1$</li></ol></li><li><p><strong>边缘密度函数</strong><br>$$p_X(x)=\int_{-\infty}^{+\infty}p(x,v)dv$$<br>$$p_Y(y)=\int_{-\infty}^{+\infty}p(v,y)dv$$</p></li></ul><h3 id="联合密度函数"><a href="#联合密度函数" class="headerlink" title="联合密度函数"></a>联合密度函数</h3><ul><li><strong>略</strong></li></ul><h2 id="条件分布"><a href="#条件分布" class="headerlink" title="条件分布"></a>条件分布</h2><h3 id="离散型随机向量的条件概率分布"><a href="#离散型随机向量的条件概率分布" class="headerlink" title="离散型随机向量的条件概率分布"></a>离散型随机向量的条件概率分布</h3><ul><li><p><strong>在$X=x_i$下, $Y$的条件分布律</strong><br>$$P(Y=y_i|X=x_i)=\frac{P(Y=y_i,X=x_i)}{P(X=x_i)}=\frac{p_{ij}}{p_i}$$</p></li><li><p><strong>$Y$的边际分布</strong><br>$$P(Y=y_i)=\sum_{i=1}^{+\infty}P(Y=y_i,X=x_i)=\sum_{i=1}^{+\infty}P(Y=y_i|X=x_i)P(X=x_i)$$</p></li></ul><h3 id="连续型随机变量的条件概率"><a href="#连续型随机变量的条件概率" class="headerlink" title="连续型随机变量的条件概率"></a>连续型随机变量的条件概率</h3><ul><li><p><strong>在$X=x$的条件下, $Y$的条件分布函数</strong><br>$$F_{Y|X=x}(y)=P(Y\leq y|X=x)=\int_{-\infty}^{y}\frac{p(x,v)}{p_X(x)}dv$$</p></li><li><p><strong>在$X=x$的条件下, $Y$的条件密度函数</strong><br>$$p_{Y|X=x}(y)=\frac{p(x,v)}{p_X(x)}$$</p></li></ul><h2 id="随机变量的独立性"><a href="#随机变量的独立性" class="headerlink" title="随机变量的独立性"></a>随机变量的独立性</h2><ul><li><p><strong>定义3.9</strong><br>设$X$和$Y$是两个离散型随机变量, 若对任意的一组$(x_i,y_j)$,<br>$$P(X=x_i,Y=y_j)=P(X=x_i)P(Y=y_j)$$<br>即对任意的$i,j$, $p_{ij}=p_i\cdot p_j$, 则称<strong>随机变量$X$和$Y$相互独立</strong></p></li><li><p><strong>定义3.10</strong><br>设$X_1,X_2,\cdots,X_n$都是离散型随机变量, 若对任意的$x_1,x_2,\cdots x_n$,<br>$$P(X=x_1,X=x_2,\cdots,X=x_n)=P(X=x_1)P(X=x_2)\cdots P(X=x_n)$$<br>即对任意的$i,j$, $p_{ij}=p_i\cdot p_j$, 则称<strong>随机变量$X$和$Y$相互独立</strong></p></li><li><p><strong>定理3.1</strong><br>设$X_1,X_2,\cdots,X_n$相互独立, 若函数$Y_1=g_1(X_1,X_2,\cdots,X_m)$和$Y_2=g_2(X_{m+1},X_{m+2},\cdots,X_n)$仍然是随机变量, 则$Y_1$和$Y_2$独立</p></li><li><p><strong>定义3.11</strong><br>设$n$维随机向量$(X_1,X_2,\cdots,X_n)$的联合密度函数为$p(x_1,x_2,\cdots,x_n)$, 而$X_i$的边缘密度函数为$p_i(x_i)$. 如果<br>$$p(x_1,\cdots,x_n)=p_1(x_1)p_2(x_2)\cdots p_n(x_n)$$<br>就称随机变量$X_1,X_2,\cdots,X_n$<strong>相互独立</strong>, 或者简称<strong>独立</strong></p></li><li><p><strong>定理3.2</strong><br>独立的充要条件:<br>$$F(x,y)=F_X(x)F_Y(y)$$</p></li><li><p><strong>定理3.3</strong><br>联合密度函数为$f(x,y)$时, 二者独立的充要条件:<br>$$\exists g_1,g_2,\quad f(x,y)=g_1(x)g_2(y)$$</p></li></ul><h2 id="二维随机向量函数的分布"><a href="#二维随机向量函数的分布" class="headerlink" title="二维随机向量函数的分布"></a>二维随机向量函数的分布</h2><h3 id="二维离散型随机向量函数的分布"><a href="#二维离散型随机向量函数的分布" class="headerlink" title="二维离散型随机向量函数的分布"></a>二维离散型随机向量函数的分布</h3><ul><li><strong>略</strong></li></ul><h3 id="二维连续性随机变量函数的分布"><a href="#二维连续性随机变量函数的分布" class="headerlink" title="二维连续性随机变量函数的分布"></a>二维连续性随机变量函数的分布</h3><ol><li><p>和的分布$Z=X+Y$<br>$$p_Z(z)=\int_{-\infty}^{+\infty}p(x,z-x)dx$$</p></li><li><p>商的分布$Z+X/Y$<br>$$p_Z(z)=\int_{-\infty}^{+\infty}|y|p(zy,y)dy$$</p></li><li><p>最大(小)值的分布$M=\max, N=\min$<br>$$F_M(z)=F_X(z)F_Y(z)$$<br>$$F_N(z)=1-(1-F_X(z))(1-F_Y(z))$$<br>求导可得密度函数</p></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Probability Course in 2019 Spring&lt;br&gt;
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Probability and Mathematical Statistics" scheme="https://Maxwell-lyu.github.io/tags/Probability-and-Mathematical-Statistics/"/>
    
  </entry>
  
  <entry>
    <title>Problem Solving IV 03</title>
    <link href="https://Maxwell-lyu.github.io/2019/03/12/Learn-PS-20190312-PS-IV-03/"/>
    <id>https://Maxwell-lyu.github.io/2019/03/12/Learn-PS-20190312-PS-IV-03/</id>
    <published>2019-03-12T05:47:35.000Z</published>
    <updated>2019-10-13T12:48:34.563Z</updated>
    
    <content type="html"><![CDATA[<h1 id="Chapter-9-Isomorphisms"><a href="#Chapter-9-Isomorphisms" class="headerlink" title="Chapter 9: Isomorphisms"></a>Chapter 9: Isomorphisms</h1><h2 id="Definitions-and-Examples"><a href="#Definitions-and-Examples" class="headerlink" title="Definitions and Examples"></a>Definitions and Examples</h2><ul><li><p><strong>Isomorphic</strong> (同构)</p><blockquote><p>Two groups $(G, \cdot)$ and $(H, \circ)$ are isomorphic if there exists a one-to-one and onto map $\phi: G\to H$ such that the group operation is preserved; that is,<br>$$\phi(a \cdot b) = \phi(a) \circ \phi(b)$$<br>for all $a$ and $b$ in $G$. If $G$ is isomorphic to $H$, we write $G\cong H$.   </p></blockquote></li><li><p><strong>Isomorphism</strong></p><blockquote><p>The map $\phi$ is called an isomorphism.  </p></blockquote></li><li><p><strong>Theorem 9.6</strong>  </p><blockquote><p>Let $\phi: G\to H$ be an isomorphism of two groups. Then the following statements are true.  </p><ol><li>$\phi^{-1}: H\to G$ is an isomorphism  </li><li>$|G|=|H|$  </li><li>If $G$ is abelian, then $H$ is abelian</li><li>If $G$ is cyclic, then $H$ is cyclic</li><li>If $G$ is a subgroup of order $n$, then $H$ is a subgroup of order $n$</li></ol></blockquote></li><li><p><strong>Theorem 9.7</strong>  </p><blockquote><p>All cyclic groups of infinite order are isomorphic to $\mathbb{Z}$</p></blockquote></li><li><p><strong>Theorem 9.8</strong>  </p><blockquote><p>If $G$ is a cyclic group of order $n$, then G is isomorphic to $\mathbb{Z}_n$.</p></blockquote></li><li><p><strong>Corollary 9.9</strong>  </p><blockquote><p>If $G$ is a group of order $p$, where $p$ is a prime number, then $G$ is isomorphic to $\mathbb{Z}_p$</p></blockquote></li><li><p><strong>Theorem 9.10</strong>  </p><blockquote><p>The isomorphism of groups determines an equivalence relation on the class of all groups.<br>Classifying all groups <strong>up to isomorphism</strong>; two groups are the same if they are isomorphic.  </p></blockquote></li></ul><h3 id="Cayley’s-Theorem"><a href="#Cayley’s-Theorem" class="headerlink" title="Cayley’s Theorem"></a>Cayley’s Theorem</h3><ul><li><p><strong>Theorem 9.12</strong> Cayley   </p><blockquote><p>Every group is isomorphic to a group of permutations.</p></blockquote></li><li><p><strong>Left Regular Representation</strong> of $G$.  </p><blockquote><p>The isomorphism $g\to \lambda_g$<br>where $g\in G$, $\lambda_g(a)=ga$, $\bar{G}=\{\lambda_g:g\in G\}$ is the permutation group that is isomorphic with $G$</p></blockquote></li></ul><h2 id="Direct-Products"><a href="#Direct-Products" class="headerlink" title="Direct Products"></a>Direct Products</h2><h3 id="External-Direct-Products"><a href="#External-Direct-Products" class="headerlink" title="External Direct Products"></a>External Direct Products</h3><ul><li><p><strong>Proposition 9.13</strong>  </p><blockquote><p>Let $G$ and $H$ be groups. The set $G\times H$ is a group under the operation $(g_1, h_1)(g_2, h_2) = (g_1g_2, h_1h_2)$ where $g1, g2 \in G$ and $h_1, h_2 \in H$.</p></blockquote></li><li><p><strong>External Direct Product</strong> of $G$ and $H$ (外直积) </p><blockquote><p>The group $G\times H$</p></blockquote></li><li><p><strong>Theorem 9.17</strong>   </p><blockquote><p>Let $(g, h) \in G\times H$. If $g$ and $h$ have finite orders $r$ and $s$ respectively, then the order of $(g, h)$ in $G\times H$ is the least common multiple of $r$ and $s$. </p></blockquote></li><li><p><strong>Corollary 9.18</strong>  </p><blockquote><p>Let $(g_1, . . . , g_n) \in \prod G_i$. If $g_i$ has finite order $r_i$ in $G_i$, then the order of $G_i$ is the least common multiple of $r_1,\cdots, r_n$.</p></blockquote></li><li><p><strong>Theorem 9.21</strong>  </p><blockquote><p>The group $\mathbb{Z}_m\times \mathbb{Z}<em>n$ is isomorphic to $\mathbb{Z}</em>{mn}$ if and only if $gcd(m,n) = 1$.</p></blockquote></li><li><p><strong>Corollary 9.22</strong>  </p><blockquote><p>Let $n_1, \cdots,n_k$ be positive integers. Then<br>$$\prod_{i=1}^k\mathbb{Z}_{n_i}\cong\mathbb{Z}_{n_1\cdots n_k}$$<br>if and only if $gcd(n_i,n_j)=1$ for $i\ne j$</p></blockquote></li><li><p><strong>Corollary 9.23</strong></p><blockquote><p>If<br>$$m=p_1^{e_1}\cdots p_k^{e_k}$$<br>where the $p_i$s are distinct primes, then<br>$$\mathbb{Z}<em>m\cong\mathbb{Z}</em>{p_1^{e_1}}\times\cdots\times\mathbb{Z}_{p_k^{e_k}}$$</p></blockquote></li></ul><h3 id="Internal-Direct-Products"><a href="#Internal-Direct-Products" class="headerlink" title="Internal Direct Products"></a>Internal Direct Products</h3><ul><li><p><strong>Internal Direct Product</strong> (内直积)</p><blockquote><p>Let $G$ be a group with subgroups $H$ and $K$ satisfying the following conditions.</p><ol><li>$G=HK=\{hk:h\in H,k\in K\}$</li><li>$H\cap K={e}$</li><li>$hk=kh$ for all $k\in K$ and $h\in H$  </li></ol><p>Then G is the internal direct product of H and K.</p></blockquote></li><li><p><strong>Theorem 9.27</strong>  </p><blockquote><p>Let $G$ be the internal direct product of subgroups $H$ and $K$. Then $G$ is isomorphic to $H\times K$.</p></blockquote></li><li><p><strong>Theorem 9.29</strong>  </p><blockquote><p>Let $G$ be the internal direct product of subgroups $H_i$, where $i = 1, 2, \cdots, n$. Then $G$ is isomorphic to $\prod_iH_i$</p></blockquote></li></ul><h1 id="Chapter-10-Normal-Subgroups-and-Factor-Groups"><a href="#Chapter-10-Normal-Subgroups-and-Factor-Groups" class="headerlink" title="Chapter 10: Normal Subgroups and Factor Groups"></a>Chapter 10: Normal Subgroups and Factor Groups</h1><h2 id="Factor-Groups-and-Normal-Subgroups"><a href="#Factor-Groups-and-Normal-Subgroups" class="headerlink" title="Factor Groups and Normal Subgroups"></a>Factor Groups and Normal Subgroups</h2><h3 id="Normal-Subgroups"><a href="#Normal-Subgroups" class="headerlink" title="Normal Subgroups"></a>Normal Subgroups</h3><ul><li><p><strong>Normal Subgroup</strong> of a group $G$ (正规子群)</p><blockquote><p>A subgroup $H$ of a group $G$ is normal in $G$ if $gH = Hg$ for all $g \in G$.<br>A normal subgroup of a group $G$ is one in which the right and left cosets are precisely the same.</p></blockquote></li><li><p><strong>Theorem 10.3</strong></p><blockquote><p>Let $G$ be a group and $N$ be a subgroup of $G$. Then the following statements are equivalent.</p><ol><li>The subgroup $N$ is normal in $G$</li><li>For all $g\in G$, $gNg^{-1}\subset N$</li><li>For all $g\in G$, $gNg^{-1}=N$</li></ol></blockquote></li></ul><h3 id="Factor-Groups"><a href="#Factor-Groups" class="headerlink" title="Factor Groups"></a>Factor Groups</h3><ul><li><p><strong>Factor Group</strong> (因子群) or <strong>Quotient Group</strong> (商群) of $G$</p><blockquote><p>If $N$ is a normal subgroup of a group $G$, then the cosets of $N$ in $G$ form a group $G/N$ under the operation $(aN)(bN) = abN$.<br>This group is called the factor or quotient group of $G$ and $N$.</p></blockquote></li><li><p><strong>Theorem 10.4</strong>  </p><blockquote><p>Let $N$ be a normal subgroup of a group $G$. The cosets of $N$ in $G$ form a group $G/N$ of order $[G : N]$.</p></blockquote></li></ul><h2 id="The-Simplicity-of-the-Alternating-Group"><a href="#The-Simplicity-of-the-Alternating-Group" class="headerlink" title="The Simplicity of the Alternating Group"></a>The Simplicity of the Alternating Group</h2><ul><li><p><strong>Simple Groups</strong> (简单群)</p><blockquote><p>Groups with no nontrivial normal subgroups.</p></blockquote></li><li><p><strong>Lemma 10.8</strong>  </p><blockquote><p>The alternating group $A_n$ is generated by 3-cycles for $n \geq 3$.</p></blockquote></li><li><p><strong>Lemma 10.9</strong>  </p><blockquote><p>Let $N$ be a normal subgroup of $A_n$, where n ≥ 3. If $N$ contains a 3-cycle, then $N = A_n$</p></blockquote></li><li><p><strong>Lemma 10.10</strong>  </p><blockquote><p>For $n \geq 5$, every nontrivial normal subgroup $N$ of $A_n$ contains a 3-cycle.</p></blockquote></li><li><p><strong>Theorem 10.11</strong>  </p><blockquote><p>The alternating group, $A_n$, is simple for $n \geq 5$.</p></blockquote></li></ul><h1 id="Chapter-11-Homomorphisms"><a href="#Chapter-11-Homomorphisms" class="headerlink" title="Chapter 11: Homomorphisms"></a>Chapter 11: Homomorphisms</h1><h2 id="Group-Homomorphisms"><a href="#Group-Homomorphisms" class="headerlink" title="Group Homomorphisms"></a>Group Homomorphisms</h2><ul><li><p><strong>Homomorphism</strong> (同态) between groups $(G, \cdot)$ and $(H, \circ)$</p><blockquote><p>A map $\phi: G\to H$ such that $\phi(g_1\cdot g_2)=\phi(g_1)\circ\phi(g_2)$ for $g_1, g_2 \in G$. </p></blockquote></li><li><p><strong>Homomorphic Image</strong> of $\phi$</p><blockquote><p>The range of $\phi$ in $H$.</p></blockquote></li><li><p><strong>Proposition 11.4</strong></p><blockquote><p>Let $\phi: G_1\to G_2$ be a homomorphism of groups.   </p><ol><li>If $e$ is the identity of $G_1$, then $\phi(e)$ is the identity of $G_2$;  </li><li>For any element $g \in G_1$, $\phi(g^{-1}) = [\phi(g)]^{−1}$;  </li><li>If $H_1$ is a subgroup of $G_1$, then $\phi(H_1)$ is a subgroup of $G_2$;</li><li>If $H_2$ is a subgroup of $G_2$, then $\phi^{-1}(H_2) = \{g \in G_1 : \phi(g) \in H_2\}$ is a subgroup of $G_1$.<br>Furthermore, if $H_2$ is normal in $G_2$, then $\phi^{-1}(H_2)$ is normal in $G_1$.</li></ol></blockquote></li><li><p><strong>Theorem 11.5</strong>  </p><blockquote><p>Let $\phi: G\to H$ be a group homomorphism. Then the kernel of $\phi$ is a normal subgroup of $G$.</p></blockquote></li></ul><h2 id="The-Isomorphism-Theorems"><a href="#The-Isomorphism-Theorems" class="headerlink" title="The Isomorphism Theorems"></a>The Isomorphism Theorems</h2><ul><li><p>The <strong>Natural</strong> or <strong>Canonical Homomorphism</strong></p><blockquote><p>Let $H$ be a normal subgroup of $G$. $\phi:G\to G/H$, $\phi(g)=gH$<br>is the natural or canonical homomorphism.</p></blockquote></li><li><p><strong>Theorem 11.10</strong> First Isomorphism Theorem  </p><blockquote><p>If $\psi : G \to H$ is a group homomorphism with $K = \textrm{ker} \psi$, then $K$ is normal in $G$. Let $\phi : G \to G/K$ be the canonical homomorphism. Then there exists a unique isomorphism $\eta : G/K \to \psi(G)$ such that $\psi = \eta\phi$.</p></blockquote></li><li><p><strong>Theorem 11.12</strong> Second Isomorphism Theorem</p><blockquote><p>Let $H$ be a subgroup of a group $G$ (not necessarily normal in $G$) and $N$ a normal subgroup of $G$. Then $HN$ is a subgroup of $G$, $H \cap N$ is a normal subgroup of $H$, and<br>$$H/H \cap N \cong HN/N$$</p></blockquote></li><li><p><strong>Theorem 11.13</strong> Correspondence Theorem</p><blockquote><p>Let $N$ be a normal subgroup of a group $G$. Then $H \mapsto H/N$  is a one-to-one correspondence between the set of subgroups $H$ containing $N$ and the set of subgroups of $G/N$.<br>Furthermore, the normal subgroups of $G$ containing $N$ correspond to normal subgroups of $G/N$.</p></blockquote></li><li><p><strong>Theorem 11.14</strong> Third Isomorphism Theorem</p><blockquote><p>Let $G$ be a group and $N$ and $H$ be normal subgroups of $G$ with $N \subset H$. Then<br>$$G/H\cong\frac{G/N}{H/N}$$</p></blockquote></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;Chapter-9-Isomorphisms&quot;&gt;&lt;a href=&quot;#Chapter-9-Isomorphisms&quot; class=&quot;headerlink&quot; title=&quot;Chapter 9: Isomorphisms&quot;&gt;&lt;/a&gt;Chapter 9: Isomorph
      
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Problem Solving" scheme="https://Maxwell-lyu.github.io/tags/Problem-Solving/"/>
    
      <category term="Abstract Algebra" scheme="https://Maxwell-lyu.github.io/tags/Abstract-Algebra/"/>
    
  </entry>
  
  <entry>
    <title>Problem Solving IV 02</title>
    <link href="https://Maxwell-lyu.github.io/2019/03/07/Learn-PS-20190307-PS-IV-02/"/>
    <id>https://Maxwell-lyu.github.io/2019/03/07/Learn-PS-20190307-PS-IV-02/</id>
    <published>2019-03-07T12:15:53.000Z</published>
    <updated>2019-06-19T09:39:20.000Z</updated>
    
    <content type="html"><![CDATA[<p>My note when <ruby> previewing<rt> Copying the Textbook of</rt> </ruby>  abstract algebra.<br><a id="more"></a> </p><h1 id="Chapter-5-Permutation-Groups"><a href="#Chapter-5-Permutation-Groups" class="headerlink" title="Chapter 5: Permutation Groups"></a>Chapter 5: Permutation Groups</h1><h2 id="Definitions-and-Notation"><a href="#Definitions-and-Notation" class="headerlink" title="Definitions and Notation"></a>Definitions and Notation</h2><h3 id="Symmetric-Group"><a href="#Symmetric-Group" class="headerlink" title="Symmetric Group"></a>Symmetric Group</h3><ul><li><strong>Symmetric Group</strong> on n letters 对称群  <blockquote><p>$S_X=S_n$ is the permutation of a set $X=\{1,2,\cdots,n\}$  </p></blockquote></li><li><p><strong>Theorem 5.1</strong></p><blockquote><p>The symmetric group on n letters, $S_n$, is a group with $n!$ elements, where the binary operation is the composition of maps.<br>It is not necessarily commutative</p></blockquote><blockquote><p><strong>Proof</strong>:  </p><ol><li>Identity: $\forall x\in X, x\to x$  </li><li>Associative: map composition is associative  </li><li>Inverse: $f^{-1}$ exists since $f$ is one-to-one and onto  </li><li>Size: number of permutations is $n!$  </li></ol></blockquote></li><li><strong>Permutation Group</strong><blockquote><p>A subgroup of $S_n$</p></blockquote></li></ul><h3 id="Cycle-Notation"><a href="#Cycle-Notation" class="headerlink" title="Cycle Notation"></a>Cycle Notation</h3><ul><li><strong>Cycle</strong> of Length $k$ 轮换<blockquote><p>A permutation $\sigma\in S_X$<br>There exists elements $a_1$, $a_2$, $\cdots$, $a_k\in X$ such that<br>$\sigma(a_1)=a_2$, $\sigma(a_2)=a_3$, $\cdots$, $\sigma(a_k)=a_1$<br>$\{a_1,a_2,\cdots,a_k\}$ denotes the cycle $\sigma$<br>Not every permutation is a cycle.</p></blockquote></li><li><strong>Disjoint Cycle</strong><blockquote><p>$\forall i,j,\ a_i\ne b_j$</p></blockquote></li><li><p><strong>Proposition 5.8</strong></p><blockquote><p>Let $\sigma$ and $\tau$ be two disjoint cycles in $S_X$. Then $\sigma\tau=\tau\sigma$</p></blockquote><blockquote><p><strong>Proof</strong>:</p><ol><li>$x$ is neither in $\{a_1,a_2,\cdots,a_k\}$ nor $\{b_1,b_2,\cdots,b_l\}$<br>$\sigma(x)=\tau(x)=x\Rightarrow\sigma\tau(x)=\tau\sigma(x)=x$</li><li>$x$ in $\{a_1,a_2,\cdots,a_k\}$<br>Then $x$ is not in $\{b_1,b_2,\cdots,b_l\}$<br>Because they are disjoint, $\sigma(x)\notin\{b_1,b_2,\cdots,b_l\}$<br>Then $\sigma\tau(x) = \sigma(x)$, and $\tau\sigma(x) = \tau(\sigma(x))=\sigma(x)$</li><li>$\sigma\tau=\tau\sigma$</li></ol></blockquote></li><li><p><strong>Theorem 5.9</strong></p><blockquote><p>Every permutation in $S_n$ can be written as the product of disjoint cycles.</p></blockquote><blockquote><p><strong>Proof</strong>: 咕咕咕</p></blockquote></li></ul><h3 id="Transpositions"><a href="#Transpositions" class="headerlink" title="Transpositions"></a>Transpositions</h3><ul><li><strong>Transpositions</strong> 对换<blockquote><p>Permutation which is a cycle of length 2</p></blockquote></li><li><strong>Proposition 5.12</strong><blockquote><p>Any permutation of a finite set containing at least two elements can be written as the product of transpositions.</p></blockquote></li><li><p><strong>Lemma 5.14</strong></p><blockquote><p>If the identity is written as the product of r transpositions, $id=\tau_1\tau_2\cdots \tau_r$ then r is an even number.</p></blockquote><blockquote><p><strong>Proof</strong>: 咕咕咕 </p></blockquote></li><li><p><strong>Theorem 5.15</strong> </p><blockquote><p>If a permutation $\tau$ can be expressed as the product of an even number of transpositions, then any other product of transpositions equaling $\tau$ must also contain an even number of transpositions.<br>Similarly, if $\tau$ can be expressed as the product of an odd number of transpositions, then any other product of transpositions equaling $\tau$ must also contain an odd number of transpositions.</p></blockquote><blockquote><p><strong>Proof</strong>:<br>$\sigma=\sigma_1\sigma_2\cdots\sigma_m=\tau_1\tau_2\cdots\tau_n$<br>$id=\sigma\sigma^{-1}=\sigma_1\sigma_2\cdots\sigma_m(\tau_1\tau_2\cdots\tau_n)^{-1}=\sigma_1\sigma_2\cdots\sigma_m\tau_1\tau_2\cdots\tau_n$<br>Then $m+n$ must be even.<br>So even+even or odd+odd</p></blockquote></li></ul><h3 id="The-Alternating-Groups"><a href="#The-Alternating-Groups" class="headerlink" title="The Alternating Groups"></a>The Alternating Groups</h3><ul><li>The <strong>Alternation Group</strong> on $n$ <strong>Letters</strong> 交代群<blockquote><p>The set of all even permutations $A_n$ </p></blockquote></li><li><p><strong>Theorem 5.16</strong></p><blockquote><p>The set $A_n$ is a subgroup of $S_n$</p></blockquote><blockquote><p><strong>Proof</strong></p><ol><li>The product of 2 even permutations is even</li><li>The identity is even</li><li>The inverse is even</li></ol></blockquote></li><li><p><strong>Proposition 5.17</strong></p><blockquote><p>The number of even permutations in $S_n$, $n\geq2$, is equal to the number of odd permutations.<br>Hence, the order of $A_n$ is $n!/2$.</p></blockquote><blockquote><p><strong>Proof</strong>:<br>Prove a bijection $\lambda_\sigma(\tau)=\sigma\tau$</p></blockquote></li></ul><h2 id="Dihedral-Groups"><a href="#Dihedral-Groups" class="headerlink" title="Dihedral Groups"></a>Dihedral Groups</h2><ul><li>The n-th <strong>Dihedral Group</strong> 二面体群  <blockquote><p>The group of rigid motions of a regular $n-gon$</p></blockquote></li><li><strong>Theorem 5.20</strong><blockquote><p>The dihedral group, $D_n$, is a subgroup of $S_n$ of order $2n$</p></blockquote></li><li><p><strong>Theorem 5.23</strong></p><blockquote><p>The group $D_n$, $n\geq 3$, consists of all products of the two elements $r$ and $s$, satisfying the relations<br>$$r^n=1$$<br>$$s^2=1$$<br>$$srs = r^{-1}$$</p></blockquote><blockquote><p><strong>Proof</strong>:<br>$r$ is the rotation $r^k=k\frac{360\degree}{n}$, $1,r,r^2\cdots r^{n-1}$<br>$s_i$ is the mirror. If $n$ is even, then there are $n/2$   $s_i$ for each pair of across vertices, and $n/2$ $s_i$ for each pair of across edges. If $n$ is odd, then there are $n$ $s_i$ for each vertex.</p></blockquote></li></ul><h3 id="The-Motion-Group-of-a-Cube"><a href="#The-Motion-Group-of-a-Cube" class="headerlink" title="The Motion Group of a Cube"></a>The Motion Group of a Cube</h3><ul><li>The across vertices of the cube is labeled the same number.  </li><li><strong>Proposition 5.24</strong><blockquote><p>The group of rigid motions of a cube contains 24 elements.</p></blockquote></li><li><strong>Theorem 5.28</strong><blockquote><p>The group of rigid motions of a cube is $S_4$.</p></blockquote></li></ul><h1 id="Chapter-6-Cosets-and-Lagrange’s-Theorem"><a href="#Chapter-6-Cosets-and-Lagrange’s-Theorem" class="headerlink" title="Chapter 6: Cosets and Lagrange’s Theorem"></a>Chapter 6: Cosets and Lagrange’s Theorem</h1><h2 id="Cosets"><a href="#Cosets" class="headerlink" title="Cosets"></a>Cosets</h2><ul><li><strong>Left Coset</strong> of $H$ with <strong>Representative</strong> $g\in G$ 陪集<blockquote><p>$gH=\{gh:h\in H\}$</p></blockquote></li><li><strong>Right Coset</strong> of $H$<blockquote><p>$Hg=\{hg:h\in H\}$</p></blockquote></li><li><strong>Lemma 6.3</strong><blockquote><p>Let $H$ be a subgroup of a group $G$ and suppose that $g_1, g_2 \in G$. The following conditions are equivalent.</p><ol><li>$g_1H=g_2H$</li><li>$Hg_1^{-1}=Hg_2^{-1}$</li><li>$g_1H\subset g_2H$</li><li>$g_2\in g_1H$</li><li>$g_1^{-1}g_2\in H$</li></ol></blockquote></li><li><p><strong>Theorem 6.4</strong>  </p><blockquote><p>Let $H$ be a subgroup of a group $G$. Then the left cosets ofH in $G$ partition $G$. That is, the group $G$ is the disjoint union of the left cosets of $H$ in $G$.</p></blockquote><blockquote><p><strong>Proof</strong>:<br>$g_1H\cap g_2H\ne\emptyset\Rightarrow\exists a=g_1h_1=g_2h_2\Rightarrow g_1=g_2h_2h_1^{-1}\Rightarrow g_1\subset g_2H$<br>By Lemma 6.3, $g_1H=g_2H$</p></blockquote></li><li>The <strong>Index</strong> of $H$ in $G$<blockquote><p>$[G:H]$ the number of left cosets of $H$ in $G$</p></blockquote></li><li><p><strong>Theorem 6.8</strong></p><blockquote><p>Let $H$ be a subgroup of a group $G$. The number of left cosets of $H$ in $G$ is the same as the number of right cosets of $H$ in $G$.</p></blockquote><blockquote><p><strong>Proof</strong>:<br>Find a bijective map $\phi:\mathcal {L}_H\to\mathcal {R}_H$, $\phi(gH)=Hg^{-1}$<br>$Hg_1^{-1}=\phi(g_1H)=\phi(g_2H)=Hg_2^{-1}$<br>By Lemma 6.3</p></blockquote></li></ul><h2 id="Lagrange’s-Theorem"><a href="#Lagrange’s-Theorem" class="headerlink" title="Lagrange’s Theorem"></a>Lagrange’s Theorem</h2><ul><li><p><strong>Proposition 6.9</strong></p><blockquote><p>Let $H$ be a subgroup of $G$ with $g \in G$ and define a map $\phi :H \to gH$ by $\phi(h) = gh$. The map $\phi$ is bijective; hence, the number of elements in $H$ is the same as the number of elements in $gH$.</p></blockquote><blockquote><p><strong>Proof</strong>: 咕咕咕</p></blockquote></li><li><p><strong>Theorem 6.10</strong> Lagrange</p><blockquote><p>Let $G$ be a finite group and let $H$ be a subgroup of $G$. Then $|G|/|H| = [G : H]$ is the number of distinct left cosets of $H$ in $G$. In particular, the number of elements in $H$ must divide the number of elements in $G$.<br>The converse is false.</p></blockquote><blockquote><p><strong>Proof</strong>:<br>The group $G$ is partitioned into $[G : H]$ distinct left cosets. Each left coset has $|H|$ elements; therefore, $|G| = [G : H]|H|$.</p></blockquote></li><li><strong>Corollary 6.11</strong><blockquote><p>Suppose that $G$ is a finite group and $g \in G$. Then the order of $g$ must divide the number of elements in $G$.</p></blockquote></li><li><p><strong>Corollary 6.12</strong></p><blockquote><p>Let $|G| = p$ with $p$ a prime number. Then $G$ is cyclic and any $g \in G$ such that $g \ne e$ is a generator.</p></blockquote><blockquote><p><strong>Proof</strong>: 咕咕咕</p></blockquote></li><li><p><strong>Corollary 6.13</strong></p><blockquote><p>Let $H$ and $K$ be subgroups of a finite group $G$ such that $G\supset H\supset K$. Then<br>$$[G:K]=[G:H][H:K]$$</p></blockquote><blockquote><p><strong>Proof</strong>:<br>$$[G:K]=\frac{|G|}{|K|}=\frac{|G|}{|H|}\frac{|H|}{|K|}=[G:H][H:K]$$</p></blockquote></li><li><p><strong>Proposition 6.15</strong></p><blockquote><p>The group $A_4$ has no subgroup of order 6.</p></blockquote><blockquote><p><strong>Proof</strong>: 咕咕咕</p></blockquote></li><li><p><strong>Theorem 6.16</strong></p><blockquote><p>Two cycles $\tau$ and $\mu$ in $S_n$ have the same length if and only if there exists a $\sigma\in S_n$ such that $\mu = \sigma\tau\sigma^{-1}$.</p></blockquote><blockquote><p><strong>Proof</strong>: 咕咕咕</p></blockquote></li></ul><h2 id="Fermat’s-and-Euler’s-Theorems"><a href="#Fermat’s-and-Euler’s-Theorems" class="headerlink" title="Fermat’s and Euler’s Theorems"></a>Fermat’s and Euler’s Theorems</h2><ul><li>The <strong>Euler $\phi$-Function</strong><blockquote><p>the map $\phi: \mathbb{N}\to\mathbb{N}$ defined by $\phi(n)=1$ for $n = 1$, and, for $n &gt; 1$, $\phi(n)$ is the number of positive integers $m$ with $1 ≤ m &lt; n$ and $gcd(m,n) = 1$.<br>$$\phi(n)=n\prod_{p|n\textrm{ and }p\textrm{ is prime}}(1-\frac{1}{p})$$<br>一个因子一次，例如$8$只需计算一次$p=2$</p></blockquote></li><li><strong>Theorem 6.17</strong> <blockquote><p>Let $U(n)$ be the group of units in $\mathbb{Z}_n$. Then $|U(n)| = \phi(n)$.</p></blockquote></li><li><p><strong>Theorem 6.18</strong> Euler’s Theorem</p><blockquote><p>Let $a$ and $n$ be integers such that $n &gt; 0$ and $gcd(a, n) = 1$. Then $a^{\phi(n)} \equiv 1 (mod\ n)$.</p></blockquote><blockquote><p><strong>Proof</strong>:<br>$|U(n)|=\phi(n)$ by Theorem 6.17<br>$\forall a\in U(n), a^{\phi(n)}=1$<br>$a^{\phi(n)} \equiv 1 (mod\ n)$</p></blockquote></li><li><strong>Theorem 6.19</strong> Fermat’s Little Theorem<blockquote><p>Let $p$ be any prime number and suppose that $p \nmid a$ ($p$ does not divide $a$). Then<br>$$a^{p-1}\equiv 1(mod\ p)$$<br>For any integer $b$, $b^p\equiv b(mod\ p)$</p></blockquote></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;My note when &lt;ruby&gt; previewing&lt;rt&gt; Copying the Textbook of&lt;/rt&gt; &lt;/ruby&gt;  abstract algebra.&lt;br&gt;
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Problem Solving" scheme="https://Maxwell-lyu.github.io/tags/Problem-Solving/"/>
    
      <category term="Abstract Algebra" scheme="https://Maxwell-lyu.github.io/tags/Abstract-Algebra/"/>
    
  </entry>
  
  <entry>
    <title>Probability Ch2</title>
    <link href="https://Maxwell-lyu.github.io/2019/03/07/Learn-PMS-20190307-PMS-02/"/>
    <id>https://Maxwell-lyu.github.io/2019/03/07/Learn-PMS-20190307-PMS-02/</id>
    <published>2019-03-07T00:04:38.000Z</published>
    <updated>2019-03-21T01:47:48.000Z</updated>
    
    <content type="html"><![CDATA[<p>Probability Course in 2019 Spring<br><a id="more"></a> </p><h1 id="随机变量及其概率分布"><a href="#随机变量及其概率分布" class="headerlink" title="随机变量及其概率分布"></a>随机变量及其概率分布</h1><h2 id="随机变量及其分布函数"><a href="#随机变量及其分布函数" class="headerlink" title="随机变量及其分布函数"></a>随机变量及其分布函数</h2><h3 id="随机变量"><a href="#随机变量" class="headerlink" title="随机变量"></a>随机变量</h3><ul><li><strong>定义2.1</strong><br>设$\varOmega=\{e\}$是随机试验的样本空间, 如果对每个$e\in\varOmega$, 都对应一个单值实函数$X=X(e)$, 称$X$为随机变量<br>随机变量在某范围内取值表示随机事件</li><li><strong>概率分布</strong><br>随机变量的取值与概率的对应关系, 称之为$X$的概率分布</li></ul><h3 id="随机变量的分布函数"><a href="#随机变量的分布函数" class="headerlink" title="随机变量的分布函数"></a>随机变量的分布函数</h3><ul><li><strong>定义2.2</strong><br>设$X$是一个随机变量, $x$是任意实数, 称函数<br>$$F(X)=P(X\leq x)(-\infty&lt;x&lt;\infty)$$<br>为随机变量$X$的分布函数</li><li><strong>基本性质</strong><ol><li>$F(x)$为单调不减函数, 即对任意实数$x_2&gt;x_1$, 有$F(x_2)\geq F(x_1)$</li><li>$0\leq F(x)\leq 1$, 且$F(-\infty)=\lim_{x\to-\infty}F(x)=0$, $F(+\infty)=\lim_{x\to+\infty}F(x)=1$</li><li>$F(x)$为右连续, 即$F(x_0+0)=\lim{x\to x_0+0}F(x)=F(x_0)$<br>任意随机变量的分布函数必满足这三个性质, 满足这三个性质的必定为某个随机变量的分布函数</li></ol></li></ul><h2 id="离散型随机变量及其分布"><a href="#离散型随机变量及其分布" class="headerlink" title="离散型随机变量及其分布"></a>离散型随机变量及其分布</h2><h3 id="离散型随机变量"><a href="#离散型随机变量" class="headerlink" title="离散型随机变量"></a>离散型随机变量</h3><ul><li><strong>定义2.3</strong><br>若随机变量$X$的可能取值为有限个或可列无限多个, 则称$X$为离散型随机变量</li><li><strong>定义2.4</strong><br>设离散型随机变量$X$的所有可能取值为$x_1,x_2,\cdots,x_n,\cdots$, $X$取值$x_k$的相应概率为$p_k$, 即<br>$$P(X=x_k)=p_k$$<br>称之为离散型随机变量$X$的分布律, 分布律具有如下性质  <ol><li>$p_k\geq0$, $k=1,2,\cdots$</li><li>$\sum_{k}p_k=1$</li></ol></li></ul><h3 id="常见离散型随机变量"><a href="#常见离散型随机变量" class="headerlink" title="常见离散型随机变量"></a>常见离散型随机变量</h3><ul><li><p><strong>0-1分布</strong><br>若随机变量的可能取值只有0, 1, 且<br>$$P(X=1)=p, P(X=0)=q, (0&lt;p&lt;1, q=1-p)$$<br>则称$X$服从0-1分布   </p></li><li><p><strong>二项分布</strong><br> 若随机变量的分布律为<br> $$p_k=P(X=k)=C_n^kp^kq^{n-k}, k=0,1,\cdots, n$$<br> 其中$0&lt;p&lt;1,q=1-p$, 则称$X$服从参数为$n,p$的二项分布, 记为$X\sim B(n,p)$  </p></li><li><p><strong>泊松分布</strong><br>如果随机变量$X$的分布律为<br>$$p_k=P(X=k)=\frac{\lambda^k}{k!}e^{-\lambda}, k=0,1,2,\cdots$$<br>其中$\lambda&gt;0$为常数, 则称$X$服从参数为$\lambda$的泊松分布, 记为$X\sim P(\lambda)$<br>是用于表示<strong>大量试验</strong>中<strong>稀有事件</strong>出现的频数的概率模型  </p><ul><li>$\lambda$的概率意义: 事件的平均发生次数</li></ul></li><li><strong>几何分布</strong><br>若随机变量X的分布律为<br>$$p\{X=k\}=q^{k-1}p$$<br> 其中$0&lt;p&lt;1,q=1-p$, 则称$X$服从参数为$p$的二项分布, 记为$X\sim G(p)$<br>表示贝努里试验进行到事件首次出现为止, 所需次数$X$服从几何分布 </li><li><strong>超几何分布</strong><br>$$p\{X=k\}=\frac{C_M^kC_{N-M}^{n-k}}{C_N^n},k=0,1,\cdots,\min(n,M)$$<br>其中$n,M,N$为参数, 则称$X$服从参数为$n,M,N$的超几何分布, 记为$X\sim H(n,M,N)$<br>表示不放回随机抽样<br>若放回, 则满足二项分布$B(n, \frac{M}{N})$, 若$N\to\infty$, 与二项分布近似相等</li></ul><h2 id="连续型随机变量及其分布"><a href="#连续型随机变量及其分布" class="headerlink" title="连续型随机变量及其分布"></a>连续型随机变量及其分布</h2><h3 id="连续型随机变量"><a href="#连续型随机变量" class="headerlink" title="连续型随机变量"></a>连续型随机变量</h3><ul><li><strong>定义2.5</strong><br>设随机变量$X$的分布函数为$F(x)$, 若存在非负可积函数$p(x)$, 对任意实数$x$有<br>$$F(x)=\int_{-\infty}^xp(t)dt$$<br>则称$X$为连续型随机变量, 称$p(x)$为$X$的概率密度函数, 简称密度函数<br>由定义可见, 任何连续型随机变量的密度函数具有如下性质: <ol><li>$p(x)\geq 0$</li><li>$\int_{-\infty}^{+\infty}p(x)dx=1$</li><li>对于任意实数$a,b(a&lt;b)$<br>$$P(a&lt;X\leq b)=F(b)-F(a)=\int_a^bp(x)dx$$</li><li>由于$p(x)$为可积函数, 根据微积分性质, 分布函数$F(x)$为连续函数</li><li>若$p(x)$在$x$连续, 则分布函数$F(x)$可导, 且$p(x)=F’(x)$</li></ol></li></ul><h3 id="常见连续型随机变量"><a href="#常见连续型随机变量" class="headerlink" title="常见连续型随机变量"></a>常见连续型随机变量</h3><ul><li><strong>均匀分布</strong><br>若随机变量$X$的概率密度函数为<br>$$p(x)=\begin{cases}<br>   \frac{1}{b-a}  &amp;a&lt;x&lt;b \\<br>   0 &amp;其他<br>\end{cases}$$<br>则称$X$在区间$[a,b]$上服从均匀分布, 记为$X\sim U[a,b]$<br>$X$的分布函数为<br>$$F(x)=\begin{cases}<br> 0 &amp;x&lt;a\\<br> \frac{x-a}{b-a} &amp;a\leq x&lt;b\\<br> 1 &amp;x\geq b<br>\end{cases}$$</li><li><strong>指数分布</strong><br>若随机变量$X$的概率密度函数为<br>$$p(x)=\begin{cases}<br> \lambda e^{-\lambda x} &amp; x\geq 0\\<br> 0 &amp;x&lt;0<br>\end{cases}$$<br>则称$X$服从参数为$\lambda$的指数分布, 记为$X\sim E(\lambda)$<br>$X$的分布函数为<br>$$F(X)=\begin{cases}<br> 1-e^{-\lambda x} &amp;x\geq 0\\<br> 0 &amp;其他<br>\end{cases}$$</li><li><strong>正态分布</strong><br>若随机变量$X$的密度函数为<br>$$p(x)=\frac{1}{\sqrt{2\pi\sigma}}e^{-\frac{(t-\mu)^2}{2\sigma^2}}dt,-\infty &lt; x &lt;\infty$$<br>其中$\mu,\sigma(&gt;0)$为常数, 则称$X$服从参数为$\mu,\sigma^2$的正态分布, 记为$X\sim N(\mu, \sigma^2)$<br> 正态分布的分布函数为<br> $$F(x)=\int_{-\infty}^x\frac{1}{\sqrt{2\pi\sigma}}e^{-\frac{(t-\mu)^2}{2\sigma^2}}dt$$<br> 当$\mu=0, \sigma =1$时, $X\sim N(0, 1)$, 称$X$服从<strong>标准正态分布</strong>, 其密度函数和分布函数特别记为$\varphi(x)$和$\varPhi(x)$<br> $$\varphi(x)=\frac{1}{\sqrt{2\pi}}e^{-\frac{x^2}{2}}$$<br> $$\varPhi(x)=\int_{-\infty}^x\frac{1}{\sqrt{2\pi}}e^{-\frac{t^2}{2}}$$<br> 对标准正态分布的分布函数$varPhi(x)$有, $\varPhi(-x)=1-\varPhi(x)$</li><li><strong>定理2.1</strong><br>若随机变量$X\sim N(\mu, \sigma^2)$, 则$Z=\frac{X-\mu}{\sigma}\sim N(0, 1)$</li></ul><h2 id="随机变量函数的分布"><a href="#随机变量函数的分布" class="headerlink" title="随机变量函数的分布"></a>随机变量函数的分布</h2><ul><li><strong>随机变量的函数</strong><br> 设$X$是随机变量, $y=g(x)$是普通实函数。构造随机变量$Y$, $X$当取值时$x$时, $Y$取值$y=g(x)$，称$Y$是随机变量$X$的函数，记为$Y=g(X)$. 我们需要讨论，已知$X$的概率分布，如何求$Y=g(X)$的概率分布. 分为离散型和连续型两种情况讨论. </li></ul><h3 id="离散型随机变量的函数"><a href="#离散型随机变量的函数" class="headerlink" title="离散型随机变量的函数"></a>离散型随机变量的函数</h3><ul><li>设$X$是离散型随机变量, 其分布律为$x_k\mapsto p_k$, 对于$X$的函数$Y=g(X)$, $Y$也是离散型随机变量  <ol><li>若$y_1,y_2,\cdots, y_n,\cdots$互不相同, 则:<br>$$P(Y=y_k)=P(Y=g(x_k))=P(X=x_k)=p_k$$</li><li>若有相同的, 则相同的$y_k$对应的概率相加:<br>$$P(Y=y_k)=\sum_{i:y_k=g(x_i)}P(X=x_i)$$</li></ol></li></ul><h3 id="连续型随机变量的函数"><a href="#连续型随机变量的函数" class="headerlink" title="连续型随机变量的函数"></a>连续型随机变量的函数</h3><ul><li>设$X$是连续型随机变量, $y=g(x)$为连续实函数, 则$Y=g(X)$也是连续型随机变量. 己知$X$的密度函数$p_X(x)$，求$Y$的密度函数$p_Y(y)$.<br>常用的方法是分布函数法，即先求Y的分布函数$F_Y(y)$<br>$$F_Y(y)=P(Y\leq y)=P(g(X)\leq y)=\int_{x:g(x)\leq y}p_X(x)dx$$</li><li><p>然后$p_Y=(y)=F’_Y(y)$</p></li><li><p><strong>定理</strong><br>若随机变量$X$的分布函数$F(x)$严格单调递增, 则随机变量$Y=F(X)$服从$[0,1]$上的均匀分布</p></li><li><p><strong>定理2.2</strong><br> 设随机变量$X$的可能取值范围为$(a,b)$, $X$的概率密度为$p(x)$，$a&lt;x&lt;b$(其中$a$可为$-\infty$, $b$可为$+\infty$), 设函数$y=(x)$处处可导, 且恒有$g’(x)&gt;0$(或恒有$g’(x)&lt;0$), 则$Y=g(X)$为连续型随机变量，其概率密度为<br> $$p_Y(y)=\begin{cases}<br> p_X[g^{-1}(y)]\cdot|[g^{-1}(y)]’| &amp;\alpha&lt;y&lt;\beta\\<br> 0 &amp;其他<br> \end{cases}$$<br> 其中$\alpha=\min\{g(a),g(b)\}$, $\beta=\max\{g(a),g(b)\}$, $g^{-1}(y)$为$y=g(x)$的反函数</p></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Probability Course in 2019 Spring&lt;br&gt;
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Probability and Mathematical Statistics" scheme="https://Maxwell-lyu.github.io/tags/Probability-and-Mathematical-Statistics/"/>
    
  </entry>
  
  <entry>
    <title>Logic Ch1</title>
    <link href="https://Maxwell-lyu.github.io/2019/03/01/Learn-ML-20190301-ML-01/"/>
    <id>https://Maxwell-lyu.github.io/2019/03/01/Learn-ML-20190301-ML-01/</id>
    <published>2019-03-01T07:17:50.000Z</published>
    <updated>2019-03-11T11:28:46.000Z</updated>
    
    <content type="html"><![CDATA[<p>Logic Course in 2019 Spring<br><a id="more"></a> </p><h1 id="第一讲：命题逻辑"><a href="#第一讲：命题逻辑" class="headerlink" title="第一讲：命题逻辑"></a>第一讲：命题逻辑</h1><h2 id="命题逻辑的语法"><a href="#命题逻辑的语法" class="headerlink" title="命题逻辑的语法"></a>命题逻辑的语法</h2><p><strong>定义1.1</strong>(字母表)  </p><ol><li>命题符：$P_0,P_1,P_2,\cdots,P_n,\cdots,n\in \mathbb{N}$, 记$PS=\{P_n|n\in\mathbb{N}\}$  </li><li>联结词：$\neg$, $\wedge$, $\vee$, $\rightarrow$  </li><li>辅助符：$($, $)$</li></ol><p><strong>定义1.2</strong>(命题)</p><ol><li>命题符为命题  </li><li>若$A$, $B$为命题, 则$(\neg A)$, $(A\wedge B)$, $(A\vee B)$, $(A\rightarrow B)$为命题  </li><li>命题仅限于此  </li><li><strong>BNF范式</strong>表达：$\varphi\Coloneqq P|(\neg\varphi)|(\varphi_1\wedge\varphi_2)|(\varphi_1\vee\varphi_2)|(\varphi_1\rightarrow\varphi_2),P\in PS$ </li><li><strong>闭包法</strong>也可定义命题<br> 令$C_\neg$, $C_\wedge$, $C_\vee$, $C_\rightarrow$为所有字母表符号串之集上的函数：<br> $$C_\neg(A)=(\neg A)$$<br> $$C_*(A,B)=(A*B)$$<br> 这里$*\in \{\wedge, \vee, \rightarrow\}$  </li></ol><p><strong>定义1.3</strong>(命题集)<br>所有命题的集合$PROP$是满足以下条件的最小集合：</p><ol><li>$PS\subseteq PROP$</li><li>若$A\in PROP$, 则$C_\neg(A)\in PROP$</li><li>若$A,B\in PROP$, 则$C_\wedge(A,B)$, $C_\vee(A,B)$, $C_\rightarrow(A,B)\in PROP$</li><li>即$PROC$为函数$C_\neg$, $C_\wedge$, $C_\vee$, $C_\rightarrow$下$PS$的归纳闭包</li></ol><p><strong>引理1.4</strong>(括号引理)<br>若$A$为命题, 则$A$中所有左括号的个数等于右括号的个数</p><p><strong>引理1.5</strong><br>$A\in PROP$等价于存在有穷序列$A_0,A_1,\cdots,A_n$使$A$为$A_n$且对任何$i\leq n$,   </p><ul><li>或(a) $A_i\in PS$  </li><li>或(b) 存在$k&lt;i$使$A_i$为$\neg A_k$  </li><li>或(c) 存在$k,l&lt;i$使$A_i$为$(A_k*A_l)$, 这里$*$为$\wedge$,   $\vee$, $\rightarrow$之一<br>以上序列$A_0,A_1,\cdots,A_n$被称为$A$的<strong>构造序列</strong>  </li></ul><p><strong>结构归纳</strong></p><ul><li>每个命题皆有构造过程, 但构造过程不一定唯一</li><li>若$A_0,A_1,\cdots,A_n$为$A$的最短构造过程, 则称$n$为$A$的<strong>构造长度</strong></li><li>对$A$的结构作归纳证明一些性质, 事实上是对$A$的构造长度作归纳, 而这是自然数上的归纳</li></ul><h2 id="命题的语义"><a href="#命题的语义" class="headerlink" title="命题的语义"></a>命题的语义</h2><p><strong>什么是命题的语义</strong><br>对于任意的<strong>赋值</strong>, $v:PS\rightarrow\{T,F\}$, 定义一个<strong>解释</strong><br>$$\hat{v}:PROP\rightarrow\{T,F\}$$  </p><p><strong>定义1.6</strong><br>令真值集$B=\{T,F\}$</p><ul><li>联结词$\neg$被解释为一元函数$H_\neg:B\rightarrow B$</li><li>联结词$*$被解释为二元函数$H_*:B^2\rightarrow B$<br>这里$*\in \{\wedge, \vee, \rightarrow\}$ </li><li>定义为真值表, 此处略</li></ul><p><strong>定义1.7</strong>(命题的语义)  </p><ul><li>$v$为一个赋值, 指它为函数$v:PS\rightarrow B$<br>从而对任何命题符$P-i$, $v(P_i)$为$T$或$F$</li><li><p>对于任何赋值$v$, 定义$\hat{v}：PROP\rightarrow B$如下：  </p><ul><li>$\hat{v}(P_n)=v(P_n)$, $n\in\mathbb{N}$</li><li>$\hat{v}(\neg A)=H_\neg(\hat{v}(A))$</li><li>$\hat{v}(A * B)=H_*(\hat{v}(A), \hat{v}(B))$, 这里$*\in \{\wedge, \vee, \rightarrow\}$<blockquote><p>  确实应该是$H_*(\hat{v}(A),\hat{v}(B))$</p></blockquote></li></ul></li><li><p><strong>引理1.8</strong><br>设$A$为命题, $v_1$, $v_2$为赋值, 若$v_1\upharpoonright FV(A)=v_2\upharpoonright FV(A)$, 即对于$P\in FV(A)$, $v_1(P)=v_2(P)$, 则$\hat{v_1}(A)=\hat{v_2}(A)$</p></li><li><p><strong>定义1.9</strong><br>设$A$为命题, $v$为赋值  </p><ol><li>$v$满足$A$, 记为$v\vDash A$, 指$\hat{v}(A)=T$</li><li>$A$为永真式(tautology), 记为$\vDash A$, 指对任何$v$有$\hat{v}(A)=T$</li><li>$A$可满足, 指有$v$使$v\vDash A$</li><li>设$\Gamma$为命题集, $A$为$\Gamma$的语义结论, 记为$\Gamma\vDash A$, 指对所有$v$, 若对任何$B\in \Gamma$有$\hat{v}(B)=T$, 则$\hat{v}(A)=T$</li></ol></li><li><p><strong>定义1.10</strong><br>设$A$为命题, $FV(A)=\{Q_1, \cdots, Q_n\}$. $n$元函数$H_A:B^n\to B$定义如下: 对于任何$(a_1,\cdots,a_n)\in B^n$, $H_A(a_1,\cdots, a_n)=\hat{v}(A)$, 这里赋值$v$满足$v(Q_i)=a_i(1\leq i\leq n)$. 下面称$f:B^n\to B$为$n$元真值函数, 称$H_A$为$A$定义的真值函数</p></li><li><p><strong>定义1.11</strong>  </p><ol><li>命题$A$为析合范式($\vee\wedge$-nf)指$A$呈形$\bigvee_{i=1}^m(\bigwedge_{k=1}^nP_{i,k})$, 这里$P_{i,k}$为命题符或命题符的否定(即呈形$\neg P_i$)</li><li>命题$A$为合析范式($\wedge\vee$-nf)指$A$呈形$\bigwedge_{i=1}^l(\bigvee_{k=1}^nQ_{i,k})$, 这里$Q_{i,k}$为命题符或命题符的否定(即呈形$\neg Q_i$)<br>其中$\bigwedge_{k=1}^n$为$(\cdots(((B_1\wedge B_2)\wedge B_3)\cdots\wedge B_n)\cdots)$的简写; $\bigvee_{k=1}^n$为$(\cdots(((B_1\vee B_2)\vee B_3)\cdots\vee B_n)\cdots)$的简写</li></ol></li><li><p><strong>定理1.12</strong>  </p><ol><li>存在命题$A$, 其为$\vee\wedge$-nf使$f=H_A$</li><li>存在命题$A’$, 其为$\wedge\vee$-nf使$f=H_{A’}$</li></ol></li><li><p><strong>定义1.13</strong>  </p><ol><li>设$A, B$为命题, $A$与$B$逻辑等价, 记为$A\simeq B$, 指对任何赋值$v$,<br>$$v\vDash A\textrm{ iff }v\vDash B$$</li></ol></li><li><p><strong>命题1.14</strong>  </p><ol><li>$A\simeq A$</li><li>若$A\simeq B$, 则$B\simeq A$</li><li>若$A\simeq B$且$B\simeq C$, 则$A\simeq C$</li><li>若$A\simeq B$, 则$(\neg A)\simeq (\neg B)$</li><li>若$A_1\simeq B_1$且$A_2\simeq B_2$, 则$(A_1* A_2)\simeq(B_1*B_2)$, 这里$*\in\{\wedge,\vee,\rightarrow\}$</li></ol></li><li><p><strong>命题1.15</strong><br>设$FV(A\wedge B)=\{Q_1, \cdots, Q_n\}$且$H_A:B^n\rightarrow B$, $H_B:B^n\rightarrow B$. 我们有$A\simeq B\textrm{ iff }H_A=H_B$</p></li><li><p><strong>命题1.16</strong><br>若$A$为命题，则存在$\wedge\vee$-nf$B$和$\vee\wedge$-nf$B’$使$A\simeq B$且$A\simeq B’$, 这时称$B$和$B’$分别为$A$的$\wedge\vee$-nf和$\vee\wedge$-nf</p></li></ul><h2 id="自然推理系统及其性质"><a href="#自然推理系统及其性质" class="headerlink" title="自然推理系统及其性质"></a>自然推理系统及其性质</h2><ul><li><p><strong>定义1.17</strong><br>一个矢列是一个二元组$(\Gamma, \Delta)$, 记为$\Gamma\vdash\Delta$, 这里$\Gamma, \Delta$为命题的有穷集合(可以为空), 称$\Gamma$为前件, $\Delta$为后件. 命题逻辑的自然推理系统$G’$由以下公里和规则组成, $\Gamma, \Delta, \Lambda, \Theta$表示任何命题有穷集合, $A, B$表示任何命题, $\Lambda, A, \Delta$为集合$\Lambda\cup\{A\}\cup\Delta$的缩写  </p><ul><li>公理: 左右两边有一样的</li><li>规则: <ul><li>否定调换左右</li><li>左或右且分为两个</li><li>左且右或逗号隔开</li><li>箭头看作有否定的或</li><li>$$\textrm{Cut}: \frac{\Gamma\vdash\Lambda,A\quad\Delta,A\vdash\Theta}{\Gamma,\Delta\vdash\Lambda,\Theta}$$<br>规则的上矢列被称为前提, 下矢列被称为结论. $G’$系统中的规则被称为推理规则, 规则中被作用的命题被称为主命题, 而不变的命题被称为辅命题</li></ul></li></ul></li><li><p><strong>定义1.18</strong><br>设$\Lambda$为$\{A_1,A_2,\cdots, A_m\}$, $\Delta$为$\{B_1,B_2,\cdots, B_n\}$  </p><ol><li>$\Lambda\vdash\Delta$有反例(falsifiable)指存在赋值$v$使$v\vDash(A_1\wedge \cdots\wedge A_m)\wedge(\neg B_1\wedge\cdots\wedge\neg B_n)$, 这时称$v$反驳$\Lambda\vdash\Delta$  </li><li>$\Lambda\vdash\Delta$有效(valid)指对任何赋值$v$, $v\vDash(A_1\wedge\cdots\wedge A_m)\rightarrow(B_1\vee B_2\vee\cdots\vee B_n)$, 这时称$v$满足$\Lambda\vdash\Delta$  </li><li>$\Lambda\vdash\Delta$有效也被记为$\Lambda\vDash\Delta$</li><li>当$m=0$时, $\vdash B_1,\cdots B_n$有反例指$(\neg B_1\wedge\cdots\wedge\neg B_n)$可满足; $\vdash B_1,\cdots B_n$有效指$(B_1\vee \cdots\vee B_n)$永真</li><li>当$n=0$时, $A_1,\cdots A_n\vdash$有反例指$(A_1\wedge \cdots\wedge A_m)$可满足; $A_1,\cdots A_n\vdash$有效指$(A_1\wedge \cdots\wedge A_m)$不可满足</li><li>约定$\{\}\vdash\{\}$非有效</li></ol></li><li><p><strong>命题1.19</strong><br>$\Gamma\vdash\Delta$有效$\textrm{ iff }$$\Gamma\vdash\Delta$无反例</p></li><li><p><strong>引理1.20</strong><br>对于$G’$系统中的每条异于$\textrm{Cut}$的规则:   </p><ol><li>赋值$v$反驳规则的结论$\textrm{ iff }$$v$至少反驳规则的一个前提</li><li>$v$满足规则的结论$\textrm{ iff }$$v$满足规则的所有前提</li><li>每个前提有效$\textrm{ iff }$结论有效</li></ol></li><li><p><strong>定义1.21</strong><br>设$\Gamma\vdash\Lambda$为矢列, 树$T$为$\Gamma\vdash\Lambda$的证明树指:  (见书本图片)</p></li><li><p><strong>定义1.22</strong><br>设$\Gamma\vdash\Lambda$为矢列, $\Gamma\vdash\Lambda$可证(provable)指存在$\Gamma\vdash\Lambda$的证明树</p></li></ul><ul><li><p><strong>定理1.23</strong>($G’$的soundness)<br>若$\Gamma\vdash\Delta$在$G’$中可证, 则$\Gamma\vdash\Delta$有效  </p></li><li><p><strong>定理1.24</strong>($G’$的completeness)<br>若$\Gamma\vdash\Delta$有效, 则$\Gamma\vdash\Delta$在$G’$中可证. 这就是$G’$的完全性</p></li><li><p><strong>系1.25</strong><br>$\Gamma\vdash\Delta$可证$\textrm{ iff }$$\Gamma\vdash\Delta$有效</p></li><li><p><strong>系1.26</strong><br>若$\Gamma\vdash\Delta$在$G’$中可证, 则$\Gamma\vdash\Delta$在$G’$中由一个无$\textrm{Cut}$证明</p></li><li><p><strong>定理1.27</strong>(compactness)<br>设$\Gamma$为命题的集合, 若$\Gamma$的任何有穷子集可满足, 则$\Gamma$可满足</p></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Logic Course in 2019 Spring&lt;br&gt;
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Mathematical Logic" scheme="https://Maxwell-lyu.github.io/tags/Mathematical-Logic/"/>
    
  </entry>
  
  <entry>
    <title>Probability Ch1</title>
    <link href="https://Maxwell-lyu.github.io/2019/02/28/Learn-PMS-20190228-PMS-01/"/>
    <id>https://Maxwell-lyu.github.io/2019/02/28/Learn-PMS-20190228-PMS-01/</id>
    <published>2019-02-28T00:29:38.000Z</published>
    <updated>2019-04-27T01:12:26.000Z</updated>
    
    <content type="html"><![CDATA[<p>Probability Course in 2019 Spring<br><a id="more"></a> </p><h1 id="随机事件与概率"><a href="#随机事件与概率" class="headerlink" title="随机事件与概率"></a>随机事件与概率</h1><h2 id="随机事件及其运算"><a href="#随机事件及其运算" class="headerlink" title="随机事件及其运算"></a>随机事件及其运算</h2><h3 id="随机试验与随机事件"><a href="#随机试验与随机事件" class="headerlink" title="随机试验与随机事件"></a>随机试验与随机事件</h3><ul><li><strong>随机现象</strong>：非确定性现象</li><li><strong>随机试验</strong>：$E$：对随机现象的的一次观测</li><li><strong>样本空间</strong>：$\varOmega$：所有可能结果的集合</li><li><strong>基本事件</strong>或<strong>样本点</strong>：$e$：样本空间的元素, 即$E$的每个可能结果</li><li><strong>随机事件</strong>：$A,B,C$等：样本空间$\varOmega$的子集合, 简称事件</li></ul><h3 id="事件间的关系及运算"><a href="#事件间的关系及运算" class="headerlink" title="事件间的关系及运算"></a>事件间的关系及运算</h3><ol><li>事件间的关系<ol><li><strong>包含关系</strong><br>如果事件$A$发生必然导致事件$B$发生, 则事件$B$包含事件$A$, 记$B\supset A$  </li><li><strong>互不相容关系</strong><br>若事件$A$与$B$不可能同时发生, 则称$A,B$互不相容（或互斥）, 此时$A$与$B$没有共同的样本点  </li><li><strong>相等关系</strong><br>若$B\supset A$, 且$A\supset B$, 则称$A$与$B$相等, 记为$A=B$, 两者样本点完全相同</li></ol></li><li>事件的运算<ol><li><strong>事件的并</strong><br>事件$A$与$B$至少发生一个所构成的事件成为$A$与$B$的并, 记为$A\cup B$, 其样本点由$A$与$B$的样本点合并而成<br>事件$A_1,A_2,\cdots,A_n$至少发生一个的事件称为$A_1,A_2,\cdots,A_n$的并, 记为$A_1\cup A_2\cup\cdots\cup A_n$或$\bigcup_{i=1}^nA_i$  </li><li><strong>事件的交</strong><br>事件$A$与$B$同时发生的事件成为$A$与$B$的交, 记为$A\cap B$或$AB$, 其样本点由$A$与$B$共同的样本点而成<br>事件$A_1,A_2,\cdots,A_n$同时发生的事件称为$A_1,A_2,\cdots,A_n$的交, 记为$A_1\cap A_2\cap\cdots\cap A_n$或$\bigcap_{i=1}^nA_i$或$A_1A_2\cdots A_n$  </li><li><strong>事件的差</strong><br>事件$A$发生而$B$不发生的事件称为$A$与$B$的差, 记为$A-B$, 其样本点由$A$中除去$B$的样本点组成  </li><li><strong>对立事件</strong><br>$A$不发生的事件称为$A$的对立事件, 记为$\bar{A}$, 其样本点由$\varOmega$中除$A$以外的样本点组成   </li><li><strong>注意如下等式</strong>  <ol><li>$A=(A-B)\cup AB$  </li><li>$A\cup B = A\cup (B-A)=(A-B)\cup AB \cup (B-A)$  </li><li>$A-B=A-AB=A\bar{B}$</li><li>$\bar{A}=\varOmega-A,A\cup\bar{A}=\varOmega$  </li></ol></li><li><strong>满足如下运算律</strong>  <ol><li>交换律 $A\cup B=b\cup A, A\cap B=B\cap A$</li><li>结合律 $(A\cup B)\cup C=A\cup(B\cup C),(A\cap B)\cap C=A\cap(B\cap C)$  </li><li>分配律 $A\cup(B\cap C)=(A\cup B)\cap(A\cup C),A\cap(B\cup C)=(A\cap B)\cup(A\cap C)$  </li><li>德摩根定律 $\overline{A\cup B}=\bar{A}\cap\bar{B},\overline{A\cap B}=\bar{A}\cup\bar{B}$</li></ol></li></ol></li></ol><h2 id="事件的概率及性质"><a href="#事件的概率及性质" class="headerlink" title="事件的概率及性质"></a>事件的概率及性质</h2><h3 id="频率与概率"><a href="#频率与概率" class="headerlink" title="频率与概率"></a>频率与概率</h3><ul><li><strong>频率</strong>：设随机事件$A$在$n$次重复实验中共出现$n_A$次, 将其比值$n_A/n$定义为$A$发生的频率, 记为$f_n(A)$, 即<br>$$f_n(A)=\frac{n_A}{n}$$ </li><li><strong>频率的性质</strong>  <ol><li>$0\leq f_n(A)\leq 1$</li><li>$f_n(\varOmega)=1$</li><li>若$A_1, A_2,\cdots, A_n$互不相容, 则<br>$$f_n(\bigcup_{i=1}^nA_i)=\sum_{i=1}^nf_n(A_i)$$</li></ol></li><li><strong>频率的稳定性</strong>与<strong>统计概率</strong><br>随试验次数的增加, 事件的频率将在某个数值附近稳定地摆动, 此数值定义为$A$发生的概率, 称为统计概率</li></ul><h3 id="概率的定义及性质"><a href="#概率的定义及性质" class="headerlink" title="概率的定义及性质"></a>概率的定义及性质</h3><ul><li><strong>定义1.1</strong><br>设$E$是随机实验, $\varOmega$为其样本空间。对于$E$的每一个随机事件$A$, 对应一个实数$P(A)$, 如果几何函数$P(\cdot)$满足：  <ol><li>非负性 $P(A)\geq 0$</li><li>规范性 $P(\varOmega)=1$</li><li>可列可加性 若$A_1, A_2,\cdots, A_n,\cdots$两两互不相容, 则<br>$$P(\bigcup_{i=1}^\infty A_i)=\sum_{i=1}^\infty P(A_i)$$<br>则称$P(A)$为事件$A$的概率</li></ol></li><li><strong>概率的性质</strong><ol><li>$P(\varPhi)=0$</li><li>若$A_1, A_2,\cdots, A_n$为$n$个两两互不相容事件, 则有<br>$$P(\bigcup_{i=1}^nA_i)=\sum_{i=1}^nP(A_i)$$</li><li>对任意两事件$A,B$有<br>$$P(A-B)=P(A)-P(AB)$$</li><li>对任意两事件$A,B$有<strong>加法定理</strong><br>$$P(A\cup B)=P(A)+P(B)-P(A\cap B)$$<br>利用归纳法推广：<br>$$P(\bigcup_{i=1}^nA_i)=\sum_{i=1}^nP(A_i)-\sum_{1\leq i\leq j\leq n}P(A_iA_j)+\sum_{1\leq i\leq j\leq k\leq n}P(A_iA_jA_k)+\cdots+(-1)^{n-1}P(A_1A_2\cdots A_n)$$</li><li>对任意事件$A$, $P(\bar{A})=1-P(A)$</li></ol></li></ul><h2 id="等可能概型（古典概型）"><a href="#等可能概型（古典概型）" class="headerlink" title="等可能概型（古典概型）"></a>等可能概型（古典概型）</h2><ul><li><strong>古典概型</strong>  <ol><li>样本空间$\varOmega$的元素个数为有限个</li><li>样本空间中每个基本事件（基本点）发生的可能性相同</li></ol></li><li><strong>计算</strong><br>  $$P(A)=\frac{m}{n}=\frac{A包含的样本点数}{样本点总数}$$</li><li><strong>不放回抽样</strong><br>$N$件产品, $M$件次品, 取出$n$件, 有$k$件次品<br>  $$p = \frac{C_m^kC_{N-M}^{n-k}}{C_N^n}$$</li><li><strong>有放回抽样</strong><br>$N$件产品, $M$件次品, 取出$n$件, 有$k$件次品<br> $$p=\frac{C_n^kM^k(N-M)^{n-k}}{N^n}=C_n^k(\frac{M}{N})^k(1-\frac{M}{N})^{n-k}$$</li></ul><h2 id="几何概率"><a href="#几何概率" class="headerlink" title="几何概率"></a>几何概率</h2><ul><li><strong>定义1.2</strong><br>若随机试验的样本空间对应一个度量有限的几何区域$S$, 每一基本事件与$S$内任意点一一对应, 则任一随机事件对应$n$中的某一子区域$D$.若事件的概率只和对应的区域$D$的度量成正比, 与的形状及$D$在$S$中的位置无关。发生的概率定义为<br>$$P(A)=\frac{m(A)}{n(\Omega)}=\frac{A对应区域D的度量}{\Omega对应区域S的度量}$$</li></ul><h2 id="条件概率"><a href="#条件概率" class="headerlink" title="条件概率"></a>条件概率</h2><h3 id="条件概率-1"><a href="#条件概率-1" class="headerlink" title="条件概率"></a>条件概率</h3><ul><li><p><strong>定义1.3</strong><br>设$A$, $B$为两个随机事件, 且$P(B)&gt;0$, 称<br>$$P(A|B)=\frac{P(AB)}{P(B)}$$  </p><p>为在事件$B$发生的条件下, 事件$A$发生的概率, 概率的性质仍适用  </p></li></ul><h3 id="乘法公式"><a href="#乘法公式" class="headerlink" title="乘法公式"></a>乘法公式</h3><ul><li><p><strong>乘法公式</strong><br>由条件概率公式可以得到, 当$P(B)&gt;0$时,<br>$P(AB)=P(B)P(A|B)$<br>$P(AB)=P(A)P(B|A)$</p><p>推广：设$A_1,A_2,\cdots,A_n$为$n$个随机事件, 当$P(A_1,A_2,\cdots,A_n)&gt;0$时,<br>$P(A_1A_2\cdots A_n)=P(A_1)P(A_2|A_1)P(A_3|A_1A_2)\cdots P(A_n|A_1A_2\cdots A_{n-1})$ </p></li></ul><h3 id="全概率公式与贝叶斯公式"><a href="#全概率公式与贝叶斯公式" class="headerlink" title="全概率公式与贝叶斯公式"></a>全概率公式与贝叶斯公式</h3><ul><li><strong>定义1.4</strong><br>若$n$个事件$A_1,A_2,\cdots,A_n$满足<ol><li>$A_1,A-2,\cdots,A_n$两两互不相容</li><li>$A_1\cup A_2\cup\cdots\cup A_n=\varOmega$<br>则称$A_1,A_2,\cdots,A_n$为样本空间$\varOmega$的一个<strong>划分</strong>或<strong>完备事件组</strong><br>若事件$A_1,A_2,\cdots,A_n$为完备事件组, 则在随机试验的每次试验中, $A_1,A_2,\cdots,A_n$必发生且仅发生一个</li></ol></li><li><strong>定理1.1</strong>（全概率公式）<br>设$A_1,A_2,\cdots,A_n$为完备事件组, 则对事件$B$有<br>$$P(B)=\sum_{k=1}^nP(A_k)P(B|A_k)$$</li><li><strong>定理1.2</strong>（贝叶斯公式）<br>设$A_1,A_2,\cdots,A_n$为完备事件组, 则对事件$B$有<br>$$P(A_i|B)=\frac{P(A_i)P(B|A_i)}{\sum_{k=1}^nP(A_k)P(B|A_k)}$$  </li></ul><h2 id="独立性"><a href="#独立性" class="headerlink" title="独立性"></a>独立性</h2><h3 id="独立性定义"><a href="#独立性定义" class="headerlink" title="独立性定义"></a>独立性定义</h3><ul><li><strong>定义1.5</strong><br>设$A$, $B$是两个随机事件, 若满足等式<br>$$P(AB)=P(A)P(B)$$<br>则称事件$A$, $B$<strong>相互独立</strong>, 简称<strong>独立</strong></li><li><strong>定理1.3</strong><br>若随机事件$A$与$B$相互独立, 则$\bar{A}$与$B$, $A$与$\bar{B}$, $\bar{A}$与$\bar{B}$也相互独立  </li></ul><h3 id="多个事件的独立性"><a href="#多个事件的独立性" class="headerlink" title="多个事件的独立性"></a>多个事件的独立性</h3><ul><li><strong>定理1.4</strong>（分组独立性定理）<br>设事件$A_1,A_2,\cdots,A_n$相互独立, 将其任意分为没有公共事件的$k$个组, 每个组任意做事件运算, 得到一个新事件, 则这$k$个新事件相互独立</li><li><p><strong>$n$个事件独立性</strong><br>对$n$个事件$A_1,A_2,\cdots,A_n$, 如果下列等式成立<br>$$\begin{cases}<br>  P(A_iA_j)=P(A_i)P(A_j) \\<br>  P(A_iA_jA_k)=P(A_i)P(A_j)P(A_k) \\<br>  \cdots \cdots \\<br>  P(A_{i_1}A_{i_2}\cdots A_{i_m})=P(A_{i_1})P(A_{i_2})\cdots P(A_{i_m})\\<br>  \cdots \cdots \\<br>  P(A_1A_2\cdots A_n) = P(A_1)P(A_2)\cdots P(A_n)<br>\end{cases}$$<br>则称事件$A_1,A_2,\cdots,A_n$相互独立</p></li><li><p><strong>小概率事件原理</strong><br>设随机试验中某事件$A$发生的概率为$p$, 无论$p$多么小, 只要不断重复独立地做$n$次实验, $A$迟早会发生的概率为1<br>$$P(A_1\cup A_2 \cup\cdots A_n)=1-(1-p)^n\to 1$$</p></li></ul><h3 id="可靠性分析"><a href="#可靠性分析" class="headerlink" title="可靠性分析"></a>可靠性分析</h3><p>设有$n$个独立工作的原件构成的系统, 第$i$个原件正常工作的事件记为$A_i$, 正常工作的概率$P(A_i)=p_i$, 系统正常工作的概率记为$B$</p><ol><li><strong>串联方式</strong>构成的系统<br>$$P(B_1)=P(A_1A_2\cdots A_n)=P(A_1)P(A_2)\cdots P(A_n)=p_1p_2\cdots p_n$$</li><li><strong>并联方式</strong>构成的系统<br>$$P(B_2)=P(A_1\cup A_2\cup\cdots\cup A_n)=1-P(\bar{A_1}\bar{A_2}\cdots \bar{A_n})=1-\prod_{i=1}^n(1-p_i)$$</li></ol><h2 id="独立重复试验模型"><a href="#独立重复试验模型" class="headerlink" title="独立重复试验模型"></a>独立重复试验模型</h2><ul><li><strong>$n$重伯努利试验</strong><ol><li>每次实验只有两个结果, $A$与$\bar{A}$, 且$P(A)=p$, $P(\bar{A})=1-p=q$</li><li>试验进行$n$次, 每次试验结果相互独立</li></ol></li><li><strong>定理1.5</strong><br>$n$重伯努利试验中, $A$发生$k$次的概率记为$P_n(k)$<br>$$P_n(k)=C_n^kp^kq^{n-k},(k=0,1,\cdots,n;q=1-p)$$<br>注意$\sum_{k=0}^nP_n(k)=\sum_{k=0}^nC_n^kp^kq^{n-k}=(p+q)^n=1$</li><li><strong>定理1.6</strong>（泊松定理）<br>设$n$为正整数, $\lambda=np_n$为常数, 则对任意正整数$k$有<br>$$\lim_{n\to\infty}C_n^kp_n^k(1-p_n)^{n-k}=\frac{\lambda^k}{k!}e^{-\lambda}$$<br>用于在$n$较大, $p$较小时进行近似计算</li></ul>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Probability Course in 2019 Spring&lt;br&gt;
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Probability and Mathematical Statistics" scheme="https://Maxwell-lyu.github.io/tags/Probability-and-Mathematical-Statistics/"/>
    
  </entry>
  
  <entry>
    <title>Problem Solving IV 01</title>
    <link href="https://Maxwell-lyu.github.io/2019/01/30/Learn-PS-20190130-PS-IV-01/"/>
    <id>https://Maxwell-lyu.github.io/2019/01/30/Learn-PS-20190130-PS-IV-01/</id>
    <published>2019-01-30T03:07:53.000Z</published>
    <updated>2019-06-19T08:29:54.000Z</updated>
    
    <content type="html"><![CDATA[<p>My note when <ruby> previewing<rt> Copying the Textbook of</rt> </ruby>  abstract algebra.<br><a id="more"></a> </p><h1 id="Chapter-3：Groups"><a href="#Chapter-3：Groups" class="headerlink" title="Chapter 3：Groups"></a>Chapter 3：Groups</h1><h2 id="Integer-Equivalence-Classes-and-Symmetries"><a href="#Integer-Equivalence-Classes-and-Symmetries" class="headerlink" title="Integer Equivalence Classes and Symmetries"></a>Integer Equivalence Classes and Symmetries</h2><h3 id="The-Integers-mod-n"><a href="#The-Integers-mod-n" class="headerlink" title="The Integers mod n"></a>The Integers mod n</h3><ul><li>模n和: addition modulo n: $(a+b)\%n$  </li><li><p>模n积: multiplication modulo n: $(ab)\%n$  </p></li><li><p><strong>Proposition 3.4</strong><br>Let $\mathbb{Z}_n$ be the set of equivalence classes of the integers mod $n$ and $a$, $b$, $c$ $\in$ $\mathbb{Z}_n$.</p><ol><li>communicative  交换律<blockquote><p>$a+b \equiv b+a\quad(mod\ n)$<br>$a\times b \equiv b\times a\quad(mod\ n)$  </p></blockquote></li><li>associative 结合律<blockquote><p>$(a+b)+c \equiv a+(b+c)\quad(mod\ n)$<br>$(a\times b)\times c \equiv a\times (b\times c)\quad(mod\ n)$   </p></blockquote></li><li>identities 特征值（0元素，数1<blockquote><p>$a+0 \equiv a\quad(mod\ n)$<br>$a\times1\equiv a\quad(mod\ n)$</p></blockquote></li><li>distribution 分配律<blockquote><p>$a\times(b+c)\equiv ab+ac\quad(mod\ n)$</p></blockquote></li><li>inverse 相反数（负元素<blockquote><p>$a+(-a)\equiv0\quad(mod\ n)$</p></blockquote></li><li>multiplicative inverse 倒数<blockquote><p>$a\ne 0$ required.<br>$gcd(a,n)=1\Leftrightarrow \exists b$, $a\times b \equiv 1\quad (mod\ n)$</p></blockquote></li></ol></li></ul><h3 id="Symmetries"><a href="#Symmetries" class="headerlink" title="Symmetries"></a>Symmetries</h3><ul><li><strong>Permutation</strong> of a set:</li><li><blockquote><p>a one-to-one and onto map $\pi:S\to S$</p></blockquote></li><li><strong>Symmetry</strong> of a geometric figure:  <blockquote><p>a rearrangement of the figure preserving the arrangement of its sides and vertices as well as its distances and angles.<br>边布局、点布局、长度和角度均不变，<ruby> [布局]<rt> Arrangement</rt> </ruby> 不考虑顶点标号的<ruby> [排列]<rt> Permutation</rt> </ruby> </p></blockquote></li><li><strong>Rigid Motion</strong> of an object：<blockquote><p>a map from the plane to itself preserving the symmetry.<br>不造成形变，到自身的映射，相当于重新分配点的标号<br>$A\to B, B\to C, A\to A$ is denoted as:<br>$$\begin{pmatrix}A &amp; B &amp; C \\ B &amp; C &amp; A\end{pmatrix}$$</p></blockquote></li><li><strong>Composing</strong> motion<blockquote><p>similar to composing functions/maps</p></blockquote></li></ul><h2 id="Definitions-and-Examples"><a href="#Definitions-and-Examples" class="headerlink" title="Definitions and Examples"></a>Definitions and Examples</h2><h3 id="Definitions"><a href="#Definitions" class="headerlink" title="Definitions"></a>Definitions</h3><ul><li><strong>Binary operations</strong> or <strong>Law of Composition</strong> on a set $G$:  <blockquote><p>$f:G\times G\to G$<br> every $(a,b)\in G\times G$ is mapped to a unique element denoted as $a\circ b$ or $ab$<br> 双射</p></blockquote></li><li><strong>Composition</strong> of 2 elements:  <blockquote><p>$a\circ b$ or $ab$</p></blockquote></li><li><strong>Group</strong> $(G,\circ)$<blockquote><p>a set $G$ together with a law of composition $(a,b)\mapsto a\circ b$ that satisfies the following 3 axioms:  </p><ol><li><strong>Associative</strong><br>$\forall a,b,c\in G$, $(a\circ b)\circ c=a\circ(b\circ c)$</li><li><strong>Identity Element</strong><br>$\forall a\in G$, $\exists e\in G$, $e\circ a=a\circ e=a$</li><li><strong>Inverse Element</strong><br>$\forall a\in G$, $\exists a^{-1}$ that $a\circ a^{-1}=a^{-1}\circ a=e$</li></ol></blockquote></li><li><strong>Abelian Group</strong> or <strong>Commutative Group</strong><blockquote><p>a group $(G,\circ )$ that $\forall a,b\in G$, $a\circ b=b\circ a$</p></blockquote></li><li><strong>Cayley Table</strong><blockquote><p>describe a group in terms of an addition or multiplication table<br>类似乘法表的形式，将每对元素映射的结果记录在表中</p></blockquote></li><li><strong>Order</strong> of a group<blockquote><p>A group is <strong>finite</strong>, or has <strong>finite order</strong>, if it contains a finite number of elements.<br>The order is $|G|=n$<br>Otherwise, the group is said to be <strong>infinite</strong> or to have <strong>infinite order</strong>.<br>The order is $|G|=\infty$  </p></blockquote></li></ul><h3 id="Examples"><a href="#Examples" class="headerlink" title="Examples"></a>Examples</h3><ul><li><strong>Group of Units</strong> of $\mathbb{Z}_n$<blockquote><p>The set of all elements in $\mathbb{Z}_n$ that is relatively prime to $n$</p></blockquote></li><li><strong>Symmetries</strong> of an equilateral triangle form a nonabelian group.<blockquote><p>Described in Section 3.1</p></blockquote></li><li><strong>General Linear Group</strong><blockquote><p>The set of invertible matrices forms a group<br>只有可逆阵满足，群定义<ruby> [公理3]<rt> Inverse Element</rt> </ruby> </p></blockquote></li><li><strong>Quaternion Group</strong><blockquote><p>$Q_8=\{\pm 1,\pm I,\pm J,\pm K\}$<br>$1=\begin{pmatrix}1 &amp; 0 \\ 0 &amp; 1\end{pmatrix}$, $I=\begin{pmatrix}0 &amp; 1 \\ -1 &amp; 0\end{pmatrix}$, $J=\begin{pmatrix}0 &amp; i \\ i &amp; 0\end{pmatrix}$, $K=\begin{pmatrix}i &amp; 0 \\ 0 &amp; -i\end{pmatrix}$<br>$I^2=J^2=K^2=-1$<br>$IJ=K$, $JK=I$, $KI=J$, $JI=-K$, $KJ=-I$, $IK=-J$  </p></blockquote></li><li><strong>Nonzero Complex Number</strong><blockquote><p>$$z^{-1}=\frac{a-bi}{a^2+b^2}$$  </p></blockquote></li></ul><h3 id="Basic-Properties-of-Groups"><a href="#Basic-Properties-of-Groups" class="headerlink" title="Basic Properties of Groups"></a>Basic Properties of Groups</h3><ul><li><strong>Proposition 3.17</strong> 特征元素唯一<br>The <strong>identity element</strong> in a group G is <strong>unique</strong>.<blockquote><p><strong>Proof</strong>:<br>$e=e’e=e’$</p></blockquote></li><li><strong>Proposition 3.18</strong> 逆元素唯一<br>The <strong>inverse</strong> of an element in a group G is <strong>unique</strong>.<blockquote><p><strong>Proof</strong>:<br>$(g^{-1})=e(g^{-1})=(g^{-1})’g(g^{-1})=(g^{-1})’e=(g^{-1})’$</p></blockquote></li><li><strong>Proposition 3.19</strong> 取逆分配<br>Let $G$ be a group. If $a,b\in G$, then $(ab)^{-1}=b^{-1}a^{-1}$.<blockquote><p><strong>Proof</strong>:<br>$abb^{-1}a^{-1}=aea^{-1}=aa^{-1}=e$<br>$b^{-1}a^{-1}ab=b^{-1}eb=b^{-1}b=e$<br>Inverse is unique</p></blockquote></li><li><strong>Proposition 3.20</strong> 两次取逆<br>Let $G$ be a group. For any $a\in G$, $(a^{-1})^{-1}=a$.<blockquote><p><strong>Proof</strong>:<br>$(a^{-1})^{-1}=e(a^{-1})^{-1}=aa^{-1}(a^{-1})^{-1}=ae=a$  </p></blockquote></li><li><strong>Proposition 3.21</strong> 方程唯一解<br>Let $G$ be a group and $a,b\in G$. Then the equations $ax = b$ and $xa = b$ have unique solutions in $G$. The <strong>right and left cancellation laws</strong> are true in groups.<blockquote><p><strong>Proof</strong>:<br>$x_1=a^{-1}ax_1=a^{-1}ax_2=x_2$<br>$x_1=x_1aa^{-1}=x_2aa^{-1}=x_2$</p></blockquote></li><li><strong>Proposition 3.22</strong> 消去律<br>If $G$ is a group and $a,b,c\in G$, then $ba=ca\Rightarrow b=c$ and $ab=ac\Rightarrow b=c$. <blockquote><p><strong>Proof</strong>:<br>$ba=ca\Rightarrow baa^{-1}=caa^{-1}\Rightarrow b=c$<br>$ab=ac\Rightarrow a^{-1}ab=a^{-1}ac\Rightarrow b=c$</p></blockquote></li><li><strong>Exponential Notation</strong> for $g\in G$ and $n\in\mathbb{N}$ 幂  <blockquote><p>$g^0=e$<br>$g^n=g\cdot g\cdots g$(n times)<br>$g^{-n}=g^{-1}\cdot g^{-1}\cdots g^{-1}$(n times)</p></blockquote></li><li><strong>Theorem 3.23</strong>  <blockquote><ol><li>$g^mg^n=g^{m+n}$, $\forall m,n\in\mathbb{Z}$</li><li>$(g^m)^n=g^{mn}$, $\forall m,n\in\mathbb{Z}$</li><li>$(gh)^n=(h^{-1}g^{-1})^{-n}$, $\forall n\in\mathbb{Z}$</li><li>Only for abelian groups, $(gh)^n=g^nh^n$, $\forall n\in\mathbb{Z}$</li></ol></blockquote></li></ul><h2 id="Subgroups"><a href="#Subgroups" class="headerlink" title="Subgroups"></a>Subgroups</h2><h3 id="Definitions-1"><a href="#Definitions-1" class="headerlink" title="Definitions"></a>Definitions</h3><ul><li><strong>Subgroup</strong> $H$ of a group $G$ 子群  <blockquote><p>A subset H of G such that when the group operation of G is restricted to H, H is a group in its own right.<br>元素为子集，二元操作不变，仍满足群公理</p></blockquote></li><li><strong>Trivial Subgroup</strong><blockquote><p>$H=\{e\}$</p></blockquote></li><li><strong>Proper Subgroup</strong> 真子群<blockquote><p>$H\ne G$</p></blockquote></li></ul><h3 id="Examples-1"><a href="#Examples-1" class="headerlink" title="Examples"></a>Examples</h3><ul><li><strong>$\mathbb{Q}^*$</strong> is a subgroup of <strong>$\mathbb{R}^*$</strong><blockquote><p><strong>Proof</strong>:</p><ol><li>1 is the identity element</li><li>$(p/q)^{-1}=q/p$</li><li>Multiplication is associative in both $\mathbb{Q}^<em>$ and $\mathbb{R}^</em>$  </li></ol></blockquote></li><li><strong>$\{1,-1,i,-i\}$</strong> is a subgroup of <strong>$\mathbb{C}^*$</strong>  </li><li><p><strong>$SL_2(\mathbb{R})$</strong> is a subgroup of <strong>$GL_2(\mathbb{R})$</strong>  </p><blockquote><p><strong>$GL_2(\mathbb{R})$</strong>: general linear group.<br><strong>$SL_2(\mathbb{R})$</strong>: special linear group, matrices of determinant 1.  </p></blockquote><blockquote><p><strong>Proof</strong>:</p><ol><li>$I_2$ is the identity element.  </li><li>$A=\begin{pmatrix}a &amp; b \\ c &amp; d\end{pmatrix}$, $A^{-1}=\begin{pmatrix}d &amp; -b \\ -c &amp; a\end{pmatrix}$</li><li>Multiplication is associative.</li><li>The product also has determinant 1, by $|AB|=|A||B|$.</li></ol></blockquote></li><li>A subset $H$ of a group $G$ can be a group without being a subgroup of $G$.<blockquote><p>$(\mathbb{M}<em>{2\times 2},+)$ is a subset of but not a subgroup of $GL</em>{2}$.<br>此处二元操作不同，因而不是子群  </p></blockquote></li><li>One way of telling whether or not two groups are the same is by examining their subgroups.  <blockquote><p>判断群是否同构，可判断子群的数量及各自的大小是否相同  </p></blockquote></li></ul><h3 id="Some-Subgroup-Theorems"><a href="#Some-Subgroup-Theorems" class="headerlink" title="Some Subgroup Theorems"></a>Some Subgroup Theorems</h3><ul><li><p><strong>Proposition 3.30</strong> 子群充要条件1</p><blockquote><p>A subset H of G is a subgroup if and only if it satisfies the following conditions:  </p><ol><li>The identity $e$ of $G$ is in $H$.  </li><li>If $h_1$, $h_2\in H$, then $h_1h_2\in H$.  </li><li>If $h\in H$, then $h^{-1}\in H$.  </li></ol></blockquote><blockquote><p><strong>Proof</strong>:<br>$\Rightarrow$: </p><ol><li>$ee_H=e_H=e_He_H\Rightarrow e=e_H$</li><li>$H$ is a group</li><li>$H$ is a group, then $h(h^{-1})’=e$, $(h^{-1})’\in H$, also (h^{-1})’\in G$. By uniqueness of inverse, $(h^{-1})’=h^{-1}$.  </li></ol><p>$\Leftarrow$:<br>These conditions plus the associativity of the binary operation will prove that $H$ is a group.</p></blockquote></li><li><p><strong>Proposition 3.31</strong> 子群充要条件2</p><blockquote><p>Let $H$ be a subset of a group $G$. Then $H$ is a subgroup of $G$ if and only if $H\ne \emptyset$, and whenever $g$, $h\in H$ then $gh^{−1}$ is in $H$.  </p></blockquote><blockquote><p><strong>Proof</strong>:<br>$\Rightarrow$:<br>$h\in H\Rightarrow h^{-1}\in H\Rightarrow gh^{-1}\in H$</p><p>$\Leftarrow$:   </p><ol><li>Let $g=h$, we have $e\in H$</li><li>Let $g=h_1$, $h=h_2^{-1}$, we have $gh^{-1}=h_1(h_2^{-1})^{-1}=h_1h_2\in H$</li><li>Let $g=e$, we have $h^{-1}\in H$</li><li>By Proposition 3.30  </li></ol></blockquote></li></ul><h1 id="Chapter-4-Cyclic-Groups"><a href="#Chapter-4-Cyclic-Groups" class="headerlink" title="Chapter 4: Cyclic Groups"></a>Chapter 4: Cyclic Groups</h1><h2 id="Cyclic-Subgroups"><a href="#Cyclic-Subgroups" class="headerlink" title="Cyclic Subgroups"></a>Cyclic Subgroups</h2><h3 id="Definitions-2"><a href="#Definitions-2" class="headerlink" title="Definitions"></a>Definitions</h3><ul><li><strong>Cyclic Subgroup</strong> of a group $G$ generated by $a$: 循环子群<blockquote><p>$\langle a\rangle=\{a^k:k\in\mathbb{Z}\}$, $a\in G$  </p></blockquote></li><li><p><strong>Theorem 4.3</strong></p><blockquote><p>$\langle a\rangle$ is a subgroup of $G$.<br>$\langle a\rangle$ is the smallest subgroup of $G$ that contains a.  </p></blockquote><blockquote><p><strong>Proof</strong>:  </p><ol><li>$e=a^0\in \langle a\rangle$</li><li>$g=a^m\in \langle a\rangle$，$h=a^n\in \langle a\rangle$, then $gh=a^{m+n}\in \langle a\rangle$</li><li>$g=a^n\in \langle a\rangle$，then $g^{-1}=a^{-n}\in \langle a\rangle$  </li><li>Any subgroup $H$ containing $a$ must contain all powers of $a$, then $\langle a\rangle\subset H$, $\langle a\rangle$ is the smallest</li></ol></blockquote></li><li><strong>Cyclic Group</strong> $G$ 循环群<blockquote><p>$\exists a\in G$, $G=\langle a\rangle$</p></blockquote></li><li><strong>Generator</strong> of a cyclic group 生成元<blockquote><p>$a$ in $\langle a\rangle$</p></blockquote></li><li><strong>Order</strong> of a cyclic group $G$: 阶<blockquote><p>$a\in G$, the smallest positive integer $n$ that $a^n=e$<br>$|a|=n$<br>If there is no such $n$, $|a|=\infty$</p></blockquote></li><li><p><strong>Theorem 4.9</strong></p><blockquote><p>Every cyclic group is abelian.</p></blockquote><blockquote><p><strong>Proof</strong>:<br>$g=a^r\in \langle a\rangle$，$h=a^s\in \langle a\rangle$, $gh=a^ra^s=a^{r+s}=a^{s+r}=a^sa^r=hg$</p></blockquote></li></ul><h3 id="Subgroups-of-Cyclic-Groups"><a href="#Subgroups-of-Cyclic-Groups" class="headerlink" title="Subgroups of Cyclic Groups"></a>Subgroups of Cyclic Groups</h3><ul><li><p><strong>Theorem 4.10</strong></p><blockquote><p>Every subgroup of a cyclic group is cyclic.</p></blockquote><blockquote><p><strong>Proof</strong>: (Brief Version)<br>Let $m$ be the smallest natural number such that $a^m\in H$. Such an $m$ exists by the Principle of Well-Ordering.<br>$h=a^m\in H$, we must show that every $h’\in H$ can be written as a power of $h$<br>$h’=a^k=a^{mq+r}=(a^m)^qa^r=h^qa^r\in H$, where $0\leq r&lt;m$<br>$a^r=a^kh^{-q}$, then $a^r\in H$<br>$r=0$, because $m$ is the smallest positive integer that $a^m\in H$<br>$h’=h^q$<br>$H=\langle h\rangle$ is a cyclic group</p></blockquote></li><li><strong>Corollary 4.11</strong><blockquote><p>The The subgroups of $\mathbb{Z}$ are exactly $n\mathbb{Z}$ for $n=1,2,\cdots$.</p></blockquote></li><li><p><strong>Proposition 4.12</strong></p><blockquote><p>Let $G$ be a cyclic group of order $n$ and suppose that $a$ is a generator for $G$. Then $a^k = e$ if and only if $n$ divides $k$.</p></blockquote><blockquote><p><strong>Proof</strong>:<br>$\Rightarrow$:<br>$e=a^k=a^{nq+r}=a^{nq}a^r=ea^r=a^r$<br>$r=0$, $n$ divides $k$ </p><p>$\Leftarrow$:<br>$a^k=a^{ns}=(a^n)^s=e^s=e$</p></blockquote></li><li><p><strong>Theorem 4.13</strong></p><blockquote><p>Let G be a cyclic group of order n and suppose that $a\in G$ is a generator of the group. If $b=a^k$, then the order of $b$ is $n/d$, where $d = gcd(k,n)$.</p></blockquote><blockquote><p><strong>Proof</strong>:<br>Suppose $e=b^m=a^{km}$<br>The order $m$ is the smallest integer $n$ that $n$ divides $km$<br>The smallest $km$ is $lcm(k,m)$, which is $kn/d$<br>Then $m=n/d$  </p></blockquote></li><li><strong>Corollary 4.14</strong>  <blockquote><p>The generators of $\mathbb{Z}_n$ are the integers r such that $1\leq r&lt;n$ and $gcd(r,n) = 1$.<br>See the <strong>Group of Units</strong> of $\mathbb{Z}_n$  </p></blockquote></li></ul><h2 id="Multiplicative-Group-of-Complex-Numbers"><a href="#Multiplicative-Group-of-Complex-Numbers" class="headerlink" title="Multiplicative Group of Complex Numbers"></a>Multiplicative Group of Complex Numbers</h2><h3 id="Definitions-3"><a href="#Definitions-3" class="headerlink" title="Definitions"></a>Definitions</h3><ul><li><strong>Complex Numbers</strong> 复数<blockquote><p>$\mathbb{C}=\{a+bi:a,b\in\mathbb{R}\}$<br>$a$ is <strong>Real Part</strong> 实部<br>$b$ is <strong>Imaginary Part</strong> 虚部  </p></blockquote></li><li><strong>Rectangular</strong> or <strong>Cartesian</strong><blockquote><p>$z=a+bi$</p></blockquote></li><li><strong>Complex Conjugate</strong> 共轭复数<blockquote><p>$z^*=a-bi$</p></blockquote></li><li><strong>Absolute Value</strong> or <strong>Modulus</strong><blockquote><p>$|z|=\sqrt{a^2+b^2}$</p></blockquote></li><li><strong>Polar Coordinates</strong>  <blockquote><p>$z=r(\cos\theta+i\sin\theta)=r\textrm{cis}(\theta)$<br>$r=|z|$  </p></blockquote></li></ul><h3 id="Theorems"><a href="#Theorems" class="headerlink" title="Theorems"></a>Theorems</h3><ul><li><strong>Proposition 4.20</strong>  <blockquote><p>$z=r\textrm{cis}\theta$, $w=s\textrm{cis}\phi$<br>$zw=rs\textrm{cis}(\theta+\phi)$  </p></blockquote></li><li><p><strong>Theorem 4.22</strong> DeMoivre</p><blockquote><p>$[r\textrm{cis}\theta]^n=r^n\textrm{cis}(n\theta)$</p></blockquote><blockquote><p><strong>Proof</strong>:<br>Induction on n.</p></blockquote></li></ul><h3 id="The-Circle-Group-and-the-Roots-of-Unity"><a href="#The-Circle-Group-and-the-Roots-of-Unity" class="headerlink" title="The Circle Group and the Roots of Unity"></a>The Circle Group and the Roots of Unity</h3><ul><li><strong>Circle Group</strong><blockquote><p>$\mathbb{T}=\{z\in\mathbb{C}:|z|=1\}$</p></blockquote></li><li><strong>Proposition 4.24</strong>  <blockquote><p>The circle group is a subgroup of $\mathbb{C}$</p></blockquote></li><li><strong>$n$-th Roots of Unity</strong><blockquote><p>The $z$ satisfying $z^n=1$</p></blockquote></li><li><p><strong>Theorem 4.25</strong>  </p><blockquote><p>The $n$-th roots of unity is $z=\textrm{cis}(\frac{2k\pi}{n})$  </p></blockquote><blockquote><p><strong>Proof</strong>:<br>$z^n=\textrm{cis}(2k\pi)=1$  </p></blockquote></li><li><strong>Primitive $n$-th Root of Unity</strong>  <blockquote><p>A generator for the group of the nth roots of unity.</p></blockquote></li></ul><h2 id="The-Method-of-Repeated-Squares"><a href="#The-Method-of-Repeated-Squares" class="headerlink" title="The Method of Repeated Squares"></a>The Method of Repeated Squares</h2><ul><li>Calculate $x^a(\textrm{mod }b)$  </li><li>First: $a=\sum{2^{a_i}}$  </li><li>Calculate: $x^{2^{a_i}}(\textrm{mod }b)$ (This is quick)</li><li>Add up.</li></ul>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;My note when &lt;ruby&gt; previewing&lt;rt&gt; Copying the Textbook of&lt;/rt&gt; &lt;/ruby&gt;  abstract algebra.&lt;br&gt;
    
    </summary>
    
    
      <category term="Course" scheme="https://Maxwell-lyu.github.io/tags/Course/"/>
    
      <category term="Problem Solving" scheme="https://Maxwell-lyu.github.io/tags/Problem-Solving/"/>
    
      <category term="Abstract Algebra" scheme="https://Maxwell-lyu.github.io/tags/Abstract-Algebra/"/>
    
  </entry>
  
  <entry>
    <title>Tag &amp; Category Test</title>
    <link href="https://Maxwell-lyu.github.io/2019/01/16/Tests-test/"/>
    <id>https://Maxwell-lyu.github.io/2019/01/16/Tests-test/</id>
    <published>2019-01-16T10:25:00.000Z</published>
    <updated>2019-01-16T11:07:50.000Z</updated>
    
    <summary type="html">
    
    </summary>
    
      <category term="Test" scheme="https://Maxwell-lyu.github.io/categories/Test/"/>
    
    
      <category term="Administration" scheme="https://Maxwell-lyu.github.io/tags/Administration/"/>
    
      <category term="Test" scheme="https://Maxwell-lyu.github.io/tags/Test/"/>
    
  </entry>
  
  <entry>
    <title>Hello Hexo!</title>
    <link href="https://Maxwell-lyu.github.io/2019/01/13/Hello-Hexo/"/>
    <id>https://Maxwell-lyu.github.io/2019/01/13/Hello-Hexo/</id>
    <published>2019-01-13T14:30:37.000Z</published>
    <updated>2019-01-13T14:37:48.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="你好，博客"><a href="#你好，博客" class="headerlink" title="你好，博客"></a>你好，博客</h1><p>一直以来，总幻想着自已会时不时写点什么，让许多一闪而过的念头留下些许痕迹。然而，懒惰是强大的，一次次在键盘上打出的，只有WASD。<br>今天也许会变得不一样。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;你好，博客&quot;&gt;&lt;a href=&quot;#你好，博客&quot; class=&quot;headerlink&quot; title=&quot;你好，博客&quot;&gt;&lt;/a&gt;你好，博客&lt;/h1&gt;&lt;p&gt;一直以来，总幻想着自已会时不时写点什么，让许多一闪而过的念头留下些许痕迹。然而，懒惰是强大的，一次次在键盘上打出的，
      
    
    </summary>
    
    
      <category term="Administration" scheme="https://Maxwell-lyu.github.io/tags/Administration/"/>
    
  </entry>
  
</feed>
