ふくふくHukuhuku Inc.
EP.16STEM対象: 高2以上 16分公開: 2026-05-10

計算理論の地平:P vs NP・近似アルゴリズム・最近の発見

「世界で最も重要な未解決問題」P vs NP から、現代の確率的データ構造、そして 2010〜2020 年代の新発見まで。コンピュータサイエンスの「これからの 10 年」を、自分の手で動かして体感する。

#中高生#計算理論#P vs NP#確率的データ構造
CO📔 Google Colab で開く(上から順にセルを実行)
シェア

ここまで、ソートと探索を実装してきました。今回は 「そもそも何が効率的に解けて、何が解けないのか」 という、コンピュータサイエンスの最も深い問い ── 計算理論の世界を覗きます。教科書の枠を超えて、現代の研究の地平までいきます。

今回のゴール

① P と NP の違いを実例で分かる ② 「効率的には解けない(と信じられている)問題」が現実にある ③ 完璧を諦めて「近似で解く」という現代の主流の考え方 ④ Bloom Filter・ のような「確率的データ構造」を実装する ⑤ 2020 年代の新発見(量子優位性・新しいハッシュ等)

Step 0: 問題 ─ 100万ドル懸賞

P = 多項式時間で解ける問題(ソート、最短経路など)。NP = 多項式時間で検証できる問題(解を渡されれば正解か確かめられる)。 P = NP か? ── 解くのと検証するのが同じ難しさか。21世紀最大の未解決問題で、Clay Mathematics Institute が 100 万ドル懸賞 をかけています(ミレニアム懸賞問題)。

なぜ重要か

もし P=NP が証明されたら、現代の暗号(RSA, AES)はほぼ全部破られる。タンパク質構造予測・最適配送ルート計画・新薬開発・ ソルバが劇的に高速化する。世界が変わる。逆に P≠NP が証明されれば「効率解は原理的にない」と確定。多くの研究者は P≠NP と予想していますが、まだ証明されていない

Step 1: NP-完全な問題を実装してみる

ナップサック問題:価値と重さを持つ品物の集合から、重量制限内で価値最大の組み合わせを選ぶ。現実的な品数(n=100)でも厳密解は爆発的に時間がかかる

総当たり vs 動的計画法 vs 貪欲近似
Python
import time, random, itertools
random.seed(0)n, capacity = 22, 50          # 全数探索の限界くらいitems = [(random.randint(1, 20), random.randint(1, 30)) for _ in range(n)]  # (weight, value)
# ① 総当たり O(2^n)def brute(items, cap):    best = 0    for mask in range(1 << len(items)):        w = sum(items[i][0] for i in range(len(items)) if mask >> i & 1)        v = sum(items[i][1] for i in range(len(items)) if mask >> i & 1)        if w <= cap:            best = max(best, v)    return best
# ② DP O(n × cap)def dp(items, cap):    table = [0] * (cap + 1)    for w, v in items:        for c in range(cap, w - 1, -1):            table[c] = max(table[c], table[c - w] + v)    return table[cap]
# ③ 貪欲(価値/重さ比、近似)def greedy(items, cap):    sorted_items = sorted(items, key=lambda x: -x[1] / x[0])    total = 0    for w, v in sorted_items:        if cap >= w:            cap -= w; total += v    return total
t0 = time.perf_counter(); v_b = brute(items, capacity);  t_b = time.perf_counter() - t0t0 = time.perf_counter(); v_d = dp(items, capacity);     t_d = time.perf_counter() - t0t0 = time.perf_counter(); v_g = greedy(items, capacity); t_g = time.perf_counter() - t0print(f"総当たり: {v_b}  ({t_b:.4f} s)")print(f"DP:       {v_d}  ({t_d:.4f} s)")print(f"貪欲近似: {v_g}  ({t_g:.4f} s, ratio={v_g/v_b:.2%})")
現代の戦略

n=100 では総当たり 2^100 ≒ 10^30 通り、宇宙の年齢でも終わらない。だから現代は:① 厳密解が必要なら DP(疑似多項式時間)/ ② 大規模なら 近似アルゴリズム / ③ で解の良さそうな部分から探索(学習型解法)。

Step 2: 確率的データ構造 ─ Bloom Filter

「URL がスパムリストに入ってるか」を 100 億エントリで瞬時に判定したい。普通の set だと数百GBのメモリ。Bloom Filter は誤判定(false positive)を許容する代わりに、メモリを 1/100 〜 1/1000 に削減できます。

Bloom Filter を自分で実装
Python
import hashlib, math
class BloomFilter:    def __init__(self, n_items, fp_rate=0.01):        # ビット配列のサイズと使うハッシュ関数の数        self.size = int(-n_items * math.log(fp_rate) / (math.log(2) ** 2))        self.k = int(self.size / n_items * math.log(2))        self.bits = [False] * self.size
    def _hashes(self, x):        h = hashlib.md5(str(x).encode()).digest()        for i in range(self.k):            yield int.from_bytes(h[i*2:(i+1)*2], 'big') % self.size
    def add(self, x):        for h in self._hashes(x):            self.bits[h] = True
    def contains(self, x):        return all(self.bits[h] for h in self._hashes(x))
