人気ブログランキング |

ベン図とHaskell

ベン図を Haskell で記述してみた。Data.List モジュールの集合演算を利用するので Data.List をインポートする。

Prelude> import Data.List

まず領域 D の要素をアルファベット1文字の a,b,c,d,e,f とする。

Prelude Data.List> domain = "abcdef"

領域 D のべき集合を計算する関数 pow を定義する。
Prelude Data.List> pow [] = [[]]; pow (x:xs) = map (x:) (pow xs) ++ pow xs
Prelude Data.List> pow domain
["abcdef","abcde","abcdf","abcd","abcef","abce","abcf","abc","abdef","abde","abdf","abd","abef","abe","abf","ab","acdef","acde","acdf","acd","acef","ace","acf","ac","adef","ade","adf","ad","aef","ae","af","a","bcdef","bcde","bcdf","bcd","bcef","bce","bcf","bc","bdef","bde","bdf","bd","bef","be","bf","b","cdef","cde","cdf","cd","cef","ce","cf","c","def","de","df","d","ef","e","f",""]

領域の要素数より、集合の方が格段に多いことが分かる。

Prelude Data.List> length domain
6
Prelude Data.List> length $ pow domain
64

要素が集合に属しているかどうかは、Prelude の elem 関数で調べることができる。

Prelude Data.List> elem 'a' "abc"
True
Prelude Data.List> elem 'd' "abc"
False

領域 D の要素を主語とする述語の真理値は要素が主語に含まれているかどうかで判別できるから次のように定義できる。

Prelude Data.List> p1 x = elem x "abd"
Prelude Data.List> p2 x = elem x "bcd"
Prelude Data.List> p1 'a'
True

これらの述語は domain の要素について排中律を満たしている。

Prelude Data.List> map (p1) domain
[True,True,False,True,False,False]

Haskell の内包表記を使うと、これらの述語で集合を内包的に定義できる。

Prelude Data.List> [x| x <- domain, p1 x]
"abd"
Prelude Data.List> [x| x <- domain, p2 x]
"bcd"

Data.List モジュールには集合演算 union と intersect が定義してある。

Prelude Data.List> "abd" `union` "bcd"
"abdc"
Prelude Data.List> "abd" `intersect` "bcd"
"bd"

これらの集合演算は述語の論理演算の真理集合と一致している。

Prelude Data.List> [x| x <- domain, (p1 x) || (p2 x)]
"abcd"
Prelude Data.List> [x| x <- domain, (p1 x) && (p2 x)]
"bd"

このように、ベン図の様々な概念を Haskell でプログラムすることができる。

# by tnomura9 | 2020-01-27 16:43 | Comments(0)

ベン図の集合と論理

素朴集合の直観的なモデルとしてベン図があるが、ベン図上で集合と論理がどのように表現されるかを考えてみた。

まず、考察の対象とする個体の集合を領域(D, domain) と呼ぶことにする。ベン図では全体集合と呼ばれている。領域 D の要素は個体であり、集合は含まれていない。

この領域 D の部分集合を集合(Set)と定義する。今考えているのは領域 D が有限集合なので、その部分集合である集合は必ず存在する。

領域 D のべき集合を Pow(D) とすると、Pow(D) の要素は領域 D における集合を網羅している。

述語 P(x) とは領域 D から二値集合 {True, False} への関数である。また領域 D の要素と述語 P(x) のペア (a, P) を命題という。P(a) は a の P(x) による値で True, または False だが、これを表記に注目してP(a)という命題とみなしてもいい。

述語 P(x) を True にする領域 D の要素を集めるとそれは集合になる。この集合を述語 P(x) の真理集合と呼ぶ。述語 P(x) は無限に考えることができるが、領域 D の個体全てに P(a) が True であるか False であるかを割り当てることが述語 P(x) の条件である。P(a)が真であるか偽であるか確定できないラッセルの集合のようなものの述語は排除される。

述語 P(x) の真理集合は必ず領域 D の部分集合であり、領域 D の部分集合の全ては Pow(D) の要素である。したがって、述語Pが無限にあってもそのなかには真理集合が同じ述語どうしがある。真理集合が同じ述語どうしは論理的に同値である。無限の述語があっても、それは真理集合によって同値類に分けられる。

