2

私は現在、人工知能クラスの最終プロジェクトに取り組み始めています (コンピューター サイエンスの学士号の一環として)。このプロジェクトでは、人工知能の分野で興味深い問題を選択し、クラスから 1 つまたは複数のトピックを展開して、それを解決する必要があります。後で結果を説明するレポートを作成し、レポートと作成したコードの両方を提出します。

明らかに、私たちは古典的な問題の研究において最先端に匹敵することは期待されていませんが、珍しい問題を(かなりの程度まで)調べて解決することを期待されています(このアプローチを選択するほとんどの人は、単純なコンピューターを解決することを選択するか、 AI研究コミュニティによってまだ完全に解決されていないボードゲームなど)、またはより一般的な問題を斬新な方法で調査し、おそらく新しい興味深いヒューリスティックまたは既存のアルゴリズムへの変更を提案します. 後者の場合、最新の研究結果を上回ることは期待されておらず、新しい視点を提供するだけです。

私のパートナーと私がこのプロジェクトのために選んだテーマは倉庫番で、これは私たちを 2 番目のグループに分類します (これは死ぬほど研究されていません。なぜなら、共通のテスト セットの 3 分の 2 しか最高のソルバーで解決できないからです。この問題に対する最先端のソルバーは複雑すぎて、パートタイムの 2 週間のプロジェクトでそれらに近づこうとは思えません)。検索問題のアプローチを使用して倉庫番の問題を解決したいと考えています。

とにかく、倉庫番ソルバーの実装を開始する前に、実行を意図した検索ベースのソルバーの実装に使用するのに、私たちがよく知っている数少ない言語 (C、C++、Java、および Python) のどれがより適しているか疑問に思い始めました。非常に大きな検索空間での検索 (倉庫番には非常に深い検索ツリーがあり、解決するのに 300 回以上の移動が必要な問題と、非常に高い分岐係数 [一部の問題では 100 以上] があります。この高い分岐係数は、次の場合に達成されることに注意してください。プレイヤーの移動ではなく、ストーン\ボックスの移動のみが考慮されるため、各状態で、4 つの方向のいずれかに任意のストーンを移動できます)。

私がこの問題を検討し始めた主な理由は、人工知能に関する別のコース (製品設計への AI 技術の適用を扱う) で、可能なすべての部屋デザインの状態空間を検索して部屋を設計する自動ルーム デザイナーを作成したためです。 (指定された部屋のサイズと家具のセットを使用して) 最高スコアの状態を返します (いくつかのヒューリスティックによって測定されます)。このプログラムは Java で書かれており、実行のたびに数万の検索ノードを検索しただけでメモリ不足になりました。これが起こった主な理由は、そのプロジェクトに非常にオブジェクト指向のアプローチを選択したためだと思います。それは Java で書かれており、すべての検索状態はオブジェクトによって表され、そのようなすべての状態は、サーチャー オブジェクトによって到達されると、

さて、問題の一部はメモリ集約型アルゴリズム (A*) の使用と、それを実装するために選択した方法にあることがわかりましたが、Java の使用も問題の一部であったかどうか疑問に思っています。
1. 検索問題と検索アルゴリズムを実装する場合、一般的にどのプログラミング手法がより適しているか? (オブジェクト指向、関数型、またはその他)
2. 検索問題と検索アルゴリズムを実装する場合、Java、C、C++、または Python のどのプログラミング言語がより適していますか? (他の言語も可能ですが、その構文が前述の言語のいずれかに非常に類似している場合に限られます)

具体的には、これらの言語のどの機能とプロパティを使用して、非常に大きな検索空間をメモリ (および実行時間) 効率的な方法で検索することを目的とした問題解決ツールを実装できますか?

4

5 に答える 5

1

私は何人かの人々を知っていますが、あなたが Java で説明したようなメモリ集約型のアルゴリズムをすべて実行しています。機能させることはできますが、基本的なコレクションと配列に頼る必要があります。

そうは言っても、あまり賢いとは思えません。効率的な Java をコーディングする場合は、基本的に C/C++ コードに似たコードを記述します。次に、最後のステップとして、C/C++ を直接記述して、さらに最適化する機会を得ることができます (おそらく、速度とメモリがさらに 2 倍向上します)。

これはあなたの質問に私を取得します:

  1. 検索問題と検索アルゴリズムを実装する場合、一般的にどのプログラミング手法がより適していますか? (オブジェクト指向、機能的またはその他)

関数型プログラムはしばしば非常に見栄えがよく、アルゴリズムの問​​題に自然に適合するように見えます。問題は、ほとんどの場合、命令型アルゴリズムの方が高速であることです (そして、バグなしで書くのははるかに困難です)。オブジェクト指向、よくわかりませんが、命令型に数えます。オブジェクト階層は、(それによって得られるものと比較して) 通常は望まない計算上のオーバーヘッドをもたらします。

  1. 検索問題と検索アルゴリズムを実装する場合、Java、C、C++、または Python のどのプログラミング言語がより適していますか? (他の言語も可能ですが、その構文が前述の言語のいずれかに非常に類似している場合に限られます)

Python の簡潔さは関数型言語に似ていると思いますが (ファーストクラスの機能を備えています)、本格的なものを扱うには遅すぎます。あなたが提案した言語のうち、私はおそらく C++ を選びます。Java の方が優れているわけではありませんが、おそらく遅いからです。1 つの可能性は、Java に近いか同等の速度で簡潔なプログラミング (Python に匹敵する) を可能にする Scala のようなものを使用することです。

于 2013-02-22T08:05:18.623 に答える
0

ほとんどの人が使い慣れている言語の使用に制限されている場合は、おそらく c++ をお勧めします。

