🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Prolog

Prologは、非手続き型プログラミング言語です。述語論理を使った論理型言語と言われており、自然言語解析や理解、推論などのAIに有効です。エキスパートシステム開発などに用いられています。

Q&A

1回答

1118閲覧

ある自然数以下の自然数の列挙

grape_ll

総合スコア83

Prolog

Prologは、非手続き型プログラミング言語です。述語論理を使った論理型言語と言われており、自然言語解析や理解、推論などのAIに有効です。エキスパートシステム開発などに用いられています。

0グッド

2クリップ

投稿2021/10/28 01:57

編集2021/10/31 01:10

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)).

どのように考え,どこを修正すればよいか教えていただきたいです.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/10/29 10:18

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. $
grape_ll

2021/10/29 10:58

知識足らずで申し訳ございません. s( )というのはprologでは1を加算する関数という風に決まっていると,調べたところで書いてあり,実際実行してみてもそのようになっているみたいです. 例えば1=s(0), 2=s(s(0))のような形です. このsを使えば自然数を記述することが出来ると学びました. 欲しい結果はまさしくis_natural_less_thanのような形です. 質問の方に追記させていただきます.ご指摘ありがとうございます. また書かれている ^D% user://1 compiled 0.01 sec, 3 clauses の部分は一体何をするためのモノなのでしょうか,今までにみた資料の中では見たことがないので教えていただけると幸いです.
退会済みユーザー

退会済みユーザー

2021/10/29 14:16

環境が書いてなかったので、(コマンドラインを見れば分かる通り)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. $
grape_ll

2021/10/31 01:08

le(A,3)としたのは,間違いでした,正しくはle(A,s(s(s(0))))です,もうしわけございません. ペアノ数表記な理由は公理的集合論に基づくためです. そのほか,質問に追記させていただきます,ご指摘ありがとうございます
退会済みユーザー

退会済みユーザー

2021/10/31 01:38

修正ありがとうございます。 これで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. $
guest

回答1

0

質問から時間がたっていますが回答します。Webで検索すればかなりの情報が得られます。SWI-prologで実行しました。

昇順列挙

手前にチェックを入れました。X = s(X0), Y = s(Y0)

prolog

1?- [user]. 2|: le(0,_). 3|: le(X,Y) :- X = s(X0), Y = s(Y0), le(X0,Y0). 4|: 5% user://1 compiled 0.02 sec, 2 clauses 6true. 7 8?- le(0,0). 9true. 10 11?- le(0,s(0)). 12true. 13 14?- le(s(0),0). 15false. 16 17?- le(s(0),s(0)). 18true. 19 20?- le(X,0). 21X = 0 ; 22false. 23 24?- le(X,s(s(s(0)))). 25X = 0 ; 26X = s(0) ; 27X = s(s(0)) ; 28X = s(s(s(0))) ; 29false. 30 31?- le(s(s(0)),s(0)). 32false. 33 34?- le(s(s(0)),s(s(0))). 35true. 36 37?- le(s(0),s(s(s(0)))). 38true. 39 40?-

降順列挙

s(s(...))が無限に続くのでカットで打ち切ることにしました。条件はX==0です。他に良い条件があるかもしれません。降順列挙は成功しますが、いくつかカットしきれていないものがあります。

prolog

1?- [user]. 2|: le(X,X) :- (X == 0 -> !, true; true). 3|: le(X,Y) :- Y = s(_), le(s(X),Y), (X == 0 -> !, true; true). 4|: 5% user://1 compiled 0.00 sec, 2 clauses 6true. 7 8?- le(0,0). 9true. 10 11?- le(0,s(0)). 12true. 13 14?- le(s(0),s(s(0))). 15true ; 16 17ERROR: Stack limit (1.0Gb) exceeded 18ERROR: Stack sizes: local: 0.8Gb, global: 0.2Gb, trail: 1Kb 19ERROR: Stack depth: 10,064,234, last-call: 0%, Choice points: 3 20ERROR: Possible non-terminating recursion: 21ERROR: [10,064,234] user:le(<compound s/1>, <compound s/1>) 22ERROR: [10,064,233] user:le(<compound s/1>, <compound s/1>) 23?- | . 24 25ERROR: Stream user_input:29:6 Syntax error: Unexpected end of clause 26?- le(X,s(s(s(0)))). 27X = s(s(s(0))) ; 28X = s(s(0)) ; 29X = s(0) ; 30X = 0. 31 32?- le(s(0),0). 33false. 34 35?- le(s(s(0)),s(0)). 36ERROR: Stack limit (1.0Gb) exceeded 37ERROR: Stack sizes: local: 0.8Gb, global: 0.1Gb, trail: 0Kb 38ERROR: Stack depth: 10,063,535, last-call: 0%, Choice points: 3 39ERROR: In: 40ERROR: [10,063,535] user:le(<compound s/1>, <compound s/1>) 41ERROR: [10,063,534] user:le(<compound s/1>, <compound s/1>) 42ERROR: [10,063,533] user:le(<compound s/1>, <compound s/1>) 43ERROR: [10,063,532] user:le(<compound s/1>, <compound s/1>) 44ERROR: [10,063,531] user:le(<compound s/1>, <compound s/1>) 45ERROR: 46ERROR: Use the --stack_limit=size[KMG] command line option or 47ERROR: ?- set_prolog_flag(stack_limit, 2_147_483_648). to double the limit. 48?- le(X,0). 49X = 0. 50 51?-

投稿2023/08/04 01:45

xebme

総合スコア1090

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問