このような条件のもとにあっては、集合は述語による内包的定義で定義することができる。

このモデルでは論理演算は2値集合 {True, False} における2項演算である。これは単に命題の値に関する演算規則でしかない。たとえば P(a) ∧ Q(b) の真理値は P(a) の真理値と Q(b) の真理値のみから計算される。命題 P(a) と Q(b) の内部的な論理関係は問題にされない。このような定義では含意は単なる2項演算であり A -> B = ¬A ⋁ B である。

集合演算と論理の関係も考えてみる。集合 A を内包的に定義する述語を A(x) とし、集合 B を内包的に定義する述語を B(x) とする。集合 A と集合 B の両方に属する要素を a とすると、A(a) は True で B(a) も True である。このとき A(a) ∧ B(a) も True である。a が集合 A と 集合 B の共通部分であるとき命題 A(a) ∧ B(a) は常に真となる。しかし要素 a が A と B の共通部分に含まれないとき、たとえば、A(a) の真理値が True でも B(a) の真理値が False の場合 A(a) ∧ B(a) は False となるから A(a) ∧ B(a) が True となるのは a が集合 A と 集合 B の共通部分の要素の時だけである。逆に A(a) ∧ B(a) が真の時、a は必ず A ⋂ B の要素である。したがって A(x) ∧ B(x) は集合 A ⋂ B を内包的に定義する述語である。

この集合演算と論理演算の対応関係は、述語の論理演算に関してしか成立しない。つまり、A(x) と B(x) は同じ個体 x を主語としていなければならない。たとえば、領域 D で命題 A(a) と命題 B(b) の真理値が True の場合、A(a) ∧ B(b) の値も True だが、これが A と B の共通部分の存在を表しているというわけではない。集合と論理の関係は全般的なものではなく、限定的なものだ。

ベン図ではまた、量化子のある命題も説明できる。∀xA(x) は述語 A(x) がすべての個体について True となる場合に真であるから、これは A = D であることを示している。この命題の主語は D の要素である個体ではなく、集合であるから P(a) などの個体と述語からなる命題とは異なっている。P(a) と ∀xA(x) が関連して議論されるのは、その真理値の論理演算についてのみである。

