中の人の徒然草426 集合に関する自分の考えをプログラムで整理
using System;
using System.Collections.Generic;
//可能性
enum Possibility
{
Absolutely,
Possible,
Impossible,
}
//集合
class Set
{
//集合の説明
private string m_explanation;
//集合の有無
private bool m_isSet;
public bool IsSet
{
get { return m_isSet; }
}
//対応
private Func<object, Possibility> m_contained;
//部分集合
List<Set> m_subSet;
//保持する元
List<object> m_elments;
//説明文および集合と元(要素)の対応を指定する
public Set( string explanation, Func<object,
Possibility> isFunc )
: this( explanation, isFunc, true ) { }
//集合の有無も指定する
public Set( string explanation, Func<object,
Possibility> isFunc, bool isSet )
{
this.m_explanation = explanation;
this.m_contained = isFunc;
this.m_isSet = isSet;
this.m_subSet = new List<Set>();
this.m_elments = new List<object>();
}
//指定した元が集合に属するか判定する
public bool Contained( object element )
{
//基本チェック
Possibility pos = this.m_contained( element );
switch ( pos ) {
case Possibility.Absolutely:
if ( element is Set &&
!this.m_elments.Contains( element ) ) {
this.m_elments.Add( element );
} else {
if ( !this.m_elments.Contains( element ) )
this.m_elments.Add( element );
}
return true;
case Possibility.Impossible:
return false;
case Possibility.Possible:
break;
}
bool result = true; //正しいと仮定
//元が部分集合かチェック
Set obj = element as Set;
Possibility subFlag = Possibility.Impossible;
if ( obj != null ) {
if ( this.m_subSet.Contains( obj ) ) {
return true;
} else {
subFlag = this.IsSubSet( obj );
if ( subFlag == Possibility.Absolutely )
this.m_subSet.Add( obj );
if ( subFlag == Possibility.Impossible )
return false;
}
} else {
if ( pos == Possibility.Absolutely &&
this.m_elments.Contains( element ) == false ) {
this.m_elments.Add( element );
}
}
//元が部分集合のものかチェック
if ( subFlag == Possibility.Possible )
return SubSetCheck( element );
//最終結果を返す
return result;
}
//指定された集合が部分集合かチェックする
private Possibility IsSubSet( Set target )
{
bool result = false;
if ( this.m_explanation.Equals( target.m_explanation ) )
return Possibility.Possible;
if ( target.m_subSet.Count == 0 ) {
result = this.IsElement( target );
if ( result == false )
return Possibility.Impossible;
else return Possibility.Possible;
}
if ( this.m_contained( target )
== Possibility.Impossible ) {
return Possibility.Impossible;
} else {
foreach ( Set sub in target.m_subSet ) {
if ( this.IsSubSet( sub ) ==
Possibility.Impossible )
return Possibility.Impossible;
}
return Possibility.Possible;
}
}
//自身の要素かチェックする
private bool IsElement( Set target )
{
if ( target.m_elments.Count != 0 ) {
foreach ( object element in target.m_elments ) {
if ( this.Contained( element ) == false )
return false;
}
return true;
}
return true;
}
//部分集合の要素かチェック
private bool SubSetCheck( object target )
{
foreach ( Set subSet in this.m_subSet ) {
if ( subSet.Contained( target ) == false )
return false;
}
return true;
}
//集合の説明を返す
public override string ToString()
{
return this.m_explanation;
}
}
class Program
{
//実験
static void Main()
{
//メタ集合(集合の集合の普遍集合)
Func<object, Possibility> metaF = ( x ) => {
if ( x == null ) return Possibility.Possible;
bool hit = x.GetType() == typeof( Set );
if ( hit ) return Possibility.Absolutely;
return Possibility.Possible;
};
Set metaSet = new Set( "メタ集合", metaF );
//全ての集合を元として持つ集合
Func<object, Possibility> setF = ( x ) => {
if ( x == null ) return Possibility.Impossible;
Set y = x as Set;
if ( y == null )
return Possibility.Possible;
if ( y.IsSet == false )
return Possibility.Impossible;
return Possibility.Possible;
};
Set setSet = new Set( "集合の集合", setF );
/*どの集合にも属しない元からなる集合
(集合の集合のNOT集合)
長いからNOT集合とする*/
Func<object, Possibility> notF = ( x ) => {
bool result = setSet.Contained( x );
if ( result == false )
return Possibility.Absolutely;
return Possibility.Impossible;
};
Set notSet = new Set( "NOT集合", notF, false );
//メタ集合に属するか?
Action<object, Set> MessageShow =
( x, y ) =>
Console.WriteLine( "{0}は{1}に属するか?:{2}",
x, y, y.Contained( x ) );
MessageShow( setSet, metaSet );
MessageShow( notSet, metaSet );
Console.WriteLine();
//自然数の集合は集合の集合に属するか?
Func<object, Possibility> nf = ( x ) => {
if ( x == null )
return Possibility.Impossible;
if ( x is int == false ) {
if ( x is Set ) return Possibility.Possible;
else return Possibility.Impossible;
}
bool hit = ( ( int ) x ) > 0; //0も含まないとする
if ( hit ) return Possibility.Absolutely;
else return Possibility.Impossible;
};
Set N = new Set( "自然数の集合", nf );
int a = -1;
MessageShow( a, N );
int b = 0;
MessageShow( b, N );
int c = 1;
MessageShow( c, N );
Console.WriteLine();
//自然数の集合はどこに属する?
MessageShow( N, setSet );
MessageShow( N, notSet );
MessageShow( N, metaSet );
Console.WriteLine();
//自然数の奇数の集合
Func<object, Possibility> of = ( x ) => {
if ( x is int == false )
return Possibility.Impossible;
int value = ( int ) x;
bool result = ( value > -1 && value % 2 == 1 );
if ( result ) return Possibility.Absolutely;
else return Possibility.Impossible;
};
Set oddSet = new Set( "自然数の奇数の集合", of );
int d = 0;
MessageShow( d, oddSet );
int e = 1;
MessageShow( e, oddSet );
int f = 2;
MessageShow( f, oddSet );
Console.WriteLine();
//奇数集合はどこに属する?
MessageShow( oddSet, N );
MessageShow( oddSet, setSet );
MessageShow( oddSet, notSet );
MessageShow( oddSet, metaSet );
Console.WriteLine();
//集合の集合は2つの集合を含むか?
MessageShow( notSet, setSet );
MessageShow( metaSet, setSet );
Console.WriteLine();
//終了
Console.WriteLine();
Console.WriteLine( "終了しました。");
Console.WriteLine( "Enterキーを押して下さい。" );
Console.ReadLine();
}
}
私が考えた事は・・・1.集合は対応を調べる手段を持たねばならない。
持たなければ、元を調べられないと言う事であり、集合の原理に反する。
2.1により集合を写像もしくは対応そのものと看做す事ができる。
3.あらゆる集合は集合演算ができなければならない。
出来なければそれは集合ではない。
プログラムでは型システムでチェック。
4.3により全ての集合にNOT集合と普遍集合がなければならない。
5.部分集合の定義(※1)により、部分集合の全ての元は上位集合の写像範囲内でなければならない。
※1:部分集合の定義は「全てのAの元がBに属する時、AはBの部分集合である。」
プログラムにして再認識したのですが、1と5が意外と難しい問題です。集合の集合に数値が属するか否かは、部分集合を調べないと分かりません。つまり、部分集合で元を判定しないと分からない集合が存在すると言う事です。そもそも、集合の集合なのですから、元が集合に含まれるかを考えなければならないのです。
あと、メタ集合(集合の集合の普遍集合。集合演算に必要)が集合の集合に含まれない事がはっきりしました。仮に含むとすると、メタ集合は集合でない元を含むので、部分集合の定義に反します。すなわち、メタ集合は集合の集合とは呼べません。
あと、集合の集合のNOT集合である、集合でない元で構成される集合は、集合の集合で属するか否かに依存する対応を持つ事もはっきりしました。
これらは予想がついたのですが、1つ予想外の事実が分かりました。それは、ファジイ集合が自ずと出てくる事です。ファジイ理論は少しだけ調べた事があるのですが、ファジイ集合の存在は忘れていました。しかし今回、属することの意味を考えたとき、「可能性がある」「可能性がない」「絶対に属する」という3値が必要となりました。それで昔調べたファジイ理論を思い出し、調べてみるとファジイ集合の存在が分かりました。あとでファジイ理論を復習する必要がありますね。
それと、本題とは関係がありませんが、なんとなくC#でプログラミングしたのですが、関数の定義が多いからF#の方が美しいかもしれないと後で思いました。数学の検証はF#にするべきかもしれません。
やはり、集合論のパラドックスは、属するという意味が厳密に定義されていない点に問題あるようです。また、濃度も曖昧です。プログラミングできるほど厳密に定義されていません。代数的に演算できるぐらいにならないと、実務的な観点から言うと不足しています。まだ不完全な理論です。しかし集合論に矛盾は存在しないと思います。部分集合の定義からメタ集合の属性がはっきりしました。詳細に定義を追うと自ずと答えが見えてきます。従って、矛盾ではなく定義不足だと思います。
ちなみに、今のところツェルメロの「大きすぎる集合は考えない」という立場は反対です。集合論は数学の範囲を超える理論です。それを狭める必要はないと思います。システム開発で似たような理論を自然に使っているしね。システム開発は数学の範囲外の事が多すぎます(自分の勉強不足も否めない)
「全て今までどおりしたいが、利益を出したい。」なんて依頼も頻繁にあります。それは、人間として当たり前の感覚なので否定するつもりは毛頭ありませんが、冷静に考えて理論的には難しいです。今まで通りしていて利益が出るのならば、現在利益が出ているはずです。こうした場合、仕方がないのでその旨を丁寧に伝えて、今まで通りに見えるけどちょっと変えて利益を出すシステムを提案します。この様な現在の数学で解明できない事を、集合論は定義できる可能性があります。それを捨てるのは余りに惜しいです。
数学に限らず、出来ないと思考停止したり、小さくまとまったりするのではなく、常に出来るように変えるのがよいと私は考えています。今まで人類はそうしてきました。これからもそうするべきではないでしょうか?