"""Figure 4 — Final pipeline architecture. Five input streams converge into a LightGBM OOF stacker, a rank-cutoff top-50% decision, and the submission. The high-order stream carries the two propagation formulae H_k = R C^k and G_k = S R C^k rendered with mathtext. """ from pathlib import Path import matplotlib.pyplot as plt from matplotlib.patches import FancyBboxPatch, FancyArrowPatch from style import apply, save, PALETTE as C, COL2 # noqa: E402 KEY = "fig4_architecture" TITLE = "Figure 4. Final pipeline architecture" def _box(ax, x, y, w, h, text, color, fs=7.6, fc_alpha=0.16, weight="bold"): ax.add_patch(FancyBboxPatch((x, y), w, h, boxstyle="round,pad=0.06,rounding_size=0.12", fc=color, ec=color, alpha=fc_alpha, lw=1.5)) ax.text(x + w / 2, y + h / 2, text, ha="center", va="center", fontsize=fs, fontweight=weight, color="black") def _arrow(ax, a, b, color="black", lw=1.3): ax.add_patch(FancyArrowPatch(a, b, arrowstyle="-|>", mutation_scale=12, color=color, lw=lw)) def make(root, out): apply() fig, ax = plt.subplots(figsize=(COL2, 4.3)) ax.set_xlim(0, 13.6); ax.set_ylim(0, 6.2); ax.axis("off") # source _box(ax, 0.2, 2.7, 1.9, 0.9, "Official\nData", C[7], fs=8.5) # five feature streams streams = [ (4.6, "Author–Paper graph", "LightGCN score / rank", C[0]), (3.7, "Coauthor + citation graph", "explicit graph / meta-path feats", C[1]), (2.8, "feature.pkl", "content sim. + rich profile", C[2]), (1.9, "mixed graph", "DeepWalk / Node2Vec pair feats", C[3]), (1.0, "$R\\,C^{k}$ and $S\\,R\\,C^{k}$", "high-order propagation feats", C[4]), ] for y, src, feat, col in streams: _box(ax, 3.7, y - 0.30, 3.4, 0.62, f"{feat}", col, fs=7.2) ax.text(3.7 + 3.4 + 0.08, y, src, ha="left", va="center", fontsize=6.6, color="dimgray") _arrow(ax, (2.1, 3.15), (3.7, y)) # high-order propagation formula panel, linked to its feature stream ax.add_patch(FancyBboxPatch((8.45, 0.30), 3.15, 1.30, boxstyle="round,pad=0.06,rounding_size=0.12", fc=C[4], ec=C[4], alpha=0.10, lw=1.3)) ax.text(8.55, 1.42, "high-order propagation", fontsize=7.2, color=C[4], fontweight="bold") ax.text(10.0, 1.10, "$H_k = R\\,C^{\\,k}$", fontsize=11, color=C[4], ha="center") ax.text(10.0, 0.72, "$G_k = S\\,R\\,C^{\\,k}$", fontsize=11, color=C[4], ha="center") ax.text(10.0, 0.42, "$R$: author–paper $C$: citation $S$: coauthor", fontsize=6.2, color="dimgray", ha="center") _arrow(ax, (7.1, 1.0), (8.45, 0.95), color=C[4], lw=1.2) # stacker + decision + submission _arrow(ax, (7.1, 2.8), (9.4, 4.3)) _box(ax, 9.4, 3.85, 2.5, 0.95, "LightGBM\nOOF stacker\n(259-d)", C[5], fs=8) _arrow(ax, (10.65, 3.85), (10.65, 3.05)) _box(ax, 9.4, 2.15, 2.5, 0.85, "rank cutoff\ntop 50% + known pos.", C[6], fs=7.6) _arrow(ax, (11.9, 2.55), (12.6, 2.55)) _box(ax, 12.5, 2.10, 1.0, 0.9, "sub.", C[7], fs=8) ax.set_title("Final two-stage stacking pipeline", fontsize=10) save(fig, KEY, out) return dict(key=KEY, title=TITLE, status="ok", files=[f"{KEY}.pdf", f"{KEY}.png", f"{KEY}.svg"], sources=["schematic"], caption=( "Final pipeline. Five feature streams — LightGCN score/rank, explicit graph and meta-path " "features, content similarity and rich author–content profiles, DeepWalk/Node2Vec pair " "features, and high-order propagation features — are concatenated into a 259-d vector and " "fed to a LightGBM out-of-fold stacker. A rank-cutoff decision (top 50% positive, known " "positives forced to 1) produces the submission. High-order features are defined by " "$H_k = R\\,C^{k}$ (author reaches papers $k$ citation hops away) and $G_k = S\\,R\\,C^{k}$ " "(same, mediated by coauthorship), where $R$ is the author–paper matrix, $C$ the citation " "matrix and $S$ the coauthorship matrix.")) if __name__ == "__main__": from style import ensure_dirs r = make(Path("."), ensure_dirs(Path("."))) print(r["key"], r["status"])