∃xA(x) の場合には集合 A が存在するとき、あるいは A ≠ Φ のとき True である。また、これは ¬(∀x(¬A(x)) と同値である。両者の同値関係はそれぞれの真理値の論理演算結果を考慮して判断される。このときも命題の主語は集合であって、単純命題のような個体ではなく、両者を直接的に比較することはできない。

このようにベン図をモデルとして集合と論理を考えた場合、一階述語論理については、論理と集合の間の関係は部分的なものであることが分かる。また、単純命題と量化子のある命題については、直接的に論じることはできず、その真理値の論理演算に関してのみ議論できることが分かる。

一階述語論理が命題論理の拡張であるとしても、一階述語論理が命題論理を包含している訳ではないような気がする。また、量化子を用いた命題の場合は、個体を主語とし、述語とのペアで作られる単純命題とは性質が異なるような気がする。

実際には、一階述語論理には主語の違う命題を扱っている様に見えるものがある。たとえば、イプシロン・デルタ論法のばあい次のような命題になる。

 ∀ε>0, ∃δ>0 s.t. ∀x∈R, 0<|x-a|<δ ⇒ |f(x)-b|<ε

これを集合で扱いやすいように記述すると、次のようになる。

∃δ A(δ) -> ∀ε B(ε)

含意の前項の述語 A(x) と後項の B(x) では主語が違っている。この場合は、述語の論理演算を真理集合に読み替えることはできない。主語が違うからだ。しかし、実際には前項の命題も、後項の命題も量化子を用いた命題なので、実際の述語は集合である。δ の真理集合を D ε の真理集合を E とすると上の命題は、

A ≠ φ -> B = {x | x < ε}

という形になる。これは集合を主語と考えても、前項と後項の述語は同一の主語を要素とするとは言えない。つまり、イプシロン・デルタ論法の論理式の正当性は論理の形式だけで導き出すことはできず。集合 A と集合 B の間の内部的な関連性が必要になってくる。

それでは、この論理式に論理はどのように関わっていると考えればいいのだろうか。それは、前項と後項の真理値の組み合わせに対し含意を用いた複合命題の真理値がどう変わるかという関わりの分析だけになる。量化子を用いて命題を作りその真理値を考慮すれば、真理値と真理値の関係として論理を適用することができることになる。

論理的に妥当であるということは、命題の真理値と演算規則から導き出される真理値について妥当であるということを意味する。様々な構造の命題を真理値のみに注目して分析するのが論理の仕事なのだ。

一階述語論理といえども、論理を集合として扱うのは難しそうだ。

ただし、イプシロン・デルタ論法を集合で表現することはできる。イプシロンとデルタの直積を考えればいいのだ。正の実数の集合の直積を考える。実数の直積は2次元平面のグラフをつくると視覚化できる。横軸に ε 縦軸に δ をとると、縦軸と横軸の座標の交点がイプシロンとデルタのペアになる。また、この直積集合から真理値への写像 f(x,y) を考えると、イプシロンデルタ論法は次のように表現できる。

(δ, y) -> f(δ, y) = True

これなら含意の前項も A(x,y) というペア (x,y) の述語であるし、後項も B(x,y) という同じペアに対する述語になるので、A(x,y) -> B(x,y) という述語の論理式からなる述語が定義できて、真理集合 A が真理集合 B に包含
されることがわかる。イプシロン・デルタ論法では、∃δとなっているが、δ の値は任意に取ることができるので、この含意の命題の真理集合は正の実数の直積集合と等しい、すなわち、全ての正の実数について成り立つと言える。

論理も集合も、数学的対象の性質を述べるときのフレームワークとして使える。すなわち、論理の場合は命題を真理値に抽象化することによって命題間の論理的構造を明確にし、集合の場合は、数学的対象の集合の性質を調べることによって集合と要素の枠組みを明確にしている。

しかしながら、論理の抽象化の様式と集合の抽象化の様式は少し異なっており、単純に集合は論理だと言い切ることはできない気がする。

# by tnomura9 | 2020-01-24 07:50 | Comments(0)

CSS のみでタブを作る

CSSのみでタブ切り替えを実装する方法を解説したページを見つけた。


そこで、実装法のアイディアを追いかけてみた。

input type="radio" id="tab2" name="tab"
label for="tab2"


#tab-area input[type="radio"]
  display: none

根底の発想はタブの切り替えにラジオボタンを利用するらしい。このとき、ラジオボタンとラベルを別に記述できることを利用する。ラジオボタンとラベルを for 属性で関連付けると、ラベルをクリックすることでラジオボタンをチェックすることができる。最後に、CSS の display: none でラジオボタンを隠すとラベルだけのタブを作ることができる。

次のアイディアはチェックされたラジオボタンに関連付けられた要素を表示することだ。ラジオボタンに関連付けられた要素はつぎのようになっている。

div class="tab-box"
  div id="tab-content1">コンテンツ1の内容<
  div id="tab-content2">コンテンツ2の内容<
  div id="tab-content3">コンテンツ3の内容<

これらは最初は tab-box ごと hight 0 で隠されている。
#tab-area .tab-box div
  height: 0;

チェックされたラジオボタンに対応するコンテンツはセレクタで次のように指定され、hight: auto で表示される。

#tab1:checked ~ .tab-box #tab-content1,
#tab2:checked ~ .tab-box #tab-content2,
#tab3:checked ~ .tab-box #tab-content3
  height: auto
  opacity: 1
  padding: 10px

この実装のポイントは、チェックされたラジオボタンに対応するコンテンツをセレクタで指定する方法だ。同じ階層の要素を意味する ~ が利用されている。ちょっとトリッキーな実装だが、セレクタの活用で case 文でプログラムをしたのと同じような結果を得ることができる。

# by tnomura9 | 2020-01-17 00:31 | Comments(0)

CSS グリッド

最近は、ホームページのレイアウトを CSS で行うときは CSS グリッドを使うらしい。


CSSグリッドを使うと、ボックスを2次元に配列することができる。

まず、個々のボックスを配列するための枠が必要だ。これは親要素がその役割を果たすことになる。これをグリッドコンテナと呼ぶ。親要素をグリッドコンテナに設定するには、CSS プロパティの display を使って値を grid にする。

#mainframe {display: grid}

次にグリッドの線引きをする。線引きの単位は fr (fraction) が使える。ウィンドウの幅によって自動的にグリッドの割り振りをしてくれる。縦の線引きは grid-template-columns で、横の線引きは grid-template-rows だ。

#mainframe {
display: grid
grid-template-columns: 3fr 1fr
grid-template-rows: 1fr 3fr
}

