🐓

新しい情報管理モデル ー フィボナッチ忘却 ー

に公開

Nature forgets by addition

新しい情報管理モデル ーフィボナッチ忘却(Fibonacci Forgets) ー

ログ、メール、会話履歴、GITなど、私たちを取り巻く情報は常に増え続けます。
普通は古いものを 削除して管理します。

しかし人間は別のやり方をしています。

それは、記憶の下層に落とすという方法です。

人間は、夜寝ている間に記憶の再構築をやっているという説があります。
しかも、情報に重みを付け、必要な情報、印象に残った出来事を優先的にを覚えています。

同じように、メモリー管理も、要らない情報は定期的に束ねて下層に落とせばよいのです。
閾値を超えたら、束ねて下層へ。情報を圧縮します。


自然界は、単純な加算、フィボナッチ数列で出来ています。

F(n+1) = F(n) + F(n-1)

この単純な加算から

  • 黄金比
  • フラクタル構造
  • 成長パターン

などが現れます。

なぜなら、それが、生物生成の仕組みそのものだからです。
ヒマワリの種、菊の花びら、カタツムリの渦巻き、蝸牛神経、脳神経もフィボナッチ数列が現れているとされています。
そして、実は、忘れる仕組みもフィボナッチ数列が使われています。


フィボナッチメモリー(Fibonacci Memory)

このアイデアをシンプルに実装すると、
次のような構造になります。
Layer0 個別情報 Layer1 小さな束 Layer2 大きな束 Layer3 概念

そして各層の容量を
1, 1, 2, 3, 5, 8, 13 ...

という フィボナッチ数列で管理します。

すると

  • 上位層 → 厳密
  • 下位層 → 粗い

という自然な階層ができます。

この束ねて下層に落とす仕組み、これを

Fibonacci Forgetting(フィボナッチ忘却)

と呼ぶことにします。
ここでは、下層に落としただけで、まだ、削除はしていません。

必要な時取り出すことも、容量が閾値を超えれば下層から圧縮、あるいは削除していきます。


動く最小コード

以下はフィボナッチ忘却メモリの
とてもシンプルな実装です。

from dataclasses import dataclass

# Fibonacci thresholds
FIB = [1, 1, 2, 3, 5, 8, 13, 21]


@dataclass
class FibonacciForgettingMemory:
    layers: list

    @classmethod
    def new(cls, depth=6):
        return cls(layers=[[] for _ in range(depth)])

    def add(self, item):
        """add item to top layer"""
        self.layers[0].append(item)
        self._cascade(0)

    def _cascade(self, level):
        """apply Fibonacci forgetting"""
        if level >= len(self.layers) - 1:
            return

        limit = FIB[level]

        if len(self.layers[level]) > limit:

            # bundle by addition (simple count)
            bundle = len(self.layers[level])

            # clear layer
            self.layers[level] = []

            # push bundled information to lower layer
            self.layers[level + 1].append(bundle)

            # continue cascade
            self._cascade(level + 1)

    def state(self):
        return self.layers


# demo
mem = FibonacciForgettingMemory.new()

events = [
    "promo","promo","promo","promo",
    "friend","promo","promo","promo",
    "promo","promo","promo","promo",
]

for e in events:
    mem.add(e)

print(mem.state())

コードの説明

このコードでは
情報は 加算で蓄積
溢れたら 束ねる
束ねた情報は 下位層へ落とします。

という人間の忘却の仕組みに似ています。

応用できそうな分野
このアイデアはまだラフですが、
いくつかの用途に応用できそうです。

応用例

例えば
メール管理
ログ圧縮
キャッシュ管理
LLMメモリ管理
GIT管理も良いですね。
 大きな修正は重く、小さな修正は軽いといった重みを付けて管理すれば探すのが楽です。

それを全て
addition(加算)だけ
で実装できる点も面白いと思っています。

更に

フィナボッチメモリーの概念図にしてみました。(表題の図)

フィボナッチ数列は、自然そのものですので、アイデアを含め利用は原則自由です。


おまけ

AIにGitで使いやすいように作ってもらったので載せておきます。
ご自身の責任で利用してください。

主な仕様
各アイテム(例: コミット)に weight(重み)を付与
重みはフィボナッチ数列から自動選択(新しいアイテムほど大きいフィボナッチ値を与える)
束ねるとき(cascade時)は、重みの合計を保持 → 下層に落ちた束の「全体の重み」として扱う
上層(最近の層)ほど重みが大きく、下層に行くほど重みが「粗く・相対的に小さく」なる自然な階層化を実現
from typing import Any, List, Dict, Optional

class FractalFibMemoryWithFibWeights:
"""
フラクタル版 Fibonacci Forgetting + 重みをフィボナッチ数列で表現
- 新しいアイテムほど大きいフィボナッチ重みを与える
- 束ねるときは重みの合計を保持 → 下層の「重要度」の目安に
- Gitコミット管理に最適(最近の変更ほど重く、古いものは粗く忘却)
"""

