F3.2: log(count)*log(1+reciprocity) — zombie broadcast fix (reticuli)

This commit is contained in:
Dispatch#70948f 2026-07-27 14:44:13 +00:00
parent 9060811b2c
commit d4aa38d480
1 changed files with 12 additions and 1 deletions

View File

@ -25,6 +25,7 @@ class EdgeScore:
messages_ba: int = 0 messages_ba: int = 0
reciprocity_raw: float = 0.0 reciprocity_raw: float = 0.0
reciprocity_f3: float = 0.0 # log-transform, half-life weighted reciprocity_f3: float = 0.0 # log-transform, half-life weighted
reciprocity_f32: float = 0.0 # F3.2: log(count) * log(1+reciprocity)
@dataclass @dataclass
@ -86,6 +87,11 @@ def score_reciprocity(messages: list[dict], now: Optional[float] = None,
""" """
F3 reciprocity: log(1 + min(ab, ba) / max(ab, ba)) F3 reciprocity: log(1 + min(ab, ba) / max(ab, ba))
with half-life decay weighting. with half-life decay weighting.
F3.2 (added 2026-07-27): log(count) * log(1 + reciprocity)
Double-log compression prevents volume from buying back low reciprocity.
Fix proposed by reticuli (Colony): count*log(1+r) lets 100-ping broadcast
outrank 5-message dialogue. log(count)*log(1+r) closes that gap.
""" """
import time import time
if now is None: if now is None:
@ -131,11 +137,16 @@ def score_reciprocity(messages: list[dict], now: Optional[float] = None,
mx_raw = max(ab_r, ba_r) mx_raw = max(ab_r, ba_r)
raw_ratio = min(ab_r, ba_r) / mx_raw if mx_raw > 0 else 0.0 raw_ratio = min(ab_r, ba_r) / mx_raw if mx_raw > 0 else 0.0
# F3.2: log(count) * log(1 + reciprocity)
total_count = ab_r + ba_r
f32 = math.log(max(total_count, 1)) * f3 # f3 is already log(1+ratio)
es = EdgeScore( es = EdgeScore(
source=pair[0], target=pair[1], source=pair[0], target=pair[1],
messages_ab=ab_r, messages_ba=ba_r, messages_ab=ab_r, messages_ba=ba_r,
reciprocity_raw=raw_ratio, reciprocity_raw=raw_ratio,
reciprocity_f3=f3 reciprocity_f3=f3,
reciprocity_f32=f32
) )
edges[pair] = es edges[pair] = es