Mathematica入门(一)原则1:任何元素都是一个表达式

我比较喜欢Mathematica,感觉用起来特别方便,因为我大多时候需要把公式计算出来,涉及到符号运算、数值计算。没有Mathematica,我会手动计算公式,经过多次转化,结果也不知道对不对。如果有了结果,才会运用Matlab进行数值计算。这个过程特别烦心。因为中间的数学符号运算太难算了。

有了Mathematica减少了不少的工作压力。真的很方便。符号运算应该是Mathematica最突出的地方。数值计算有些地方做得不错,像解方程、微分方程。但是规划求解就弱了很多,很多地方不如Lingo,图论也不如Sege。当然一个软件不可能做得尽善尽美的。

我所涉及到的内容做如下 比较:

matlab:矩阵相关运算、求解模拟器很方便。

mathematica:符号运算、方程求解、特别是微分方程求解很方便。

SageMath:用python做出来的,对别人的包特别熟悉,那特别方便。

Lingo:线性规划、非线性规划等特别方便。

Julia:最近特别火,便捷性要与Matlab、python、mathematica、Lingo等对齐,速度要与C对齐,如果真的实现了,那一定是完美的。但是包管理不是很好,经常出错。用了一段时间,感觉Julia 是mathematica和Lingo两个合体。逻辑是采用了mathematica的逻辑,一切都是表达式。

 

下面开始说说Mathematica。说说Mathematica逻辑:

1 第一条原则:任何元素都是一个表达式(Expression)

Mathematica 所处理的每一个对象都是一个表达式(Expression),而每一个表达式,要么是一个被称为原子(Atom)的个体,要么是一个普通的表达式(Normal Expression)。

1.1 原子和内置的 AtomQ 判定函数

原子包括数、符号和字符串,其中数又包括整数、实数、有理数和复数。其它所有对象均为复合表达式,称为普通表达式。通过应用内置断语函数 AtomQ,我们可以检验一个表达式是一个原子还是一个复合表达式。例如

 

In[x]=      Clear[Global '*']#清除变量所有值,注意mathematica函数体要用[...]括起来。而且mathematica函数首字母大写,所以以后我们给函数命名时首字母小写,小驼峰法,避免与系统函数冲突。
In[x]=      {AtomQ[x], AtomQ[Sin[x]], AtomQ[1+I*2], AtomQ[2/4]}#Atom[]就是检验是否为原子。
Out[X]:=    {True, False, True, True}#In是输入,Out是返回

1.2 Mathematica 普通(复合)表达式

Mathematica 语言中,每一个普通(复合)表达式都是根据如下的通用模式构建的:

expr[el1, ..., eln]  #以后看到expr就是表达式的意思。

该模式中必须含有一个符号< expr >和一对单方括号。(符号< expr >本身也可以是一个常规表达式,不必一定要是原子)。方括号内可以没有任何元素,也可以有一个或由逗号分隔开的若干个元素<el1>,...,<eln>。这些元素本身又可以是原子或普通表达式。例如在表达式 Sin[x] 中,符号<expr> 为 Sin,它含有一个元素 <x>,是一个原子(只要 x 到目前还没有做过其他定义的话。这将涉及到一个表达式的计算运行问题,我们会在后面讨论)。由此可见在 Mathematica 语言中,任何一个表达式都具有树的结构,其中树的枝为普通(子)表达式,而其叶则都是原子。

1.3 内置函数的文字表达形式和 FullForm 命令

由于如上所述的结构,任何一个 Mathematica 内置函数/命令,都相应有一个等价的文字表述形式,使得所有表达式都能按这种结构表示为一种统一的形式。我们可以借助内置的 FullForm 函数来看清这一点。FullForm 给出一个对象/表达式的一个内部表达形式,它是真正被内核直接接受的形式。例如:

由于如上所述的结构,任何一个 Mathematica 内置函数/命令,都相应有一个等价的文字表述形式,使得所有表达式都能按这种结构表示为一种统一的形式。我们可以借助内置的 FullForm 函数来看清这一点。FullForm 给出一个对象/表达式的一个内部表达形式,它是真正被内核直接接受的形式。例如:

In[X]:=	{z * Sin[x +y], FullForm[z * Sin[ +y]]}
Out[X]:=	{z Sin[x +y], Times[z, Sin[Plus[x, y]]]}

这里,大括号中的第二个表达式与第一个是等价的,但是它明确地显示了前面描述的结构。 任何函数也都可以用文字形式给出。例如:

In[X]:=	{Plus[1, 2, 3, 4], Times[1, 2, 3, 4]}
Out[X]:=	{10, 24}

 

1.4 所有的普通表达式都是一个树(tree),TreeForm 命令

普通表达式是一个树这一事实可以通过内置的 TreeForm 命令非常清楚地看出来:

