若尔当标准型

若尔当标准型#

我们对若尔当标准型的讨论始于两个最基本与最常见的问题:

  • 如何将线性空间 \(V\) 分解为线性变换 \(A\) 的不变子空间 \(V_i\) 的直和?
  • 如何使线性变换 \(A\) 在 \(V\) 的一组基上具有最简洁的矩阵形式?

对于问题一, 一个合理的附加条件是 \(A\) 在这些不变子空间 \(V_i\) 上具有良好的性质, 这样要研究 \(A\), 只需在每个更小的空间上研究, 并且充分利用那些性质, 最后汇总为 \(V\) 即可. 问题二则是为了方便计算, 我们可以利用这种简洁矩阵的性质, 提供远比普通矩阵乘法等更优的算法.

对于这两个问题, 我们首先想到的应该是线性变化的对角化. 对于可对角化的线性变换, 充要条件之一便是线性空间 \(V\) 可以被分解为特征子空间的直和 \(V = E_{\lambda_1} \oplus E_{\lambda_2} \oplus \cdots \oplus E_{\lambda_r}\); 并且我们知道这一变换在其特征向量组成的基下是对角矩阵, 这样两个问题就都得到解决. 遗憾的是, 并非每一个矩阵都可以对角化. 我们要讨论的便是一种类似对角化的, 可以对每个变换进行的分解.

可交换的线性变换

可交换的线性变换#

这篇文章讨论可交换的线性变换, 即对于线性变换 \(A\), \(B\), 有 \(AB = BA\).

引理#

对于多项式 \(f\), \(f(A)\) 与 \(B\) 可交换的充要条件是 \(A\), \(B\) 可交换.

充要条件#

复数域上线性变换 \(A\), \(B\) 可交换的充要条件是:

\(A\) 的每个广义特征空间 \(E_{\lambda}\) 都是 \(B\) 的不变子空间.

其中广义特征空间 \(E_{\lambda} = \{\mathbf{v} ~ | ~ (A - \lambda I)^m \; \mathbf{v} = \mathbf{0}, m \in \mathbb{N}_+\}\). 线性空间 \(V\) 总是可以分解为其上某一线性变换的广义特征空间的直和.

证明:
充分性: 任取 \(A\) 在重数 \(m\) 的广义特征空间 \(E_{\lambda}\), \(\forall \mathbf{v} \in E_{\lambda}; B \mathbf{v} \in E_{\lambda}\). 于是 \(B (A - \lambda I)^m \mathbf{v} = B \; \mathbf{0} = \mathbf{0}\), \((A - \lambda I)^m B \mathbf{v} = (A - \lambda I)^m (B \mathbf{v}) = \mathbf{0}\). 注意到 \((A - \lambda I)^m\) 是关于 \(A\) 的多项式, 由此可得 \(E_{\lambda}\) 上 \(A\) 与 \(B\) 可交换.

异步非阻塞串口数据接收

异步非阻塞串口数据接收#

异步?#

异步 (asynchronous) 编程是一种并发的编程模式, 可以有效节省 CPU 阻塞等待 I/O 事件造成的时间浪费, 借以提高性能.

在这里也简单介绍一下 并行 (parallel)并发 (concurrent) 的区别. 并发是指多个任务可以被同时运行的现象; 但需要注意的是, 并发在某一时刻可能并不一定有多个任务在运行. 但是并行是严格的多线程工作模式, 在某一时刻有多个任务在同时工作. 于是很容易看出, 并行也被包含在并发之中.

异步的核心在于一个字 “”. 简而言之, 异步编程好似去食堂窗口买饭, 当你告诉他你要点的餐以后, 不是一定要在窗口前等着, 而是可以去做点别的事情, 比如买瓶饮料什么的, 直到老板通知你取餐, 这就是一次异步事件. 在编程时我们调用一个异步 API, 若它不能立刻返回结果, 那么也不会阻塞等待, 而是立刻向后执行; 直到获取到结果再通知我们进行处理.

不同的语言有各色的异步支持, JavaScriptRust 的异步模型都很有代表性. JavaScript 中, 异步函数可以返回一个 Promise 对象, 其名字形象地说明了它的功能: 我承诺完成你要的操作; 潜台词则是我保证 将来 会完成你要的操作, 不一定是立刻做到. RustFuture 机制则更为直白: 你的任务我将来会完成的.

非多线程的异步程序的本质是 CPU 的 时分复用, 它用划分时间片交替运行各项任务来模拟同时运行每项任务. 必须指出, 有些语言实际上使用多线程实现的异步, 在这种情况下可以实现真正的并行, 即每个时刻多项任务同时被运行. 于是很容易推断, 若 CPU 本来就没有空闲时间, 那么非多线程的异步也并不能提高效率. 这也是为什么异步大多都被用于 I/O 操作, 因为可以有效利用好 I/O 事件中因为等待而空闲的 CPU 时间. 若是 CPU 密集型的工作, 例如科学计算等, 使用异步模型反而会因为时间片切换而损失性能. 这种情况更适合用多线程的方法提高效率.

在移动介质中安装操作系统

在移动介质中安装操作系统#

所需工具:

  • 安装了任意 linux 发行版的电脑
  • 此处使用安装了 debian 的 VMware 虚拟机
  • 系统安装光盘文件 (.iso 文件)
  • 我选择的发行版是 debian
  • 容量足够的移动介质 (如 U 盘)

1. 检查移动介质 (如 U 盘) 的分区表类型#

我们计划使用更现代的 UEFI 引导操作系统启动, 为了具有更好的兼容性, 移动介质的分区表类型应为 GPT.

因此第一步是将 MBR 类型的移动介质转换为 GPT 分区表类型. 假如你的介质已为 GPT, 可以跳过此章.

1.1. 检查分区表类型#

使用 fdisk 命令检查介质:

# fdisk -l
Disk /dev/sdb: 15.24 GiB, 16358834176 bytes, 31950848 sectors
Disk model: SD/MMC
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x00109879

上面显示了在我的机器上返回的信息, 其中: