【初心者向け】「三角不等式(Triangle Inequality)」の体感方法？

まずは基本中の基本から。
**三角不等式**(<font color="blue">Triangle Inequality</font>)
<font color="green">‖x+y‖<=‖x‖+‖y‖</font>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597772/8903475d-89f3-ad32-6ea9-ba3302c5f82a.png)

* <font color="green">‖x‖</font>と<font color="green">‖y‖</font>が同一直線上にある場合のみ<font color="green">‖x+y‖=‖x‖+‖y‖</font>が成立。その時の三角形の面積は<font color="green">0</font>に退化する。

**単位円**(<font color="blue">Unit Circle</font>)上の直径を長編とする**直角三角形**では、**正弦定理**（<font color="blue">Law of Sines</font>）<font color="green">a/sin(a)+b/sin(b)+c/sin(c)~2r</font>の特殊形たる**ターレスの定理**(<font color="blue">Thales' theorem</font>)によって必ずその対角が<font color="green">π/2ラジアン(<font color="blue">90度</font>)となり、残り2角<font color="green">α</font>,<font color="green">β</font>の合計も三角形の内角の和が<font color="green">πラジアン</font>(<font color="blue">180度</font>)である事から<font color="green">π/2ラジアン</font>(<font color="blue">90度</font>)と定まる。
[【初心者向け】三角関数と指数・対数関数の「巡回性」について。](https://qiita.com/ochimusha01/items/61d8cfa89dc078cbe472)
![CFS005.gif](https://cdn-ak.f.st-hatena.com/images/fotolife/o/ochimusha01/20201209/20201209005721.gif)

```R
#CFS=Circle Function Single
CFS<-function(Radian){
cx<-seq(-1,1,length=60)
f0<-function(x) sqrt(1-x^2)
cy<-f0(cx)
plot(cx,cy,asp=1,type="l",main="Mean proportional",xlab="X",ylab="sqrt(1-X^2)")

#塗りつぶし（背景）
polygon(cx, #x
cy, #y
density=c(30), #塗りつぶす濃度
angle=c(45),　 　　　#塗りつぶす斜線の角度
col=c(200,200,200)) 　#塗りつぶす色

#塗りつぶし（三角）
polygon(c(-1,cx[Radian],1), #x
c(0,cy[Radian],0), #y
density=c(30), #塗りつぶす濃度
angle=c(45),　 　　　#塗りつぶす斜線の角度
col=rgb(0,0,1)) 　#塗りつぶす色
#線追加（三角）
segments(cx[Radian],cy[Radian],cx[Radian],0,col=rgb(1,0,0))

#文字追加
text(c(-1,cx[Radian],1,cx[Radian]),c(0,cy[Radian],0,0), labels=c("a","d","c","b"),col=c(rgb(0,0,0),rgb(1,0,0),rgb(0,0,0),rgb(1,0,0)),cex=c(2,2,2,2))
text(0,0,labels="0",col=rgb(0,1,0),cex=2)

}
#アニメーション
library("animation")
Time_Code=rev(seq(1,59, length=30))
saveGIF({
for (i in Time_Code){
　CFS(i)
}
}, interval = 0.1, movie.name = "CFS01.gif")
```
![CFS90Sift002.gif](https://cdn-ak.f.st-hatena.com/images/fotolife/o/ochimusha01/20201209/20201209005932.gif)

```R
#CFS90Sift=Circle Function Single 90Sift
CFS90Sift<-function(Radian){
cx<-seq(-1,1,length=60)
f0<-function(x) sqrt(1-x^2)
cy<-f0(cx)
plot(cy,cx,asp=1,type="l",main="Mean proportional",xlab="sqrt(1-Y^2)",ylab="Y")

#塗りつぶし（背景）
polygon(cy, #x
cx, #y
density=c(30), #塗りつぶす濃度
angle=c(45),　 　　　#塗りつぶす斜線の角度
col=c(200,200,200)) 　#塗りつぶす色

#塗りつぶし（三角）
polygon(c(0,cy[Radian],0), #x
c(-1,cx[Radian],1), #y
density=c(30), #塗りつぶす濃度
angle=c(45),　 　　　#塗りつぶす斜線の角度
col=rgb(0,0,1)) 　#塗りつぶす色

#線追加（三角）
segments(cy[Radian],cx[Radian],0,cx[Radian],col=rgb(1,0,0))

#文字追加
text(c(0,cy[Radian],0,0),c(1,cx[Radian],-1,cx[Radian]), labels=c("a","d","c","b"),col=c(rgb(0,0,0),rgb(1,0,0),rgb(0,0,0),rgb(1,0,0)),cex=c(2,2,2,2))
text(0,0,labels="0",col=rgb(0,1,0),cex=2)
}

#アニメーション
library("animation")
Time_Code=rev(seq(1,59, length=30))
saveGIF({
for (i in Time_Code){
　CFS90Sift(i)
}
}, interval = 0.1, movie.name = "CFS90Sift01.gif")
```
* この時<font color="green">‖x+y‖=‖x‖+‖y‖</font>が成立するのは<font color="green">cos(θ)=0</font>か<font color="green">sin(θ)=0</font>の場合のみ。

ちなみに**単位円**において**三角比**(<font color="blue">Triangular ratio</font>)概念が通用する範囲は以下の6通り。
[【Rで球面幾何学】「半円しか描けなかった」世界の思い出？](https://qiita.com/ochimusha01/items/cf74b1fff650edb0a496)

* **第一象限**(<font color="blue">cos(θ)>=0,sin(θ)>=0</font>)のみ。
* **第一象限**とそれに隣接する**第二象限**(<font color="blue">cos(θ)=1→0→-1,sin(θ)=0→1→0</font>)。
* **第一象限**とそれに隣接する**第四象限**(<font color="blue">cos(θ)=0→1→0,sin(θ)=1→0→-1</font>)。
* **第三象限**(<font color="blue">cos(θ)<=0,sin(θ)<=0</font>)のみ。
* **第三象限**とそれに隣接する**第四象限**(<font color="blue">cos(θ)=1→0→-1,sin(θ)=0→-1→0</font>)。
* **第三象限**とそれに隣接する**第二象限**(<font color="blue">cos(θ)=0→-1→0,sin(θ)=1→0→-1</font>)。

とりあえず現時点では役立てる方法を思いつきませんが**Ravi変換**や**相加相乗平均の不等式**(<font color="blue">Additive Geometric Mean Inequality</font>)<font color="green">a+B>=2sqrt(a×b)</font>(<font color="blue">a=bの時のみ等号が成立</font>)との関係が深い事でも知られています。
[Ravi変換](https://shakayami-math.hatenablog.com/entry/2019/03/04/022518)
[相加相乗平均の不等式とそのエレガントな証明](https://mathtrain.jp/amgm)

<font color=purple>証明</font>
>長さがそれぞれ<font color="green">a</font>,<font color="green">b</font>,<font color="green">c</font>であるような3つの線分に関して, 三角不等式「**一番長い辺が他の2つの辺の和より小さい**」が成立する時,<font color="green">a</font>,<font color="green">b</font>,<font color="green">c</font>を3辺とする三角形が成立する。
>
>数式化すると、

- <font color="green">a+b>c</font>
- <font color="green">b+c>a</font>
- <font color="green">c+a>b</font>

>1文字(<font color="blue">ここではaにする</font>)について整理すると、

- <font color="green">a>c−b</font>
- <font color="green">b+c>a</font>
- <font color="green">a>b−c</font>

>まとめて

- <font color="green">|b−c|</font>

>特に<font color="green">max{a,b,c}=a</font>である時<font color="green">a>|b−c|</font>であるから

- <font color="green">a<b+c</font>

>これを「**一番長い辺が他の2つの辺の和より小さい**」と表した。

ところでコンピューター言語においては容易に「**区間や条件や個数を定めて発生させた乱数データ**」を通常の数列の様に扱う事が可能です。
![image.gif](https://cdn-ak.f.st-hatena.com/images/fotolife/o/ochimusha01/20201209/20201209012802.gif)

```R
ND<-function(x){
cx<-rnorm(1000)
cy<-rnorm(1000)
plot(cx,cy,xlim=c(-4,4),ylim=c(-4,4),main="Normal Distribution",xlab="",ylab="")
}
#アニメーション
library("animation")
Time_Code=seq(1,16,length=16)
saveGIF({
for (i in Time_Code){
　ND(i)
}
}, interval = 0.1, movie.name = "ND01.gif")
```
<font color=purple>中心推定付</font>
![image.gif](https://cdn-ak.f.st-hatena.com/images/fotolife/o/ochimusha01/20210117/20210117000455.gif)

```R
ND<-function(x){
cx<-rnorm(1000)
cy<-rnorm(1000)
plot(cx,cy,xlim=c(-4,4),ylim=c(-4,4),main="Normal Distribution",xlab="",ylab="")
text(mean(cx),mean(cy),"X",col=rgb(0,1,0))
}
#アニメーション
library("animation")
Time_Code=seq(1,16,length=16)
saveGIF({
for (i in Time_Code){
　ND(i)
}
}, interval = 0.1, movie.name = "ND01.gif")
```
<font color=purple>同心円表示付(N=1000)</font>
![image.gif](https://cdn-ak.f.st-hatena.com/images/fotolife/o/ochimusha01/20210117/20210117002845.gif)

```R
ND<-function(x){
cx<-rnorm(1000)
cy<-rnorm(1000)
plot(cx,cy,xlim=c(-4,4),asp=1,ylim=c(-4,4),main="Normal Distribution",xlab="",ylab="")
c0<-seq(-pi,pi,length=61)
cx0<-cos(c0)
cy0<-sin(c0)
par(new=T)#上書き指定
plot(cx0+mean(cx),cy0+mean(cy),type="l",asp=1,xlim=c(-4,4),ylim=c(-4,4),main="",xlab="",ylab="",col=rgb(0,1,0))
par(new=T)#上書き指定
plot(cx0*2+mean(cx),cy0*2+mean(cy),type="l",asp=1,xlim=c(-4,4),ylim=c(-4,4),main="",xlab="",ylab="",col=rgb(0,1,0))
par(new=T)#上書き指定
plot(cx0*3+mean(cx),cy0*3+mean(cy),type="l",asp=1,xlim=c(-4,4),ylim=c(-4,4),main="",xlab="",ylab="",col=rgb(0,1,0))
text(mean(cx),mean(cy),"X",col=rgb(0,1,0))
}
#アニメーション
library("animation")
Time_Code=seq(1,16,length=16)
saveGIF({
for (i in Time_Code){
　ND(i)
}
}, interval = 0.1, movie.name = "ND02.gif")
```
<font color=purple>同心円表示付(N=100)</font>
![image.gif](https://cdn-ak.f.st-hatena.com/images/fotolife/o/ochimusha01/20210117/20210117003225.gif)

```R
ND<-function(x){
cx<-rnorm(100)
cy<-rnorm(100)
plot(cx,cy,xlim=c(-4,4),asp=1,ylim=c(-4,4),main="Normal Distribution",xlab="",ylab="")
c0<-seq(-pi,pi,length=61)
cx0<-cos(c0)
cy0<-sin(c0)
par(new=T)#上書き指定
plot(cx0+mean(cx),cy0+mean(cy),type="l",asp=1,xlim=c(-4,4),ylim=c(-4,4),main="",xlab="",ylab="",col=rgb(0,1,0))
par(new=T)#上書き指定
plot(cx0*2+mean(cx),cy0*2+mean(cy),type="l",asp=1,xlim=c(-4,4),ylim=c(-4,4),main="",xlab="",ylab="",col=rgb(0,1,0))
par(new=T)#上書き指定
plot(cx0*3+mean(cx),cy0*3+mean(cy),type="l",asp=1,xlim=c(-4,4),ylim=c(-4,4),main="",xlab="",ylab="",col=rgb(0,1,0))
text(mean(cx),mean(cy),"X",col=rgb(0,1,0))
}
#アニメーション
library("animation")
Time_Code=seq(1,16,length=16)
saveGIF({
for (i in Time_Code){
　ND(i)
}
}, interval = 0.1, movie.name = "ND03.gif")
```
<font color=purple>同心円表示付(N=10)</font>
![image.gif](https://cdn-ak.f.st-hatena.com/images/fotolife/o/ochimusha01/20210117/20210117003848.gif)

```R
ND<-function(x){
cx<-rnorm(10)
cy<-rnorm(10)
plot(cx,cy,xlim=c(-4,4),asp=1,ylim=c(-4,4),main="Normal Distribution",xlab="",ylab="")
c0<-seq(-pi,pi,length=61)
cx0<-cos(c0)
cy0<-sin(c0)
par(new=T)#上書き指定
plot(cx0+mean(cx),cy0+mean(cy),type="l",asp=1,xlim=c(-4,4),ylim=c(-4,4),main="",xlab="",ylab="",col=rgb(0,1,0))
par(new=T)#上書き指定
plot(cx0*2+mean(cx),cy0*2+mean(cy),type="l",asp=1,xlim=c(-4,4),ylim=c(-4,4),main="",xlab="",ylab="",col=rgb(0,1,0))
par(new=T)#上書き指定
plot(cx0*3+mean(cx),cy0*3+mean(cy),type="l",asp=1,xlim=c(-4,4),ylim=c(-4,4),main="",xlab="",ylab="",col=rgb(0,1,0))
text(mean(cx),mean(cy),"X",col=rgb(0,1,0))
}
#アニメーション
library("animation")
Time_Code=seq(1,16,length=16)
saveGIF({
for (i in Time_Code){
　ND(i)
}
}, interval = 0.1, movie.name = "ND04.gif")
```
三次元だとこんな感じ。こうした画像の、ガウスが「**円の面積がπなら1辺の長さはsqrt(π)に決まってるじゃん!!**」と問答無用で殴りかかってくる感じが好きです。
![image.gif](https://cdn-ak.f.st-hatena.com/images/fotolife/o/ochimusha01/20201110/20201110010727.gif)

```R
library(rgl)
Rtime<-seq(0,2*pi,length=60)
cx<-rnorm(1000)
cy<-rnorm(1000)
cz<-rnorm(1000)
plot3d(cx,cy,cz,type="p",xlim=c(-4,4),ylim=c(-4,4),zlim=c(-4,4))
movie3d(spin3d(axis=c(0,0,1),rpm=5),duration=10,fps=25,movie="~/Desktop/r06")
```

そして実際、数学再勉強者としてそういう部分がこうした概念の再獲得に役立ったりしてるのです。 例えば以下。

吉田武「**オイラーの贈物**」「**基礎理論**(<font color="blue">Basic Theory</font>)」より

>**連続性**(<font color="blue">Continuity</font>)を扱う**数直線**(<font color="blue">Number line</font>)上においては**端点**(<font color="blue">End Point</font>)の設定により以下の記法(<font color="blue">Notation</font>)を用いる。

```R
> c0<-seq(0,10,length=11)
> c0
 [1]  0  1  2  3  4  5  6  7  8  9 10
#閉区間(Closed Interval)[a,b](a<=x<=b)
> c0[c0>=3 & c0<=6]
[1] 3 4 5 6
#開区間(Open Interval)(a,b)(a<x<b)
> c0[c0>3 & c0<6]
[1] 4 5
#半開区間(Semi-Open Interval)[a,b)(a=<x<b)
> c0[c0>=3 & c0<6]
[1] 3 4 5
#半開区間(Semi-Open Interval)(a,b](a<=>x>a)
> c0[c0>3 & c0<=6]
[1] 4 5 6
```

>ここで**絶対値**(<font color="blue">Absolute Value</font>)<font color="green">|x|</font>の概念を導入しよう。xの符号の正負に関りなくその大きさのみを取り出す。**定義**(<font color="blue">Definition</font>)は以下。

```R
#|x|≡x(x>=0の時)
> abs(6)
[1] 6
#|x|≡-x(x<0の時)
> abs(-6)
[1] 6
```

>この記号を用いれば不等式を以下の様に簡潔に表せる。

```R
> c0<-seq(-5,5,length=11)
> c0
 [1] -5 -4 -3 -2 -1  0  1  2  3  4  5
#不等式-a<x<a
#|x|<a(ただしa>0)
> c0[c0>-3 & c0<3]
[1] -2 -1  0  1  2
#幾何学的に考えれば数直線上の0を中心とした幅2aの中に数xが存在する事を意味する。
```
とっさに想起したのが「**0除算が発生する為、X<=0やy<=0の場合が扱えない一次関数や数列**」でした。数学再学習者とはいえ、あくまで「**はじめにコンピューターありき**」なんですね。

<font color=purple>三角不等式の証明</font>

>二数a</font>,b</font>の正負を場合分けする事により、容易に以下を得る。

- |a,b|=|a|*|b|</font>

>また任意のa,bに対して以下が成り立つので、

- -|a|<=a<=|a|</font>
- -|b|<=b<=|b|</font>
 
>辺々を加え以下が成立する。

- -(|a|+|b|)<=a+b<=|a|+|b|</font>

>これは絶対値の定義によって以下の様に書け**三角不等式**(<font color="blue">Triangle Inequalty</font>)と呼ばれる。

- |a+b|<=|a|+|b|</font>

>等号はa>=0の時成り立つ。この式でa</font>を(a-b)</font>に置き換えると、

- |(a-b)+b|=|a|<=|a-b|+|b|</font>

>より

- |a|-|b|<=|a-b|</font>

>を得る。これは最も基本的な不等式である。

さて、こうした数理の再学習にあたって私はどうしたか？　なんと「**実験**」とか始めたのです。

```R
#数列単位で比較出来る。
c(1,2,3)>c(2,1,3)
[1] FALSE TRUE FALSE

#最小-5、最大5の乱数10個で試してみる。
a=round(runif(10,-5,5))
a
[1] -1 1 1 -1 -1 -3 4 4 -3 3
abs(a)
[1] 1 1 1 1 1 3 4 4 3 3

b=round(runif(10,-5,5))
b
[1] 1 -3 4 4 -4 3 -3 4 4 3
abs(b)
[1] 1 3 4 4 4 3 3 4 4 3
a==b
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE TRUE
a!=b
[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE FALSE TRUE FALSE
a>b
[1] FALSE TRUE FALSE FALSE TRUE FALSE TRUE FALSE FALSE FALSE
a<b
[1] TRUE FALSE TRUE TRUE FALSE TRUE FALSE FALSE TRUE FALSE
a<=b
[1] TRUE FALSE TRUE TRUE FALSE TRUE FALSE TRUE TRUE TRUE
a>=b
[1] FALSE TRUE FALSE FALSE TRUE FALSE TRUE TRUE FALSE TRUE

#式の動作の確認
abs(a*b)==abs(a)*abs(b)
[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
-(abs(a)+abs(b))<=a+b
[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
-(abs(a)+abs(b))<=a+b
[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
a+b<=abs(a)+abs(b)
[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
abs(a)-abs(b)<=abs(a-b)
[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
```
こうやって私は「**正規分布の半径3以上で急速に収束していく感じ**」を次第に捉えていったのでした。思えば遠くに来たもんだ…
[【初心者向け】誤差関数(ERF)と相補誤差関数 (ERFC)。](https://qiita.com/ochimusha01/items/ee8b32e4b2cc7ce4acb0)
![image.gif](https://qiita-user-contents.imgix.net/https%3A%2F%2Fcdn-ak.f.st-hatena.com%2Fimages%2Ffotolife%2Fo%2Fochimusha01%2F20201113%2F20201113111114.gif?ixlib=rb-1.2.2&auto=format&gif-q=60&q=75&w=1400&fit=max&s=1be74c11a381d9d345d61b6c2be72199)
そういえば、あえて一昔前の教科書を選んだ事で「**コンピューター革命**」を実感する場面も。

>循環小数(recurring decimal)0.3333…(無限に続く)について

- A=0.3333…(無限に続く)

>とする。両辺を10倍して

10A=3.33333…(無限に続く)=3+A

>よって

- 9A=3

>よって

- A=1/3

>0.9999…(無限に続く)を途中で1と置いている訳だが、有理数(rational number)のこうした側面を認めないと実数(real number)の連続性(continuity)仮定が崩壊してしまう。

コンピューター処理が普及したらあまり気にされなくなった案件…

```R
#通常ライブラリには、そもそも循環小数への配慮自体がない。
1/3*10
[1] 3.333333

#代数ライブラリyacasは逆に約分自体をしない。
library(Ryacas)
yacas("1/3*10")
expression(10/3)
```

エンジニアというより、むしろ数学教育者に読んで欲しい内容。「**実験**」って楽しいの…