線引きをすると自動的に線に番号が 1 .. n と番号が振られるので、どの区画に要素を配置するかはその線番号で指定する。たとえば縦線の 1 と 2 の間に要素を配置する場合は、

grid-column: 1/2;

だ。横線の2と3の間の指定は、

grid-column: 2/3;

になる。

css グリッドを使うとレイアウトが乱れないらしい。便利になったものだ。見た目重視の場合は Bootstrap などのライブラリを使うのだろうが、レイアウトだけがほしいときは、ちょいちょいとCSSグリッドで記述できるのは嬉しい。

CSS グリッドの詳しい使い方は次のサイトで説明されている。


# by tnomura9 | 2020-01-12 13:18 | Comments(0)

duckduckgo

Raspberry Pi のウェブブラウザの chromium の検索窓の検索エンジンは duckduckgo になっている。個人情報を一切記録しない検索エンジンとして人気が出ているらしい。検索エンジンのスカイウォーカーみたいなものだ。アクセス数が増えていけば検索の精度も上がっていくのだろう。

コンピュータの消費電力がどんどん下がっていっているので、個人的な特化した分野の検索エンジンをネットに公開する人も増えてくるのではないだろうか。インターネットは自由な活動の場でもあってほしい気がする。

オープンソースの活動のおかげで、オープンソースのソフトのほうが信頼できるという時代が来始めているような気がする。

# by tnomura9 | 2020-01-12 07:24 | Comments(0)

Raspberry Pi の SFTP

Raspberry Pi は標準で sftp のサーバーが動いているようだ。Windows 10 のコマンドプロンプトで sftp クライアントを起動すると Raspbery Pi にアクセスできた。

C:\Users\XXX>sftp pi@192.168.xx.xxx
pi@192.168.11.200's password:
Connected to pi@192.168.xx.xxx.
sftp> ls

クライアント側のファイルのリストは lls で調べる。
sftp> lls

ファイルのアップロードは get, ダウンロードは put コマンドで行う。
sftp> get hello.txt

sftp を終了するときは exit と入力する。
sftp> exit

sftp についての詳しい使い方はネット検索で見ることができる。Raspberry Pi をサーバーにするとすぐに SFTP が使えることが分かった。

また、FileZilla のクライアントプログラムをダウンロードすれば。Windows 10 でドラッグアンドドロップでファイルのアップロードやダウンロードができる。

ubuntu への FileZilla のインストールも簡単だ。apt update と apt install filezilla を実行するだけだ。

~$ sudo apt update
[sudo] ****** のパスワード:
~$ sudo apt install filezilla

要するに Raspbery Pi の IP アドレスを固定にして、無線LAN のルータに接続しておけば、簡単にホームサーバーが手に入るということだ。ただ、無線 LAN は家の外にも電波が出ているので、実験用以外で使うときは有線LANにした方がいいし、SSH の接続も暗号化したほうがいい。

# by tnomura9 | 2020-01-06 18:06 | Comments(0)

TCP/IP

Raspberry Pi 3B+ をイーサーネットケーブルで、無線 LAN のルータに接続してサーバー化してネットワーク関係の実験を始めたら、TCP/IP の知識が必要になってきた。ネット検索した次のサイトがわかりやすかった。


ネットワーク管理のアプリケーションは設定を行ったりするので初心者には危険だが、ネットワークの状態を表示するだけの次のコマンドは安全だ。

ネットワーク・カードの MAC アドレスや IP アドレスを確認する。ifconfig や ip addr。

~ $ifconfig
または
~ $ ip addr

ARP テープルを表示する arp。

~ $ arp

通信経路を表示する traceroute

~ $ traceroute google.co.jp

これだけのコマンドを実行して見るだけで冒頭のサイトの解説がわかりやすくなる。

