実際には #define LV_T unsigned int のように 2 バイトの符号なし整数型として定められている,論理値を記述するための型であり,これを論理値型とよびます.変域は {0, 1, …, 65535} です.次のプログラムは,論理値型の変数 lv1,lv2,lv3 にそれぞれ 000Ah = 0000 0000 0000 1010b,8000h = 1000 0000 0000 0000b,FFFFh = 1111 1111 1111 1111b を代入し,十進数として表示します. #include "bml16.lib" int main(void) { LV_T lv1, lv2, lv3; lv1 = 0x000A; printf("lv1: 0000 0000 0000 1010b = %5d\n", lv1); lv2 = 0x8000; printf("lv2: 1000 0000 0000 0000b = %5d\n", lv2); lv3 = 0xFFFF; printf("lv3: 1111 1111 1111 1111b = %5d\n", lv3); return 0; }プログラムを実行すると lv1: 0000 0000 0000 1010b = 10 lv2: 1000 0000 0000 0000b = 32768 lv3: 1111 1111 1111 1111b = 65535のように表示されます. 2. double lvtotv(const LV_T lv)
論理値型の論理値 lv を,これと同一視される真理値 lv ⁄ 216 = lv ⁄ 65536 へ変換します.真理値は,16 ビットの仮数部からなる倍精度浮動小数点数型として記述されます.次のプログラムは,論理値型の論理値 lv1,lv2,lv3 をそれぞれ倍精度浮動小数点数型の真理値 tv1,tv2,tv3 へ変換して表示します. #include "bml16.lib" int main(void) { LV_T lv1 = 0x000A, lv2 = 0x8000, lv3 = 0xFFFF; double tv1, tv2, tv3; tv1 = lvtotv(lv1); printf("tv1: 0.0000 0000 0000 1010b = %18.16f\n", tv1); tv2 = lvtotv(lv2); printf("tv2: 0.1000 0000 0000 0000b = %18.16f\n", tv2); tv3 = lvtotv(lv3); printf("tv3: 0.1111 1111 1111 1111b = %18.16f\n", tv3); return 0; }プログラムを実行すると tv1: 0.0000 0000 0000 1010b = 0.0001525878906250 tv2: 0.1000 0000 0000 0000b = 0.5000000000000000 tv3: 0.1111 1111 1111 1111b = 0.9999847412109375が表示され,これは,論理値 0000 0000 0000 1010b = 10 が真理値 0.0000 0000 0000 1010b = 10 ⁄ 216 = 0.000152587890625 と同一視されることなどを反映しています. 3. LV_T tvtolv(const double frac)
倍精度浮動小数点数型の小数 frac を,frac に最も近い真理値をとる論理値型の論理値へ変換します.次のプログラムは,倍精度浮動小数点数型の真理値 tv1,tv2,tv3 (前述の lvtotv の使用例を参照) を,それぞれ論理値型の論理値 lv1,lv2,lv3 へ変換して表示します. #include "bml16.lib" int main(void) { LV_T lv1, lv2, lv3; double tv1 = 0.000152587890625, tv2 = 0.5, tv3 = 0.9999847412109375; lv1 = tvtolv(tv1); printf("lv1: 0.000152587890625 = %5d/65536\n", lv1); lv2 = tvtolv(tv2); printf("lv2: 0.5 = %5d/65536\n", lv2); lv3 = tvtolv(tv3); printf("lv3: 0.9999847412109375 = %5d/65536\n", lv3); return 0; }プログラムを実行すると lv1: 0.000152587890625 = 10/65536 lv2: 0.5 = 32768/65536 lv3: 0.9999847412109375 = 65535/65536が表示され,これは,論理値 0000 0000 0000 1010b = 10 が真理値 0.0000 0000 0000 1010b = 10 ⁄ 216 = 0.000152587890625 と同一視されることなどを反映しています. 別の例として次のプログラムは,倍精度浮動小数点数型の小数 frac を,これに最も近い真理値をとる論理値型の論理値 lv へ変換して表示すると共に,lv を倍精度浮動小数点数型の真理値 tv へ変換して表示します. #include "bml16.lib" int main(void) { LV_T lv; double frac, tv; frac = 0.333333; printf("frac: %f\n", frac); lv = tvtolv(frac); printf("lv : %d\n", lv); tv = lvtotv(lv); printf("tv : %18.16f\n", tv); return 0; }プログラムを実行すると frac: 0.333333 lv : 21845 tv : 0.3333282470703125が表示され,これは,論理値 21845 = 5555h = 0101 0101 0101 0101b と同一視される真理値が 0.0101 0101 0101 0101b = 21845 ⁄ 216 = 0.3333282470703125 = 0.333333 − 0.0000047529296875 である一方,論理値 21846 = 5556h = 0101 0101 0101 0110b と同一視される真理値は 0.0101 0101 0101 0110b = 21846 ⁄ 216 = 0.3333435058593750 = 0.333333 + 0.000010505859375 であり,真理値が 0.333333 により近いのは前者であることを反映しています. 4. LV_T not(const LV_T lv)
論理値 lv の否定を返します.使用例については,後述の eqv を参照してください.5. LV_T and(const LV_T lv1, const LV_T lv2)
論理値 lv1 と lv2 の論理積を返します.使用例については,後述の eqv を参照してください.6. LV_T ior(const LV_T lv1, const LV_T lv2)
論理値 lv1 と lv2 の包含的論理和を返します.使用例については,後述の eqv を参照してください.7. LV_T xor(const LV_T lv1, const LV_T lv2)
論理値 lv1 と lv2 の排他的論理和を返します.使用例については,後述の eqv を参照してください.8. LV_T imp(const LV_T lv1, const LV_T lv2)
論理値 lv1 から lv2 への含意を返します.使用例については,後述の eqv を参照してください.9. LV_T eqv(const LV_T lv1, const LV_T lv2)
論理値 lv1 と lv2 の同値を返します.次のプログラムは,論理値型の論理値 lv1,lv2 に対し各演算を適用した結果を表示します. #include "bml16.lib" int main(void) { LV_T lv1, lv2, lv3; lv1 = 0xFF00; printf("lv1 : 1111 1111 0000 0000b = %5d\n", lv1); lv2 = 0x0F0F; printf("lv2 : 0000 1111 0000 1111b = %5d\n", lv2); lv3 = not(lv1); printf("not lv1 : 0000 0000 1111 1111b = %5d\n", lv3); lv3 = and(lv1, lv2); printf("lv1 and lv2: 0000 1111 0000 0000b = %5d\n", lv3); lv3 = ior(lv1, lv2); printf("lv1 ior lv2: 1111 1111 0000 1111b = %5d\n", lv3); lv3 = xor(lv1, lv2); printf("lv1 xor lv2: 1111 0000 0000 1111b = %5d\n", lv3); lv3 = imp(lv1, lv2); printf("lv1 imp lv2: 0000 1111 1111 1111b = %5d\n", lv3); lv3 = eqv(lv1, lv2); printf("lv1 eqv lv2: 0000 1111 1111 0000b = %5d\n", lv3); return 0; }プログラムを実行すると lv1 : 1111 1111 0000 0000b = 65280 lv2 : 0000 1111 0000 1111b = 3855 not lv1 : 0000 0000 1111 1111b = 255 lv1 and lv2: 0000 1111 0000 0000b = 3840 lv1 ior lv2: 1111 1111 0000 1111b = 65295 lv1 xor lv2: 1111 0000 0000 1111b = 61455 lv1 imp lv2: 0000 1111 1111 1111b = 4095 lv1 eqv lv2: 0000 1111 1111 0000b = 4080が表示され,これは,論理値 1111 1111 0000 0000b = 65280 に対しその否定が 0000 0000 1111 1111b = 255 であること,および,論理値 1111 1111 0000 0000b = 65280 と 0000 1111 0000 1111b = 3855 に対し論理積が 0000 1111 0000 0000b = 3840 であることなどを反映しています. 10. double cond(const LV_T lv1, const LV_T lv2)
論理値 lv1 による論理値 lv2 の条件化演算の結果を,倍精度浮動小数点数型で返します.特に lv1 が 0000 0000 0000 0000b のときは,便宜上 0 を返します.次のプログラムは,論理値 lv1 による論理値 lv2 の条件化演算の結果を表示します. #include "bml16.lib" int main(void) { LV_T lv1, lv2, lv3; double tv; lv1 = 0x000F; printf("lv1 : 0000 0000 0000 1111b = %5d\n", lv1); lv2 = 0x9999; printf("lv2 : 1001 1001 1001 1001b = %5d\n", lv2); lv3 = and(lv1, lv2); printf("lv1 and lv2: 0000 0000 0000 1001b = %5d\n", lv3); tv = cond(lv1, lv2); printf("lv2 | lv1 : %18.16f\n", tv); return 0; }プログラムを実行すると lv1 : 0000 0000 0000 1111b = 15 lv2 : 1001 1001 1001 1001b = 39321 lv1 and lv2 : 0000 0000 0000 1001b = 9 lv2 cond by lv1: 0.6000000000000000が表示され,これは,lv1 が 0000 0000 0000 1111b (真理値 0.0000 0000 0000 1111b = 15 ⁄ 216) および lv2 が 1001 1001 1001 1001b (真理値 0.1001 1001 1001 1001b = 39321 ⁄ 216) のとき,lv1 と lv2 の論理積は 0000 0000 0000 1001b (真理値 0.0000 0000 0000 1001b = 9 ⁄ 216) なので,lv1 による lv2 の条件化演算の結果は 0.0000 0000 0000 1001b ⁄ 0.0000 0000 0000 1111b = (9 ⁄ 216) ⁄ (15 ⁄ 216) = 9 ⁄ 15 = 0.6 となることを反映しています.11. void prtlv(const char* str, const LV_T lv)
論理値 lv と同一視される真理値を,文字列 str とコロンに続き二進数および括弧付きの十進数にて表示します.なお,文字列の長さの上限は,定数 MAXLEN としてマクロ定義されています.次のプログラムは,論理値型の論理値 cake,eat,happy と同一視される真理値を二進数および十進数にて表示します. #include "bml16.lib" int main(void) { LV_T cake = 0x4441, eat = 0x8181, happy = 0x9385; char str[MAXLEN]; strcpy(str, "cake"); prtlv(str, cake); strcpy(str, "eat"); prtlv(str, eat); strcpy(str, "happy"); prtlv(str, happy); return 0; }プログラムを実行すると cake: 0.0100010001000001 (0.2666168212890625) eat: 0.1000000110000001 (0.5058746337890625) happy: 0.1001001110000101 (0.5762481689453125)が表示され,これは,論理値 4441h = 0100 0100 0100 0001b = 17473,8181h = 1000 0001 1000 0001b = 33153,9385h = 1001 0011 1000 0101b = 37765 と同一視される真理値がそれぞれ 0.0100 0100 0100 0001b = 17473 ⁄ 216 = 0.2666168212890625,0.1000 0001 1000 0001b = 33153 ⁄ 216 = 0.5058746337890625,0.1001 0011 1000 0101b = 37765 ⁄ 216 = 0.5762481689453125 であることを反映しています. 12. void prtatoms(const char *atomfile)
ファイル atomfile に記述されている各原子論理式に関し,その名称とコロンに続き原子論理式のとる論理値に対応する真理値を二進数および括弧付きの十進数にて表示します.次のプログラム #include "bml16.lib" int main(void) { LV_T lv1, lv2, lv3; char atomfile[] = "ATOMS.DAT"; prtatoms(atomfile); return 0; }は,内容が cake:17473↵ eat:33153↵ happy:37765↵ [EOF]のファイル ATOMS.DAT に記述されている各原子論理式に関し,その名称とコロンに続き原子論理式のとる論理値に対応する真理値を二進数および括弧付きの十進数にて表示します.プログラムを実行すると cake: 0.0100010001000001 (0.2666168212890625) eat: 0.1000000110000001 (0.5058746337890625) happy: 0.1001001110000101 (0.5762481689453125)が表示されます (前述の prtlv の使用例を参照). 13. LV_T evalform(const char *atomfile, const char *form, const int prtsw)
ファイル atomfile に記述されている原子論理式の論理値に基づいて計算された論理式 form の論理値を,論理値型で返します.ここに,prtsw が ON (1 としてマクロ定義) のとき原子論理式のとる論理値に対応する真理値を二進数および括弧付きの十進数にて表示し,OFF (0 としてマクロ定義) のときは表示しません.evalform 内において条件化演算 cond の倍精度浮動小数点数型の戻り値は便宜上 2 バイトの符号なし整数型すなわち論理値型へ変換され,論理演算 not,and,ior,xor,imp,eqv の戻り値と同様に扱われますので,例えば cond(x,and(y,z)) と記述するべきところを and(cond(x,y),cond(x,z)) のように記述しても論理値は形式的に計算されます.次のプログラム #include "bml16.lib" int main(void) { char atomfile[] = "ATOMS.DAT", form[] = "cond(cake,happy)"; evalform(atomfile, form, ON); return 0; }は,内容が cake:17473↵ eat:33153↵ happy:37765↵ [EOF]のファイル ATOMS.DAT に記述されている原子論理式の論理値に基づいて計算された論理式 cond(cake,happy) の論理値に対応する真理値を cond(cake,happy): 0.0000000000000100 (0.0000610351562500)のように二進数および括弧付きの十進数にて表示します.14. double evalgap(const char *atomfile, const char *knowfile, const int prtsw)
論理式とそのとるべき真理値 (知識とよぶ) がいくつか記述されているファイル knowfile が与えられたとき,各知識を構成する論理式に関し,ファイル atomfile に記述されている原子論理式の論理値に基づいて計算された真理値と knowfile 内に記述されている真理値との差 (間隙とよぶ) を計算し,すべての知識に関する平均自乗間隙と間隙の絶対値の最大値 (最大絶対間隙とよぶ) とを倍精度浮動小数点数型で返します.atomfile や knowfile の内容は不変です.ここに,prtsw が ON (1 としてマクロ定義) のとき各論理式に関する間隙を表示し,OFF (0 としてマクロ定義) のときは表示しません.次のプログラム #include "bml16.lib" int main(void) { char atomfile[] = "ATOMS.DAT", knowfile[] = "KNOWS.DAT"; evalgap(atomfile, knowfile, ON); return 0; }は,内容が cake:46084↵ eat:26703↵ happy:11172↵ now:10113↵ rotten:20859↵ tomorrow:05720↵ [EOF]のファイル ATOMS.DAT および内容が cond(and(cake,eat),happy)):1↵ cond(and(now,cake),rotten):0↵ cond(and(and(now,cake),eat),and(tomorrow,cake)):0↵ cond(and(and(now,cake),not(eat)),and(tomorrow,cake)):1↵ cond(and(tomorrow,cake),rotten):0.8↵ and(and(cake,rotten),eat):0↵ cond(and(cake,not(eat)),happy):0↵ [EOF]のファイル KNOWS.DAT に基づき,KNOWS.DAT に記述されている各論理式に関する間隙を表示したのち,すべての論理式に関する平均自乗間隙と最大絶対間隙とを倍精度浮動小数点数型で表示します.プログラムを実行すると [1] cond(and(cake,eat),happy)): 0.9999847412109375 = 1.0000000000000000-0.0000152587890625 [2] cond(and(now,cake),rotten): 0.0000000000000000 = 0.0000000000000000+0.0000000000000000 [3] cond(and(and(now,cake),eat),and(tomorrow,cake)): 0.0000000000000000 = 0.0000000000000000+0.0000000000000000 [4] cond(and(and(now,cake),not(eat)),and(tomorrow,cake)): 0.9999847412109375 = 1.0000000000000000-0.0000152587890625 [5] cond(and(tomorrow,cake),rotten): 0.8000030517578125 = 0.8000000000000000+0.0000030517578125 [6] and(and(cake,rotten),eat): 0.0000000000000000 = 0.0000000000000000+0.0000000000000000 [7] cond(and(cake,not(eat)),happy): 0.0000000000000000 = 0.0000000000000000+0.0000000000000000 GAP DEV: 0.0000082373237077; MAX ABSOL GAP: 0.0000152587890625のように表示されます.例えば [1] から始まる最初の行において,論理式 cond(and(cake,eat),happy)) の後の倍精度浮動小数点数 0.9999847412109375 は ATOMS.DAT に基づいて計算された cond(and(cake,eat),happy)) の論理値に対応する真理値を,等号の後の 1.0000000000000000 は KNOWS.DAT に記述されている真理値を,最後の −0.0000152587890625 は間隙を表します.また,最終行において,GAP DEV (DEV は偏差を意味する) の後の 0.0000082373237077 はすべての論理式に関する平均自乗間隙を,MAX ABSOL GAP の後の 0.0000152587890625 は最大絶対間隙を表します. 15. double optatoms(const char *atomfile, const char *knowfile, const int numtrials, const int prtsw)
ライブラリには, i.原子論理式がとる論理値を疑似乱数発生器を利用して段階的に変えつつ平均自乗間隙を極小化し,その結果を返す関数 double _localopt(char *atomfile, char *knowfile, int prtsw) ii.平均自乗間隙が CONVRGNCYFACTOR 回続けて不変となるまで,_localopt を MAX_LOCALTRIALS 回を上限として繰り返し適用することにより得られた平均自乗間隙のうち,最も小さいものを返す関数 double _globopt(char *atomfile, char *knowfile, int prtsw) が含まれています.optatoms は,疑似乱数発生器の種を変えつつ _globopt を numtrials 回適用することにより得られた平均自乗間隙のうち,最も小さいものを返す関数です.ファイル atomfile には,この平均自乗間隙に対応する原子論理式の論理値が記述されます.ここに,prtsw が ON (1 としてマクロ定義) のとき経過を表示し,OFF (0 としてマクロ定義) のときは表示しません.マクロ定義されている CONVRGNCYFACTOR,MAX_LOCALTRIALS や引数 numtrials を増やせば,平均自乗間隙がより真の最小に近づき得る反面,計算時間も増えます.次のプログラム #include "bml16.lib" int main(void) { char atomfile[] = "ATOMS.DAT", knowfile[] = "KNOWS.DAT"; optatoms(atomfile, knowfile, 10, OFF); return 0; }は,ファイル KNOWS.DAT に基づき,evalgap の戻り値がなるべく小さくなるように ATOMS.DAT を記述します.その際,ATOMS.DAT が存在しないとき新たに作成し,既に存在するときは内容を更新します.evalgap の使用例における ATOMS.DAT は,内容が cond(and(cake,eat),happy)):1↵ cond(and(now,cake),rotten):0↵ cond(and(and(now,cake),eat),and(tomorrow,cake)):0↵ cond(and(and(now,cake),not(eat)),and(tomorrow,cake)):1↵ cond(and(tomorrow,cake),rotten):0.8↵ and(and(cake,rotten),eat):0↵ cond(and(cake,not(eat)),happy):0↵ [EOF]のファイル KNOWS.DAT に基づき,このプログラムを実行した結果の一例です. 16. void demo_bird1(void)
いくつかの鳥の種類,鳥であること,飛ぶこと,反射神経が優れていること,自転車に乗ることに関する知識が与えられたとき,平均自乗間隙がなるべく小さくなるような原子論理式の論理値を求めるとともにいくつかの推論を演示します.次のプログラム #include "bml16.lib" int main(void) { demo_bird1(); return 0; }を実行すると,例えば Optimizing truth values of atoms according to knowledges.............................. /* [num] 'logic formula':' optimized tv' = 'desired tv'+-'gap' */ [1] cond(falcon,bird): 0.9998168945312500 = 1.0000000000000000-0.0001831054687500 [2] cond(falcon,fly): 0.9011383056640625 = 0.9000000000000000+0.0011383056640625 [3] cond(pigeon,bird): 0.9998168945312500 = 1.0000000000000000-0.0001831054687500 [4] cond(pigeon,fly): 0.9091339111328125 = 0.9000000000000000+0.0091339111328125 [5] cond(fly,good_reflexes): 0.7333374023437500 = 0.7500000000000000-0.0166625976562500 [6] cond(penguin,bird): 0.9999847412109375 = 1.0000000000000000-0.0000152587890625 [7] cond(penguin,fly): 0.0000000000000000 = 0.0000000000000000+0.0000000000000000 [8] cond(falcon,ride_bicycle): 0.0001373291015625 = 0.0000000000000000+0.0001373291015625 GAP DEV: 0.0067310138571315; MAX ABSOL GAP: 0.0166625976562500 *** Atoms *** falcon: 0.0101100011000111 (0.3467864990234375) bird: 0.0101111111111011 (0.3749237060546875) fly: 0.1111000000000000 (0.9375000000000000) pigeon: 0.0101011111111111 (0.3437347412109375) good_reflexes: 0.1011001010011001 (0.6976470947265625) penguin: 0.0000101010100000 (0.0415039062500000) ride_bicycle: 0.1010001000111011 (0.6337127685546875) *** Inferences *** cond(and(not(bird),good_reflexes),ride_bicycle): 0.1111111111111111 (0.9999847412109375) cond(ride_bicycle,good_reflexes): 0.1111111111001010 (0.9991760253906250) cond(ride_bicycle,fly): 0.1111110001111011 (0.9862518310546875)のように表示されます.最大絶対間隙は 0.0166625… であり,これは知識がある程度一貫していることを示唆します.なお,ライブラリ内で疑似乱数発生器の種を srand により変化させていますので,原子論理式の論理値および推論の結果は常に上述のようになるわけではありませんが,何度か試せば一定の傾向が観測できます. 17. void demo_bird2(void)
いくつかの鳥の種類,鳥であること,飛ぶこと,反射神経が優れていること,自転車に乗ることに関する知識が与えられたとき,平均自乗間隙がなるべく小さくなるような原子論理式の論理値を求めるとともにいくつかの推論を演示します.前述の demo_bird1 における知識に新たな知識が追加された版です.次のプログラム #include "bml16.lib" int main(void) { demo_bird2(); return 0; }を実行すると,例えば Optimizing truth values of atoms according to knowledges.............................. /* [num] 'logic formula':' optimized tv' = 'desired tv'+-'gap' */ [1] cond(falcon,bird): 0.9999847412109375 = 1.0000000000000000-0.0000152587890625 [2] cond(falcon,fly): 0.8983306884765625 = 0.9000000000000000-0.0016693115234375 [3] cond(pigeon,bird): 0.9996185302734375 = 1.0000000000000000-0.0003814697265625 [4] cond(pigeon,fly): 0.9442901611328125 = 0.9000000000000000+0.0442901611328125 [5] cond(fly,good_reflexes): 0.6932830810546875 = 0.7500000000000000-0.0567169189453125 [6] cond(penguin,bird): 0.9983825683593750 = 1.0000000000000000-0.0016174316406250 [7] cond(penguin,fly): 0.0040588378906250 = 0.0000000000000000+0.0040588378906250 [8] cond(falcon,ride_bicycle): 0.0000000000000000 = 0.0000000000000000+0.0000000000000000 [9] cond(good_reflexes,ride_bicycle): 0.8500213623046875 = 0.7500000000000000+0.1000213623046875 GAP DEV: 0.0411024773356990; MAX ABSOL GAP: 0.1000213623046875 *** Atoms *** falcon: 0.0100011101100010 (0.2788391113281250) bird: 0.1110111111101011 (0.9371795654296875) fly: 0.1101000010101001 (0.8150787353515625) pigeon: 0.1100101101011101 (0.7943878173828125) good_reflexes: 0.1001111111111111 (0.6249847412109375) penguin: 0.0010011001111010 (0.1502990722656250) ride_bicycle: 0.1000100000000000 (0.5312500000000000) *** Inferences *** cond(and(not(bird),good_reflexes),ride_bicycle): 0.0000000000000000 (0.0000000000000000) cond(ride_bicycle,good_reflexes): 0.1111111111111111 (0.9999847412109375) cond(ride_bicycle,fly): 0.1111000011110001 (0.9411773681640625)のように表示されます.前述の demo_bird1 において最大絶対間隙は 0166625… でしたが,新たに知識“反射神経が優れているものは自転車に乗る”を意味する cond(good_reflexes,ride_bicycle) = 0.75 を追加したことによって,最大絶対間隙が 0.1000213… に増加しています.なお,ライブラリ内で疑似乱数発生器の種を srand により変化させていますので,原子論理式の論理値および推論の結果は常に上述のようになるわけではありませんが,何度か試せば一定の傾向が観測できます. 18. void demo_bird3(void)
いくつかの鳥の種類,鳥であること,飛ぶこと,反射神経が優れていること,自転車に乗ることに関する知識が与えられたとき,平均自乗間隙がなるべく小さくなるような原子論理式の論理値を求めるとともにいくつかの推論を演示します.前述の demo_bird2 における知識の一部が差しかえられた版です.次のプログラム #include "bml16.lib" int main(void) { demo_bird3(); return 0; }を実行すると,例えば Optimizing truth values of atoms according to knowledges.............................. /* [num] 'logic formula':' optimized tv' = 'desired tv'+-'gap' */ [1] cond(falcon,bird): 0.9792022705078125 = 1.0000000000000000-0.0207977294921875 [2] cond(falcon,fly): 0.9792022705078125 = 0.9000000000000000+0.0792022705078125 [3] cond(pigeon,bird): 0.9953308105468750 = 1.0000000000000000-0.0046691894531250 [4] cond(pigeon,fly): 0.8891601562500000 = 0.9000000000000000-0.0108398437500000 [5] cond(fly,good_reflexes): 0.7954864501953125 = 0.7500000000000000+0.0454864501953125 [6] cond(penguin,bird): 0.9940490722656250 = 1.0000000000000000-0.0059509277343750 [7] cond(penguin,fly): 0.0220947265625000 = 0.0000000000000000+0.0220947265625000 [8] cond(falcon,ride_bicycle): 0.0054931640625000 = 0.0000000000000000+0.0054931640625000 [9] cond(and(not(bird),good_reflexes),ride_bicycle): 0.7327728271484375 = 0.7500000000000000-0.0172271728515625 GAP DEV: 0.0329383375386894; MAX ABSOL GAP: 0.0792022705078125 *** Atoms *** falcon: 0.0010000010101110 (0.1276550292968750) bird: 0.1111111000000000 (0.9921875000000000) fly: 0.1010011001000000 (0.6494140625000000) pigeon: 0.1001011010110100 (0.5886840820312500) good_reflexes: 0.1100010111011111 (0.7729339599609375) penguin: 0.0101101010001010 (0.3536682128906250) ride_bicycle: 0.1101111101111111 (0.8730316162109375) *** Inferences *** cond(and(not(bird),good_reflexes),ride_bicycle): 0.1011101110010111 (0.7327728271484375) cond(ride_bicycle,good_reflexes): 0.1110001000010011 (0.8831024169921875) cond(ride_bicycle,fly): 0.1001100111000110 (0.6006774902343750)のように表示されます.demo_bird2 において最大絶対間隙 0.1000213… の原因であった第 9 の知識“反射神経が優れているものはたぶん自転車に乗る”を意味する cond(good_reflexes,ride_bicycle) = 0.75 を,新たな知識“鳥ではなく反射神経が優れているものはたぶん自転車に乗る”を意味する cond(and(not(bird),good_reflexes),ride_bicycle) = 0.75 へ差しかえたことによって,最大絶対間隙が 0.0792022… に減少しています.なお,ライブラリ内で疑似乱数発生器の種を srand により変化させていますので,原子論理式の論理値および推論の結果は常に上述のようになるわけではありませんが,何度か試せば一定の傾向が観測できます.19. void demo_cake1(void)
ケーキがあること,食べること,幸せであることに関する知識が与えられたとき,平均自乗間隙がなるべく小さくなるような原子論理式の論理値を求めるとともにいくつかの推論を演示します.次のプログラム #include "bml16.lib" int main(void) { demo_cake1(); return 0; }を実行すると,例えば OPTIMIZING TRUTH VALUES OF ATOMS.......... [1] cond(and(cake,eat),happy): 0.9999847412109375 = 1.0000000000000000-0.0000152587890625 [2] cond(and(cake,not(eat)),happy): 0.0000000000000000 = 0.0000000000000000+0.0000000000000000 [3] cond(eat,cake): 0.0000152587890625 = 0.0000000000000000+0.0000152587890625 GAP DEV: 0.0000124587490986; MAX ABSOL GAP: 0.0000152587890625 ATOMS cake: 0.0000001111000011 (0.0146942138671875) eat: 0.1100000000010101 (0.7503204345703125) happy: 0.1111110000010101 (0.9846954345703125) INFERENCES cond(cake,happy): 0.0000000001000100 (0.0010375976562500) cond(cake,eat): 0.0000000001000100 (0.0010375976562500)のように表示されます.[1] ケーキがあってそれを食べれば必ず幸せである,[2] ケーキがあってそれを食べなければ必ず不幸せである,[3] 食べればケーキは必ずなくなる,という知識が与えられたとき,疑似乱数発生器を利用しつつ求められた最大絶対間隙がなるべく小さいような原子論理式の論理値は,常に上述のようになるわけではありませんが,何度試しても“ケーキがあれば幸せである”を意味する cond(cake,happy) はほとんど 0 であり“ケーキがあればほとんど不幸せである”が得られ,“ケーキがあれば食べる”を意味する cond(cake,eat) はほとんど 0 であり“ケーキがあればほとんど食べない”が得られます.すなわち,ケーキを食べると幸せであることはわかっているが,ケーキを食べるとケーキがなくなってしまい不幸せになるので,ケーキを食べるわけにはいかず不幸せである,というジレンマに陥っています. 20. void demo_cake2(void)
ケーキがあること,食べること,幸せであること,今であること,明日であることに関する知識が与えられたとき,平均自乗間隙がなるべく小さくなるような原子論理式の論理値を求めるとともにいくつかの推論を演示します.demo_cake1 における知識に,時間の概念が追加された版です.次のプログラム #include "bml16.lib" int main(void) { demo_cake2(); return 0; }を実行すると,例えば OPTIMIZING TRUTH VALUES OF ATOMS.......... [1] cond(and(cake,eat),happy)): 0.9999847412109375 = 1.0000000000000000-0.0000152587890625 [2] cond(and(now,cake),rotten): 0.0000000000000000 = 0.0000000000000000+0.0000000000000000 [3] cond(and(and(now,cake),eat),and(tomorrow,cake)): 0.0000000000000000 = 0.0000000000000000+0.0000000000000000 [4] cond(and(and(now,cake),not(eat)),and(tomorrow,cake)): 0.9999847412109375 = 1.0000000000000000-0.0000152587890625 [5] cond(and(tomorrow,cake),rotten): 0.8028564453125000 = 0.8000000000000000+0.0028564453125000 [6] and(and(cake,rotten),eat): 0.0000000000000000 = 0.0000000000000000+0.0000000000000000 [7] cond(and(cake,not(eat)),happy): 0.0003051757812500 = 0.0000000000000000+0.0003051757812500 GAP DEV: 0.0010858096217012; MAX ABSOL GAP: 0.0028564453125000 ATOMS cake: 0.1001111101101110 (0.6227722167968750) eat: 0.0110100001100000 (0.4077148437500000) happy: 0.0110100011101100 (0.4098510742187500) now: 0.0011010110011001 (0.2093658447265625) rotten: 0.1110000000010001 (0.8752593994140625) tomorrow: 0.1011111101111110 (0.7480163574218750) INFERENCES cond(and(now,cake),and(now,eat)): 0.0000000000000000 (0.0000000000000000) cond(and(now,cake),and(now,happy)): 0.0000000001100001 (0.0014801025390625) cond(and(tomorrow,cake),and(tomorrow,happy)): 0.0000110110000110 (0.0528259277343750) cond(and(tomorrow,cake),and(tomorrow,eat)): 0.0000110101110011 (0.0525360107421875)のように表示されます.[1] 今ケーキがあってそれを食べれば必ず幸せである,[2] 今ケーキがあればそれは決して腐っていない,[3] 今ケーキがあってそれを食べれば決して明日ケーキはない,[4] 今ケーキがあってそれを食べなければ必ず明日ケーキはある,[5] 明日ケーキがあればおそらくそれは腐っている,[6] ケーキがあって腐っていれば決して食べる人はいない,[7] ケーキがあってそれを食べなければ決して幸せではない,という知識が与えられたとき,疑似乱数発生器を利用しつつ求められた最大絶対間隙がなるべく小さいような原子論理式の論理値に対し,“今ケーキがあれば今ケーキを食べる”を意味する cond(and(now,cake),and(now,eat)) は 0 であり“今ケーキがあれば決して今ケーキを食べない”が得られ,“今ケーキを食べれば今幸せである”を意味する cond(and(now,cake), and(now,happy)) もほとんど 0 であり“今ケーキを食べればほとんど今不幸せである”が得られ,“明日ケーキを食べれば明日幸せである”を意味する cond(and(tomorrow,cake), and(tomorrow,happy)) もほとんど 0 であり“明日ケーキを食べればほとんど明日不幸せである”が得られ,“明日ケーキがあれば明日食べる”を意味する cond(and(tomorrow,cake),and(tomorrow,eat)) もほとんど 0 であり“明日ケーキがあればほとんど明日食べない”が得られますので,状況は demo_cake1 の使用例から変わっていないように見えます. 別の例では OPTIMIZING TRUTH VALUES OF ATOMS.......... [1] cond(and(cake,eat),happy)): 0.9999847412109375 = 1.0000000000000000-0.0000152587890625 [2] cond(and(now,cake),rotten): 0.0000000000000000 = 0.0000000000000000+0.0000000000000000 [3] cond(and(and(now,cake),eat),and(tomorrow,cake)): 0.0000000000000000 = 0.0000000000000000+0.0000000000000000 [4] cond(and(and(now,cake),not(eat)),and(tomorrow,cake)): 0.9999847412109375 = 1.0000000000000000-0.0000152587890625 [5] cond(and(tomorrow,cake),rotten): 0.8000030517578125 = 0.8000000000000000+0.0000030517578125 [6] and(and(cake,rotten),eat): 0.0000000000000000 = 0.0000000000000000+0.0000000000000000 [7] cond(and(cake,not(eat)),happy): 0.0000000000000000 = 0.0000000000000000+0.0000000000000000 GAP DEV: 0.0000082373237077; MAX ABSOL GAP: 0.0000152587890625 ATOMS cake: 0.0000010101000000 (0.0205078125000000) eat: 0.0110110010011011 (0.4242401123046875) happy: 0.1010111000011001 (0.6800689697265625) now: 0.1010111001001110 (0.6808776855468750) rotten: 0.0101101100001100 (0.3556518554687500) tomorrow: 0.1111101111001010 (0.9835510253906250) INFERENCES cond(and(now,cake),and(now,eat)): 0.1111000011110001 (0.9411773681640625) cond(and(now,cake),and(now,happy)): 0.1111000011110001 (0.9411773681640625) cond(and(tomorrow,cake),and(tomorrow,happy)): 0.0000000000000000 (0.0000000000000000) cond(and(tomorrow,cake),and(tomorrow,eat)): 0.0000000000000000 (0.0000000000000000)のように表示されます.“今ケーキがあれば今ケーキを食べる”を意味する cond(and(now,cake),and(now,eat)) はほとんど 1 であり“今ケーキがあればほとんど今ケーキを食べる”が得られ,“今ケーキを食べれば今幸せである”を意味する cond(and(now,cake),and(now,happy)) もほとんど 1 であり“今ケーキを食べればほとんど今幸せである”が得られますので,先の例とは対照的です.一方,“明日ケーキを食べれば明日幸せである”を意味する cond(and(tomorrow,cake),and(tomorrow,happy)) も 0 であり“明日ケーキを食べれば明日不幸せである”が得られ,“明日ケーキを食べれば明日食べる”を意味する cond(and(tomorrow,cake),and(tomorrow,eat)) 0 であり“明日ケーキを食べれば明日食べない”が得られますので,先の例と変わりません.