「AIって、なんだか難しそう…」 「G検定の勉強、どこから手をつければいいの?」
こんにちは!AIやテクノロジーの世界を、できるだけ分かりやすくお伝えしたいブロガーの「AIナビゲーター・ニコイチ」(と呼んでください!)です。
皆さんは、「AIが自分で考えて計画を立てる」と聞いて、どんなことを想像しますか? SF映画に出てくるような、超賢いロボットでしょうか? 実は、その基本的な考え方は、AI研究のかなり初期から考えられていたんです。
今回ご紹介する「STRIPS(ストリップス)」は、まさにその「AIの計画力」の元祖とも言える技術。1970年代に生まれた古典的な技術ですが、その考え方は現代のAIにも脈々と受け継がれていて、G検定でも頻出の重要キーワードなんです!
「え、古いの? じゃあ覚えなくてもいいんじゃ…?」
いえいえ、そんなことはありません! STRIPSを理解することは、AIが「世界をどう認識し」「どうやって目標達成までの道のりを考えるか」という、AIの思考プロセスの基礎を学ぶことに繋がります。まるで、AIの赤ちゃんの頃を覗き見るような面白さがあるんですよ。
この記事では、AIの知識ゼロの方でも大丈夫なように、
- STRIPSって、そもそも何なの?
- どんな仕組みで計画を立てるの?
- G検定ではどこがポイントなの?
といった疑問に、たくさんの具体例や、できれば図も交えながら、世界一(!?)分かりやすくお答えしていきます! 肩の力を抜いて、コーヒーでも飲みながら、AIの計画術の世界を一緒に探検してみましょう!
そもそも「プランニング」って何? ~AIが計画を立てるってどういうこと?~
「プランニング」と聞くと、皆さんは何を思い浮かべますか?
- 週末の旅行計画? (どこに行って、何を見て、どこに泊まるか…)
- 晩ごはんの料理のレシピ? (材料を切って、炒めて、煮込んで…)
- 朝、家を出るまでの準備? (起きて、顔を洗って、着替えて、朝ごはん食べて…)
そう、プランニングとは、「目標を達成するために、何を、どの順番でやるか」を決めることです。私たち人間は、普段あまり意識せずにやっていますよね。
AIにおけるプランニングも、基本は同じです。AI(特にロボットなど)に、「ある目的を達成するための行動の手順(=プラン)」を自動的に考えさせる技術、それがAIプランニングです。
AIがプランニング問題を解くためには、主に3つの情報が必要です。
- 初期状態 (Initial State): スタート地点。現状はどうなっているか?
- 旅行計画なら:「今は自宅にいる、予算は〇〇円」
- 料理なら:「冷蔵庫に人参と玉ねぎがある、コンロは空いている」
- 目標状態 (Goal State): ゴール地点。最終的にどうなりたいか?
- 旅行計画なら:「〇〇ホテルにチェックインしている、××の景色を見ている」
- 料理なら:「カレーライスが完成している」
- 利用可能なアクション (Available Actions): 状態を変えるための行動の選択肢。
- 旅行計画なら:「電車に乗る」「飛行機に乗る」「ホテルを予約する」
- 料理なら:「野菜を切る」「鍋で炒める」「水を加えて煮込む」
AIプランニングシステムは、この3つの情報をもとに、初期状態から目標状態にたどり着くための、最適なアクションの順番(プラン)を見つけ出そうとします。まるで、パズルのピースを組み合わせて完成図を目指すようなイメージですね!
【G検定 ここがポイント!】 プランニング問題は「初期状態」「目標状態」「利用可能なアクション」の3つの要素で構成される、という基本をしっかり押さえておきましょう!
AIプランニングの古典!「STRIPS」登場
さて、いよいよ本日の主役、STRIPSの登場です!
STRIPS(Stanford Research Institute Problem Solver)は、1971年にアメリカのスタンフォード研究所(SRI)で開発されました。まさに、AI研究が熱を帯びていた「第1次AIブーム」の真っ只中です。
当時の研究者たちは、「人間のように賢い機械を作りたい!」という夢を持っていました。その「賢さ」の一つとして、「自分で考えて行動計画を立てる能力」が重要だと考えられていたんですね。
STRIPSは、ロボットが「隣の部屋にある箱を取ってきて、この部屋のテーブルの上に置いて」といったタスクをこなすためのプランを、自動で生成することを目指して開発されました。
なぜSTRIPSが画期的だったのか?
それは、プランニング問題を記述するための「標準的な方法」を提案した点にあります。それまでは、研究者ごとにバラバラな方法でプランニング問題を扱っていましたが、STRIPSが登場したことで、
- 問題を形式的(カッチリとしたルール)に記述できるようになった
- 他の研究と比較したり、共通の土台で議論したりできるようになった
のです。いわば、プランニング界の「共通言語」を作ったようなものですね。この功績により、STRIPSは「古典的プランニング」の代表格として、その後の多くのAI研究の基礎となりました。
【G検定 ここがポイント!】 STRIPSは1970年代(第1次AIブーム)に開発された、初期の代表的な自動プランニングシステム/言語であること、そしてプランニング問題の標準的な記述方法を確立した点を覚えておきましょう。
STRIPSの仕組みを分解!~AIはどうやって世界を理解し、行動を決める?~
では、STRIPSは具体的にどのようにしてプランニング問題を表現し、解いているのでしょうか? その仕組みを、3つのステップに分けて見ていきましょう。
世界の状態を「事実のリスト」で表す (State)
STRIPSでは、世界の特定の状況を、「現在、真実であること」のリストで表現します。ちょっと難しく聞こえるかもしれませんが、要は「今、何がどうなっているか」を箇条書きにしたもの、と考えてください。
例えば、古典的な「ブロック積み問題」で考えてみましょう。(これは、ロボットアームが積み木を操作する問題で、プランニング研究でよく使われる例題です)
この状態をSTRIPS風に記述すると、こんな感じになります。
- OnTable(A):ブロックAはテーブルの上にある
- OnTable(B):ブロックBはテーブルの上にある
- Clear(A):ブロックAの上には何もない(=持ち上げられる状態)
- Clear(B):ブロックBの上には何もない
- Empty(Arm):ロボットアームは何も持っていない
このリストが、ある瞬間の「世界の写真」のようなものになります。
ポイント:閉世界仮説 (Closed World Assumption) STRIPSのシンプルな考え方の一つに、「リストに書かれていないことは、偽(そうではない)とみなす」というルールがあります。これを閉世界仮説と言います。上の例で言えば、「Holding(A)(アームがAを持っている)」はリストにないので、「アームはAを持っていない」と判断するわけです。知らないことは「偽」と割り切る、潔い考え方ですね!
身近な例:お掃除ロボットの状態 お掃除ロボットの状態も、事実のリストで表現できます。
- At(Charger):充電ドックにいる
- Battery(Full):バッテリーは満タン
- DustBin(Empty):ゴミ容器は空っぽ
- Mode(Idle):待機モード
行動を「レシピ」のように定義する (Action)
次に、AI(ロボット)が実行できる行動、つまり「アクション」を定義します。STRIPSでは、各アクションをまるで料理のレシピのように、以下の3つの要素で記述します。
- アクション名 (Action Name): 行動の名前(例: PickUp(A) Aを持ち上げる)
- 前提条件 (Preconditions): その行動をするために満たされている必要のある条件。
- 料理で言えば、「カレーを作る」ための前提条件は「材料(人参、玉ねぎ、肉など)がある」「鍋がある」「コンロが使える」といったことですね。
- 効果 (Effects): その行動を実行した結果、状態がどう変化するか。これはさらに2つに分かれます。
- 追加リスト (Add List): 行動後に新しく真になる事実。
- 削除リスト (Delete List): 行動後に真ではなくなる(リストから消える)事実。
- 料理で言えば、「野菜を切る」というアクションの効果は、追加リストに「切った野菜がある」が加わり、削除リストで「丸ごとの野菜がある」が消える、といったイメージです。
ブロック積みのアクション例:
- アクション名: PickUp(X) (ブロックXをテーブルから拾い上げる)
- 前提条件:
- OnTable(X) (Xはテーブルの上にある)
- Clear(X) (Xの上には何もない)
- Empty(Arm) (アームは空である)
- (これら全部が満たされていないと、拾い上げられない)
- 効果:
- 追加リスト: Holding(X) (アームがXを持つ)
- 削除リスト: OnTable(X), Clear(X), Empty(Arm) (これらの状態ではなくなる)
アクション名 | 引数 | 前提条件 | 効果 (追加リスト) | 効果 (削除リスト) |
PickUp | X | OnTable(X), Clear(X), Empty(Arm) | Holding(X) | OnTable(X), Clear(X), Empty(Arm) |
PutDown | X | Holding(X) | OnTable(X), Clear(X), Empty(Arm) | Holding(X) |
Stack | X, Y | Holding(X), Clear(Y) | On(X, Y), Clear(X), Empty(Arm) | Holding(X), Clear(Y) |
Unstack | X, Y | On(X, Y), Clear(X), Empty(Arm) | Holding(X), Clear(Y) | On(X, Y), Clear(X), Empty(Arm) |
身近な例:お掃除ロボットのアクション
- アクション名: StartCleaning()
- 前提条件: At(Charger), Battery(Full), DustBin(Empty)
- 効果:
- 追加リスト: Mode(Cleaning), Location(RoomA) (仮に部屋Aから掃除)
- 削除リスト: At(Charger), Mode(Idle)
【G検定 ここがポイント!】 アクションは「前提条件(Preconditions)」と「効果(Effects)」(特に追加リストと削除リスト)で定義される! この構造はSTRIPSの核心なので、しっかり理解しましょう。
スタートとゴールを設定! (Initial State & Goal State)
最後に、プランニングのスタート地点とゴール地点を明確にします。
- 初期状態 (Initial State): プランニングを開始する時点での世界の状況。先ほど説明した「事実のリスト」で記述します。
- 目標状態 (Goal State): 達成したい最終的な状況。これも「事実のリスト」で記述しますが、目標に含まれていない事実がどうなっているかは問わないのが一般的です(部分的な指定でOK)。
ブロック積み問題の例:
- 初期状態: { OnTable(A), OnTable(B), Clear(A), Clear(B), Empty(Arm) }
- (AとBがテーブルにあり、どちらも上が空で、アームも空)
- 目標状態: { On(A, B) }
- (ブロックAがブロックBの上に乗っていれば、それでOK! 他のブロックの状態やアームの状態は問わない)
旅行計画の例:
- 初期状態: { At(Home), Have(Ticket), Weather(Sunny) }
- 目標状態: { At(Hotel_Paris), Visited(Eiffel_Tower) }
- (パリのホテルにいて、エッフェル塔を訪れていれば目標達成!)
これで、AIが計画を立てるための材料が全て揃いました!
AIはどうやって計画(プラン)を見つけるの? ~試行錯誤のプロセス~
さて、材料(初期状態、目標状態、アクション)が揃ったら、いよいよAIがプラン(=アクションの実行順序)を見つけ出す番です。STRIPSプランナーは、主に探索アルゴリズムという方法を使って、ゴールまでの道のりを探します。
プラン=アクションの実行順序
プランとは、初期状態から目標状態に至るための、具体的なアクションの並びのことです。 例えば、先ほどのブロック積み問題(初期状態: A,Bがテーブル、目標: AがBの上)なら、
- PickUp(A) (Aを持ち上げる)
- Stack(A, B) (AをBの上に置く)
という2つのアクションの順番が、一つのプランになります。
2つの探し方:ゴールから遡る? スタートから進む?
プランを探す方法は、大きく分けて2つのアプローチがあります。
- 後向き探索 (Backward Search / Regression Planning): ゴールから逆算する!
- 考え方: 「目標を達成するには、その直前に何をしていたはずか?」と考えて、必要な前提条件を洗い出し、さらにその前提条件を満たすアクションは…と、ゴールからスタートに向かって遡っていく方法です。オリジナルのSTRIPSはこちらを採用していました。
- メリット: ゴールに関係のあるアクションに絞って考えられるので、効率的な場合がある。
- デメリット: 前提条件が複雑だと、考えるのが大変になることがある。
- 例: 「カレーを作りたい(ゴール)」→「そのためにはルーを入れる直前の状態(煮込んだ具材がある)が必要」→「煮込むためには、炒めた具材と水が必要」→…と遡るイメージ。
- 前向き探索 (Forward Search / Progression Planning): スタートから試していく!
- 考え方: 「初期状態から、今できるアクションはどれかな?」と、スタートからゴールに向かって、適用可能なアクションを次々に試していく方法です。
- メリット: 実際に実行可能な手順を追っていくので、現実的なプランが見つかりやすい。
- デメリット: ゴールに関係ないアクションも試してしまう可能性があり、無駄な探索が増えやすい。
- 例: 「冷蔵庫に人参と玉ねぎがある(スタート)」→「できることは…野菜を切る!」→「切った野菜がある状態になった」→「次は…炒められる!」→…と進むイメージ。
どちらの方法にも一長一短があり、問題の性質によって使い分けられます。
賢い探し方:探索アルゴリズム
これらの探索を効率的に行うために、コンピュータサイエンスでお馴染みのグラフ探索アルゴリズムが使われます。
- 幅優先探索 (BFS): 一番ステップ数の少ない(最短の)プランを見つけたい場合に有効。ただし、可能性を全部調べていくので、メモリをたくさん使うことがあります。
- 深さ優先探索 (DFS): 一つの可能性をとことん掘り下げていく方法。メモリはあまり使わないけれど、最適でないプランを見つけたり、無限に考え続けてしまう(ループ)ことも。
- A*探索 (A-star Search): ゴールまでの「近道度」を予測しながら探索する方法。ヒューリスティック関数という「勘」のようなものを使って、効率的に最適なプランを見つけようとします。プランニングでは、「目標達成に足りない事実の数」などがヒューリスティックとして使われることがあります。
「ヒューリスティック関数って何?」と思った方、大丈夫です!ここでは「ゴールまでの距離をなんとなく教えてくれるナビゲーター」くらいのイメージでOKですよ。
擬似コードを読み解いてみよう!(前向き探索)
ここで、簡単な前向き探索(幅優先探索ベース)がどんな風に動くか、擬似コード(プログラムの設計図のようなもの)で見てみましょう。プログラミングが苦手な方も、雰囲気だけ掴んでみてください!
Python
# 擬似コード:簡単な前向き探索(幅優先探索ベース)
function Forward_Search(initial_state, goal_state, actions):
# 1. 準備:スタート地点と空っぽのプランをリストに入れる
queue = [(initial_state, [])] # (状態, ここまでのプラン) のリスト(キュー)
visited_states = {initial_state} # 一度見た状態を覚えておくリスト(セット)
# 2. リストが空になるまで繰り返す
while queue is not empty:
# 3. リストの先頭から「現在の状態」と「そこまでのプラン」を取り出す
current_state, current_plan = queue.pop(0) # BFSなので先頭から
# 4. ゴール達成チェック!
if goal_state is subset of current_state: # 目標が現在の状態に含まれていたら
return current_plan # やった!プランが見つかった!
# 5. 今できるアクションを探す
for action in actions:
# 6. 前提条件を満たしているかチェック
if action.preconditions is subset of current_state:
# 7. アクションを実行したらどうなるか? 次の状態を計算
next_state = apply_action(current_state, action)
# 8. その状態、初めて見た?
if next_state not in visited_states:
# 9. 初めてなら、プランにこのアクションを追加して、リストの最後に入れる
new_plan = current_plan + [action]
queue.append((next_state, new_plan))
visited_states.add(next_state) # 見たことを覚えておく
# 10. リストが空になっても見つからなかったら…
return Failure # 残念!プランは見つかりませんでした
# アクション適用関数(状態を変化させる関数)
function apply_action(state, action):
new_state = state.copy() # 現在の状態をコピー
# 削除リストの事実を削除
for fact in action.delete_list:
if fact in new_state:
new_state.remove(fact)
# 追加リストの事実を追加
for fact in action.add_list:
new_state.add(fact)
return new_state # 新しい状態を返す
どうでしょう? AIが一つ一つ状態を確認し、試せるアクションを実行し、新しい状態をチェックして…という地道な作業を繰り返してプランを探している様子が、少しイメージできたでしょうか?
状態遷移を図で見てみよう!
アクションを実行すると、状態が変わります。この変化を「状態遷移」と言います。簡単なブロック積み問題で見てみましょう。
初期状態(S0): { OnTable(A), OnTable(B), Clear(A), Clear(B), Empty(Arm) }
↓ アクション PickUp(A) を実行 (前提条件を満たしているので実行可能)
状態(S1): { OnTable(B), Clear(B), Holding(A) } (OnTable(A), Clear(A), Empty(Arm)が消え、Holding(A)が追加された)
↓ アクション Stack(A, B) を実行 (前提条件 Holding(A), Clear(B) を満たしているので実行可能)
状態(S2): { On(A, B), Clear(A), Empty(Arm) } (Holding(A), Clear(B)が消え、On(A,B), Clear(A), Empty(Arm)が追加された)
お!状態S2には、目標状態 { On(A, B) } が含まれていますね! これでプラン [PickUp(A), Stack(A, B)] が見つかりました。
【G検定 ここがポイント!】 プラン探索には前向き探索と後向き探索があること、そして探索を効率化するために探索アルゴリズム(BFS, DFS, Aなど)が使われることを理解しておきましょう。特にA探索で使われるヒューリスティック関数は重要ワードです。
STRIPSってどんなことに使われているの? ~意外と身近な応用例~
「1970年代の技術でしょ? 今でも使われているの?」と思うかもしれませんが、STRIPSの基本的な考え方は、形を変えながら現代の様々な分野で活かされています。
- ロボットの行動計画:
- お掃除ロボット: 「部屋全体を掃除する」という目標のために、「まず充電ドックを出る」「次に壁際を走る」「障害物を避ける」「最後にドックに戻る」といった行動計画を立てるのに、STRIPS的な考え方が使われています。
- 工場の自動搬送ロボット(AGV): 「部品Aを棚Bから取ってきて、組み立てラインCに運ぶ」といったタスクの計画。
- 災害救助ロボット: 「瓦礫をどかす」「要救助者を探す」といった複雑な手順の計画。
- ゲームAI:
- RPGのキャラクター(NPC): プレイヤーが近づいたら「話しかける」、敵を見つけたら「攻撃する」、体力が減ったら「回復魔法を使う」など、状況に応じた行動計画を立てるのに使われます。皆さんが普段プレイしているゲームのキャラクターも、もしかしたらSTRIPSの子孫かもしれませんね!
- 戦略シミュレーションゲーム: ユニット(兵士や作業員)に「資源を集める」「建物を建てる」「敵を攻撃する」といった指示を出す際の、効率的な手順計画。
- その他の応用:
- 物流・配送計画: トラックがどの順番で荷物を積み、どのルートで配送すれば効率的か、といった計画。
- Webサービスの連携: 複数のWebサービス(例:地図サービス、予約サービス、決済サービス)を組み合わせて、ユーザーの要求(例:「近くのレストランを予約して」)を満たす手順の計画。
- ソフトウェアテスト: ソフトウェアが正しく動作するかを確認するためのテスト手順の自動生成。
もちろん、現代の応用では、STRIPSそのままではなく、より高度に進化したプランニング技術が使われていることが多いです。しかし、その根底にはSTRIPSで確立された「状態」「アクション」「前提条件」「効果」といった考え方が流れているのです。
STRIPSだけじゃない?他のプランニング手法との比較(ざっくり)
STRIPSは古典的プランニングの代表ですが、万能ではありません。いくつかの限界も抱えています。そして、その限界を克服するために、様々な新しいプランニング技術が登場してきました。
STRIPS(古典的プランニング)の限界点:
- 決定論的 (Deterministic): アクションの結果は常に1つに決まる、という前提。
- 現実:「ロボットアームが物を掴もうとして、失敗する」こともあるけど、STRIPSでは基本的に成功する前提。
- → 不確実な状況を扱えない。
- 完全情報 (Fully Observable): 世界の状態を全て正確に把握している、という前提。
- 現実:「センサーの死角があって見えない場所がある」「センサーにノイズが入る」こともあるけど、STRIPSでは完璧に分かっている前提。
- → 不完全な情報やセンサーの誤差を扱えない。
- 静的 (Static): プランを実行している間に、外部要因で勝手に状態が変わらない、という前提。
- 現実:「ロボットがブロックを運んでいる途中で、誰かが別のブロックを動かす」こともあるけど、STRIPSでは想定外。
- → 変化する環境に対応できない。
- 離散的 (Discrete): 時間や状態が、飛び飛びの値(ON/OFFなど)で表される、という前提。
- 現実:「燃料の残量」「移動にかかる時間」のように連続的な値もあるけど、STRIPSでは扱いにくい。
- → 時間やリソース(資源)の制約をうまく扱えない。
- 表現力の限界:
- 「もし〇〇だったら、効果が変わる」(条件付き効果)
- 「〇〇しながら△△する」(並行アクション)
- といった複雑な状況を記述するのが難しい。
これらの限界を克服するために、
- 確率的プランニング: アクションの成功/失敗が確率的に決まる状況に対応。
- 時間的プランニング: アクションの実行時間や、時間的な制約を扱える。
- 階層型タスクネットワーク (HTN): 大きなタスクを小さなサブタスクに分解しながら計画する。(より人間の思考に近い?)
- 状況計算 (Situation Calculus): より厳密な論理学に基づいて世界の変化を記述する。
といった、様々な発展形が登場しています。
また、STRIPSの記述能力を拡張したPDDL (Planning Domain Definition Language) という言語も広く使われています。PDDLを使うと、STRIPSでは難しかった数値や時間制約なども扱えるようになります。(G検定対策としては、PDDLという名前を知っておく程度で大丈夫でしょう)
【G検定 ここがポイント!】 STRIPS(古典的プランニング)には限界点(決定論的、完全情報、静的、離散的など)があることを理解しておくのが重要です!これらの限界があるからこそ、新しいAI技術(確率的プランニング、強化学習など)が発展してきた、という流れを掴むと、AI全体の理解が深まります。
まとめ:G検定合格へ!STRIPS完全理解
お疲れ様でした!AIの計画術の元祖、STRIPSプランニングの世界、いかがでしたか?
最後に、G検定合格に向けて、STRIPSの重要ポイントをもう一度おさらいしましょう!
- STRIPSとは?
- 1970年代(第1次AIブーム)に生まれた、初期の代表的な自動プランニングシステム/言語。
- AI研究における探索・推論分野の重要な成果。
- 基本的な考え方:
- 世界の状態を事実のリスト (State) で表現する。
- アクションを前提条件 (Preconditions) と効果 (Effects: 追加リスト/削除リスト) で定義する。← 最重要!
- プランニングのプロセス:
- 初期状態から目標状態へ遷移させるアクションの系列(プラン)を見つける。
- 探索方法には前向き探索と後向き探索がある。
- 探索には探索アルゴリズム (BFS, DFS, A*など) が使われる(特にヒューリスティック関数に注意)。
- 応用分野:
- ロボットの行動計画(お掃除ロボット、産業用ロボットなど)
- ゲームAI(NPCの行動決定など)
- 限界点:
- 古典的プランニングの限界(決定論的、完全情報、静的、離散的など)を理解しておく。
STRIPSは古い技術ですが、その考え方は非常にシンプルかつ本質的です。AIが「世界をモデル化し、行動の結果を予測し、目標達成への道筋を立てる」という基本的な思考プロセスを学ぶ上で、これ以上ない題材と言えるでしょう。
このSTRIPSの考え方をしっかり身につけておけば、G検定はもちろん、今後AIの他の分野(例えば強化学習など)を学ぶ上でも、きっと役に立つはずです!
この記事が、皆さんのG検定合格、そしてAIへの興味・理解を深める一助となれば、これ以上嬉しいことはありません。応援しています!
【おまけ】 もし、STRIPSやプランニングについてもっと深く知りたくなったら、「人工知能学会 プランニング専門部会」のウェブサイトや、関連する書籍・論文などを調べてみるのも面白いかもしれませんね!
コメント