prologを用いて,ある自然数(0を含む)Bを与えたときに,B以下となる自然数Aを列挙していく,というものをA=0からとA=Bから出していくという者の二通りで別々に組みたいのですが,勉強したてということもあり,うまくできません.
欲しい結果としては,
le(A,s(s(s(0)))).
A=0;
A=s(0);
A=s(s(0));
A=s(s(s(0))).
false
もしくはこれの逆順で表示されるものです.
s()は1を加算するように決まっていて,s(0)=1, s(s(0))=2のようになります.
Ubuntu20.04で行っています.
0から列挙(昇順)していこうとして,次のようなものを書いたのですが,これだとMが加算されると0じゃなくなってしまい,うまく回らないです.
prolog
1ils(M,N) :- M<N. 2le(0,_). 3le(s(M),N) :- le(M,N), ils(M,N).
次にA=Bから列挙(降順)しようとして次のようなものを描いたのですが,想定した動きをしてくれませんでした.
prolog
1le(N,N). 2le(s(N),s(N)) :- le(N,N).
実行結果
?- le(M,s(s(0))).
M = s(s(0)) ;
M = s(s(0)) ;
M = s(s(0)).
どのように考え,どこを修正すればよいか教えていただきたいです.
ilsやleやsの意味が分からないので、何とも言えず、また実行した結果がどうなったら正解だと思っているのかも分かりません。
自然数であることをチェックしないのであれば組み込みのbetween述語で列挙できると思います。
prologの基礎を学んでから、質問したい内容を説明できるようになってから質問して頂ければ幸いです。
私もprologは齧った程度でちゃんと書けてるのか分かりませんが、ご参考までに実行した結果を貼っておきます。
$ docker run -it --rm swipl
Welcome to SWI-Prolog (threaded, 64 bits, version 8.3.29)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.
For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).
?- [user].
|: is_natural_less_than(X,M):-is_natural_less_than(0,M,X).
|: is_natural_less_than(X,M,X):-X>=0,M>=X.
|: is_natural_less_than(X,M,V):-X>=0,M>=X,X1 is X + 1,is_natural_less_than(X1,M,V).
|: ^D% user://1 compiled 0.01 sec, 3 clauses
true.
?- is_natural_less_than(X,5).
X = 0 ;
X = 1 ;
X = 2 ;
X = 3 ;
X = 4 ;
X = 5 ;
false.
?- halt.
$
知識足らずで申し訳ございません.
s( )というのはprologでは1を加算する関数という風に決まっていると,調べたところで書いてあり,実際実行してみてもそのようになっているみたいです.
例えば1=s(0), 2=s(s(0))のような形です.
このsを使えば自然数を記述することが出来ると学びました.
欲しい結果はまさしくis_natural_less_thanのような形です.
質問の方に追記させていただきます.ご指摘ありがとうございます.
また書かれている
^D% user://1 compiled 0.01 sec, 3 clauses
の部分は一体何をするためのモノなのでしょうか,今までにみた資料の中では見たことがないので教えていただけると幸いです.
環境が書いてなかったので、(コマンドラインを見れば分かる通り)dockerでSWI-prologの公式イメージを実行しています。
^Dは端末からのCtrl+D入力を表しています(実際にそのように端末に表示される)。
つまりl: というプロンプト表示でCtrl+Dで入力を終了したということです。
なので、後ろの「% user://1 compiled 0.01 sec, 3 clauses」はコンパイルした結果です。
s(...)はsだったりsucだったりsuccだったりする後者関数ですね。定義が足りなすぎます。
ils(...)や、le(...)も定義してください。また、2種類のコードを書かれていますが、それぞれどういう出力を期待しているかも記述してください。
さらに、今回の記述で欲しい結果は書かれましたが、「le(A,s(s(s(0))).」でなく「le(A,3).」なのはなぜでしょうか?ペアノ数表記が欲しい理由も良く分からず、困惑します。
最後になりましたが、処理系や環境の記述もお願いします。
とりあえず疑問の解消の前にコードだけ書いておきます。
$ docker run -it --rm swipl
Welcome to SWI-Prolog (threaded, 64 bits, version 8.3.29)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.
For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).
?- [user].
|: conv(0,0).
|: conv(s(X),N):-N>0,N1 is N - 1,conv(X,N1).
|: is_less_equal(X,X).
|: is_less_equal(X,Y):-is_less_than(X,Y).
|: is_less_than(0, s(_)).
|: is_less_than(s(X), s(Y)):-is_less_than(X, Y).
|: is_natural_less_equal(X,M):-conv(S,M),is_natural_less_equal(0,S,X).
|: is_natural_less_equal(X,M,X):-is_less_equal(0,X),is_less_equal(X,M).
|: is_natural_less_equal(X,M,V):-is_less_equal(0,X),is_less_equal(X,M),X1=s(X),is_natural_less_equal(X1,M,V).
|: ^D% user://1 compiled 0.01 sec, 9 clauses
true.
?- is_natural_less_equal(A,3).
A = 0 ;
A = s(0) ;
A = s(s(0)) ;
A = s(s(s(0))) ;
false.
?- halt.
$
le(A,3)としたのは,間違いでした,正しくはle(A,s(s(s(0))))です,もうしわけございません.
ペアノ数表記な理由は公理的集合論に基づくためです.
そのほか,質問に追記させていただきます,ご指摘ありがとうございます
修正ありがとうございます。
これで3回目の指摘になりますが、ils(...)や、le(...)も定義してください。また、2種類のコードを書かれていますが、それぞれどういう出力を期待しているかも記述してください。
(意図したとおりに動いていれば名前や挙動を元に定義が推測可能なのですが、動いていない上に名前が適当だと意図が不明確で定義の推測ができません。)
環境がUbuntu20.04なのは分かりましたが、prologの処理系は何をお使いなのでしょうか?
SWI-PrologとGNU Prologなどの名前とバージョンをご記載ください。
上記のご記載をいただくと、ようやく質問本文の意図を確認する質問が出来ます。。。
最後に現質問でのコードを記載しておきます。
$ docker run -it --rm swipl
Welcome to SWI-Prolog (threaded, 64 bits, version 8.3.29)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.
For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).
?- [user].
|: is_less_equal(X,X).
|: is_less_equal(X,Y):-is_less_than(X,Y).
|: is_less_than(0, s(_)).
|: is_less_than(s(X), s(Y)):-is_less_than(X, Y).
|: is_natural_less_equal(X,M):-is_natural_less_equal(0,M,X).
|: is_natural_less_equal(X,M,X):-is_less_equal(0,X),is_less_equal(X,M).
|: is_natural_less_equal(X,M,V):-is_less_equal(0,X),is_less_equal(X,M),X1=s(X),is_natural_less_equal(X1,M,V).
|: ^D% user://1 compiled 0.01 sec, 7 clauses
true.
?- is_natural_less_equal(A,s(s(s(0)))).
A = 0 ;
A = s(0) ;
A = s(s(0)) ;
A = s(s(s(0))) ;
false.
?- halt.
$