AI の分野で一般的な言語に分岐したい場合で、ソルバーを実装するのが比較的簡単だと思う場合は、prolog を使用します。オンラインで発見的アルゴリズムの例を見つけることができることを知っています。ご存知のように、ミニマックスとアルファベータの剪定は一般的です。

また、プロローグと連動してゲームをプレイする際に使ったGDLという言語があります。http://en.wikipedia.org/wiki/Game_Description_Languageを参照してください。これには、Lisp 構文でプロローグ述語と呼ばれるものが含まれています。

于 2013-02-21T18:06:23.477 に答える
0

C++ 構造体を使用すると、Java のオブジェクトよりもいくらかのスペースを節約できるかもしれませんが、問題の根源は現在のアルゴリズムの実装です。メモリ要件は指数関数的に拡大するようです。

疑似計算: を仮定しますn = 10 000。そのため、 RAM100 000 000に変換するオブジェクトが必要です。1 GbJava から C++ に切り替えて (そして、既知の問題を未知の問題と引き換えに)、0.5 GBRAM に落とし込んだとします。ただし、n を 2 倍にするとメモリ割り当てが 4 倍になることを除けば、n = 20 000 の場合は4 GBJava RAM と2 GBC++ RAM が必要になります...

代わりに、よりメモリ効率の高いアルゴリズムの実装に注目すると、n が大きい GB ではなく MB を突然使用していることに気付くでしょう。私は、ジャスト イン タイム選択 (リスト ベースのアーキテクチャをイテレータ ベースのアーキテクチャと交換する) を実装することで、これを非常に劇的に経験しました。

于 2013-02-22T09:05:54.760 に答える
0

通常、ベスト ファースト検索 (BFS) ではスペース要求を管理するのが最も困難です。これは、実際には検索スペース全体を格納することになり、サイズが指数関数的になることが多いためです。

スペースは、見込みがないと思われる検索スペースの一部 (スコアが低い) を破棄することで管理できます。その結果、検索の完全性が失われる (「十分な」回答で問題ない場合) か、一部が破棄された場合に再検索が行われます。検索の再検討が必要です。このアイデアの極端なバージョンは「深さ優先検索」(DFS) と呼ばれ、現在最も有望なブランチのみを保持します。DFS と BFS の間の妥協案は、いわゆるビーム検索です。この種のスペース トレードオフ スキームは、プログラミング言語に依存しません。それらを検索アルゴリズムに結び付けます。

スペースを効果的に管理できること、また管理しなければならないことがわかったら、検索時間を管理する必要があります。一般に、最良のアルゴリズムが常に勝利し、多くの場合、生の検索ではありません。AI の世界では、多くの場合、「最適なアルゴリズム」がわからないため、ブルート フォース検索に頼ります。生のブルート フォース検索の場合、得られる問題に最適なヒューリスティックが必要です。これはアルゴリズムの問​​題ではありません。どうにかして取得しなければならないドメイン知識です。AI のほとんどは、間違いなく、ドメインの知識を取得して活用しようとするものです。アルゴリズムと発見的知識はどちらも言語に依存しません。

最後に、並列言語を使用して検索時間を管理することができます(ただし、これによって得られるのはせいぜい N 倍の速度向上だけです)。このためには、オンデマンドで大量に並列計算を安価に生成できる言語が必要です。現代の言語 (Java、C#) の多くには、扱いにくい呼び出しを伴う扱いにくい組み込みの「スレッド」構造があります。C と C++ にはこのビルトインはありませんが、「フォーク」ライブラリを使用できます。残念ながら、これらはさらに使いにくく、多くの場合制限があります (たとえば、OS が提供するスレッドよりも多くの並列グレインを使用することはできず、せいぜい数千に制限されているか、ビッグスタックの仮定のためです。この場合のスキームは、スレッドをワーカーのように扱い、それぞれがフロンティアの一部の 1 単位を拡張することです。

もう 1 つの方法は、問題の構造に十分に一致する十分な粒度を持つことです。基本的に並列処理を使用して、検索空間内のノードを管理します。このためには、大きなスタックの問題を解決する必要があります。そうしないと、スタック スペースが不足してしまいます :-( PARLANSE と呼ばれる独自の言語でソフトウェア エンジニアリング ツールをサポートするために、いくつかの検索ベースのアルゴリズムを実行します。 ; サブ計算 ABC などをフォークするための (|| ABC )組み込みの並列処理演算子、および半順序並列処理と汎用並列処理(spawn X)があります。サブ計算 X を fork します。これらの演算子はすべて安価です。並列作業をフォークするのに数百サイクルしかかかりません。これが可能なのは、演算子が言語に組み込まれており、コンパイラがそれらを理解するためです。PARLANSE を使用してコード化された深さ優先検索を確認できます。(||演算子をよく探す必要がありますが、そこにあります (ヒント: 内側のループを見つけてください!) PARLANSE の並列処理の本当に便利な特性は、計算とその子を中止する機能です。これにより、「最良の答え」が可能になります。検索スペースでその結果を伝播し、他の検索子を殺します。

IBM のX-10 並列スーパーコンピューティング言語には、動的な子 ( finishコンストラクト) を生成する機能があり、非常に有望に思えます。

于 2013-02-22T10:25:55.503 に答える
0

私の意見:

Java: 特に数学的なものに関しては、あまりにも冗長で醜い構文です。また、メモリ/CPU リソースが多すぎます。

C: オブジェクト指向のポインターフリー言語に慣れているとしたら、まったく恐ろしいことです。

C++: 強力で高速ですが、多くの異なるアルゴリズムで実験を行うには重すぎてコンパイルが遅すぎます。

Python: すべての中で最も遅い。おそらくプロトタイプの作成には適していますが、大規模な計算にはあまり適していません。

于 2013-02-21T16:47:25.297 に答える