In[X]:=	TreeForm[z * Sin[x +y]]

 

既然有树的结构,我们就可以对一个表达式的子树加注指标或进行访问。在下面的例子中,<expr> 是 Times (乘法命令):

In[X]:=	a = z * Sin[x +y];
In[X]:=	FullForm[a]
Out[X]:=	Times[z, Sin[Plus[x, y]]]

 

1.5 表达式的头和 Head 命令

一般来说,一个表达式在方括号前面都有一个名称,这个名称称为表达式的头。Mathematica 有一个内置函数叫 Head,它可以用来得到任何表达式的头。例如:

In[X]:=	Head[a]
Out[X]:=	Times

一个表达式的头本身可以是一个原子,也可以是一个普通表达式。例如:

In[X]:=	Clear[b, f, g, h, x];
In[X]:=	b = f[g][h][x];
In[X]:=	Head[b]
Out[X]:=	f[g][h]
In[X]:=	Head[f[g][h]]
Out[X]:=	f[g]
In[X]:=	Head[f[g]]
Out[X]:=	f

每一个表达式都有一个头,即使是原子也一样。原子的头有 String,Symbol,Integer,Real,Rational 以及 Complex。例如:

In[X]:=	{Head[f], Head[2], Head[Pi],Head[3.14], Head["abc"], Head[2 / 3], Head[1 +I]}
Out[X]:=	{Symbol, Integer, Symbol, Real, String, Rational, Complex}

1.6 通过指标来访问表达式的各个部分

通过应用指标({Part 命令}),我们也可以访问一个表达式内部的组成部分(即方括号里面的元素)。这一点可以从下面这个例子中清楚地看到:

In[X]:=	{a0, a1, a2, a2, 0, a2, 1, a2, 1, 0, a2, 1, 1, a2, 1, 2}
Out[X]:=	{Times, z, Sin[x +y], Sin, x +y, Plus, x, y}

(双重方括号是Part 命令的简写形式:

In[X]:=	a2, 1
Out[X]:=	x +y

 

In[X]:=	Part[a,{2, 1}]
Out[X]:=	x +y

 


在这个例子中,我们实际上是把一个表达式解构成它的各个组成部分。对照前面由 TreeForm 得到的数图,可以看出我们的步骤是从树干出发,沿着树枝,最后到达叶子。我们也看到所有最后一个元素为零的地址(即指标序列)所对应的都是子表达式的 Heads,这是一个约定。原则上讲,任何一个表达式都可以按此方法进行解构,更重要的是,我们可以对其子表达式进行变更。

1.7 表达式的层级和 Level 命令

利用内置函数 Level 命令,我们还可以进入离树干某一距离上的所有枝(或子表达式)。考虑下面的例子:

In[X]:=	Clear@aD;
In[X]:=	a = z * Sin[x +y] +z1 * Cos[x1 +y1]
Out[X]:=	z1 Cos[x1 +y1] +z Sin[x +y]

它的完全形式是:

In[X]:=	FullForm[a]
Out[X]:=	Plus[Times[z1, Cos[Plus[x1, y1]]], Times[z, Sin[Plus[x, y]]]]

它的树图是:

In[X]:=	TreeForm[a]

那么该树的层级依次为:

In[X]:=	Level[a, {0}]
In[X]:=	Level[a, {1}]
In[X]:=	Level[a, {2}]
In[X]:=	Level[a, {3}]
In[X]:=	Level[a, {4}]
Out[X]:=	{z1 Cos[x1 +y1] +z Sin[x +y]}
Out[X]:=	{z1 Cos[x1 +y1], z Sin[x +y]}
Out[X]:=	{z1, Cos[x1 +y1] z, Sin[x +y]}
Out[X]:=	{x1 +y1, x +y}
Out[X]:=	{x1, y1, x, y}

Level[a, {n}]给出了 a 离树干相距 n 层的所有枝或叶。如果想要得到具有 n 层亚枝或叶的所有的枝,我们则要在层级命令中设定负数层级:Level[a, {-n}]。 如:

In[X]:=	Level[a, {-1}]
In[X]:=	Level[a, {-2}]
In[X]:=	Level[a, {-3}]
In[X]:=	Level[a, {-4}]
Out[X]:=	{z1, x1, y1, z, x, y}
Out[X]:=	{x1 +y1, x +y}
Out[X]:=	{Cos[x1 +y1], Sin[x +y]}
Out[X]:=	{z1 Cos[x1 +y1], z Sin[x +y]}

注意,一般情况下,负数层级是不可能用正数层级来得到的。它们给出的是不同类型的信息。我们这里所描述的,在 Mathematica 中称为标准层级设定(Standard Level Specification)。有许多内置函数将标准层级设定作为一个(往往是可选的)变量。

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bowen2006

你的鼓励是我的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值