6

正確に何を尋ねようとしているのかわかりません。初期状態と最終状態といくつかのルールを簡単に取り、そこに到達するためのパス/選択肢を決定できるコードを作成できるようにしたいと考えています。

たとえば、スタークラフトのようなゲームを考えてみてください。工場を建設するには、兵舎と司令センターがすでに建設されている必要があります。もし何も持っていなくて工場が欲しいなら、「司令センター」→「兵舎」→「工場」と言うかもしれません。それぞれのことには時間とリソースが必要であり、パスで注意して考慮する必要があります。工場を 5 分にしたい場合は、10 分にしたい場合よりも選択肢が少なくなります。

また、エンジンは利用可能なリソースを計算し、それらを効果的に利用できる必要があります。これらの 3 つの建物には、合計で 600 のミネラルが必要になる可能性がありますが、エンジンは、200 になるときにコマンド センターを計画する必要があります (またはコストがかかります)。

これは最終的に、10 海兵 @ 5 分、歩兵の武器のアップグレードは 6:30、30 海兵は 10 分、工場 @ 11 などと同様の要件になります。

では、このようなことをするにはどうすればよいでしょうか。私が最初に考えたのは、何らかの手続き型言語を使用して、すべての決定をゼロから行うことでした。システムと分岐をシミュレートし、さまざまな選択を行うことができました。最終的に、いくつかの選択はすぐに目標を達成することを不可能にします (もし私が 20 の補給所を建設したとしても、その工場を時間通りに作れない可能性があります.)

それでは、関数型言語はこのために設計されたものではないと思いましたか? プロローグを書こうとしましたが、時間や距離の計算などに問題がありました。そして、「計画」を返す最良の方法がわかりません。

私は書くことができると思っていました:

depends_on(factory, barracks)
depends_on(barracks, command_center)
builds_from(marine, barracks)
build_time(command_center, 60)
build_time(barracks, 45)
build_time(factory, 30)
minerals(command_center, 400)
...
build(X) :- 
  depends_on(X, Y),
  build_time(X, T),
  minerals(X, M),
...

ここで私は混乱します。この関数とクエリを構築して、必要なものに近いものを取得する方法がわかりません。建設中に鉱物が収集される速度や、追加の金で他の可能な経路をどうにかして説明する必要があります. 10 分間に 1 人の海兵隊員だけが必要な場合は、10 分で 1 人の海兵隊員で終了する方法がたくさんあるため、エンジンに多くの計画を生成してもらいたいと思います (あまりにも多くの後にそれをカットするかもしれません。プロローグでそれをどのように行うかわかりません)。 )。

この道を進む方法についてのアドバイス、または他のオプションについてのアドバイスを探しています。ハノイの塔や AI の祖先の例よりも役立つものを見つけることができなかったので、プロローグを使用して実際のことを行う方法を説明するいくつかの優れた記事でさえ素晴らしいでしょう. そして、どうにかしてこれらのルールを便利な方法で設定できる場合、ハノイのすべての塔の例のように標準出力に書き込む以外に、プロローグが思いついた(クエリを解決する方法)「計画」を取得する方法はありますか?それともそれが好ましい方法ですか?

私の他の質問は、私のメイン コードは ruby​​ (および潜在的に他の言語) であり、prolog と通信するためのオプションは、ruby 内から私の prolog プログラムを呼び出すこと、prolog 内から仮想ファイル システムにアクセスすること、またはある種のデータベース構造 (可能性は低い) です。 )。私は SWI-Prolog atm を使用しています。これを Ruby で手続き的に行う方がよいでしょうか、それとも prolog や haskall のような関数型言語でこれを構築する方が、統合に余分な労力をかける価値があるでしょうか?

これが不明確な場合は申し訳ありません。お役に立てれば幸いです。不明確な点については、もう一度言い直します。

4

2 に答える 2

7

あなたの質問は、最初に Prolog を試す手続き型言語のユーザーにとって典型的であり、非常に一般的です。解決するのは非常に簡単です。世界の連続する状態間の関係について考える必要があります。あなたの世界の状態は、たとえば、経過時間、利用可能な鉱物、すでに構築したものなどで構成されます。このような状態は、Prolog 用語で簡単に表すことができ、たとえば のようになりますtime_minerals_buildings(10, 10000, [barracks,factory]))。このような状態が与えられた場合、その状態の可能な後続の状態がどのように見えるかを説明する必要があります。例えば:

state_successor(State0, State) :-
     State0 = time_minerals_buildings(Time0, Minerals0, Buildings0),
     Time is Time0 + 1,
     can_build_new_building(Buildings0, Building),
     building_minerals(Building, MB),
     Minerals is Minerals0 - MB,
     Minerals >= 0,
     State = time_minerals_buildings(Time, Minerals, Building).

連続した状態について話していることを明確にするために、明示的な命名規則 ( State0-> ) を使用しています。Stateもちろん、統一を節頭に取り込むこともできます。サンプル コードは純粋に仮説的なものであり、最終的なアプリケーションではかなり異なるものになる可能性があります。この場合、新しい状態の経過時間は古い状態の時間 + 1 であること、新しい鉱物の量は を構築するのに必要な量だけ減少することBuilding、および述語 があることを説明していcan_build_new_building(Bs, B)ますB。で与えられた建物を想定して建設されるBs既に構築されています。これは一般的に非決定論的な述語であり、バックトラックですべての可能な答え (= 建設可能な新しい建物) を生成すると仮定します。そのような述語を定義する演習として残します。

state_successor/2世界の状態をその直接の可能性のある後継者に関連付ける述語が与えられると、目的の最終状態につながる状態のパスを簡単に定義できます。最も単純な形式では、連続する状態のリストを記述する次の DCG のようになります。

states(State0) -->
     (   { final_state(State0) } -> []
     ;   [State0],
         { state_successor(State0, State1) },
         states(State1)
     ).

次に、たとえば反復的な深化を使用してソリューションを検索できます。

?- initial_state(S0), length(Path, _), phrase(states(S0), Path).

また、すでに検討した状態を追跡し、再調査などを避けることができます。

あなたが投稿したサンプルコードと混同する理由は、基本的に、必要build/1なものを説明するのに十分な引数がないためです。少なくとも 2 つの引数が必要です。1 つは世界の現在の状態であり、もう 1 つはこの特定の状態の後継となる可能性のあるものです。このような関係があれば、必要なものはすべて簡単に記述できます。これがあなたの質問に答えることを願っています。

于 2013-09-03T21:40:32.980 に答える
2

警告: 私のプロローグは錆びていて浅いので、これはベースから外れている可能性があります

おそらく、「差分エンジン」アプローチが適切でしょう。

  • 「工場の建設」などの目標が与えられた場合、
  • 後方連鎖関係は has-barracks をチェックし、最初に build-barracks を指示します。
  • has-command-center をチェックし、build-command-center を指示します。
  • 等々、
  • 途中で計画(およびコスト)を蓄積する

これが実用的であれば、状態ベースのアプローチよりも柔軟かもしれません...または、別のTシャツを着ても同じことかもしれません!

于 2013-09-05T15:05:25.390 に答える