概要
eml(x, y)=exp(x) - ln(y)という関数を定義し、EMLを加減剰余のような演算子のように扱い、定数1のみで、あらゆる初等関数が作れる(らしい)。
まず、eml(1, 1)=exp(1)-ln(1)=eで、定数eができる。
同様に、eml(x, 1)=exp(x)-ln(1)=e^xで、関数e^xができる。
ln(x)=e-(e-ln(x))のため、eml(1, eml(eml(1, x), 1))=eml(1, eml(exp(1)-ln(x), 1))=eml(1, eml(e-ln(x), 1))=eml(1, exp(e-ln(x))-ln(1))=eml(1, exp(e-ln(x)))=exp(1)-ln(exp(e-ln(x)))=e-(e-ln(x))=ln(x)で、関数ln(x)ができる。
ln(1)=0のため、ln(1)=eml(1, eml(eml(1, 1), 1))=0で、定数0ができる。
逆ポーランド記法(RPN)
ネストしたemlを二分木で表現すると、何かとつらい?ので、これを逆ポーランド記法にするとカッコがなくなる。
例えば、1+2*3=1+(2*3)の順番だが、スタックに定数や変数を積み(push)、2項演算子で2つ値を取出し(pop)演算結果を積む(push)、スタックマシンで表現すると、1 2 3 * +となる。
よって、(1+2)*3の場合は、1 2 + 3 *の違いとなる。
これをeml演算子をEと表現すると、冒頭の4つは以下の表現となる。
- 定数e:
11Eeml(1, 1) - 関数exp(x):
x1Eeml(x, 1) - 関数ln(x):
11xE1EEeml(1, eml(eml(1, x), 1)) - 定数0:
111E1EEeml(1, eml(eml(1, 1), 1))
NANDゲート
AND,OR,NOT,XORがこの業界なら常識でしょうが、NOT(AND)のNAND演算が1つあれば、これらが作れる(万能論理ゲート(Universal Gate))。
NOT(x)=NAND(x, x)
AND(x, y)は、z=NAND(x, y)とおき、AND(x, y)=NOT(z)=NAND(z, z) 1
OR(x, y)=NOT(AND(NOT(x), NOT(y))) ←ド・モルガンの法則x | y = !(!x & !y) 2
OR(x, y)=NAND(NOT(x), NOT(y))=NAND(NAND(x, x), NAND(y, y))
NOR(x, y)は、z=OR(x, y)とおき、NOR(x, y)=NOT(z)=NAND(z, z)
XOR(x, y)は、z=NAND(x, y)とおき、XOR(x, y)=NAND(NAND(x, z), NAND(y, z))
NANDゲートを数えると、
NOT 1個
AND 2個
OR 3個
NOR 4個
XOR 4個
なんかemlもNANDぽい感じがしてきた。
もっともっと
-1があれば、ln(-1)=iπとなり、iも1とlnで作れるらしく(最適化されていないK=131)、-i*i*π=πが作れるらしい(最適化されていないK=193)。
どんだけ大変なんじゃ。
Brainf*ckぽいな。この感じ。
x-1とx-y
後から追記。こちらの方が基本形だった。
x-1は、exp(ln(x))-ln(e)=x-1を目指す。
x-yは、exp(ln(x))-ln(exp(y))=x-yを目指す。
既知の定数e: 11E eml(1, 1)、関数ln(x): 11xE1EE eml(1, eml(eml(1, x), 1))を使い、
x-1=exp(ln(x))-ln(e)=eml(ln(x), e)=(ln(x))eEにeとln(x)を展開するとx-1=11xE1EE11EE (K=11)。
x-yはln(e)がln(exp(y))に変えるだけなので、上記のe=11Eの部分がeml(y, 1)=y1Eに変わり、x-y=11xE1EEy1EE (K=11)。
-xと-1と1/x
まず、xをあえて冗長な表現を考えると、ln(exp(x))=xを使う。
eml(x, 1)=exp(x)=aとおき、eml(1, a)=exp(1)-ln(a)=e-x=bとおく。
eml(b, 1)=exp(b)=exp(e-x)から、eml(1, eml(b, 1))=exp(1)-ln(exp(e-x))=e-(e-x)=x。
a=x1E、b=1aE、x=1b1EEより、x=11x1EE1EEが冗長な表現となる。
-xは、無限大を経由し、ln(0)=-INF、exp(-INF)=0を使い、exp(x)=0で消すことを考える。
定数0をz=111E1EEの記号zを使い、eml(1, z)=e-ln(0)=e-(-INF)=+INFとおく。
eml(1, +INF)=e-ln(+INF)=e-(+INF)=-INFとおく。
したがって、-INF=11zEEとなる。
よって、eml(-INF, eml(x, 1))=exp(-INF)-ln(exp(x))=0-x=-xとなる。
したがって、-x=(-INF)x1EE=11zEEx1EE=11111E1EEEEx1EEとなる。
-1は-xにx=1を代入し、-1=11111E1EEEE11EE (K=15)。
おそらくDirect searchという最短表現な気がする。
逆にEML CompilerのK=17の導出方法が気になる。
1/xもexp(-INF)=0まで同じで、eml(-INF, x)=exp(-INF)-ln(x)=-ln(x)から、eml(-ln(x), 1)=exp(-ln(x))=1/x。
したがって、1/x=eml(eml(-INF, x), 1)=(-INF)xE1E=11zEExE1E=11111E1EEEExE1E (K=15)。
-xと1/xの違いは、末尾が1EEなのかE1E。
手作業で書いていると、機械語のハンドアセンブルと同じじゃないか。インタープリター作るか。
allow_inf=falseやComplexでの定数-1
RealからComplexに変えたところ、定数-1が劣化したので、Realでallow_infを変更したら違いが出た。
-1=11111E1EEEE11EE (K=15 allow_inf=true)。
-1=11111EEE1EE11E1EE (K=17 allow_inf=false|Complex)。
exp(-INF)=0を使わないと、定数e-1(K=5)を関数x-e(K=13)に入れるので、K=5+13-1=17となる。
xyとx+yとln(a)+ln(b)、x^2、2x、x+1、定数2
xyやx+yのようなf(x, y)を作るため、どちらもln(a)+ln(b)を経由する。
f(a, b)=ln(a)+ln(b)とおくと、
exp(f(x, y))=exp(ln(x))exp(ln(y))=xy
f(exp(x), exp(y))=ln(exp(x))+ln(exp(y))=x+y
ln(a)+ln(b)はe-(e-ln(a)-ln(b))を目指し、カッコの中は(e-ln(a))-ln(b)。
eml(1, eml(1, a))=e-ln(e-ln(a))=Aとおき、
eml(1, eml(A, 1))=e-ln(exp(A))=e-A=ln(e-ln(a))=Bとおき、
eml(B, b)=exp(ln(e-ln(a)))-ln(b)=e-ln(a)-ln(b)=Cとおき、
eml(1, eml(C, 1))=e-ln(exp(C))=e-C=ln(a)+ln(b)が作れる。
ln(a)+ln(b)=eml(1, eml(C, 1))=1C1EE
C=eml(B, b)=BbE
B=eml(1, eml(A, 1))=1A1EE
A=eml(1, eml(1, a))=11aEE
AをB、BをC、Cをln(a)+ln(b)に代入すると、
B=1A1EE=111aEE1EE
C=BbE=111aEE1EEbE
ln(a)+ln(b)=1111aEE1EEbE1EE (K=15)
xy=exp(ln(x)+ln(y))=eml(ln(x)+ln(y), 1)
xy=1111xEE1EEyE1EE1E (K=17)
※Figure2がもっと長いのは、y=11y1EE1EEの冗長の形でxとyの深さを揃えているため。
xyにy=xを入れると、x^2となる。
x^2=1111xEE1EExE1EE1E (K=17)
x+y=ln(exp(x))+ln(exp(y))=ln(eml(x, 1)+ln(eml(y, 1))
x+y=1111x1EEE1EEy1EE1EE (K=19)
2xは、x+yにy=xを入れる。
2x=1111x1EEE1EEx1EE1EE (K=19)
x+1は、x+yにy=1を入れる。
x+1=1111x1EEE1EE11EE1EE (K=19)
定数2は、x+1にx=1を入れる。
2=111111EEE1EE11EE1EE (K=19)
x/y
効率は無視して、簡単に実現する方法。
xyと1/xがあるのなら、組み合わせれば、x/yが出来るだろうよ。
- 関数f(x)=1/x:
11111E1EEEExE1Eexp(eml(-INF, x))(K=15) - 関数f(x,y)=xy:
1111xEE1EEyE1EE1Ef(x,y)=exp(ln(x)+ln(y))(K=17)
xyにy=1/xのRPNを入れると、K=15+17-1=31ですな。
K=17が最適と分かっているのなら、これを目指そうか。
ふと、対数ln(x)があり、これを二重対数ln(ln(x))をコピペですぐ作れる。K=7+7-1=13
exp(ln(ln(x)))=ln(x)から、ln(x)-ln(y)=eml(ln(ln(x)), y)で良い。K=13+2=15
xyと同様に、exp(ln(x)-ln(y))=exp(ln(x))/exp(ln(y))=x/yで出来上がり。K=15+2=17
- 関数ln(x):
11xE1EEeml(1, exp(eml(1, x)))(K=7)
を元にln(x)をネストする。
ln(ln(x))=1111xE1EEE1EE(K=13)
ln(x)-ln(y)=eml(ln(ln(x)), y)=(ln(ln(x)))yE=1111xE1EEE1EEyE(K=15)
x/y=eml(ln(x)-ln(y), 1)=1111xE1EEE1EEyE1E(K=17)
x^y、log_x(y)
$x^y=e^{yln(x)}$を利用する。
yln(x)=exp(ln(y)+ln(ln(x)))=1111yEE1EE11xE1EEE1EE1E (K=17+7-1=23)
x^y=exp(yln(x))=1111yEE1EE11xE1EEE1EE1E1E (K=25)
$log_x(y)=\frac{ln(y)}{ln(x)}$を利用する。
ln(y)/ln(x)=111111yE1EEE1EEE1EE11xE1EEE1E (K=17+7+7-2=29)
log_x(y)=111111yE1EEE1EEE1EE11xE1EEE1E (K=29)
オリジナルのソース
Direct Searchなるものを実行したかったが、どれか分からなかった。
rustかと思って、rust_verifyはすでに組み立てたeml構造の検証で、rust_autogen_searchが何をやっているのか分からなかった。
HIT[S1_ExpLog_Subtract] unary=Exp[v0] | binary=Subtract[v1, Log[v0]]
そもそもunaryとbinaryって、単項演算子、二項演算子だったのか。まず初見、バイナリーって何だ?と不思議だった。
バイナリーツリーやバイナリーサーチのように、バイナリーオペレーターということらしい。
三項演算子はternary。
このExp(x)の単項演算子とSubtract(x, Log(y))の二項演算子があれば、初等関数が実現できるを見つけるツールらしい。つまり、Subtract(Exp(x), Log(y))とすれば、y=1でExp(x)と機能するので、今回のeml演算子となった。
論文にedl(x, y) = exp(x) / ln(y)、− eml(y, x) = ln(x) − exp(y)に2種類の姉妹品が紹介されていたので、ログから探すと見つかる。
HIT[S3_Exp_LogBinary] unary=Log[v0] | binary=Divide[Exp[v0], v1]
HIT[S1_ExpLog_Subtract] unary=Exp[v0] | binary=Subtract[Log[v0], v1]
他にいっぱい。まあもっと計算量がかかりそうな感じ。
expの方かにcoshとか。
HIT[S3_Exp_LogBinary] unary=Exp[v0] | binary=Log[v0, v1]
HIT[S3_Exp_LogBinary] unary=Exp[v0] | binary=Log[Log[v0], v1]
HIT[S3_Exp_LogBinary] unary=Exp[v0] | binary=Log[Log[v0, v1]]
HIT[S3_Exp_LogBinary] unary=Exp[v0] | binary=Log[v1, Log[v0]]
HIT[S4_Cosh_ArcCosh_Divide] unary=Cosh[v0] | binary=ArcCosh[Divide[v0, v1]]
HIT[S4_Cosh_ArcCosh_Divide] unary=Cosh[v0] | binary=Divide[ArcCosh[v0], v1]
HIT[S4_Cosh_ArcCosh_Divide] unary=Cosh[v0] | binary=Divide[v1, ArcCosh[v0]]
お目当てのDirect Searchするツールは、EmL_recognizerだった。拡張子がcuなので、何かと思ったら、c言語なのか。
魔改造するために、これをnotebooklmに登録して、javaに翻訳してもらった。
x/2、1/2の探索
割り算x/yと、定数2を組み合わせれば、作ることは簡単。
K=17+19-1=35
論文のTable4では、1/2 (K=29(35))、x/2 (K=27)というのが、ずっと意味が分からなくて、x/2がK=27で実現できるのなら、x=1を入れた1/2もK=27で実現できる(はず)。
そこで、javaに翻訳したEmlRealConstSearchを実行すると、あっさりK=29の答えが出る。
Searching for Real Constant target: 0.5 (allow_inf=true)
Testing K=1 (Shapes: 1)... done. 0.0s
Testing K=3 (Shapes: 1)... done. 0.0s
Testing K=5 (Shapes: 2)... done. 0.0s
Testing K=7 (Shapes: 5)... done. 0.0s
Testing K=9 (Shapes: 14)... done. 0.0s
Testing K=11 (Shapes: 42)... done. 0.0s
Testing K=13 (Shapes: 132)... done. 0.001s
Testing K=15 (Shapes: 429)... done. 0.001s
Testing K=17 (Shapes: 1430)... done. 0.002s
Testing K=19 (Shapes: 4862)... done. 0.006s
Testing K=21 (Shapes: 16796)... done. 0.014s
Testing K=23 (Shapes: 58786)... done. 0.038s
Testing K=25 (Shapes: 208012)... done. 0.122s
Testing K=27 (Shapes: 742900)... done. 0.438s
Testing K=29 (Shapes: 2674440)... break. 1.313s
[HIT!] Found at K=29, rank=2004798
RPN: 1 1 1 E 1 1 1 1 1 E 1 E E E E 1 1 E 1 E 1 E E 1 E E E 1 E
次にjavaに翻訳したEmlRealUnarySearchを実行する。
maskを2^leafの組み合わせをループすると時間がかかり過ぎるので、最大2個の変数に限定すると、K=29で見つかる。当然、2ヵ所のx=1を入れれば、上記の定数1/2の結果と一致する。
bitCount(mask)<=2
Searching for Unary Function target: x/2 at x=0.5772156649015329 (allow_inf=true)
Testing K=27 (Shapes: 742900, Masks: 106)... done. 46.299s
Testing K=29 (Shapes: 2674440, Masks: 121)... break. 163.718s
[HIT!] Found at K=29, rank=2004798, mask=1028
RPN: 1 1 x E 1 1 1 1 1 E 1 E E E E 1 x E 1 E 1 E E 1 E E E 1 E
変数を最大3個に増やすと、なんとK=27で見つかる。
しかし、これ、実際に手作業で式を展開すると、余計なexpが残って、どうにもx/2なんかにはならない。
x=0.5772156649015329のみで誤差が収まった候補というだけで、別途複数の値で検証しているぽいけど、どうもx=1では検証していないらしい。
しかし、Shapesがカタラン数で、rank値がこの構造のユニークIDとなっているので、rank=555855に絞って、集中テストすれば反証が見つかるはずだが。
まあこのソースをdouble X_SAMP = 1;に修正したら、K=27は見つからず、K=29となった。
bitCount(mask)<=3
Searching for Unary Function target: x/2 at x=0.5772156649015329 (allow_inf=true)
Testing K=25 (Shapes: 208012, Masks: 378)... done. 41.161s
Testing K=27 (Shapes: 742900, Masks: 470)... break. 158.106s
[HIT!] Found at K=27, rank=555855, mask=548
RPN: 1 1 x E 1 1 x E 1 E 1 E E 1 x E 1 E 1 E E 1 E E E 1 E
x/2、1/2
1/2: 111E11111E1EEEE11E1E1EE1EEE1E (K=29)
x/2: 11xE11111E1EEEE1xE1E1EE1EEE1E (K=29)
1/2を作るには、exp(-ln(2))が作れればよい。
しかし、ln(2)がなかなか思いつかなかった。
順に追うと、2exp(e)を用意し、eml(1, 2exp(e))=e-ln(2exp(e))=e-ln(2)-ln(exp(e))=e-ln(2)-e=-ln(2)でln(2x)はln(2)+ln(x)の公式を忘れていた。(勘違いしてた・・・)
2exp(e)は、exp(-exp(e))を用意し、eml(e, exp(-exp(e)))=exp(e)+exp(e)=2exp(e)。
-exp(e)は、eml(-INF, exp(exp(e)))=0-ln(exp(exp(e))=-exp(e)。
-INFを初めて使ったのが、-x,-1のときで、eml(-INF, eml(x, 1))=0-ln(exp(x))=-x。
-x: 11111E1EEEEx1EE
exp(e): 11E1E eml(eml(1,1),1)
x=exp(e)を代入すると、-exp(e)=11111E1EEEE11E1E1EE
アンダースコアを入れると、前後に少し追加しただけ。
1/2: 111E_11111E1EEEE11E1E1EE_1EEE1E
x/2を作るには、exp(ln(x)-ln(2))が作れればよい。
同様に、2exp(e-ln(x))を用意し、eml(1, 2exp(e-ln(x)))=e-ln(2)-(e-ln(x))=ln(x)-ln(2)。
2exp(e-ln(x))は、y=e-ln(x),exp(-exp(y))を用意し、eml(y, exp(-exp(y)))=exp(y)+exp(y)=2exp(y)=2exp(e-ln(x))。
-exp(y)は、-xにx=exp(y)を入れる。y=e-ln(x)=eml(1, x)
exp(e-ln(x)): 1xE1E eml(eml(1,x),1)
x=exp(e-ln(x))を代入すると、-exp(e-ln(x))=11111E1EEEE1xE1E1EE
アンダースコアを入れると、前半にもう一つxがある。
x/2: 11xE_11111E1EEEE1xE1E1EE_1EEE1E
allow_inf=falseやComplexでの定数1/2
RealからComplexに変えたところ、定数1/2が劣化したので、Realでallow_infを変更したらさらに違いが出た。
1/2=111E11111E1EEEE11E1E1EE1EEE1E (K=29 allow_inf=true)。
1/2=111111111EEE1EE11EE1EEEE1EE11E1EE1E (K=35 allow_inf=false)。
1/2=1111111E1E1EEE1EE11E1E1EE1EEE1E (K=31 Complex)。
allow_inf=falseで流した最初のK=31は不正解。
RPNを展開すると、
exp(e-ln(2*exp(e)-exp(e-(exp(exp(e-1))))))
A=exp(e-(exp(exp(e-1))))とおくと、exp(e-ln(2*exp(e)-A))でA=4.38E-114のため2*exp(e)-A=e*exp(e)と情報落ちして、exp(e-ln(2*exp(e))=exp(-ln(2))=0.49999999999999994でHITする。
その後、K=33で5個、K=35で18個の不正解を経て、ようやくK=35で正解が見つかる。
今回は、定数2のRPNパターンを含んでいるものがK=35の2ヵ所のみで絞れたが、これをロジック化するのは難しそう。やはり近似式を見つける程度のものか。
Complex版は、e-ln(e-exp(e))を経由しているが、対数の中が-12.435980413020218でこの結果が2.520593917172769 + 3.141592653589793iの複素数で、次のステップがexpで元の実数に戻ってくる。
定数e-2、関数e-x、定数3
定数3なんて定数2と関数x+1で作れるが、K=19+19-1=37。
javaで実行すると簡単に出てきた。
Searching for Real Constant target: 3.0 (allow_inf=true)
Testing K=27 (Shapes: 742900)... done. 0.433s
Testing K=29 (Shapes: 2674440)... break. 0.719s
[HIT!] Found at K=29, rank=671014
RPN: 1 1 1 1 1 1 1 1 E E E 1 E E 1 1 E E E 1 E E 1 1 E E 1 E E
最後の2ステップが、関数e-xを実行していて、
eml(1, eml(x, 1))=e-ln(exp(x))=e-x=1x1EE (K=5)
この形は最も最初にln(x)のときにe-ln(x)=eml(1, x)=1xEを関数e-xに入れると、11xE1EEが出来ていた。
定数2ならば、A=e-2を用意すれば、関数e-xに入れて1A1EEでよく、
定数3ならば、B=e-3を用意して、関数e-xに入れて1B1EEでよい。
B=A-1なので、関数x-1に入れる。
これらを踏まえてRPN文字列を列挙すると、
- 関数e-x:
1x1EE(K=5) - 定数2:
111111EEE1EE11EE1EE(K=19) - 定数3:
11111111EEE1EE11EEE1EE11EE1EE(K=29) - 定数e-1:
111EE(K=5) - 定数e-2:
11111EEE1EE11EE(K=15) - 定数e-3:
1111111EEE1EE11EEE1EE11EE(K=25) - 関数x-1:
11xE1EE11EE(K=11) - 定数(e-1)-1:
11111EEE1EE11EE(K=15) - 定数(e-2)-1:
1111111EEE1EE11EEE1EE11EE(K=25)
定数2は、x+yにx=y=1を代入して作ったが、定数e-1を関数x-1で定数e-2を作り、関数e-xで作ったものと同じ。
定数3も、定数e-2からx-1でe-xの順で作る。
ならば、定数4は、e-4をe-3から作れば、K=25+11+5-2=39で出来るはずだが。
なぜかK=39で見つからない。ええええええええ。なんかバグっているかな。
Testing K=35 (Shapes: 129644790)... done. 94.605s
Testing K=37 (Shapes: 477638700)... done. 367.6s
Testing K=39 (Shapes: 1767263190)... done. 1461.543s
カタラン数の増加がヤバくて、もうショートカットしないと無理じゃね。
MAX_TOKENS=71
MAX_LEAVES=36
Long.MAX_VALUE=9223372036854775807
k leaves totalShapes
1 1 1
3 2 1
5 3 2
7 4 5
9 5 14
11 6 42
13 7 132
15 8 429
17 9 1430
19 10 4862
21 11 16796
23 12 58786
25 13 208012
27 14 742900
29 15 2674440
31 16 9694845
33 17 35357670
35 18 129644790
37 19 477638700
39 20 1767263190 <---1461s=24min21s
41 21 6564120420
43 22 24466267020
45 23 91482563640
47 24 343059613650
49 25 1289904147324
51 26 4861946401452
53 27 18367353072152
55 28 69533550916004
57 29 263747951750360
59 30 1002242216651368
61 31 3814986502092304
63 32 14544636039226909
65 33 55534064877048198
67 34 212336130412243110
69 35 812944042149730764
71 36 3116285494907301262
定数4
なかなか奥が深いね。
まず寝ている間に定数4を探した。
ご苦労様。9961s=2hour46min1s
Searching for Constant Real target: 4.0 (allow_inf=true)
Testing K=41 (Shapes: 6564120420)... done. 5115.977s
Testing K=43 (Shapes: 24466267020)... break. 9961.541s
[HIT!] Found at K=43, rank=8173890490
RPN: 1 1 E 1 1 1 1 1 1 1 1 E 1 1 E E E 1 E E 1 1 E E E 1 E E 1 1 E E E 1 E E 1 1 E E 1 E E
定数4: 11E11111111E11EEE1EE11EEE1EE11EEE1EE11EE1EE (K=43)
で、なんでe-3からx-1の関数でe-4を作る方法より長いのかと、ふとe-3って実数でいくつと思ったら-0.2817で、きっとx-1の途中のln(-0.2817)でNaNになっているわな。
そんな落とし穴に気が付いてよかった。
Real(double)版とComplex版があるけど、Real版はINF,-INFを使うオプションがあるが、Complex版はNaNにしている代わりにINF,-INFが使えないのだった。
AIって便利と思ったのが、RPN文字列からrankを逆引きする方法を聞いて、そのままコードを書いてもらうと、ピンポイントでテストできるツールが1分で出来て、あれ、これってインタプリターが欲しいと思っていたそのものだった。
AI解説
定数4は、exp(e)-4から関数exp(e)-xを使って実現している。exp(e)=15.15のため、定数15までこの方法が使えそう。
とAIに教えたら、解説を作ってくれた。
最初は「システムは回答できませんでした。」連発していたのが、完全にこの演算子の世界を理解しているや。
命令長 K=43 の内訳
この戦略に基づく K の積み上げを計算すると、const4.txt の結果と完璧に一致します。
- exp(e)−1 : eml(e,e) として構成。これは以前議論した葉4枚の Rank 2(1 1 E 1 1 E E)であり、K=7 です [会話履歴]。
- 関数 x−1 : 1回適用するごとに 10 トークン 増加します(K=11 ですが、結合時に葉を1つ消費するため +10)。
- exp(e)−2 : 7+10=17
- exp(e)−3 : 17+10=27
- exp(e)−4 : 27+10=37
- 最終変換 (exp(e)−x) : 最後に exp(e)−(exp(e)−4) を計算して 4 を取り出します。
- 関数 f(x)=exp(e)−x は eml(e,exp(x)) であり、K=7(1 1 E x 1 E E)です。
- 最終合計: 37+(7−1)=43
この K=43 という数値は、全探索で見つかった最短値と一致しており、この「exp(e) 起点のデクリメント」が実数領域における最善の攻略法であることを示しています
Complexでの定数4
Complexで既存のものを流したら、定数-1と定数1/2で劣化したが、ようやく定数4でメリットが出た。
4=1111111111EEE1EE11EEE1EE11EEE1EE11EE1EE (K=39) 943s Complex
4=11E11111111E11EEE1EE11EEE1EE11EEE1EE11EE1EE (K=43) 9961s Real
e-3が負の数になるため、exp(e)-3にしているところが複素数にて改善されるかもと思ったら、その通りの結果となった。
ln(x):11xE1EE
e-3:1111111EEE1EE11EEE1EE11EE
4=1_11_1111111EEE1EE11EEE1EE11EE_E1EE_11EE1EE (K=39) 943s
アンダースコアを入れると、ln(e-3)を実行している。
定数-2
Searching for Real Constant target: -2.0 (allow_inf=true)
Testing K=25 (Shapes: 208012)... done. 0.123s
Testing K=27 (Shapes: 742900)... break. 0.312s
[HIT!] Found at K=27, rank=449903
RPN: 1 1 1 1 1 1 1 E E E 1 E E 1 1 E E E 1 E E 1 1 E 1 E E
定数e-2から関数x-eで定数-2を取り出す。
AI解説
-
ベースの作成: 定数 e−2 を作ります(K=15)。
-
対数変換: 関数 ln(x) を適用して ln(e−2) とします。
- e−2≈0.718 であり、これは正の数です。
- したがって、実数モードの探索であっても ln(0.718) は NaN にならず、有効な経路として計算が進みます。
-
定数シフト: これを関数 f(x)=x−e に代入します。
- x−e は EML では eml(ln(x),exp(e)) と表現されます。
- exp(ln(e−2))−ln(exp(e))=(e−2)−e=−2 となります。
-
命令長 K=27 の内訳
-
左辺:ln(e−2) (21トークン)
- 定数 e−2 (K=15) に関数 ln(x) (K=7) を結合した形です。
- 15+(7−1)=21。
-
右辺:exp(e) (5トークン)
- eml(e,1) であり、RPN は 1 1 E 1 E です
-
結合:EML演算子 (1トークン)
- 最後を E で繋ぎます。
-
合計: 21+5+1=27
定数-3
買い物に行っている間に終わっていた。
お疲れさま。3534s=58min54s
Searching for Constant Real target: -3.0 (allow_inf=true)
Testing K=39 (Shapes: 1767263190)... done. 1307.303s
Testing K=41 (Shapes: 6564120420)... break. 3534.125s
[HIT!] Found at K=41, rank=3920687304
RPN: 1 1 1 1 1 1 1 1 E 1 1 E E E 1 E E 1 1 E E E 1 E E 1 1 E E E 1 E E 1 1 E 1 E 1 E E
定数4と同様に、e-3では負の数となるので、定数exp(e)-3を作り、関数x-exp(e)で取り出す。
AI解説
命令長 K=41 の内訳
const_3.txt で発見された K=41 という数値は、以下の積み上げによって構成されています。
- ベース:exp(e)−3 (K=27)
- exp(e)−1 (K=7) から出発し、関数 x−1 (K=11) を2回適用します。
- 計算:7+(11−1)×2=27。
- 対数変換:ln(exp(e)−3) (33トークン)
- 定数 exp(e)−3 (K=27) に関数 ln(x) (K=7) を結合します。
- 計算:27+(7−1)=33。
- 右辺の定数:exp(exp(e)) (7トークン)
- exp(e) (K=5) に関数 exp(x) (K=3) を結合した形、または eml(exp(e),1) です。
- RPN:1 1 E 1 E 1 E。
- 最終結合:EML演算子 (1トークン)
- exp(ln(exp(e)−3))−ln(exp(exp(e)))=(exp(e)−3)−exp(e)=−3。
- 合計: 33+(7−1)=41。
Complexでの定数-3
定数4と同様に、定数-3でもComplexのメリットが出た。
-3=111111111EEE1EE11EEE1EE11EEE1EE11E1EE (K=37) 424s Complex
-3=11111111E11EEE1EE11EEE1EE11EEE1EE11E1E1EE (K=41) 3534s Real
ln(x):11xE1EE
e-3:1111111EEE1EE11EEE1EE11EE
-3=_11_1111111EEE1EE11EEE1EE11EE_E1EE_11E1EE (K=37)
アンダースコアを入れると、ln(e-3)を実行している。
なお、こちらでもK=35に誤判定が出たが、e-3でなく、e-2しか含まれていなくて、おかしいわな。
Complexクラス
javaにComplexクラスってあったのか、なかったのか、ちゃんと探していないが、AIがexp,log,subの簡易実装を作ってきた。
log以外にatan2も困ったことが起きそう。
public static Complex exp(Complex z) {
double ere = Math.exp(z.re);
return new Complex(ere * Math.cos(z.im), ere * Math.sin(z.im));
}
public static Complex log(Complex z) {
double r = Math.hypot(z.re, z.im);
return new Complex(Math.log(r), Math.atan2(z.im, z.re));
}
public Complex sub(Complex z) {
return new Complex(this.re - z.re, this.im - z.im);
}
探索したいターゲットの計算のために、add,mul,divを足した。
javaに翻訳した際に、どこでそうなったか分からないが、実数Realではln(0)=-INF,exp(-INF)=0を許し、複素数Complexではln(-1)=πi、exp(πi)=-1を許すがln(0)は許さない仕様が中途半端だったが、複素数でln(0)=-INFを許したら、なんとln(-INF)=INF+πi、exp(INF+πi)=-INFと戻ってこれるようになったのだ。ただし、ln(INF+πi)=INF+0i(実数)なので、もう戻らない。
定数πi
Complexのみの定数πi=ln(-1)。
意外とあっさり出てくる。
Searching for Constant Complex target: πi z=0.0 + 3.141592653589793i
Testing K=23 (Shapes: 58786)... break. 0.035s
[HIT!] Found at K=23, rank=12738
RPN: 1 1 1 1 1 1 1 E E E 1 E E 1 1 E 1 E E E 1 E E
そのままComplex版-1とln(x)だった。K=17+7-1=23
定数-1:(K=17 rank=804 allow_inf=false,Complex)
11111EEE1EE11E1EE
関数ln(x):(K=7 rank=1 mask=4)
11xE1EE
定数(π/2)i
定数(π/2)iをフルに探索するのは無理ぽい。
意外とx/2のComplex版も複素数だと厳しい。
というわけで、x=πi専用のx/2を探索したら、いろいろ見つかる。
maskを無制限にしたら、K=21で変数6個使うので、全体でK=141。チェックツールはカタラン数をlongで管理してIDを振っているので、K=71が最大だった。あらら。
maskのビット数を5以下に制限して、K=27で変数3個使うので、全体でK=87。これも超えている。
maskのビット数を2以下に制限して、K=29で変数2個使うので、全体でK=69。チェックツールで計算すると、9.618353468608953E-17 + 1.570796326794897iで誤差4.543858477659303E-16。
maskのビット数を1いかに制限して、K=35で変数1個使うので、全体でK=55。チェックツールで計算すると、9.618353468608955E-17 + 1.5707963267948974iで誤差8.933712428580416E-16。
定数(π/2)i: 11111111111E1EEEE11EEE1EEE1EEE1EE111111EEE1EE11EE1EEE1E (K=55 rank=60859337419431)
定数πi:(K=21 rank=3688 Complex allow_inf=true)
1111111E1EEEE11EEE1EE
Searching for Unary Function Complex target: x/2 at x=0.0 + 3.141592653589793i (allow_inf=true) (bitCount is all)
[HIT!] Found at K=21, rank=12464, mask=63
RPN: xxxExxxE11EE1EE1EEE1E
K=20*6+21=141
1111111E1EEEE11EEE1EE1111111E1EEEE11EEE1EE1111111E1EEEE11EEE1EEE1111111E1EEEE11EEE1EE1111111E1EEEE11EEE1EE1111111E1EEEE11EEE1EEE11EE1EE1EEE1E
Searching for Unary Function Complex target: x/2 at x=0.0 + 3.141592653589793i (allow_inf=true) (bitCount<=5)
[HIT!] Found at K=27, rank=189150, mask=529
RPN: x111x11EEEE1EE1xE1EE11EE1EE
K=20*3+27=87
1111111E1EEEE11EEE1EE1111111111E1EEEE11EEE1EE11EEEE1EE11111111E1EEEE11EEE1EEE1EE11EE1EE
Searching for Unary Function Complex target: x/2 at x=0.0 + 3.141592653589793i (allow_inf=true) (bitCount<=2)
[HIT!] Found at K=29, rank=2298175, mask=2064
RPN: 1111xE1EEE1EE111E1EEx1E1EEE1E
K=20*2+29=69
Input: 11111111111E1EEEE11EEE1EEE1EEE1EE111E1EE1111111E1EEEE11EEE1EE1E1EEE1E
Trim: 11111111111E1EEEE11EEE1EEE1EEE1EE111E1EE1111111E1EEEE11EEE1EE1E1EEE1E
RpnID: K=69 rank=706404526389959490
Result: 9.618353468608953E-17 + 1.570796326794897i
Error: 4.543858477659303E-16
Searching for Unary Function Complex target: x/2 at x=0.0 + 3.141592653589793i (allow_inf=true) (bitCount<=1)
[HIT!] Found at K=35, rank=110852964, mask=16
RPN: 1111xE1EEE1EE111111EEE1EE11EE1EEE1E
K=20+35=55
Input: 11111111111E1EEEE11EEE1EEE1EEE1EE111111EEE1EE11EE1EEE1E
Trim: 11111111111E1EEEE11EEE1EEE1EEE1EE111111EEE1EE11EE1EEE1E
RpnID: K=55 rank=60859337419431
Result: 9.618353468608955E-17 + 1.5707963267948974i
Error: 8.933712428580416E-16
答えはもう分かっている探索ツール(初期値K,rankを入れている)を実行すると、まあ見つかる。
Searching for Constant Complex target: (π/2)i z=0.0 + 1.5707963267948966i (allow_inf=true)
Testing K=55 (Shapes: 69533550916004)... break. 0.0s
[HIT!] Found at K=55, rank=60859337419431
RPN: 1 1 1 1 1 1 1 1 1 1 1 E 1 E E E E 1 1 E E E 1 E E E 1 E E E 1 E E 1 1 1 1 1 1 E E E 1 E E 1 1 E E 1 E E E 1 E
定数i
K=55の定数(π/2)iをexp(iπ/2)=iとなるはず。手でx1Eを付ける。
チェックツールをかけると、-8.269460797427576E-16 + 1.0iで虚数部の誤差なしか。
定数i: 11111111111E1EEEE11EEE1EEE1EEE1EE111111EEE1EE11EE1EEE1E1E (K=57 rank=255073738253787)
Input: 11111111111E1EEEE11EEE1EEE1EEE1EE111111EEE1EE11EE1EEE1E1E
Trim: 11111111111E1EEEE11EEE1EEE1EEE1EE111111EEE1EE11EE1EEE1E1E
RpnID: K=57 rank=255073738253787
Result: -8.269460797427576E-16 + 1.0i
Error: 8.269460797427576E-16
答えはもう分かっている探索ツール(初期値K,rankを入れている)を実行すると、まあ見つかる。
Searching for Constant Complex target: i z=0.0 + 1.0i (allow_inf=true)
Testing K=57 (Shapes: 263747951750360)... break. 0.0s
[HIT!] Found at K=57, rank=255073738253787
RPN: 1 1 1 1 1 1 1 1 1 1 1 E 1 E E E E 1 1 E E E 1 E E E 1 E E E 1 E E 1 1 1 1 1 1 E E E 1 E E 1 1 E E 1 E E E 1 E 1 E
定数π
定数iも出来たことで、単項演算子探索でx=iを1つだけ使って(bitCount==1)、πを探したら、出てきた。
Searching for Unary Function Complex target: π at x=0.0 + 1.0i (allow_inf=true)
Testing K=37 (Shapes: 477638700, Masks: 20)... break. 12084.632s
[HIT!] Found at K=37, rank=377836955, mask=16
RPN: 1 1 1 1 x E E 1 E E 1 1 1 1 1 1 E 1 E E E E 1 1 E 1 E 1 E E E E 1 E E 1 E
f(x): 1111xEE1EE111111E1EEEE11E1E1EEEE1EE1E (K=37 rank=377836955 mask=16)
に
定数i:(K=57 rank=255073738253787 Complex allow_inf=true)
11111111111E1EEEE11EEE1EEE1EEE1EE111111EEE1EE11EE1EEE1E1E
を代入して、πになっているはず。
定数π:111111111111111E1EEEE11EEE1EEE1EEE1EE111111EEE1EE11EE1EEE1E1EEE1EE111111E1EEEE11E1E1EEEE1EE1E
あららK=37+57-1=93で、今のrankから二分木の形状を決めて、演算する仕組みだとlongで実行できないわ。
定数サマリー
基本的にReal(allow_inf=true)の結果。
Kとrankによってrpnを特定できる。
| name | value | k | rank | desc |
|---|---|---|---|---|
| 1 | 1.0 | 1 | 0 | |
| e | 2.718281828459045 | 3 | 0 | |
| e-1 | 1.718281828459045 | 5 | 0 | |
| exp(e) | 15.154262241479262 | 5 | 1 | |
| 0 | 0.0 | 7 | 1 | |
| exp(e)-1 | 14.154262241479262 | 7 | 2 | |
| -1 | -1.0 | 15 | 256 | allow_inf=true |
| e-2 | 0.7182818284590451 | 15 | 264 | |
| -1 | -1.0 | 17 | 804 | allow_inf=false,Complex |
| exp(e)-2 | 13.154262241479262 | 17 | 899 | |
| 2 | 2.0 | 19 | 1265 | |
| πi | 0+3.141592653589793i | 23 | 12738 | Complex |
| e-3 | -0.2817181715409549 | 25 | 136126 | |
| -2 | -2.0 | 27 | 449903 | |
| exp(e)-3 | 12.154262241479262 | 27 | 488935 | |
| 3 | 3.0 | 29 | 671014 | |
| 1/2 | 0.5 | 29 | 2004798 | allow_inf=true |
| 1/2 | 0.5 | 31 | 7202228 | Complex |
| 1/2 | 0.5 | 35 | 116090688 | allow_inf=false |
| -3 | -3.0 | 37 | 86120580 | time=424s Complex |
| exp(e)-4 | 11.154262241479262 | 37 | 320145580 | time=269s |
| 4 | 4.0 | 39 | 434653851 | time=943s Complex |
| -3 | -3.0 | 41 | 3920687304 | time=3534s Real |
| 4 | 4.0 | 43 | 8173890490 | time=9961s Real |
| (π/2)i | 0 + 1.5707963267948966i | 55 | 60859337419431 | handmaid Complex |
| i | 0 + i | 57 | 255073738253787 | handmaid Complex |
定数1:(K=1 rank=0)
1
定数e:(K=3 rank=0)
11E
定数e-1:(K=5 rank=0)
111EE
定数exp(e):(K=5 rank=1)
11E1E
定数0:(K=7 rank=1)
111E1EE
定数exp(e)−1:(K=7 rank=2)
11E11EE
定数+INF:(K=9 rank=1 allow_inf=true)
1111E1EEE
定数-INF:(K=11 rank=1 allow_inf=true)
11111E1EEEE
定数-1:(K=15 rank=256 allow_inf=true)
11111E1EEEE11EE
定数e-2:(K=15 rank=264)
11111EEE1EE11EE
定数-1:(K=17 rank=804 allow_inf=false,Complex)
11111EEE1EE11E1EE
定数2:(K=19 rank=1265)
111111EEE1EE11EE1EE
定数πi:(K=23 rank=12738 Complex)
1111111EEE1EE11E1EEE1EE
定数e-3:(K=25 rank=136126)
1111111EEE1EE11EEE1EE11EE
定数-2:(K=27 rank=449903)
1111111EEE1EE11EEE1EE11E1EE
定数exp(e)-3:(K=27 rank=488935)
111111E11EEE1EE11EEE1EE11EE
定数3:(K=29 rank=671014)
11111111EEE1EE11EEE1EE11EE1EE
定数1/2:(K=29 rank=2004798 allow_inf=true)
111E11111E1EEEE11E1E1EE1EEE1E
定数1/2:(K=31 rank=7202228 Complex)
1111111E1E1EEE1EE11E1E1EE1EEE1E
定数1/2:(K=35 rank=116090688 allow_inf=false)
111111111EEE1EE11EE1EEEE1EE11E1EE1E
定数-3:(K=37 rank=86120580 Complex)
111111111EEE1EE11EEE1EE11EEE1EE11E1EE
定数exp(e)−4:(K=37 rank=320145580)
11111111E11EEE1EE11EEE1EE11EEE1EE11EE
定数4:(K=39 rank=434653851 Complex)
1111111111EEE1EE11EEE1EE11EEE1EE11EE1EE
定数-3:(K=41 rank=3920687304 Real)
11111111E11EEE1EE11EEE1EE11EEE1EE11E1E1EE
定数4:(K=43 rank=8173890490 Real)
11E11111111E11EEE1EE11EEE1EE11EEE1EE11EE1EE
定数(π/2)i:(K=55 rank=60859337419431 Complex allow_inf=true)
11111111111E1EEEE11EEE1EEE1EEE1EE111111EEE1EE11EE1EEE1E
定数i:(K=57 rank=255073738253787 Complex allow_inf=true)
11111111111E1EEEE11EEE1EEE1EEE1EE111111EEE1EE11EE1EEE1E1E
単項演算子サマリー
基本的にReal(allow_inf=true)の結果。
Kとrankによってrpnの形状を特定し、maskが変数xの位置をビットパターンで特定する(EMLツリーの左側が下位ビット)。
| name | k | rank | mask | desc |
|---|---|---|---|---|
| exp(x) | 3 | 0 | 1 | |
| e-ln(x) | 3 | 0 | 2 | |
| e-x | 5 | 0 | 2 | |
| ln(x) | 7 | 1 | 4 | |
| exp(e)−x | 7 | 2 | 4 | |
| x | 9 | 3 | 4 | |
| x-1 | 11 | 24 | 4 | |
| ln(ln(x)) | 13 | 29 | 16 | 成立するxが狭い |
| x−e | 13 | 69 | 4 | |
| x-exp(e) | 15 | 211 | 4 | |
| -x | 15 | 256 | 64 | allow_inf=true |
| 1/x | 15 | 388 | 64 | allow_inf=true |
| -x | 17 | 804 | 8 | Complex allow_inf=false |
| -x | 17 | 804 | 76 | Real allow_inf=false |
| x^2 | 17 | 1122 | 80 | |
| 1/x | 17 | 1235 | 8 | allow_inf=false |
| x+1 | 19 | 1265 | 16 | Complex |
| x+1 | 19 | 1265 | 25 | Real |
| 2x | 19 | 1265 | 144 | Complex |
| 2x | 19 | 1265 | 153 | Real |
| x/2 | 21 | 12464 | 63 | x=πi Complex allow_inf=true bitCount is all |
| x/2 | 27 | 189150 | 529 | x=πi Complex allow_inf=true bitCount<=5 |
| x/2 | 29 | 2004798 | 1028 | Real allow_inf=true bitCount is all |
| x/2 | 29 | 2298175 | 2064 | x=πi Complex allow_inf=true bitCount<=2 |
| x/2 | 35 | 110852964 | 16 | x=πi Complex allow_inf=true bitCount<=1 |
| x/2 | 35 | 116090688 | 32768 | Real allow_inf=true bitCount<=1 |
関数exp(x):(K=3 rank=0 mask=1)
x1E
関数e-ln(x):(K=3 rank=0 mask=2)
1xE
関数e-x:(K=5 rank=0 mask=2)
1x1EE
関数ln(x):(K=7 rank=1 mask=4)
11xE1EE
関数exp(e)−x:(K=7 rank=2 mask=4)
11Ex1EE
関数x:(K=9 rank=3 mask=4)
11x1EE1EE
関数x-1:(K=11 rank=24 mask=4)
11xE1EE11EE
関数ln(ln(x)):(K=13 rank=29 mask=16)
1111xE1EEE1EE
関数x−e:(K=13 rank=69 mask=4)
11xE1EE11E1EE
関数x-exp(e):(K=15 rank=211 mask=4)
11xE1EE11E1E1EE
関数-x:(K=15 rank=256 mask=64 allow_inf=true)
11111E1EEEEx1EE
関数1/x:(K=15 rank=388 mask=64 allow_inf=true)
11111E1EEEExE1E
関数-x:(K=17 rank=804 mask=8 Complex allow_inf=false)
111x1EEE1EE11E1EE
関数-x:(K=17 rank=804 mask=76 Real allow_inf=false)
11xx1EEE1EEx1E1EE
関数x^2:(K=17 rank=1122 mask=80)
1111xEE1EExE1EE1E
関数1/x:(K=17 rank=1235 mask=8 allow_inf=false)
111xEE1EE11E1EE1E
関数x+1:(K=19 rank=1265 mask=16 Complex)
1111x1EEE1EE11EE1EE
関数x+1:(K=19 rank=1265 mask=25 Real)
x11xx1EEE1EE11EE1EE
関数2x:(K=19 rank=1265 mask=144 Complex)
1111x1EEE1EEx1EE1EE
関数2x:(K=19 rank=1265 mask=153 Real)
x11xx1EEE1EEx1EE1EE
関数x/2:(K=21 rank=12464 mask=63 x=πi Complex allow_inf=true bitCount is all)
xxxExxxE11EE1EE1EEE1E
関数x/2:(K=27 rank=189150 mask=529 x=πi Complex allow_inf=true bitCount<=5)
x111x11EEEE1EE1xE1EE11EE1EE
関数x/2:(K=29 rank=2004798 mask=1028 Real allow_inf=true bitCount is all)
11xE11111E1EEEE1xE1E1EE1EEE1E
関数x/2:(K=29 rank=2298175 mask=2064 x=πi Complex allow_inf=true bitCount<=2)
1111xE1EEE1EE111E1EEx1E1EEE1E
関数x/2:(K=35 rank=110852964 mask=16 x=πi Complex allow_inf=true bitCount<=1)
1111xE1EEE1EE111111EEE1EE11EE1EEE1E
関数x/2:(K=35 rank=116090688 mask=32768 Real allow_inf=true bitCount<=1)
111111111EEE1EE11EE1EEEE1EE1xE1EE1E
既知の関数のまとめ
関数をマクロ化する。
例:eml(x, 1)はexp(x)に短縮する。3
Kとrankで二分木の形状を再現できる。
二項演算子(Binary)ではcodeが変数x,yの位置を3進数で特定する(EMLツリーの左側が下位桁)。
- 関数f(x,y)=x-y:
11xE1EEy1EEeml(ln(x), exp(y))(K=11 rank=24 code=171) - 関数f(x,y)=ln(x)+ln(y):
1111xEE1EEyE1EEeml(1, exp(eml(ln(eml(1, x)), y)))(K=15 rank=121 code=1539) - 関数f(x,y)=xy:
1111xEE1EEyE1EE1Ef(x,y)=exp(ln(x)+ln(y))(K=17 rank=1122 code=1539) - 関数f(x,y)=x+y:
1111x1EEE1EEy1EE1EEf(x,y)=ln(exp(x))+ln(exp(y))(K=19 rank=1265 code=4455) - 関数f(x,y)=ln(x)-ln(y):
1111xE1EEE1EEyEeml(ln(ln(x)), y)(K=15 rank=326 code=4455) - 関数f(x,y)=x/y:
1111xE1EEE1EEyE1Eexp(ln(x)-ln(y))(K=17 rank=1327 code=4455) - 関数f(x,y)=x^y:
1111yEE1EE11xE1EEE1EE1E1Eexp(yln(x)(K=25 rank=195379 code=6723) - 関数f(x,y)=log_x(y):
111111yE1EEE1EEE1EE11xE1EEE1Eln(y)/ln(x)(K=29 rank=2354891 code=532899)
githubソース
定数探索、単項演算子探索のソースと実行結果。
メモ
複素数に拡張し、定数-1を使いln(-1)=iπとなる。
iも1とlnで作れるらしい(最適化されていないK=131)
その方針は、まず関数x/2を用意し、πiをπi/2として、オイラーの公式exp(πi/2)=cos(π/2)+isin(π/2)=0+i=iでiを取り出す。
iがあれば、-i*iπ=πからπが作れる(最適化されていないK=193)。
verify_eml_symbolic_chain.wlなるファイルを開くと、この順番の組み立てだったのか。
eConst[] := EML[1, 1];
expEML[x_] := EML[x, 1];
logEML[x_] := EML[1, expEML[EML[1, x]]];
subtractEML[x_, y_] := EML[logEML[x], expEML[y]];
minusEML[x_] := subtractEML[Log[1], x];
plusEML[x_, y_] := subtractEML[x, minusEML[y]];
invEML[x_] := expEML[minusEML[logEML[x]]];
timesEML[x_, y_] := expEML[plusEML[logEML[x], logEML[y]]];
sqrEML[x_] := timesEML[x, x];
divideEML[x_, y_] := timesEML[x, invEML[y]];
halfEML[x_] := divideEML[x, 2];
avgEML[x_, y_] := halfEML[plusEML[x, y]];
iConst[] := expEML[halfEML[logEML[-1]]];
piConst[] := divideEML[logEML[-1], iConst[]];
-
最初
AND(x, y)=NAND(NAND(x, y), NAND(x, y))と展開してしまったが、これではNANDゲートが3つ必要ということになってしまうが、NOTは同じ値のNANDなので、2回NAND(x, y)を演算する必要はない ↩ -
NANDってどこで使うのかと思えば、ド・モルガンの右辺の!(a & b)がNAND(a, b)なんだな ↩
-
長くなるからマクロ化したが、すべてemlで書くと、RPNと一致する。先に1や変数x,yを書き、カッコ閉じるのタイミングがE演算子となる。おそらくeml(1, x)=e-ln(x)のエイリアスが欲しいところ。そのまま略すとeml(x)なのか。プログラミング言語の観点から、eml(x)=eml(0, x)と想像しそうで、eml(1, x)と2つエイリアスが欲しいところ。eml0(x)とeml1(x)になってしまうな。 ↩