MATHEMATICA for babies

Outline of MATHEMATICA for babies
硕大的程序, 刺激的计算, 简单的 MMA, 专为国科大幼儿园 (附属大学) 二十周岁左右孩子设计.
(注: 本文档使用 Mathematica 打开阅读效果最佳, 打开后请自行尝试运行代码查看结果. 考虑到新版本并不自带文档, 所以默认使用的是官方的网页文档链接, 在网页的最下面有语言的选项, 只是我用的是英文版而已. )
Preface

Basic Zero: Notebook 的基本使用
该部分的作用就仅仅只是一个快速的导览/索引, 并不会在正式的讲座中出现 (毕竟读语法文档很无聊就是了), 更像是一种前置知识的东西? 不过在正式的讲座中还是会对第一次出现的语法进行简要的说明并链接到相应的位置.
话虽如此, 为了防止您 N 周目重刷这部分的时候觉得太无聊, 我往里面加了一些比较 tricky 的说明文字与拓展链接 . 所以在一周目的时候被初见杀了, 还请发挥跳过, 或是直接询问他人, 或是查询攻略之类的方法 .

1
. Cell, Input, In, Shift-Return, Out...

◼
  • 一个单元格 (单元格的层级嵌套可通过右侧的
    ]
    形式来判断)
  • ◼
  • 单元格的 Input (输入) 格式
  • ◼
  • Input 单元格在按下 Shift-Return 后会得到输出的结果
  • ◼
  • 输出的结果 Out 同样也是一个单元格
  • ◼
  • 在表达式后添加
    ;
    (英文分号) 可以抑制输出
  • ◼
  • 双击单元格右侧的
    ]
    可以折叠单元格, 这对于阅读本文档很有帮助.
  • 1
    .
    1
    . Input

    ◼
  • 1
    .
    1
    .
    1
    . 如何表示数, 以及如何输入这些数
  • ◼
  • 1
    .
    1
    .
    1
    .
    1
    . 整数 (Integer)
  • 使用
    0
    到
    9
    组成的数字串就是一个整数:
    2333(*是一个比较欢乐的整数*)
    Out[]=
    2333
    并且 Mathematica 还提供整数按照每 3 位进行隔断显示:
    114514(*是一个比较臭的整数*)
    Out[]=
    114514
    ◼
  • 1
    .
    1
    .
    1
    .
    2
    . 分数
  • 在这里你就可以接触到第一个数学计算符号, 除法
    /
    , 默认对于整数的除法返回分数 (有理数):
    2/3
    Out[]=
    2
    3
    并且显然你可以对其使用一些简单的函数来提取这个对象的一些信息, 比如使用
    Numerator
    来提取分子, 使用
    Denominator
    来提取分母.
    (提示: 你可以点击计算结果的 Out 单元格, Mathematica 会自动弹出下一步计算的可能提示, 很明显这个分子和分母的函数是直接从提示操作中得到的. )
    Denominator[%](*其中%表示前一次的计算结果*)
    Out[]=
    3
    不难注意到, 在 Mathematica 中, 一个函数的调用形式是
    <函数名称>[<函数参数*>]
    . 其中, 多个参数的函数, 各个参数之间通过逗号进行分隔.
    ◼
  • 1
    .
    1
    .
    1
    .
    3
    . 浮点数 (小数)
  • 浮点数, 或者说带小数信息的数和数学上写法是一样的:
    In[]:=
    2.0;
    可以省略
    2.0
    为
    2.
    来强制要求计算结果返回浮点数结果:
    2.3(*,但是不建议滥用;浮点数的除法默认返回浮点数,可以用来防止分数输出*)
    Out[]=
    0.666667
    当然也可以对任意计算结果使用
    N
    函数来将其转换为数值形式:
    N[2/3]
    Out[]=
    0.666667
    如果你想要反向操作, 那么可以使用
    Rationalize
    将一个数有理化:
    Rationalize[0.23333333333333]
    Out[]=
    7
    30
    ◼
  • 1
    .
    1
    .
    1
    .
    4
    . 虚数 (Complex)
  • 和数学上的记号类似, 使用
    I
    来表示一个虚数单位:
    1+I(*I为内置的虚数常量*)
    Out[]=
    1+
    ◼
  • 1
    .
    1
    .
    2
    . 如何进行数学输入
  • ◼
  • 1
    .
    1
    .
    2
    .
    1
    . 上标
    Ctrl-6
  • In[]:=
    2
    x
    Out[]=
    2
    x
    ◼
  • 1
    .
    1
    .
    2
    .
    2
    . 下标
    Ctrl-dash
    (同时按下
    Ctrl
    和
    -
    (dash) 键)
  • In[]:=
    x
    1
    Out[]=
    x
    1
    不过这里有一个比较坑的事情: 在 Mathematica 中的下标和数学上的下标不同, 数学上的下标将符号与下标当作一个符号, 而 Mathematica 中的下标与符号是分离的:
    x
    1
    /.x->4
    Out[]=
    4
    1
    为了防止在代码中产生这样的潜在 Bug, 一个更好的做法就是避免使用下标.
    ◼
  • 1
    .
    1
    .
    2
    .
    3
    . 分数
    Ctrl-/
  • In[]:=
    3
    4
    Out[]=
    3
    4
    ◼
  • 1
    .
    1
    .
    2
    .
    4
    . 数学符号
    Esc-...-Esc
  • In[]:=
    (*按下ESC,然后按下a,然后按下ESC*)​​α;
    在 Notebook 中的任何地方, 使用
    ESC-...-ESC
    都可以正常地插入这些特殊符号. 并且在插入的时候, 你可以使用类似于
    L
    A
    T
    E
    X
    的命令来进行输入.
    In[]:=
    (*按下ESC,然后输入\beta,然后按下ESC*)​​β;
    ◼
  • 1
    .
    1
    .
    3
    . 一些数据结构的输入
  • ◼
  • 1
    .
    1
    .
    3
    .
    1
    . 字符串
  • In[]:=
    "使用双引号包裹的内容是一个字符串"
    Out[]=
    使用双引号包裹的内容是一个字符串
    ◼
  • 1
    .
    1
    .
    3
    .
    2
    . 符号 (Symbol)
  • 在 Mathematica 中, 用户自定义的符号一般推荐使用驼峰命名且建议使用小写字母开头:
    thisIsASymbol
    Out[]=
    thisIsASymbol
    理论上来说, Mathematica 的符号是支持 Unicode 的, 也就是说, 你完全可以用汉字:
    这也是一个符号
    Out[]=
    这也是一个符号
    甚至表情符号来作为符号:
    😄^💧
    Out[]=
    💧
    😄
    一个比较重要的点是, 在 Mathematica (指 Notebook) 中, 如果一个符号是 “自由” 的符号 (dummy variable, 或, 没有绑定值的符号), 那么它的颜色 (默认) 会是蓝色, 而一个绑定了值的符号则会是黑色的.
    比如运行下面的代码, 你会发现
    aSymbolWithBindings
    变成了黑色
    In[]:=
    aSymbolWithBindings="aSymbolWithBindings will go black. ";
    而再次引用这个符号的时候, Mathematica 就不会输出符号, 而是输出符号所绑定的值:
    aSymbolWithBindings
    Out[]=
    aSymbolWithBindings will go black.
    (注: 请跳转至 如何赋值 一部分去了解更加详细的说明).
    ◼
  • 1
    .
    1
    .
    3
    .
    3
    . 列表 (
    List
    )
  • 使用
    {}
    花括号包围的, 用
    ,
    逗号分割的一串表达式即为列表:
    {1,2,3,4}
    Out[]=
    {1,2,3,4}
    当然, 你也完全可以使用函数来规律地生成一个列表:
    Table[i,{i,1,10}]
    Out[]=
    {1,2,3,4,5,6,7,8,9,10}
    这就和你在 Python 中使用
    [i for i in range(1, 10 + 1)]
    是一样的效果. 只是在 Mathematica 中, 一些比较复杂变态的嵌套也可以写得很简洁:
    Table[i*j,{i,1,4},{j,1,4}]
    Out[]=
    {{1,2,3,4},{2,4,6,8},{3,6,9,12},{4,8,12,16}}
    或者你可以从已有的数据中导入:
    (注: 以下例子来源于 一个简单的 monika fortune 生成器, 不知道你会不会 dokidoki 呢? 原始文件是一个比较大的 Monika 的对话, 每段对话使用
    %
    进行分隔. 因为需要从 Github 上下载, 所以需要一定的网络连接. )
    In[]:=
    monikaSTRFile=StringSplit[Import["https://gist.githubusercontent.com/li-yiyang/128ec83e7a7262aba2a2e9d18d1b4cf6/raw/abde251e9b44a3be90cdc9847a7ed8c0db87ab36/monika"],"%"];
    当然, 你也可以指定访问列表中的第 N 个元素:
    或是反过来, 用逆序的方式:
    或是多个索引的并和
    对于一个符号, 我们可以引用它的值, 反复对其重新赋值等一系列操作:
    但是同时, 当一个符号被绑定值以后, 其在表达式中出现时, 将不会被视为一个符号, 而是会被当作这个值来出现. 这可能会让你在写符号表达式的时候发现想要用的符号已经被赋值了而比较麻烦.
    注: 这里指应用序, 其实存在 “例外”, 即正则序, 该部分 (预计) 将会在 程序的计算顺序 中进行展开介绍.
    简单列举局部赋值与替换的区别: (这里要解释一下, 预计在 变量的求值空间 (scoping) 中进行介绍)
    一句话简单解释就是局部赋值可以重新绑定局部的值, 而值替换不行.
    更多请参考 Scoping Constructs. 不过对于简单使用应该不会需要了解太多.
    在 Mathematica 中, 函数是 “一等公民”, 即一个函数和一个数值是同等价的数据.
    定义一个简单的函数:
    如果你有过 C++, 或者是类似的语言的话, 你也许会熟悉类似函数定义形式 (Function Overloading):
    在这里 Mathematica 是通过模式匹配的方式对函数进行了 “Overload”. 而和简单的参数长度, 参数类型式的模式匹配不同, Mathematica 的模式匹配还支持以函数条件的形式来进行实现:
    可以用三种方式实现 (怎么跟茴香豆似的):
    或是将声明的函数赋值给一个符号, 然后调用: (不要在意函数表达式是怎么写的)
    在这里我们并不会强调使用 Lambda 函数有什么好处 (在 Basic III: 程序, 稍复杂的程序 一节中可能会开始介绍), 但是要强调的是: 滥用 Lambda 函数会降低程序的可读性.
    仅仅只是为了方便你能够辨认后文中用的一些语法糖, 不做过多的介绍.
    ◼
  • 若后文有用记得提醒我更新添加.
  • 虽然叫作是自然语言输入, 其实并没有类似于 LLM 那样的强大, 并且只支持英文输入 (毕竟技术栈应该是古早专家系统和知识数据库).
    或者你也可以试试稍微复杂一点的请求: (earth density)
    (当然, 更加复杂的数据肯定就无能为力了, 比如 mean free path of 1GeV gamma in lead)
    或者你可以使用 Wolfram | Alpha 来进行输入:
    注: 写这个的时候发现增强了好多 (14.1.0), 一开始还以为会很烂, 虽然确实 mean free path of 1GeV gamma in lead 仍然没法正确解析就是了.
    如果想要更加 “智能” 的自然语言输入? 可以试试用 LLM Notebook (前提是你需要有差不多的 API Key).
    那么除了这些, 还有没有其他更简单无脑的帮助呢? 答案是有的, 如果你有 OpenAI, Claude, Gemini 之类的 API 的话, 你可以使用 LLM 辅助的 Chat-Notebook. 不过因为我没有这种 API, 所以这里就不做演示了.
    该部分将会以处理物理实验数据为例, 介绍更多的 Mathematica 的函数与使用 (简单向的). 下一回将会是比较偏向理论向的东西.
    致谢: 该部分参考了刘倩老师粒子探测器计数课程的 slides 以及基础物理实验的物理实验中的数据分析基础的 slides.
    注: 其实只是一个简单的概统关键词的列举.
    注: 这里感觉不太好解释, 高能物理这边感觉全是 “计数”, 可以很自然地从二项分布得到各种统计分布, 但是基础物理实验的 “尺子” 该怎么变到统计? 感觉不是很好说, 有点生硬?
    所以决定直接按我喜好来了, 或者能有高人指点就更好了.
    在 Mathematica 中, 输入一个带误差的数非常容易:
    并且完全可以当它就是一个数, 进行一般的运算:
    以下是一些简单的例:
    注: 这里没有带单位, 请看后文 带单位的数 一节以获得更加良好的体验.
    (注: 该部分更适合看完 Basic III 后回过来品鉴. )
    毕竟是计算机辅助了, 直接上多元的变量就好了:
    方差自然并不难得:
    从上不难发现, 有以下结论:
    ◼
  • 练习: 修改上面的代码使得对于三个 (或者随便多少个看你喜欢) 的函数都成立.
  • 那么既然对于任意函数都实现了, 对简单的四则运算自然是不在话下了, 那么如何对于任意函数, 甚至包括用户自定义的函数都可以实现呢?
    ◼
  • 任意函数的误差传递? 利用 Mathematica 的求导实现?
  • ◼
  • 尝试用这些简单函数组成一些更大的表达式?
  • 既然是实验向的, 单位转换肯定是必不可少吧...
    并且这个带单位的数据是可以正常进行各种运算的 (假如对速度, 精度之类没有严格要求):
    想要复杂一些的单位? 没问题:
    并且其实除了单位, 一些比较常见的常量也是可以轻松输入的, 比如:
    ◼
  • 约化普朗克常数 ReducedPlanckConstant
  • ◼
  • 电子荷质比
  • 基本上用英文去搜索, 都能得到差不多的关键词来找这个常数/单位.
    那么如果想要输入各种各样的单位, 但是并不知道它英文名称该怎么办呢? 你可以尝试直接输入 “缩写”:
    或是:
    或是这样:
    虽然带单位的数用起来很爽, 但是, 古尔丹, 代价是什么呢?
    ◼
  • 在计算时间上会慢一些
  • 所以更加推荐先做单位转换, 使得所有的输入都是同样单位制下的数值, 然后进行计算, 最后以指定单位制进行输出.
    ◼
  • 对大跨度单位转换上的数值计算精度的影响
  • 注: 在这里我没有找到一个很好的例子. 如果你做的方向是天文, 粒子物理之类的, 有好的例子/可复现 bug 的话, 欢迎分享.
    这里只会介绍基本的简单 2D 绘图方法, 对于复杂的, 好看的绘图需求, 请参考 绘图.
    感觉有点简陋?
    然, 更多时候我们手里的是一组数据点, 而不是一个表达式. 那么臭做实验的该怎么画图呢?
    大部分情况下你获得的数据是一个满足一定统计规律的计数数据, 所以你需要做的事情是通过直方统计图来得到他们的统计分布的一个形状:
    ◼
  • 例 1: 假如你是一个 西藏羊八井 ASγ 实验组 的同学, 在你的表面 EAS (Extensive Air Shower) 探测阵列 (Tibet-III) 上接收到了一个原初宇宙线事例产生的簇射次级粒子信息:
  • (注: 并不是真实的数据, 也不是真的落在探测器上的响应, 而是通过广延大气簇射模拟程序 Corsika 模拟得到的次级粒子信息的一部分).
    CopyRight: 这些数据来自本文档作者 (liyiyang21a@mails.ucas.ac.cn) 的工作的结果.
    同样, 也是简单的数据拟合, 对于有复杂要求的, 需要使用更加变态模型的, 请参考 模式识别与机器学习.
    那么可以画出结果:
    使用三角函数进行一个拟合:
    那么代价是什么呢?
    ◼
  • 例: 在康普顿散射实验中的三高斯拟合 (峰, 基底)
  • ◼
  • 例: 在测量杨氏模量时, 我们可以得到黄铜的伸长量与受力的关系:
  • 注: 这部分推荐在看完后文的编程后进行观看, 这里代码写的时候没有太考虑零基础的可读性.
    用装逼的话来说, 就是找到一组系数 (向量) 使得其与函数基的点积得到的函数在输入的训练集上的由特定误差函数产生的损失最小.
    用一些例子来说:
    ◼
  • 假设有一个满足多项式表达式的数据分布
  • (注: 在学完泰勒展开后, 你可以确信对于任何 (物理上能出现的) 表达式都应当可以被展开, 如果不能展开, 只需要做延拓即可. )
    因为这里有 4 个未知的模型参数, 所以结果并不是一个确定的值, 显然, 我们的目标就是要找到这组未知模型参数的最优选择, 使得由该参数描述的函数能够 “逼近” 真实的函数.
    这里不展开如何最优化函数, 直接用 Mathematica 的自带的功能:
    可以和真实的结果进行一个比较:
    ◼
  • 考虑任意函数基
  • 随便整一个训练数据集:
    以及一个损失函数:
    最小化损失函数 (训练)
    你也可以考虑换其他的函数组合, 但是大致就是这样.
    一般而言, 可以通过:
    ◼
  • 设置初始的拟合参数 (一般对于一些特定的分布/函数, 你可以肉眼猜一个值: 比如截距, 高斯分布的峰位等)
  • ◼
  • 换用不同的拟合方法
  • 当然, 如果还是不行, 那么你可能需要考虑对数据进行一定的处理, 或者想想该如何换一种方式进行拟合, 甚至, 如果你学过了计算物理, 你可以考虑自行实现一个误差最小化的函数.
    更多请参考:
    ◼
  • 关于 MMA 拟合的更多内容
  • 虽然大雾实验没有这种需求, 但是大部分情况下数据的分类都还算是挺重要的一个东西.
    Notebook Version: 2024.9.12
    Copyright: li-yiyang (liyiyiyang21a@mails.ucas.ac.cn)