# 使ってみるbf = BloomFilter(10000, fp_rate=0.01)for x in range(10000):    bf.add(f"item-{x}")
print("入ってる:", bf.contains("item-42"))   # → Trueprint("入ってない:", bf.contains("nope"))     # → ほぼ Falsefp = sum(bf.contains(f"unknown-{x}") for x in range(10000)) / 10000print(f"誤検出率: {fp:.2%} (目標 1.00%)")
実用例

Cassandra / HBase の SSTable、CDN のキャッシュ判定、Bitcoin の SPV クライアント、Chrome の悪質URLチェック ── どれも Bloom Filter かその親戚を使っています。

Step 3: HyperLogLog ─ 「ユニーク数を 1KB で数える」

「今日サイトに来たユーザー数(重複なし)」を10億ユーザーから求めたい場合、set だと数十GB。HyperLogLog は 1.5KB 程度のメモリで誤差 1% 以内で数えられます。Google・Reddit・Redis などで実用。

HyperLogLog 簡易版
Python
import hashlib, math
class HyperLogLog:    def __init__(self, p=14):       # p=14 → 16384 バケット → 約 0.81% 誤差        self.p = p        self.m = 1 << p        self.M = [0] * self.m
    def add(self, x):        h = int(hashlib.md5(str(x).encode()).hexdigest()[:16], 16)        idx = h & (self.m - 1)        rest = h >> self.p        # 末尾の 0 の個数 + 1        rho = (rest & -rest).bit_length() if rest else 64 - self.p        self.M[idx] = max(self.M[idx], rho)
    def estimate(self):        alpha = 0.7213 / (1 + 1.079 / self.m)        Z = 1.0 / sum(2 ** -m for m in self.M)        return alpha * self.m * self.m * Z
# 1000万ユニーク要素を投入hll = HyperLogLog(p=14)true_count = 10_000_000for x in range(true_count):    hll.add(x)estimated = hll.estimate()print(f"真の値: {true_count}")print(f"推定:   {estimated:.0f}  誤差: {abs(estimated-true_count)/true_count:.2%}")

Step 4: 2010〜2020 年代の新発見・標準化 年表

「ソートも探索も完成された分野」と思われがちですが、実は今も毎年新しい論文・標準が出ています。直近10数年分の主な動きを年表で。

アルゴリズム・データ構造の主な動き(2013〜2024)
発見・採用発明者・発表元ポイント
2013HyperLogLog++Googleユニーク数推定の改良版。Redis 7 で改良が入る
2014Cuckoo FilterFan, Andersen, Kaminsky, Mitzenmacher (CMU)Bloom より省メモリ・削除可能・誤検出率低
2016Malkov & Yashunin高次元ベクトル空間の近似最近傍探索。現代ベクトルDBの中核
2018Pdqsort(pattern-defeating quicksort)Orson PetersRust 標準ソート。クイックソートの敵対的入力を回避
2018Learned Index StructuresKraska et al.(Google)機械学習で B-tree を置き換える研究
2019Quantum Supremacy 主張(Sycamore)Google53 量子ビットで「古典では実用時間で解けない」課題を解決と主張(再現性で議論続く)
2022PowersortMunro & WildTimsort のマージ戦略を数学的に最適化。後に Java 21 で標準採用
2024Java 21 が Powersort を標準採用Oracle / OpenJDK20年使われた Timsort 系統に改善余地があったと再認識
2024〜LSH の継続的改良学術界(毎年)ベクトル検索の数学的下限を更新する論文が継続
コンピュータサイエンスは終わらない

「ソートはもう完成された分野」と思われがちですが、実は今でも論文が出ています。コンピュータの使い方が変われば、最適なアルゴリズムも変わる。クラウド・GPU・量子・ストリーミング ── 計算機が新しくなるたび、CS は新しい問題を見つけます。

自由研究の提案

① 自分の SAT ソルバ: 「3SAT 問題」を貪欲・WalkSAT・DPLL の3手法で実装。NP-完全問題の難しさを肌で感じる。 ② Cuckoo Filter を実装: Bloom より新しい確率的構造。要素削除ができる、誤検出率が低い、を確認する。 ③ Learned Index: ソート済みデータの位置を線形回帰で「予測」してから。普通の二分探索より速くなるか実験。 ④ P vs NP の証明を試す: 一晩あれば証明できそうな問題ではないですが、「なぜ難しいのか」を考えるだけでも CS の本質に近づきます。Cook-Levin の定理(任意の NP 問題は SAT に還元可能)あたりが入り口。

ここまでを振り返ると

EP.01 から EP.16 まで、関数のグラフから核分裂、ソート、計算理論まで、Python が「世界を理解するための最高の道具」だということを示してきました。プログラミングは数学・物理・化学・統計・ と地続き。 「もっとやりたい」を感じてくれたなら、それが何より。次のテーマブロックでは、シミュレーション物理(流体・生態系・遺伝アルゴリズム)、データサイエンス応用、CSの最新研究などを扱う予定です。シリーズはこの先も続きます

シェア

この記事の感想を教えてください

あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。

シリーズの外も探す:

まずは、現状を聞かせてください。

要件が固まっていなくて大丈夫です。現状診断と方針提案までを無料でお手伝いします。

無料相談フォームへ hello [at] hukuhuku [dot] co [dot] jp