Tutorial 2: プログラミングの基礎と線形代数

Loop （繰り返し）　and If文

For[  start ,
 end condition : Boolean  , 
 increment ,
main content
]

For[i=1,
i≤5,
i++,
Print[i^2];
]

If[ condition : Boolean  ,   then  ,  else ]        If [ 条件  , 　満たすなら　, 満たさないなら　]

Examples

n=3
If[n > 0 && n < 1, Print["n is between 0 and 1"], Print["n is negative or greater than 1"]]

n=3

Boolean test: AND , OR

Example:  Is 1>0  AND  1<2 ?       Is     ( 2 equal 1*1 )  or  ( 2 equal 1+1 )  ?

1 >0 && 1<2
2== 1*1 || 2== 1+1

関数、変数、引用など

1. 変数と関数は基本的に同じである

Clear["Global`*"]           (*  今まで使っていたシンボルを全てクリアする  *)

Mathematicaにおいて、関数と変数に大きな違いはなく（「関数型」という言語）、どちらもシンボルとして扱われる。
例えば、

square[x_]=x^2         (* 関数squareを定義する -> ［引数　アンダスコアー ］ *)

func=a^2　　　 (* 変数funcに右辺a^2を割り当てる   *)

（引数なしの）シンボルを含める変数を評価するたまに、ルール {アシンボル -> 代入値} と　「/.」　(バックスラッシュとコロンを組み合わせた記号）

func/.{a->3}　　(* 左辺に現れた変数aをルールに割り当てると、変数funcがそれにしたがって変化される。*)

func/.{a->b}
square[b]

{func^2,Sqrt[func],Log[func]}
{square[a]^2,Sqrt[square[a]],Log[square[a]]}

2. 即時的な定義　「=」　と　　延期的な定義　「:=」

即時的な定義:例　RandomInteger[]という関数は、疑似乱数的に　0 or 1 を返す。

Table[RandomInteger[],{i,1,10}]　　(* 10回RandomInteger[]関数を呼ぶ、得られる結果からなる数列を返す*)

RandomInteger[]の名前が少し長いので、短い別名を定義することを考える。例えば：

ri[]=RandomInteger[]

Table[ri[],{i,1,10}] (* すべての要素が同じになる　*)

その理由は、シンボルriの情報を調べてみる。RandomInteger[]が現れない。

?ri

なぜならば、riを即時的に定義したからである。「=」符号を使った-> 左辺を評価してから代入。
一方、延期的にriを定義すれば、具体的にセミコロンと符号を組み合わせた「:=」を使うと、右辺をそのままの形で代入する。

ri[]:=RandomInteger[]

Table[ri[],{i,1,10}]   (* 10回ri[]を呼ぶ.  *)

今回は、要素が同じではあない。riシンボルの情報を調べるみると、確かにRandomInteger関数が表れ、「:=」記号も現れる。

?ri

3. 即時的な定義における参照名の副作用

変数xが未定義(青い色）の場合、即時的な定義を利用しても結果は同じになる。

Clear[x];myfunc1[x_]=x+1

myfunc1[3]

一方、変数aが定義されている場合(xは青い色ではなく、黒色である）、定義した時点の変数aの値で右辺の変数aが置き換わってしまう。

x=1

myfunc2[x_]=x+1

?myfunc2

延期的な定義を使っておけば、左辺の変数aは評価されずにそのまま残る。

myfunc3[a_]:=a+1

myfunc3[3]

こいう即時的な定義による副作用を避けるように、手続き型関数（Procedural function、引数を扱うなど) 野中、常に引数を局所化して、延期的に定義する「:=」

4. Moduleによる変数の局所化

例をみせることで説明する。以下の関数は引数nより、次の素数を返す。ここで、PrimeQ[i]というコマンドとは、iが素数のとき、そのときだけTrueを返す。

{PrimeQ[7],PrimeQ[10],PrimeQ[19]}

smallestPrimeOver[n_]:=( 
For[i=n,!PrimeQ[i],i++,   ];   (* iは、素数でない間に　nから、i++進む。*) 
Return[i]; 
)

上記の関数では、変数　i　は関数の中だけでなく、外でも有効であるから：

i=10
smallestPrimeOver[16766]
i

外部の変数　i　にも影響を与えてしまう。i　を関数の中だけに有効とするには、Moduleというコマンドを使う：

smallestPrimeOver[n_]:=( Module[{i},
For[i=n,!PrimeQ[i],i++,   ];
Return[i]; 
];
)

i=10
smallestPrimeOver[100]
i

ので、常に手続きのなかで使われている変数をModuleに記入する。

5. 引数はとすした参照名　と　通常の変数

関数の引数は、参照しているだけなので、通常の変数とは異なり、値を変更することはできない。例えば：

smallestPrimeOver[n_]:=( Module[{i},
i=0;
n=n+1;   (* エラーをもたらす。　nは参照名とした引数なので、割り当てることができない　*)
For[i=n,!PrimeQ[i],i++,   ];
Return[i]; 
];
)

smallestPrimeOver[100]

練習

Output: 出力 -> Return [   ]

Example:　階乗関数

factorial[n_]:=(
M=1;
For[ i=1, 
i≤n,
i++,

]
)

factorial[6]

行列とベクトルの定義とその取扱い

ベクトル

リストとして扱う。例えば、10次元の零ベクトル:

{1,2,3}

nullVect=Table[0,{i,1,10}]

したがって、リストを扱う数多くのコマンドを、ベクトルに適用できる。例えば、要素を最初に、最後にを加えるために。

Append[nullVect,10]
Prepend[nullVect,10]

また第3の成分をとるために：

{10,20,30,40}[[3]]

ベクトルを加える、スカラーにかける、内積。(addition of vectors, multiplication by a scalar, inner product)

vect1={1,2,3,4}
vect2={-1,0,-1,0}

vect1+vect2

10*vect1

内積をとるために、「.」で入力する：

vect1.vect2

行列 (matrix)

行列は、行のベクトル（=リスト）からなるリストである.

A={{a,b},{c,d}}

第一行目をアクセスするために：A[[1]], 第2行目をA[[2]]など。

A[[1]]
A[[2]]

(Subscript[A, 11])成分をとるために：A[[1,1]]

A[[1,1]]

正方形行列の場合：行列式 Det[A]

Det[A]

行列 ・ベクトル積、行列・行列積

Clear[b,x]

x={x1,x2}

A

A.x

AA={{1,2},{3,4}}
BB={{1,1},{1,1}}

AA.BB

行列とベクトルを可視化する

{AA//MatrixForm , BB//MatrixForm, x//MatrixForm}

注意：MatrixFormとは、扱うことができる式ではなく、可視化するためであけある。

aa=AA//MatrixForm

aa.x
AA.x

練習問題

Aの任意の行列とする。成分の絶対値の最大値の索引をとる関数を書けよ。( | A[[i,j]] | 最大値なら、{i,j} を返す.
役に立つ関数：　Abs[ ]  絶対値

maxnorm[A_] := (Module[{n,i,j,M},
n=Length[A];  (* 行列の行の個数　*) 
M=0;
For[i=1,i≤n,i++,
For[j=1,j≤n,j++,
If[  Abs[ A[[i,j]] ]   >M   ,   M=Abs[A[[i,j]]  ]];
];
];
 Return[M];
];
  )

maxnorm[AA]