9 Star 46 Fork 4

Junruoyu-Zheng / Ligral

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
matrix.md 5.04 KB
一键复制 编辑 原始数据 按行查看 历史
Junruoyu-Zheng 提交于 2021-01-05 15:04 . mod: update year to 2021

矩阵计算

Ligral 从 v0.2.0 开始支持矩阵。在目前的版本中,矩阵和标量是两个独立的概念,即$1\times 1$的矩阵不被视作为标量,日后可能会做出调整。关于矩阵常量的声明和一些简单的计算,已经在声明常量一节简要地介绍了,再次不再赘述。本节主要介绍矩阵在连接语句中的应用。

矩阵信号

除了一些特殊的模块,几乎所有模块都支持矩阵信号(目前没有不支持矩阵信号的模块,倒是一些矩阵专用模块如Split不支持标量信号)。一些模块对矩阵运算有特殊的规则,比如Calculator{type:'*'}执行了矩阵乘法,根据左乘和右乘的不同,输入输出的矩阵形状也不同。绝大多数的模块接受一个矩阵输入信号时,通常只是简单地遍历,比如Sin模块就是对矩阵的每一个元素$x$求$\sin{x}$。不同模块的用法详见模块文档。

形如IntegratorMemory这些可以被初始化的模块,如果初始值没有显示给出,必须显式给出矩阵的形状,否则默认采用标量。如果初始化为标量,输入的信号是矩阵,或者输入信号的形状和初始化形状不一致,会引起错误。

矩阵构建器

在声明常数一节曾提到常数矩阵可以用于连接语句。事实上,形如以下的语句,是会被解析成一个Constant加入到连接图中:

let mat = [1, 0; 0, 1];
mat -> Print;

但是,下列语句虽然是合法的,但是背后的原理却完全不一样:

[1, 0; 0, 1] -> Print;

[1, 0; 0, 1]看起来是一个矩阵常量,但是实际上是一个矩阵构建器,它能提供更为强大的语法。

首先,构建器的每一个元素都可以是一个单输出的节点组,因此您可以在其中放置常数、节点、节点链,只要保证最后的输出端口只有一个即可(如果是节点链的话,需要用圆括号括出)。例如:

let a = 0;
[1+1, (Step->Integrator); SineWave, a] -> Print;

其次,构建器的元素的输出信号也可以是一个矩阵,这一点和矩阵常量声明时的语法类似,只要保证矩阵形状时融洽的就能正确地构建矩阵信号。

let a = 0;
let mat = [1, 0; 0, 1];
[mat, [0;1]; 1+1, (Step->Integrator), a] -> Print;

在进行了优化后(尚待开发),所有关于常量的计算都会在循环之前进行初始化计算,因此使用矩阵构建器创建常量矩阵也不会比直接用Constant模块带来更多的开销。

矩阵解构器

矩阵结构是矩阵构建的逆操作,它将一个矩阵信号分解成标量信号,分别连接到若干个单输入节点。与矩阵构建器的灵活相反,矩阵解构器只允许元素是一个单输入的节点,且每个节点只能接收标量信号。如果需要将矩阵分割成更小的矩阵,参考模块SubMatrix(尚待开发)。

矩阵解构器常用来获取矩阵中的某些值,比如您在开发质点三自由度运动方程(EOM)时,通常会把三个位移状态和三个速度状态分别放进一个向量中(在 ligral 中,向量也是矩阵),用矩阵的形式开发会更加容易。但是当您需要用到这些状态求解物体受力情况时,通常需要获取每一个状态进行特殊处理,这时候就会用到矩阵解构器(以及通常成对出现的矩阵构建器)。

eom:Z -> [x; y; z];
eom:V -> [xdot; ydot; zdot];
(x, y, z, xdot, ydot, zdot) -> model;
[model:fx; model:fy; model:fz] -> eom:Z;

矩阵解构器有一种特殊类型,在解构矩阵之后再构建回一个矩阵,称之为矩阵遍历器。这要求每个元素不仅是单输入的,还必须是单输出的,相当于对原先的矩阵信号做了依次逐元素的处理。如果您需要将一个广义坐标向量中的角度元素从弧度制改为角度制,就可以这么写:

# X is [x; y; theta]
X -> [~; ~; Gain{180/pi}] -> Print;

您可能还记得~Node的简洁记法,在这里表示所连接的信号不需要处理,直接转发。

矩阵的位置

您可能已经注意到,矩阵构建器和解构器的语法看起来有些相似,矩阵解构器和矩阵遍历器的语法甚至完全相同,ligral 如何知道您需要的是什么呢?

其实很简单,矩阵构建器由于没有输入,其永远只能出现在一个连接语句的句首;矩阵解构器由于没有输出,其永远只能出现在一个连接语句的句末;而矩阵遍历器则可以出现在句中和句末(因为放弃输出是被允许的)。因此,ligral 在句首读取到的永远被解析为矩阵构建器,之后读取到的,ligral 会逐个分析是否符合矩阵遍历器的要求,即是否每个元素都是单输入单输出的,如果不满足则解释为矩阵解构器。这其实是很符合使用直觉的。

C#
1
https://gitee.com/junruoyu-zheng/ligral.git
git@gitee.com:junruoyu-zheng/ligral.git
junruoyu-zheng
ligral
Ligral
dev

搜索帮助