このディレクトリの索引

以下のサイトは 二つのスレッドとメッセージキューを使ってn回目の真となる非決定性述語の解を得る(_n回,_選択項,_副目標,_n回目の真となる非決定性の解) :- 二つのメッセージキューを生成しキュー番号_2には1からnまでを詰める(_n回,_キュー番号,_キュー番号_2), '別スレッド上で、副目標の実行とメッセージキュー_2からの実行回数の取り出しを対として行い、_n回に達したらその時の選択項とend_of_fileをメッセージキューに追加する'(_キュー番号,_キュー番号_2,_n回,_選択項,_副目標), メッセージを回収した後メッセージキューを消去する(_キュー番号,_キュー番号_2,[_n回目の真となる非決定性の解]). 二つのメッセージキューを生成しキュー番号_2には1からnまでを詰める(_n回,_キュー番号,_キュー番号_2) :- 二つのメッセージキューを生成し(_キュー番号,_キュー番号_2), キュー番号_2には1からnまでを詰める(_n回,_キュー番号_2). 二つのメッセージキューを生成し(_キュー番号,_キュー番号_2) :- message_queue_create(_キュー番号), message_queue_create(_キュー番号_2). キュー番号_2には1からnまでを詰める(_n回,_キュー番号_2) :- thread_create('1からnまで新たに生成されたキュー_2に追加する'(_n回,_キュー番号_2),_,[]). '別スレッド上で、副目標の実行とメッセージキュー_2からの実行回数の取り出しを対として行い、_n回に達したらその時の選択項とend_of_fileをメッセージキューに追加する'(_キュー番号,_キュー番号_2,_n回,_選択項,_副目標) :- thread_create(副目標の実行とメッセージキュー_2からの実行回数の取り出しを対として行い_n回に達したらその時の選択項とend_of_fileをメッセージキューに追加する(_キュー番号,_キュー番号_2,_n回,_選択項,_副目標),_,[]). 副目標の実行とメッセージキュー_2からの実行回数の取り出しを対として行い_n回に達したらその時の選択項とend_of_fileをメッセージキューに追加する(_キュー番号,_キュー番号_2,_n回,_選択項,_副目標) :- catch(_副目標,E,fail), メッセージキュー_2から取り出した度数が_n回になったらキューに情報を追加する(_キュー番号,_キュー番号_2,_n回,_選択項). 副目標の実行とメッセージキュー_2からの実行回数の取り出しを対として行い_n回に達したらその時の選択項とend_of_fileをメッセージキューに追加する(_キュー番号,_,_,_,_) :- キューに情報を追加する(_キュー番号,end_of_file). メッセージキュー_2から取り出した度数が_n回になったらキューに情報を追加する(_キュー番号,_キュー番号_2,_n回,_選択項) :- メッセージキュー_2から取り出した度数が_n回になったら(_キュー番号_2,_n回,_選択項), キューに情報を追加する(_キュー番号,_選択項). メッセージキュー_2から取り出した度数が_n回になったら(_キュー番号_2,_n回,_選択項) :- メッセージを確実に得る(_キュー番号_2,_度数), _度数 = _n回. キューに情報を追加する(_キュー番号,_選択項) :- 項をメッセージキューで扱いやすいように文字列に変換する(_選択項,_選択項文字列), thread_send_message(_キュー番号,_選択項文字列), thread_send_message(_キュー番号,end_of_file). 項をメッセージキューで扱いやすいように文字列に変換する(_選択項,_選択項文字列) :- swritef(_選択項文字列,'%t',[_選択項]). メッセージを回収した後メッセージキューを消去する(_キュー番号,_キュー番号_2,_メッセージならび) :- メッセージを回収する(_キュー番号,_メッセージならび), メッセージキューを消去する(_キュー番号,_キュー番号_2). メッセージを回収する(_キュー番号,_メッセージならび) :- メッセージを確実に得る(_キュー番号,_回収値), メッセージを回収する(_キュー番号,_回収値,_メッセージならび). メッセージを回収する(_キュー番号,end_of_file,[]) :- !. メッセージを回収する(_キュー番号,_回収値文字列,_回収値ならび) :- メッセージはend_of_fileの前にある(_キュー番号,_回収値文字列,_回収値ならび). メッセージはend_of_fileの前にある(_キュー番号,_回収値文字列,[_回収値|R]) :- メッセージキューの文字列表現を項に変換(_回収値文字列,_回収値), メッセージを確実に得る(_キュー番号,_回収値文字列_2), メッセージを回収する(_キュー番号,_回収値文字列_2,R). メッセージキューの文字列表現を項に変換(_回収値文字列,_回収値) :- read_term_from_atom(_回収値文字列,_回収値,[]). メッセージを確実に得る(_キュー番号,_メッセージ) :- メーセージが入っていたら(_キュー番号), それを取り出す(_キュー番号,_メッセージ),!. メーセージが入っていたら(_キュー番号) :- repeat, thread_peek_message(_キュー番号,_). それを取り出す(_キュー番号,_メッセージ) :- thread_get_message(_キュー番号,_メッセージ). '1からnまで新たに生成されたキュー_2に追加する'(_n回,_キュー番号) :- between(1,_n回,_度数), thread_send_message(_キュー番号,_度数), _度数 = _n回. メッセージキューを消去する(_キュー番号,_キュー番号_2) :- message_queue_destroy(_キュー番号), message_queue_destroy(_キュー番号_2). 以下のサイトは 二つのスレッドとメッセージキューを使ってn回目の真となる非決定性述語の解を得る(_n回,_選択項,_副目標,_n回目の真となる非決定性の解) :- メッセージキューを生成しキュー番号_2には1からnまでを詰める(_n回,_キュー番号,_キュー番号_2), thread_create(副目標の実行とメッセージキュー_2からの実行回数を取り出しを対として行い_n回に達したらその時の選択項とend_of_fileをメッセージキューに追加する(_キュー番号,_キュー番号_2,_n回,_選択項,_副目標),_,[]), メッセージを回収した後メッセージキューを破壊する(_キュー番号,_キュー番号_2,[_n回目の真となる非決定性の解]). メッセージキューを生成しキュー番号_2には1からnまでを詰める(_n回,_キュー番号,_キュー番号_2) :- message_queue_create(_キュー番号), message_queue_create(_キュー番号_2), thread_create('1からnまで新たに生成されたキュー_2に追加する'(_n回,_キュー番号_2),_,[]). 副目標の実行とメッセージキュー_2からの実行回数を取り出しを対として行い_n回に達したらその時の選択項とend_of_fileをメッセージキューに追加する(_キュー番号,_キュー番号_2,_n回,_選択項,_副目標) :- catch(_副目標,E,fail), メッセージキュー_2から取り出した度数が_n回になったらキューに情報を追加する(_キュー番号,_キュー番号_2,_n回,_選択項). 副目標の実行とメッセージキュー_2からの実行回数を取り出しを対として行い_n回に達したらその時の選択項とend_of_fileをメッセージキューに追加する(_キュー番号,_,_,_,_) :- キューに情報を追加する(_キュー番号,end_of_file). メッセージキュー_2から取り出した度数が_n回になったらキューに情報を追加する(_キュー番号,_キュー番号_2,_n回,_選択項) :- メッセージキュー_2から取り出した度数が_n回になったら(_キュー番号_2,_n回,_選択項), キューに情報を追加する(_キュー番号,_選択項). メッセージキュー_2から取り出した度数が_n回になったら(_キュー番号_2,_n回,_選択項) :- メッセージを確実に得る(_キュー番号_2,_度数), _度数 = _n回. キューに情報を追加する(_キュー番号,_選択項) :- 項をメッセージキューで扱いやすいように文字列に変換する(_選択項,_選択項文字列), thread_send_message(_キュー番号,_選択項文字列), thread_send_message(_キュー番号,end_of_file). 項をメッセージキューで扱いやすいように文字列に変換する(_選択項,_選択項文字列) :- swritef(_選択項文字列,'%t',[_選択項]). メッセージを回収した後メッセージキューを破壊する(_キュー番号,_キュー番号_2,_メッセージならび) :- メッセージを回収する(_キュー番号,_メッセージならび), メッセージキューを破壊する(_キュー番号,_キュー番号_2). メッセージを回収する(_キュー番号,_メッセージならび) :- メッセージを確実に得る(_キュー番号,_回収値), メッセージを回収する(_キュー番号,_回収値,_メッセージならび). メッセージを回収する(_キュー番号,end_of_file,[]) :- !. メッセージを回収する(_キュー番号,_回収値文字列,_回収値ならび) :- メッセージはend_of_fileの前にある(_キュー番号,_回収値文字列,_回収値ならび). メッセージはend_of_fileの前にある(_キュー番号,_回収値文字列,[_回収値|R]) :- メッセージキューの文字列表現を項に変換(_回収値文字列,_回収値), メッセージを確実に得る(_キュー番号,_回収値文字列_2), メッセージを回収する(_キュー番号,_回収値文字列_2,R). メッセージキューの文字列表現を項に変換(_回収値文字列,_回収値) :- read_term_from_atom(_回収値文字列,_回収値,[]). メッセージを確実に得る(_キュー番号,_メッセージ) :- repeat, thread_peek_message(_キュー番号,_), thread_get_message(_キュー番号,_メッセージ),!. '1からnまで新たに生成されたキュー_2に追加する'(_n回,_キュー番号) :- between(1,_n回,_度数), thread_send_message(_キュー番号,_度数), _度数 = _n回. メッセージキューを破壊する(_キュー番号,_キュー番号_2) :- message_queue_destroy(_キュー番号), message_queue_destroy(_キュー番号_2). % 以下のサイトは スレッドとメッセージキューを使って全解を収集する(_選択項,_副目標,_回収値ならび) :- message_queue_create(_キュー番号), thread_create(スレッドで副目標を実行する(_キュー番号,_選択項,_副目標),_,[]), メッセージを回収する(_キュー番号,_回収値ならび), message_queue_destroy(_キュー番号). スレッドで副目標を実行する(_キュー番号,_選択項,_副目標) :- call(_副目標), thread_send_message(_キュー番号,_選択項), fail. スレッドで副目標を実行する(_キュー番号,_,_) :- thread_send_message(_キュー番号,end_of_file). メッセージを回収する(_キュー番号,_メッセージならび) :- メッセージを確実に得る(_キュー番号,_回収値), メッセージを回収する(_キュー番号,_回収値,_メッセージならび). メッセージを回収する(_キュー番号,end_of_file,[]) :- !. メッセージを回収する(_キュー番号,_回収値,[_回収値|R]) :- メッセージを確実に得る(_キュー番号,_回収値_2), メッセージを回収する(_キュー番号,_回収値_2,R). メッセージを確実に得る(_キュー番号,_メッセージ) :- repeat, thread_peek_message(_キュー番号,_), thread_get_message(_キュー番号,_メッセージ),!. % 以下のサイトは % % SWI-Prologに於いてfindall/3と同等の述語をmesage_queueを使って定義してみる。 % % findall/3と同じ機能の述語をメッセージキューを利用して定義する。 % メッセージキューを使って全解を収集する(_選択項,_副目標,_回収値ならび) :- message_queue_create(_キュー番号), ( call(_副目標), thread_send_message(_キュー番号,_選択項), fail; メッセージを回収する(_キュー番号,_回収値ならび)), message_queue_destroy(_キュー番号). メッセージを回収する(_キュー番号,[]) :- \+(thread_peek_message(_キュー番号,_)),!. メッセージを回収する(_キュー番号,[_回収値|R]) :- thread_get_message(_キュー番号,_回収値), メッセージを回収する(_キュー番号,R). % 以下のサイトは % % SWI-Prologに於いてfindall/3と同等の述語をmesage_queueを使って定義してみる。 % % findall/3と同じ機能の述語をメッセージキューを利用して定義する。 % メッセージキューを使って全解を収集する(_限界数,_選択項,_副目標,_回収値ならび) :- message_queue_create(_キュー番号), スレッド上でメッセージキューに限界数までの選択項を登録する(_限界数,_キュー番号,_選択項,_副目標), 'メッセージを待ち合わせ、回収する'(_キュー番号,_回収値ならび), message_queue_destroy(_キュー番号). スレッド上でメッセージキューに限界数までの選択項を登録する(_限界数,_キュー番号,_選択項,_副目標) :- thread_create(メッセージキューに限界数までの選択項を登録する(_限界数,_キュー番号,_選択項,_副目標),_,[]). 'メッセージを待ち合わせ、回収する'(_キュー番号,_回収値ならび) :- メッセージを待ち合わせる(_キュー番号), メッセージを回収する(_キュー番号,_回収値ならび). メッセージを待ち合わせる(_キュー番号) :- repeat, thread_peek_message(_キュー番号,end_of_file),!. メッセージを回収する(_キュー番号,_回収値ならび) :- findall(_回収値,( thread_get_message(_キュー番号,_回収値), ( _回収値 = end_of_file,!,fail; true)), _メッセージならび). %%%%%%%%%%%%%%%%%%%% スレッド側 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% メッセージキューに限界数までの選択項を登録する(_限界数,_キュー番号,_選択項,_副目標) :- 副目標を実行して選択項を登録する(_キュー番号,_選択項,_副目標), ( メッセージが限界数を超えた(_キュー番号,_限界数),!,fail; fail). メッセージキューに限界数までの選択項を登録する(_,_キュー番号,_,_) :- thread_send_message(_キュー番号,end_of_file). メッセージが限界数を超えた(_キュー番号,_限界数) :- メッセージの現在の度数を数える(_キュー番号,_度数), _度数 >= _限界数, thread_send_message(_キュー番号,end_of_file),!. 副目標を実行して選択項を登録する(_キュー番号,_選択項,_副目標) :- call(_副目標), 重複メッセージにはならない(_キュー番号,_選択項), thread_send_message(_キュー番号,_選択項). 重複メッセージにはならない(_キュー番号,_選択項) :- \+(thread_peek_message(_キュー番号,_選択項)). メッセージの現在の度数を数える(_キュー番号,_度数) :- message_queue_property(_キュー番号,size(_度数)). % 以下のサイトは % % SWI-Prologに於いてfindall/3と同等の述語をmesage_queueを使って定義してみる。 % % findall/3と同じ機能の述語をメッセージキューを利用して定義する。 % メッセージキューを使って全解を収集する(_限界数,_選択項,_副目標,_回収値ならび) :- message_queue_create(_キュー番号), スレッド上でメッセージキューに限界数までの選択項を登録(_限界数,_キュー番号,_選択項,_副目標), メッセージを回収する(_キュー番号,_回収値ならび), message_queue_destroy(_キュー番号). スレッド上でメッセージキューに限界数までの選択項を登録(_限界数,_キュー番号,_選択項,_副目標) :- thread_create(メッセージキューに限界数までの選択項を登録(_限界数,_キュー番号,_選択項,_副目標),_,[]). メッセージを回収する(_キュー番号,L) :- thread_peek_message(_キュー番号,end_of_file), thread_get_message(_キュー番号,_回収値_1), メッセージを回収する(_キュー番号,_回収値_1,L),!. メッセージを回収する(_キュー番号,L) :- メッセージを回収する(_キュー番号,L). メッセージを回収する(_キュー番号,end_of_file,[]) :- !. メッセージを回収する(_キュー番号,_回収値,[_回収値|R]) :- thread_get_message(_キュー番号,_回収値_2), メッセージを回収する(_キュー番号,_回収値_2,R). %%%%%%%%%%%%%%%%%%%% スレッド側 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% メッセージキューに限界数までの選択項を登録(_限界数,_キュー番号,_選択項,_副目標) :- 副目標の実行と選択項の登録(_キュー番号,_選択項,_副目標), ( メッセージが限界数を超えた(_キュー番号,_限界数),!,fail; fail). メッセージキューに限界数までの選択項を登録(_,_キュー番号,_,_) :- thread_send_message(_キュー番号,end_of_file). メッセージが限界数を超えた(_キュー番号,_限界数) :- メッセージの現在の度数(_キュー番号,_度数), _度数 >= _限界数, thread_send_message(_キュー番号,end_of_file),!. 副目標の実行と選択項の登録(_キュー番号,_選択項,_副目標) :- call(_副目標), 重複メッセージにはならない(_キュー番号,_選択項), thread_send_message(_キュー番号,_選択項). 重複メッセージにはならない(_キュー番号,_選択項) :- \+(thread_peek_message(_キュー番号,_選択項)). メッセージの現在の度数(_キュー番号,_度数) :- message_queue_property(_キュー番号,size(_度数)). % 以下のサイトは スレッドとメッセージキューを使って全解を収集する(_選択項,_副目標,_回収値ならび) :- message_queue_create(_キュー番号), thread_create(スレッドで副目標を実行する(_キュー番号,_選択項,_副目標),_,[]), メッセージを回収する(_キュー番号,_回収値ならび), message_queue_destroy(_キュー番号). スレッドで副目標を実行する(_キュー番号,_選択項,_副目標) :- call(_副目標), thread_send_message(_キュー番号,_選択項), fail. スレッドで副目標を実行する(_キュー番号,_,_) :- thread_send_message(_キュー番号,end_of_file). メッセージを回収する(_キュー番号,_メッセージならび) :- メッセージを確実に得る(_キュー番号,_回収値), メッセージを回収する(_キュー番号,_回収値,_メッセージならび). メッセージを回収する(_キュー番号,end_of_file,[]) :- !. メッセージを回収する(_キュー番号,_回収値,[_回収値|R]) :- メッセージを確実に得る(_キュー番号,_回収値_2), メッセージを回収する(_キュー番号,_回収値_2,R). メッセージを確実に得る(_キュー番号,_メッセージ) :- repeat, thread_peek_message(_キュー番号,_), thread_get_message(_キュー番号,_メッセージ),!. % 以下のサイトは % % SWI-Prologに於いてfindall/3と同等の述語をmesage_queueを使って定義してみる。 % % findall/3と同じ機能の述語をメッセージキューを利用して定義する。 % メッセージキューを使って全解を収集する(_選択項,_副目標,_回収値ならび) :- message_queue_create(_キュー番号), ( call(_副目標), thread_send_message(_キュー番号,_選択項), fail; メッセージを回収する(_キュー番号,_回収値ならび)), message_queue_destroy(_キュー番号). メッセージを回収する(_キュー番号,[]) :- \+(thread_peek_message(_キュー番号,_)),!. メッセージを回収する(_キュー番号,[_回収値|R]) :- thread_get_message(_キュー番号,_回収値), メッセージを回収する(_キュー番号,R). % 以下のサイトは # # 目標_1と目標_2を限界度数成功させる。 # 目標_1と目標_2を限界度数成功させる(_限界度数,_目標_1,_目標_2) :- forall_n(_限界度数,_目標_1,_目標_2). forall_n(_限界度数,_目標_1,_目標_2) :- message_queue_create(_キュー番号), ( thread_create(度数(_限界度数,_キュー番号),_,[]); forall(( thread_get_message(_キュー番号,_項), ( _項 = 0,!,fail;call(_目標_1))), call(_目標_2)). 度数(_限界度数,_キュー番号) :- between(1,_限界度数,_度数), _剰余 is _度数 mod ( _限界度数 + 1 ), thread_send_message(_キュー番号,_剰余), _度数 = _限界度数. % 以下のサイトは # # 目標を限界度数成功させて指定した蒐集項をならびとして得る # 目標を限界度数成功させて指定した蒐集項をならびとして得る(_限界度数,_蒐集項,_目標,_蒐集項ならび) :- findall_n(_限界度数,_蒐集項,_目標,_蒐集項ならび). findall_n(_限界度数,_蒐集項,_目標,_蒐集項ならび) :- message_queue_create(_キュー番号), ( '子スレッドで、生成された度数を、限界度数に達したら0をキューに送る'(_限度度数,_キュー番号); キューから限界度数を示す0を受信するまで目標を成功させて蒐集項ならびを得る(_蒐集項,_目標,_キュー番号,_蒐集項ならび)). キューから限界度数を示す0を受信するまで目標を成功させて蒐集項ならびを得る(_蒐集項,_目標,_キュー番号,_蒐集項ならび) :- findall(_蒐集項,( thread_get_message(_キュー番号,_項), ( _項 = 0,!,fail;call(_目標))), _蒐集項ならび). '子スレッドで、生成された度数を、限界度数に達したら0をキューに送る'(_限度度数,_キュー番号) :- thread_create(度数(_限界度数,_キュー番号),_,[]). 度数(_限界度数,_キュー番号) :- between(1,_限界度数,_度数), _剰余 is _度数 mod ( _限界度数 + 1 ), thread_send_message(_キュー番号,_剰余), _度数 = _限界度数. % % 先にlength/2等で解の枠が決まっている場合があるが、 % findall/3述語だと、その枠を無視して、全解を蒐集して、 % その上で第三引数のならびとの単一化を試みようとする。 % 目標の解が1000万個というように多量の場合は、 % スタックオーバーフローが生じてエラーとなって終了する。 % % これに対して、この述語は子スレッドを作り出して、ここで % 本来は現在の解数を数えさせてキュー経由で親スレッドは % これを受信する。この為には親スレッドから子スレッドに解が % 取れたことを送信するためのキューが必要であるがここでは % それを省略した。子から親への片方向の通信になっている。 % % 子スレッドは1から解の限界数まで整数をキューに一気に詰め、 % さらに、終了の合図である0を詰める。親スレッドは目標が % 達成される度にキューから一つ度数情報を取り出す。 % 解の数が限界数に達した時に子スレッドが既に送信してあった % 0を受信することになり、親スレッドのfindall_n/4の目標内の % カットが発動されて強制的にfindall_n/4を終了させることが % できる。 % % ここではfindall/3を対象にしているがsetof/3やbagof/3も % 全く同様の問題があるし、解決策も同じである。 % 以下のサイトは # # 目標を限界度数成功させてその項をリストとして得る # 目標を限界度数成功させてその項をならびとして得る(_限界度数,_目標,_目標ならび) :- findall_n(_限界度数,_目標,_目標ならび). findall_n(_限界度数,_目標,_目標ならび) :- message_queue_create(_キュー番号), ( thread_create(度数(_限界度数,_キュー番号),_,[]); findnall(_目標,( thread_get_message(_キュー番号,_項), ( _項 = 0,!,fail;call(_目標))), _目標ならび)). 度数(_限界度数,_キュー番号) :- between(1,_限界度数,_度数), _剰余 is _度数 mod ( _限界度数 + 1 ), thread_send_message(_キュー番号,_剰余), _度数 = _限界度数. % 以下のサイトは # # 目標を限界度数成功させて指定した蒐集項をならびとして得る # 目標を限界度数成功させて指定した蒐集項をならびとして得る(_限界度数,_蒐集項,_目標,_蒐集項ならび) :- findall_n(_限界度数,_蒐集項,_目標,_蒐集項ならび). findall_n(_限界度数,_蒐集項,_目標,_蒐集項ならび) :- message_queue_create(_キュー番号), ( thread_create(度数(_限界度数,_キュー番号),_,[]); findall(_蒐集項,( call(_目標), thread_get_message(_キュー番号,_項), ( _項 = 0,!,fail;true)), _蒐集項ならび)). 度数(_限界度数,_キュー番号) :- between(1,_限界度数,_度数), _剰余 is _度数 mod ( _限界度数 + 1 ), thread_send_message(_キュー番号,_剰余), _度数 = _限界度数. % % 先にlength/2等で解の枠が決まっている場合があるが、 % findall/3述語だと、その枠を無視して、全解を蒐集して、 % その上で第三引数のならびとの単一化を試みようとする。 % 目標の解が1000万個というように多量の場合は、 % スタックオーバーフローが生じてエラーとなって終了する。 % % これに対して、この述語は子スレッドを作り出して、ここで % 本来は現在の解数を数えさせてキュー経由で親スレッドは % これを受信する。この為には親スレッドから子スレッドに解が % 取れたことを送信するためのキューが必要であるがここでは % それを省略した。子から親への片方向の通信になっている。 % % 子スレッドは1から解の限界数まで整数をキューに一気に詰め、 % さらに、終了の合図である0を詰める。親スレッドは目標が % 達成される度にキューから一つ度数情報を取り出す。 % 解の数が限界数に達した時に子スレッドが既に送信してあった % 0を受信することになり、親スレッドのfindall_n/4の目標内の % カットが発動されて強制的にfindall_n/4を終了させることが % できる。 % % ここではfindall/3を対象にしているがsetof/3やbagof/3も % 全く同様の問題があるし、解決策も同じである。 % 以下のサイトは # # 目標を限界度数成功させて指定した蒐集項をならびとして得る # 目標を限界度数成功させて指定した蒐集項をならびとして得る(_限界度数,_蒐集項,_目標,_蒐集項ならび) :- findall_n(_限界度数,_蒐集項,_目標,_蒐集項ならび). findall_n(_限界度数,_蒐集項,_目標,_蒐集項ならび) :- message_queue_create(_キュー番号), 度数(_限界度数,_キュー番号), findall(_蒐集項,( thread_get_message(_キュー番号,_項), ( _項 = 0,!,fail;call(_目標))), _蒐集項ならび). 度数(_限界度数,_キュー番号) :- between(1,_限界度数,_度数), _剰余 is _度数 mod ( _限界度数 + 1 ), thread_send_message(_キュー番号,_剰余), _度数 = _限界度数. % % ?- length(L,4),findall(N,between(1,10000000,N),L). % false. % 1000万要素と4要素のリストの単一化。この結論を得るまでに数秒を要する。 % % ?- length(L,4),findall_n(4,N,between(1,10000000,N),L). % L = [1,2,3,4] % % ?- length(L,4),findall_n(5,N,between(1,10000000,N),L). % false. % % ?- length(L,4),findall_n(5,N,between(1,4,N),L). % L = [1,2,3,4] % % 以下のサイトは # # グーを0、チョキを1、パーを2とし、ユーザは自分の出す手をキーボードから入力する。 # 'グーを0、チョキを1、パーを2とし、ユーザは自分の出す手をキーボードから入力する。'(_自分の出す手) :- 入力プロセスの生成(Id,Message_queue_Id), 'グーを0、チョキを1、パーを2とし'(_自分の出す手,_自分の出す手の入力値), 'ユーザは自分の出す手をキーボードから入力する。'(Id,Message_queue_Id,_自分の出す手の入力値),!. 'グーを0、チョキを1、パーを2とし'(_自分の出す手,_自分の出す手の入力値) :- グーを0(_自分の出す手,_自分の出す手の入力値). 'グーを0、チョキを1、パーを2とし'(_自分の出す手,_自分の出す手の入力値) :- チョキを1(_自分の出す手,_自分の出す手の入力値). 'グーを0、チョキを1、パーを2とし'(_自分の出す手,_自分の出す手の入力値) :- パーを2(_自分の出す手,_自分の出す手の入力値). グーを0(グー,0). チョキを1(チョキ,1). パーを2(パー,2). 'ユーザは自分の出す手をキーボードから入力する。'(Id,Message_queue_Id,_自分の出す手の入力値) :- キーボードから(_キーボードの入力ストリーム), 入力プロセスから一度得た情報を何度も供給する(Id,Message_queue_Id,Line), atom_number(Line,_自分の出す手の入力値). 入力プロセスから一度得た情報を何度も供給する(Id,Message_queue_Id,_情報) :- 入力プロセスから一度得た情報(Id,Message_queue_Id,Term), 入力プロセスから一度得た情報を何度も供給する(Id,Message_queue_Id,Term,_情報). 入力プロセスから一度得た情報を何度も供給する(Id,Message_queue_Id,_情報) :- 入力プロセスから一度得た情報を何度も供給する(Id,Message_queue_Id,_情報). 入力プロセスから一度得た情報を何度も供給する(Id,Message_queue_Id,_情報,_情報). 入力プロセスから一度得た情報を何度も供給する(Id,Message_queue_Id,_情報,_情報) :- thread_peek_massage(Message_queue_Id,_次の情報),!,fail. 入力プロセスから一度得た情報を何度も供給する(Id,Message_queue_Id,Term,_情報) :- 入力プロセスから一度得た情報を何度も供給する(Id,Message_queue_Id,Term,_情報). 入力プロセスから一度得た情報(Id,Message_queue_Id,Term) :- thread_get_message(Message_queue_Id,Term). 入力プロセスの生成(Id,Message_queue_Id) :- thread_create(キーボードからの入力(Message_queue_Id),Id,[]). キーボードからの入力(Message_queue_Id) :- message_queue_create(Message_queue_Id), キーボードからの入力(Message_queue_Id). キーボードからの入力(Message_queue_Id) :- reapeat, キーボードから(Instream), get_line(Instream,Line), thread_send_message(Message_queue_Id,Line), fail. キーボードから(user_input). % 以下のサイトは # 出典:: http://toro.2ch.net/test/read.cgi/tech/1349545643/775 # # 【お題】 # コラッツ予想とは、「任意の0でない自然数nをとり、 # ・nが偶数の場合、nを2で割る # ・nが奇数の場合、nに3をかけて1を足す # という操作を繰り返すと、有限回で1に到達する」という主張である。 # # nからスタートして1に到達するまでのステップをsとしたとき、 # n = 1 .. 100000についてsを計算し、最長のsを出力せよ。 # # ただし、それぞれのnに対するsの計算は並列(スレッド、プロセス問わない)で行う事。 # # 'コラッツ予想とは、「任意の0でない自然数nをとり、 ・nが偶数の場合、nを2で割る ・nが奇数の場合、nに3をかけて1を足す という操作を繰り返すと、有限回で1に到達する」という主張である。 nからスタートして1に到達するまでのステップをsとしたとき、 n = 1 .. 100000についてsを計算し、最長のsを出力せよ。'(_n,_最長のs) :- findall(_Idならび,( between(1,100000,_n), message_queue_create(_Id), thread_create(コラッツの予想(_ID,_n),_,[])), _Idならび), 最長のsを出力する(_Idならび). コラッツの予想(_ID,_n) :- コラッツの予想(_n,0,_回数), thread_send_massage(_ID,_回数). コラッツの予想(1,_回数,_回数) :- !. コラッツの予想(_n,_回数_1,_回数) :- 'nが偶数の場合、nを2で割る nが奇数の場合、nに3をかけて1を足す'(_n,_n_2), _回数_2 is _回数_1 + 1, コラッツの予想(_n_2,_回数_2,_回数),!. 'nが偶数の場合、nを2で割る nが奇数の場合、nに3をかけて1を足す'(_n,n_2) :- 'nが偶数の場合、nを2で割る'(_n,_n_2). 'nが偶数の場合、nを2で割る nが奇数の場合、nに3をかけて1を足す'(_n,_n_2) :- 'nが奇数の場合、nに3をかけて1を足す'(_n,_n_2). 'nが偶数の場合、nを2で割る'(_n,_n_2) :- _n_2 is _n // 2. 'nが奇数の場合、nに3をかけて1を足す'(_n,_n_2) :- 1 is _n mod 2, _n_2 is _n * 3 + 1. 最長のsを出力する(_Idならび) :- findmax(_n,( between(1,100000,_), repeat, thread_get_massage(_Id,_n)), _最長のs), writef('最長のsは %t です。\n',[_最長のs]). % 以下のサイトは # 出典:: http://toro.2ch.net/test/read.cgi/tech/1337692704/188 # # 【課題】以下のようなクラス(名前は各自決める)を定義せよ。 # mainメソッドを呼び出すと、別のスレッドthを生成し、スタートさせる。 # mainメソッドは、プロンプトとして”Command> “を印字し、キーボードからの入力を待つ。 # 入力は、以下のようなadd, removeなどを先頭とするいくつかの文字列で、 # それを何らかの方法でスレッドthに渡し、ふたたび “Command> “を印字して次の入力を待つ。 # Command> add <文字列> # スレッドthでは、mainから受け取った<文字列>の部分を取り出し、 # thの中で管理するLinkedListの要素に加える(add)。一方、 # Command> remove <文字列> とすると該当する文字列をLinkedListから消す。そのほか、 # Command> print とでき、printはLinkedListにある要素をすべて印字し # Command> exit exitはスレッドを停止し、それを待ってmainメソッドを終了する # ものである。 # 上記以外の入力は無視する。 # (ヒント:書き方はたくさんありますが、たとえば前回のProducer Consumerの例を考えてください。 # 片方が生成(入力された文字列をMqueueに格納)、他方がそれを読み出すと考えます。 # もちろんもっと簡単な方法もあると思います。上記の仕様通りに動いていれば正解です。 # 【 形態 】1. Javaアプリケーション(main()で開始) # 【GUI】4.制限なし # 【 期限 】 今日(7/14)中 # 【 Ver  】 1.7.0_03 # 【 補足 】宜しくお願いします! # # 影を用いて情報を管理する :- 取り次ぎ(_取り次ぎ), コマンドを得る(_コマンド行), 影を生み出す(影(_取り次ぎ),_影,[]), 影を用いて情報を管理する(_取り次ぎ,_命令). 影を用いて情報を管理する(_取り次ぎ,exit). 影を用いて情報を管理する(_取り次ぎ,コマンド行) :- コマンドを得る(_コマンド_2), thread_send_message(_取り次ぎ,コマンド_2), 影を用いて情報を管理する(_取り次ぎ,コマンド行_2). コマンドを得る(_コマンド行) :- write('コマンド>> '), get_line(_コマンド行). 影(_取り次ぎ) :- 言伝からコマンドを得る(_取り次ぎ,_命令,R), 影(_取り次ぎ,_命令,R,[],L). 影(_取り次ぎ,_命令,_付加情報,L_1,L) :- コマンドの実行(_取り次ぎ,_コマンド,L_1,L_2), 言伝を送る(_取り次ぎ,ok), 言伝からコマンドを得る(_取り次ぎ,_命令_2,_付加情報_2), 影(_取り次ぎ,_命令_2,_付加情報_2,L_2,L). 言伝からコマンドを得る(_取り次ぎ,_命令,R) :- 言伝を取り出す(_取り次ぎ,_言伝,[]), split(_言伝,[' '],[_命令|R]). コマンドの実行(add,[_情報],L_1,[_情報|L_1]). コマンドの実行(delete,[_情報],L_1,L_2) :- ならびから削除(_情報,L_1,L_2). コマンドの実行(print,[],L_1,L_1) :- writef('%t\n',[L_1]). コマンドの実行(_コマンド,_,L_1,L_1) :- writef('%tコマンドは存在しません。\n',[_コマンド]). ならびから削除(_,[],[]) :- !. ならびから削除(_削除する要素,[_削除する要素|_残り対象ならび],_削除されたならび) :- ならびから削除(_削除する要素,_残り対象ならび,_削除されたならび),!. ならびから削除(_削除する要素,[_要素|_残り対象ならび],[_要素|_残り削除ならび]) :- ならびから削除(_削除する要素,_残り対象ならび,_残り削除ならび),!. キューを保存する(L) :- tell('キュー保存.pro'), write(L), write('.\n'), told. 影を生み出す(Term,_影,Option) :- thread_create(Term,_影,Option). 影を終わる :- thread_self(_番号), thread_detach(_番号). 取り次ぎ(_取り次ぎ) :- message_queue_create(_取り次ぎ). 言伝を取り出す(_取り次ぎ,_言伝,_限界時間) :- thread_get_message(_取り次ぎ,_言伝,[timeout(_限界時間)]). 言伝を取り出す(_言伝) :- thread_get_message(_言伝). 言伝を送る(_番号,_言伝) :- thread_send_message(_番号,_言伝). 取り次ぎを立てる(_取り次ぎ) :- message_queue_create(_取り次ぎ,[]). 取り次ぎを解消する(_取り次ぎ) :- message_queue_destroy(_取り次ぎ).