Linux コマンドは man ページを読んだり、ネットの解説記事を読んだりしてもよくわからないことが多いが、とにかく使ってみることでそのツールの意図するものが理解できるような気がする。習うより慣れよだ。

# by tnomura9 | 2019-12-30 16:24 | Comments(0)

Windows 10 の scp

サーバー化した Raspberry Pi に Windows 10 から scp でファイルを送ろうとしたら失敗した。

C:\Users\あいう>scp hello.txt pi@192.168.***.***:~

とやっても、

hello.txt: No such file or directory

となって送れなかった。

原因はユーザディレクトリが日本語だからだった。別のアスキー文字のアカウントを作って、

C:\Users\abcde>scp hello.txt pi@192.168.***.***:~

としたら、ちゃんと送れた。Wincows 10 のユーザ名は絶対に日本語にしてはいけない。

# by tnomura9 | 2019-12-29 16:43 | Comments(0)

/bin の歩き方

Linux の /bin ディレクトリ以下にはたくさんの基本的なコマンドがはいっているが、一見しても何のコマンドかがわからなかったので次のように ls と man をパイプしてコマンドの意味を調べるようにしてみた。

~ $ ls /bin | xargs man

Q キーを押すと次のコマンドの man ページが表示される。また、途中で止めたいときは、コントロール+C とリターンキーを押すと抜けられる。

さらに、途中から読みたいときは次のようにする。

~ $ ls /bin | grep '^[f-z]' | xargs man

これでだいぶ /bin のコマンドの見通しがよくなった。

# by tnomura9 | 2019-12-25 07:47 | Comments(0)

busybox64.exe

Raspbery Pi の /bin ディレクトリを眺めていたら busybox というコマンドがあった。unix のコマンドがたくさん1個の実行ファイルに詰め込まれた十徳ナイフのようなプログラムらしい。組み込み Linux には必須のツールのようだ。Linux のコマンドは busybox の引数として渡されるアップレットとして使われる。例えば ls は、

~$ busybox ls -l

のような使い方をする。つまり組み込み型の Linux に busybox をインストールするだけで非常にたくさんのシェルコマンドを使うことができる。組み込み型の Linux を使わないのでありがたみがあまり感じられなかったが、いろいろと調べていくうちに、Windows 用の bosybox があるのを知った。これを Windows 10 にインストールすると、コマンドプロンプトから ls や grep が使えるというのだ。

さっそくやってみた。やり方は簡単で、busybox-w32 というサイトから busybox64.exe をダウンロードして、C:\busybox というディレクトリを作ってその中に入れる。次に、\busybox に移動して busybox --install を実行すると、Linux のコマンドが \busybox ディレクトリに展開される。後は C:\busybox を環境変数の PATH に追加して、ターミナルを再起動すればあら不思議。Windows のコマンドプロンプトで Linux のコマンドが使えるようになっているという仕掛けだ。レジストリは全くいじらなくて済む。日本語が文字化けするようだが、それでも、Windows のコマンドプロンプトで Linux のコマンドが使えるというのはいい感じだ。

具体的な手順だが、次のサイトにアクセスして、


ページの真ん中あたりに見つかる busybox64.exe をクリックすると、busybox64.exe がダウンロードフォルダにダウンロードされる。

次にエクスプローラで C:\busybox フォルダを作り、ダウンロードフォルダの busybox64.exe をドラッグアンドドロップする。

さらに、コマンドプロンプトを起動して、

~$ cd \busybox
~$ busybox64 --install

で \busybox フォルダに Linux コマンドを展開する。

最後に環境変数 PATH に C:\busybox を追加すれば準備完了だ。環境変数の設定のダイアログを開くには、「Windows の設定」の検索窓に「環境変数」と入力して検索すると良い。

コマンドプロンプトを終了して、再度立ち上げると、不思議不思議、Linux コマンドがコマンドプロンプトで使えるようになっている。

組み込み Linux で busybox が圧倒的に支持されている理由が少しわかった。

追記

コマンドプロンプトで busybox のアップレットを使うと表示が乱れることがある。まず bash でシェルを変えてから使うとちゃんと表示できるようだ。

C:\Users\****> bash
~ $ ls *.exe
lambda.exe



# by tnomura9 | 2019-12-24 19:32 | Comments(0)