このブログは、旧・はてなダイアリー「檜山正幸のキマイラ飼育記 メモ編」(http://d.hatena.ne.jp/m-hiyama-memo/)のデータを移行・保存したものであり、今後(2019年1月以降)更新の予定はありません。

今後の更新は、新しいブログ http://m-hiyama-memo.hatenablog.com/ で行います。

有限オーディナルと写像の圏 -- JavaScriptによる実装


/* MapFO.js -- Map Category over Finite Ordinals */

// 整数の区間を作る
// (一般的にも使えそう)
function seq(n, m) { // n, mは整数、n ≦ m と仮定
var a = new Array();
for (var i = 0; i <= (m - n); i++) {
a[i] = n + i;
}
return a;
}

// 名前空間を提供するオブジェクト
var MapFO = {
};

// 内部的に使うコンストラク
function _MapFO(n, m, values) {
this.dom = n;
this.cod = m;
this.values = values;
}

// 射の印字のために
_MapFO.prototype.toString = function() {
var s = "[" + this.dom + "] --> [" + this.cod + "]\n";
var v = this.values;
for (var i = 0; i < v.length; i++) {
s = s + (i + 1) + " |--> " + v[i] + "\n";
}
return s;
};

// 配列aが 0 ≦ a[i] ≦ m であるかどうか調べる
//(内部的に使用する)
MapFO._isValuesArray = function(a, m) { // aは配列、mは非負整数と仮定
for (var i = 0; i < a.length; i++) {
if (typeof a[i] != 'number') return false;
if (a[i] <= 0 || m < a[i] ) return false;
}
return true;
};

// この圏の対象かどうかを判定
MapFO.isObject = function(x) { // xに浮動小数点数入れるのはカンベンして!
return (
typeof x === 'number'
&&
x >= 0
);
};

// この圏の射かどうかを判定
MapFO.isMorphism = function(x) {
return (
typeof x === 'object' && x instanceof _MapFO
);
};

// 射の域
MapFO.dom = function(f) {
if (!MapFO.isMorphism(f)) throw "not a morphism";
return f.dom;
};

// 射の余域
MapFO.cod = function(f) {
if (!MapFO.isMorphism(f)) throw "not a morphism";
return f.cod;
};

// fとgが結合可能かどうかを判定
MapFO.composable = function(f, g) {
return (
MapFO.isMorphism(f)
&&
MapFO.isMorphism(g)
&&
MapFO.cod(f) === MapFO.dom(g) // 結合可能性の条件
);
};

// fとgを結合(合成)
MapFO.compose = function(f, g) {
if (!MapFO.composable(f, g)) throw "cannot compose";
var v = new Array();
for (var i = 0; i < f.dom; i++) {
v[i] = g.values[f.values[i] - 1];
}
var map = new _MapFO(f.dom, g.cod, v);
return map;
};

// 恒等
MapFO.id = function(n) {
if (!MapFO.isObject(n)) throw "not an object";
return new _MapFO(n, n, seq(1, n));
};

// 射のコンストラク
MapFO.newMorphism = function(n, m, v) {
if (!MapFO.isObject(n) || !MapFO.isObject(m)) throw "not an object";
if (!(typeof v === 'object' && v instanceof Array))
throw "values must be an array";
if (v.length != n) throw "size not match";
if (!MapFO._isValuesArray(v, m)) throw "illegal values";
return new _MapFO(n, m, v);
};

// 射のコンストラクタ 簡便バージョン
MapFO.mor = function(a1, a2, a3) {
var n, m, v;
if (typeof a3 === 'undefined') {
n = a2.length;
m = a1;
v = a2;
} else {
n = a1;
m = a2;
v = a3;
}
return MapFO.newMorphism(n, m, v);
};

// 射が等しいかどうかを判定
MapFO.eq = function(f, g) {
if (!MapFO.isMorphism(f) || !MapFO.isMorphism(g))
throw "not a morphism";
if (f.dom != g.dom || f.cod != g.cod)
return false;
for (var i = 0; i < f.dom; i++) {
if (f.values[i] != g.values[i])
return false;
}
return true;
};