# フィボナッチ数列(重み候補)。逆順で使うので大きいものから割り当て
FIB_WEIGHTS = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377][::-1]  # 大→小

def __init__(self, level: int = 0, max_depth: int = 10):
    self.level = level
    self.max_depth = max_depth
    self.items: List[Dict] = []  # {'content': Any, 'weight': int}
    self.children: List['FractalFibMemoryWithFibWeights'] = []
    self.bundle_weight: Optional[int] = None  # この層が束ねられた場合の合計重み
    
    # この層の容量(フィボナッチで階層ごとに変化)
    fib_caps = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
    self.capacity = fib_caps[min(level, len(fib_caps)-1)]

def add(self, content: Any):
    """新しいアイテムを追加(重みを自動でフィボナッチから割り当て)"""
    # 新しいほど大きい重みを割り当てる(逆順インデックスで)
    weight_index = min(len(self.items), len(self.FIB_WEIGHTS) - 1)
    weight = self.FIB_WEIGHTS[weight_index]
    
    self.items.append({
        'content': content,
        'weight': weight
    })
    
    if len(self.items) > self.capacity:
        self._cascade()

def _cascade(self):
    if not self.items:
        return
        
    # 重みの合計を計算(この束の重要度)
    total_weight = sum(item['weight'] for item in self.items)
    
    bundle = {
        'level': self.level,
        'count': len(self.items),
        'items': self.items[:],  # 生データ保持(要約したい場合はここで処理)
        'total_weight': total_weight,
        'type': 'bundle'
    }
    self.items.clear()
    
    # === 最後の1的な深層処理(あなたの理論を反映)===
    if self.level >= self.max_depth - 2:
        # 深層入り口 → 子として追加し、重みを引き継ぐ
        self.children.append(bundle)
        return
    
    # 自己相似的に子フラクタル生成
    if not self.children or (isinstance(self.children[-1], dict) or len(self.children[-1].items) > 0):
        child = FractalFibMemoryWithFibWeights(self.level + 1, self.max_depth)
        self.children.append(child)
    
    # 子に束を渡す(再帰)
    self.children[-1].add(bundle)

def state(self, depth: int = 0) -> str:
    """フラクタル構造を可視化(重みも表示)"""
    indent = "  " * depth
    if hasattr(self, 'bundle_weight') and self.bundle_weight is not None:
        return f"{indent}Bundle @ Level {self.level} (total_weight={self.bundle_weight}, count=?)\n"
    
    s = f"{indent}Level {self.level} (cap={self.capacity}): {len(self.items)} items\n"
    for item in self.items:
        s += f"{indent}  - {item['content']} (weight={item['weight']})\n"
    
    for child in self.children:
        if isinstance(child, dict):
            s += f"{indent}  └─ Bundle L{child['level']} (count={child['count']}, total_weight={child['total_weight']})\n"
        else:
            s += child.state(depth + 1)
    return s

def get_weighted_recent(self, n: int = 10) -> List[Dict]:
    """重み降順で最近のものを取得(上層優先)"""
    collected = []
    
    def collect(node):
        # 生アイテムを優先(重みが高い)
        collected.extend(node.items)
        # 子を再帰
        for c in node.children:
            if isinstance(c, dict):
                # 束は代表として1つだけ(重みでソート用)
                collected.append({
                    'content': f"[Bundle {c['count']}件]",
                    'weight': c['total_weight']
                })
            else:
                collect(c)
    
    collect(self)
    # 重みでソート(大きい=重要)
    collected.sort(key=lambda x: x['weight'], reverse=True)
    return collected[:n]

==================== デモ ====================

mem = FractalFibMemoryWithFibWeights()

コミットを追加(新しいほど重みが大きくなる)

for i in range(80):
msg = f"commit_{i:03d} - {'fix' if i % 3 == 0 else 'refactor' if i % 5 == 0 else 'feat'}"
mem.add(msg)

print("=== フラクタル構造(重み付き) ===")
print(mem.state())

print("\n=== 重み順の最近の項目(上位10) ===")
recent = mem.get_weighted_recent(10)
for item in recent:
print(f"- {item['content']} (weight={item['weight']})")

'''

特徴まとめ
重みの割り当て:新しいアイテムほど大きいフィボナッチ値(233 → 1の順で減衰)
束ね時の重み:合計値として下層に伝播 → 下層の束は「過去の重要な変更の塊」として相対的に重く残る
忘却の自然さ:上層は細かい重みで個別管理、下層は合計重みで粗く扱う
実利:Gitログで「最近の重大なrefactorは重みが残りやすい」ようになる

Nature forgets by addition.

Fibonacci Forgetting

本記事のコードはMITライセンスで公開します。
Copyright (c) 2024 moroc.b13---

Discussion