#!/usr/bin/env python3 """ Generate study diagrams for defense preparation: 1. PYTANIE 12: Network optimization models (mnemonic overview) 2. PYTANIE 21: Vector clock timeline 3. PYTANIE 22: Linearizability vs Sequential consistency, Paxos flow 4. PYTANIE 23: Segmentation types and over-segmentation 5. PYTANIE 24: HOG pipeline, SVM margin, R-CNN vs YOLO architecture All: A4-compatible, B&W, 300 DPI, laser-printer-friendly. """ import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import matplotlib.patches as mpatches from matplotlib.patches import FancyBboxPatch, FancyArrowPatch import numpy as np import os DPI = 300 BG = 'white' LN = 'black' FS = 8 FS_TITLE = 12 OUTPUT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'img') os.makedirs(OUTPUT_DIR, exist_ok=True) GRAY1 = '#E8E8E8' GRAY2 = '#D0D0D0' GRAY3 = '#B8B8B8' GRAY4 = '#F5F5F5' GRAY5 = '#C0C0C0' def draw_box(ax, x, y, w, h, text, fill='white', lw=1.2, fontsize=FS, fontweight='normal', ha='center', va='center', rounded=True): if rounded: rect = FancyBboxPatch((x, y), w, h, boxstyle="round,pad=0.05", lw=lw, edgecolor=LN, facecolor=fill) else: rect = mpatches.Rectangle((x, y), w, h, lw=lw, edgecolor=LN, facecolor=fill) ax.add_patch(rect) ax.text(x + w/2, y + h/2, text, ha=ha, va=va, fontsize=fontsize, fontweight=fontweight, wrap=True) def draw_arrow(ax, x1, y1, x2, y2, lw=1.2, style='->', color=LN): ax.annotate("", xy=(x2, y2), xytext=(x1, y1), arrowprops=dict(arrowstyle=style, color=color, lw=lw)) # ============================================================ # PYTANIE 12: Network Optimization Models (Mnemonic Overview) # ============================================================ def draw_network_models(): fig, ax = plt.subplots(1, 1, figsize=(8.27, 5)) ax.set_xlim(0, 10) ax.set_ylim(0, 7) ax.set_aspect('equal') ax.axis('off') ax.set_title('Sieciowe modele optymalizacji — „Nasz Mały Mikołaj Przydzielił Trasy Ciężarówkom Mapując"', fontsize=10, fontweight='bold', pad=10) models = [ (1, "Najkrótsza\nścieżka", "GPS, routing\nDijkstra, A*", "A→B najszybciej?", GRAY1), (2, "Maksymalny\nprzepływ", "Przepustowość\nFord-Fulkerson", "Ile max przesłać?", GRAY4), (3, "Min koszt\nprzepływu", "Najtańszy transport\nSieciowy simpleks", "X jednostek najtaniej?", GRAY4), (4, "Przydział\n(assignment)", "n→n, min koszt\nAlg. Węgierski O(n³)", "Kto robi co?", GRAY2), (5, "TSP\n(komiwojażer)", "Objazd miast\nNP-trudny, heurystyki", "Objazd wszystkiego?", GRAY3), (6, "CPM/PERT", "Harmonogram\nŚcieżka krytyczna", "Ile trwa projekt?", GRAY2), (7, "MST\n(drzewo rozp.)", "Min połączenie\nKruskal, Prim", "Połącz najtaniej?", GRAY1), ] # Layout: 3 pairs + 1, arranged in labeled groups group_positions = [ # (group_label, [(model_idx, x, y), ...]) ("DROGI", [(0, 0.3, 4.0), (6, 0.3, 1.5)]), ("PRZEPŁYW", [(1, 3.3, 4.0), (2, 3.3, 1.5)]), ("ZARZĄDZANIE", [(3, 6.3, 4.0), (5, 6.3, 1.5)]), ] box_w = 2.6 box_h = 1.8 for group_label, items in group_positions: xs = [x for _, x, y in items] ys = [y for _, x, y in items] gx = min(xs) - 0.15 gy = min(ys) - 0.3 gw = box_w + 0.3 gh = max(ys) - min(ys) + box_h + 0.6 rect = mpatches.FancyBboxPatch((gx, gy), gw, gh, boxstyle="round,pad=0.1", lw=0.8, edgecolor=GRAY3, facecolor='white', linestyle='--') ax.add_patch(rect) ax.text(gx + gw/2, gy + gh + 0.12, group_label, ha='center', fontsize=8, fontweight='bold', color='#555555') for idx, x, y in items: num, name, detail, question, fill = models[idx] draw_box(ax, x, y, box_w, box_h, '', fill=fill, fontsize=FS) ax.text(x + box_w/2, y + box_h - 0.25, f"{num}. {name}", ha='center', va='top', fontsize=8, fontweight='bold') ax.text(x + box_w/2, y + box_h/2 - 0.1, detail, ha='center', va='center', fontsize=7) ax.text(x + box_w/2, y + 0.2, f'→ „{question}"', ha='center', va='bottom', fontsize=6.5, style='italic') # TSP alone at bottom center idx = 4 x, y = 4.5, -0.1 num, name, detail, question, fill = models[idx] rect = mpatches.FancyBboxPatch((x - 0.15, y - 0.15), box_w + 0.3, box_h + 0.3, boxstyle="round,pad=0.1", lw=0.8, edgecolor=GRAY3, facecolor='white', linestyle='--') ax.add_patch(rect) ax.text(x + box_w/2, y + box_h + 0.3, "SAM (NP-trudny)", ha='center', fontsize=8, fontweight='bold', color='#555555') draw_box(ax, x, y, box_w, box_h, '', fill=fill, fontsize=FS) ax.text(x + box_w/2, y + box_h - 0.25, f"{num}. {name}", ha='center', va='top', fontsize=8, fontweight='bold') ax.text(x + box_w/2, y + box_h/2 - 0.1, detail, ha='center', va='center', fontsize=7) ax.text(x + box_w/2, y + 0.2, f'→ „{question}"', ha='center', va='bottom', fontsize=6.5, style='italic') ax.set_ylim(-0.5, 7.2) plt.tight_layout() plt.savefig(os.path.join(OUTPUT_DIR, 'network_models_mnemonic.png'), dpi=DPI, bbox_inches='tight', facecolor=BG) plt.close() print(" ✓ network_models_mnemonic.png") # ============================================================ # PYTANIE 21: Vector Clock Timeline # ============================================================ def draw_vector_clock_timeline(): fig, ax = plt.subplots(1, 1, figsize=(8.27, 4.5)) ax.set_xlim(-0.5, 11) ax.set_ylim(-0.5, 4.5) ax.axis('off') ax.set_title('Zegary wektorowe — przykład z 3 procesami', fontsize=FS_TITLE, fontweight='bold', pad=10) # Process lines procs = [('P₁', 3.5), ('P₂', 2.0), ('P₃', 0.5)] for name, y in procs: ax.plot([0.5, 10.5], [y, y], color=LN, lw=1.5) ax.text(0.1, y, name, ha='right', va='center', fontsize=10, fontweight='bold') # Events events = [ # (name, process_y, x, vector, fill) ('A', 3.5, 1.5, '[1,0,0]', GRAY1), ('B', 2.0, 2.5, '[0,1,0]', GRAY2), ('C', 2.0, 5.0, '[1,2,0]', GRAY2), ('D', 0.5, 4.0, '[0,0,1]', GRAY3), ('E', 3.5, 6.5, '[2,0,0]', GRAY1), ('F', 2.0, 8.0, '[2,3,0]', GRAY2), ] for name, y, x, vec, fill in events: circle = plt.Circle((x, y), 0.25, facecolor=fill, edgecolor=LN, lw=1.5) ax.add_patch(circle) ax.text(x, y, name, ha='center', va='center', fontsize=9, fontweight='bold') ax.text(x, y + 0.45, vec, ha='center', va='bottom', fontsize=7, fontfamily='monospace', color='#333333') # Messages (arrows between processes) # P1:A → P2:C (msg sent after A, received at C) ax.annotate("", xy=(4.75, 2.0), xytext=(1.75, 3.5), arrowprops=dict(arrowstyle='->', color='#444444', lw=1.5, connectionstyle='arc3,rad=0.05')) ax.text(3.0, 3.0, 'msg₁', ha='center', fontsize=7, color='#444444', style='italic') # P1:E → P2:F ax.annotate("", xy=(7.75, 2.0), xytext=(6.75, 3.5), arrowprops=dict(arrowstyle='->', color='#444444', lw=1.5, connectionstyle='arc3,rad=0.05')) ax.text(7.0, 3.0, 'msg₂', ha='center', fontsize=7, color='#444444', style='italic') # Concurrency annotations ax.annotate('A ∥ B\n(współbieżne)', xy=(2.0, 1.2), fontsize=7, ha='center', bbox=dict(boxstyle='round,pad=0.2', facecolor=GRAY4, edgecolor=GRAY5)) ax.annotate('C ∥ D\n(współbieżne)', xy=(4.5, 0.9), fontsize=7, ha='center', bbox=dict(boxstyle='round,pad=0.2', facecolor=GRAY4, edgecolor=GRAY5)) ax.annotate('A → C\n(przyczynowe)', xy=(3.3, 4.2), fontsize=7, ha='center', bbox=dict(boxstyle='round,pad=0.2', facecolor=GRAY1, edgecolor=GRAY3)) # Time arrow ax.annotate("", xy=(10.5, -0.3), xytext=(0.5, -0.3), arrowprops=dict(arrowstyle='->', color=GRAY3, lw=1.0)) ax.text(5.5, -0.45, 'czas →', ha='center', fontsize=8, color='#777777') plt.tight_layout() plt.savefig(os.path.join(OUTPUT_DIR, 'vector_clock_timeline.png'), dpi=DPI, bbox_inches='tight', facecolor=BG) plt.close() print(" ✓ vector_clock_timeline.png") # ============================================================ # PYTANIE 22: Linearizability vs Sequential Consistency # ============================================================ def draw_linearizability_vs_sequential(): fig, axes = plt.subplots(2, 1, figsize=(8.27, 5.5)) for i, (ax, title, subtitle, operations, result_text) in enumerate(zip( axes, ['Linearizability', 'Sequential Consistency'], ['Operacja „wygląda" atomowo w czasie rzeczywistym', 'Globalny porządek zgodny z programem, ale NIE z czasem rzeczywistym'], [ # Linearizability [ ('Klient A', 1, 3, 'write(x,1)', GRAY1), ('Klient B', 2, 4, 'read(x)→1 ✓', GRAY2), ('Klient A', 5, 7, 'write(x,2)', GRAY1), ], # Sequential consistency [ ('Klient A', 1, 3, 'write(x,1)', GRAY1), ('Klient B', 2, 4, 'read(x)→0 ✓', GRAY2), ('Klient A', 5, 7, 'write(x,2)', GRAY1), ], ], [ 'read MUSI zwrócić 1 (write zakończony w czasie rzeczywistym)', 'read MOŻE zwrócić 0 (globalny porządek: read, write(1), write(2))', ] )): ax.set_xlim(0, 9) ax.set_ylim(-0.5, 3.5) ax.axis('off') ax.set_title(f'{title}', fontsize=10, fontweight='bold') ax.text(4.5, 3.2, subtitle, ha='center', fontsize=7, style='italic', color='#555555') # Time axis ax.plot([0.5, 8.5], [0, 0], color=GRAY3, lw=0.8) for t in range(1, 9): ax.plot([t, t], [-0.05, 0.05], color=GRAY3, lw=0.8) ax.text(t, -0.2, f't{t}', ha='center', fontsize=6, color='#999999') # Client labels clients = list(dict.fromkeys([op[0] for op in operations])) client_y = {c: 1.0 + idx * 1.2 for idx, c in enumerate(clients)} for client_name, y_pos in client_y.items(): ax.text(0.3, y_pos, client_name, ha='right', va='center', fontsize=7, fontweight='bold') ax.plot([0.5, 8.5], [y_pos, y_pos], color=GRAY5, lw=0.5, linestyle=':') for client, t_start, t_end, label, fill in operations: y = client_y[client] rect = FancyBboxPatch((t_start, y - 0.2), t_end - t_start, 0.4, boxstyle="round,pad=0.05", lw=1.2, edgecolor=LN, facecolor=fill) ax.add_patch(rect) ax.text((t_start + t_end) / 2, y, label, ha='center', va='center', fontsize=7) # Result annotation ax.text(4.5, -0.45, result_text, ha='center', fontsize=7, bbox=dict(boxstyle='round,pad=0.3', facecolor=GRAY4, edgecolor=GRAY5)) plt.tight_layout() plt.savefig(os.path.join(OUTPUT_DIR, 'linearizability_vs_sequential.png'), dpi=DPI, bbox_inches='tight', facecolor=BG) plt.close() print(" ✓ linearizability_vs_sequential.png") # ============================================================ # PYTANIE 22: Paxos Protocol Flow # ============================================================ def draw_paxos_flow(): fig, ax = plt.subplots(1, 1, figsize=(8.27, 4)) ax.set_xlim(-0.5, 10.5) ax.set_ylim(-0.5, 5) ax.axis('off') ax.set_title('Paxos — uproszczony przebieg (zapis x=5)', fontsize=FS_TITLE, fontweight='bold', pad=10) # Actors actors = [ ('Proposer', 1.5, 4.0, GRAY1), ('A₁', 4.5, 4.0, GRAY2), ('A₂', 6.5, 4.0, GRAY2), ('A₃', 8.5, 4.0, GRAY2), ] for name, x, y, fill in actors: draw_box(ax, x - 0.6, y, 1.2, 0.6, name, fill=fill, fontsize=8, fontweight='bold') # Phase 1: Prepare ax.text(-0.3, 3.5, 'FAZA 1\nPrepare', ha='center', fontsize=7, fontweight='bold', bbox=dict(boxstyle='round,pad=0.2', facecolor=GRAY4, edgecolor=GRAY5)) y_prep = 3.3 for target_x in [4.5, 6.5, 8.5]: draw_arrow(ax, 2.1, y_prep + 0.15, target_x - 0.6, y_prep + 0.15, lw=1.0) ax.text(3.3, y_prep + 0.35, 'Prepare(n=1)', fontsize=6, ha='center') # Promises back y_prom = 2.7 for target_x in [4.5, 6.5]: draw_arrow(ax, target_x - 0.6, y_prom + 0.15, 2.1, y_prom + 0.15, lw=1.0, color='#555555') ax.text(3.3, y_prom + 0.35, 'Promise(n=1) ✓', fontsize=6, ha='center', color='#555555') ax.text(8.5, y_prom + 0.15, '(slow)', fontsize=6, ha='center', color='#999999') ax.text(1.5, y_prom - 0.15, 'majority\n(2/3) ✓', fontsize=6, ha='center', bbox=dict(boxstyle='round,pad=0.15', facecolor=GRAY1, edgecolor=GRAY3)) # Phase 2: Accept ax.text(-0.3, 1.8, 'FAZA 2\nAccept', ha='center', fontsize=7, fontweight='bold', bbox=dict(boxstyle='round,pad=0.2', facecolor=GRAY4, edgecolor=GRAY5)) y_acc = 1.6 for target_x in [4.5, 6.5, 8.5]: draw_arrow(ax, 2.1, y_acc + 0.15, target_x - 0.6, y_acc + 0.15, lw=1.0) ax.text(3.3, y_acc + 0.35, 'Accept(n=1, x=5)', fontsize=6, ha='center') # Accepted back y_accd = 1.0 for target_x in [4.5, 6.5]: draw_arrow(ax, target_x - 0.6, y_accd + 0.15, 2.1, y_accd + 0.15, lw=1.0, color='#555555') ax.text(3.3, y_accd + 0.35, 'Accepted ✓', fontsize=6, ha='center', color='#555555') # Result ax.text(5.0, 0.1, 'x=5 UZGODNIONE (majority zaakceptowała) → Linearizable!', fontsize=8, ha='center', fontweight='bold', bbox=dict(boxstyle='round,pad=0.3', facecolor=GRAY1, edgecolor=LN)) plt.tight_layout() plt.savefig(os.path.join(OUTPUT_DIR, 'paxos_flow.png'), dpi=DPI, bbox_inches='tight', facecolor=BG) plt.close() print(" ✓ paxos_flow.png") # ============================================================ # PYTANIE 24: HOG Pipeline Overview # ============================================================ def draw_hog_pipeline(): fig, ax = plt.subplots(1, 1, figsize=(8.27, 3.5)) ax.set_xlim(0, 10) ax.set_ylim(0, 4) ax.axis('off') ax.set_title('HOG + SVM — pipeline detekcji pieszych', fontsize=FS_TITLE, fontweight='bold', pad=10) steps = [ (0.3, 'Obraz\nwejściowy', GRAY4), (2.1, 'Oblicz\ngradienty\n(Gx, Gy)', GRAY1), (3.9, 'Podziel na\nkomórki 8×8\nhistogramy', GRAY2), (5.7, 'Normalizuj\nw blokach\n2×2', GRAY2), (7.5, 'Wektor\ncech\n(3780-dim)', GRAY3), (9.0, 'SVM\n→ pieszy\n/ nie', GRAY1), ] box_w = 1.5 box_h = 1.8 y = 1.2 for i, (x, text, fill) in enumerate(steps): draw_box(ax, x, y, box_w, box_h, '', fill=fill) ax.text(x + box_w/2, y + box_h/2, text, ha='center', va='center', fontsize=7) if i < len(steps) - 1: next_x = steps[i+1][0] draw_arrow(ax, x + box_w + 0.02, y + box_h/2, next_x - 0.02, y + box_h/2) # Annotations below annotations = [ (0.3 + box_w/2, 'pixel[x+1]-pixel[x-1]'), (2.1 + box_w/2, 'magnitude + direction'), (3.9 + box_w/2, '9 binów (0°-180°)'), (5.7 + box_w/2, 'L2-normalizacja'), (7.5 + box_w/2, 'wejście do SVM'), (9.0 + box_w/2, 'hiperpłaszczyzna'), ] for x, text in annotations: ax.text(x, y - 0.15, text, ha='center', fontsize=5.5, color='#666666', style='italic') # Title annotations ax.text(1.05, y + box_h + 0.15, '① Gradient', ha='center', fontsize=7, fontweight='bold') ax.text(2.85, y + box_h + 0.15, '② Histogram', ha='center', fontsize=7, fontweight='bold') ax.text(4.65, y + box_h + 0.15, '③ Normalize', ha='center', fontsize=7, fontweight='bold') ax.text(6.45, y + box_h + 0.15, '④ Feature vec', ha='center', fontsize=7, fontweight='bold') ax.text(8.1, y + box_h + 0.15, '⑤ Classify', ha='center', fontsize=7, fontweight='bold') plt.tight_layout() plt.savefig(os.path.join(OUTPUT_DIR, 'hog_svm_pipeline.png'), dpi=DPI, bbox_inches='tight', facecolor=BG) plt.close() print(" ✓ hog_svm_pipeline.png") # ============================================================ # PYTANIE 24: R-CNN Evolution # ============================================================ def draw_rcnn_evolution(): fig, ax = plt.subplots(1, 1, figsize=(8.27, 5)) ax.set_xlim(0, 10) ax.set_ylim(0, 7) ax.axis('off') ax.set_title('Ewolucja detektorów: R-CNN → Fast R-CNN → Faster R-CNN → YOLO', fontsize=10, fontweight='bold', pad=10) models = [ { 'name': 'R-CNN (2014)', 'y': 5.3, 'steps': ['Selective\nSearch', '2000×\nCNN', '2000×\nSVM', 'NMS'], 'speed': '~50 sec/img', 'fill': GRAY4, }, { 'name': 'Fast R-CNN (2015)', 'y': 3.7, 'steps': ['Selective\nSearch', 'CNN\n(1× cały)', 'ROI\nPooling', 'FC + NMS'], 'speed': '~2 sec/img', 'fill': GRAY2, }, { 'name': 'Faster R-CNN (2015)', 'y': 2.1, 'steps': ['CNN\nbackbone', 'RPN\n(proposals)', 'ROI\nPooling', 'FC + NMS'], 'speed': '~0.2 sec (5 fps)', 'fill': GRAY1, }, { 'name': 'YOLO (2016)', 'y': 0.5, 'steps': ['CNN\nbackbone', 'Siatka\nS×S', 'bbox+klasa\nper komórka', 'NMS'], 'speed': '~7-22 ms (45-155 fps)', 'fill': GRAY3, }, ] for model in models: y = model['y'] ax.text(0.2, y + 0.4, model['name'], fontsize=8, fontweight='bold', va='center') ax.text(0.2, y + 0.05, model['speed'], fontsize=6, va='center', color='#666666') bw = 1.5 bh = 0.8 for i, step in enumerate(model['steps']): x = 2.5 + i * 1.9 draw_box(ax, x, y, bw, bh, step, fill=model['fill'], fontsize=6.5) if i < len(model['steps']) - 1: draw_arrow(ax, x + bw + 0.02, y + bh/2, x + 1.9 - 0.02, y + bh/2, lw=0.8) # Speed improvement arrow on right ax.annotate("", xy=(9.5, 5.7), xytext=(9.5, 0.9), arrowprops=dict(arrowstyle='<->', color='#555555', lw=1.5)) ax.text(9.7, 3.3, '250×\nszybciej!', fontsize=8, fontweight='bold', ha='center', va='center', rotation=90, color='#555555') plt.tight_layout() plt.savefig(os.path.join(OUTPUT_DIR, 'rcnn_evolution.png'), dpi=DPI, bbox_inches='tight', facecolor=BG) plt.close() print(" ✓ rcnn_evolution.png") # ============================================================ # PYTANIE 23: Segmentation types comparison # ============================================================ def draw_segmentation_types(): fig, axes = plt.subplots(1, 4, figsize=(8.27, 2.5)) fig.suptitle('Typy segmentacji obrazu', fontsize=FS_TITLE, fontweight='bold', y=1.02) titles = ['Obraz wejściowy', 'Semantic\nSegmentation', 'Instance\nSegmentation', 'Panoptic\nSegmentation'] for ax, title in zip(axes, titles): ax.set_xlim(0, 6) ax.set_ylim(0, 6) ax.set_aspect('equal') ax.axis('off') ax.set_title(title, fontsize=8, fontweight='bold', pad=5) # Image: sky (top), two cars (bottom), road # Semantic: all sky=one color, all cars=one color, road=one color # Instance: sky=one, car1=distinct, car2=distinct, road=one # Panoptic: both # Original image (stylized) ax = axes[0] ax.add_patch(mpatches.Rectangle((0, 4), 6, 2, facecolor='#DDDDDD', edgecolor=LN, lw=0.5)) # sky ax.text(3, 5, 'niebo', ha='center', va='center', fontsize=7) ax.add_patch(mpatches.Rectangle((0, 0), 6, 2.5, facecolor='#AAAAAA', edgecolor=LN, lw=0.5)) # road ax.text(3, 1, 'droga', ha='center', va='center', fontsize=7) ax.add_patch(mpatches.Rectangle((0.5, 2), 2, 1.5, facecolor='#888888', edgecolor=LN, lw=0.8)) # car1 ax.text(1.5, 2.75, 'auto', ha='center', va='center', fontsize=7, color='white') ax.add_patch(mpatches.Rectangle((3.5, 2), 2, 1.5, facecolor='#666666', edgecolor=LN, lw=0.8)) # car2 ax.text(4.5, 2.75, 'auto', ha='center', va='center', fontsize=7, color='white') # Semantic: same label for both cars ax = axes[1] ax.add_patch(mpatches.Rectangle((0, 4), 6, 2, facecolor='#E8E8E8', edgecolor=LN, lw=0.5)) ax.text(3, 5, 'niebo', ha='center', va='center', fontsize=7) ax.add_patch(mpatches.Rectangle((0, 0), 6, 2.5, facecolor='#C8C8C8', edgecolor=LN, lw=0.5)) ax.text(3, 1, 'droga', ha='center', va='center', fontsize=7) ax.add_patch(mpatches.Rectangle((0.5, 2), 2, 1.5, facecolor='#888888', edgecolor=LN, lw=0.8)) ax.text(1.5, 2.75, 'auto', ha='center', va='center', fontsize=6, color='white') ax.add_patch(mpatches.Rectangle((3.5, 2), 2, 1.5, facecolor='#888888', edgecolor=LN, lw=0.8)) ax.text(4.5, 2.75, 'auto', ha='center', va='center', fontsize=6, color='white') ax.text(3, -0.3, 'te same etykiety!', ha='center', fontsize=6, color='#555555', style='italic') # Instance: different labels for cars ax = axes[2] ax.add_patch(mpatches.Rectangle((0, 4), 6, 2, facecolor='#E8E8E8', edgecolor=LN, lw=0.5)) ax.text(3, 5, '—', ha='center', va='center', fontsize=7, color='#999999') ax.add_patch(mpatches.Rectangle((0, 0), 6, 2.5, facecolor='#E8E8E8', edgecolor=LN, lw=0.5)) ax.text(3, 1, '—', ha='center', va='center', fontsize=7, color='#999999') ax.add_patch(mpatches.Rectangle((0.5, 2), 2, 1.5, facecolor='#888888', edgecolor=LN, lw=0.8)) ax.text(1.5, 2.75, 'auto#1', ha='center', va='center', fontsize=6, color='white') ax.add_patch(mpatches.Rectangle((3.5, 2), 2, 1.5, facecolor='#555555', edgecolor=LN, lw=0.8)) ax.text(4.5, 2.75, 'auto#2', ha='center', va='center', fontsize=6, color='white') ax.text(3, -0.3, 'RÓŻNE instancje!', ha='center', fontsize=6, color='#555555', style='italic') # Panoptic: both semantic labels AND instance IDs ax = axes[3] ax.add_patch(mpatches.Rectangle((0, 4), 6, 2, facecolor='#E8E8E8', edgecolor=LN, lw=0.5)) ax.text(3, 5, 'niebo (stuff)', ha='center', va='center', fontsize=6) ax.add_patch(mpatches.Rectangle((0, 0), 6, 2.5, facecolor='#C8C8C8', edgecolor=LN, lw=0.5)) ax.text(3, 1, 'droga (stuff)', ha='center', va='center', fontsize=6) ax.add_patch(mpatches.Rectangle((0.5, 2), 2, 1.5, facecolor='#888888', edgecolor=LN, lw=0.8)) ax.text(1.5, 2.75, 'auto#1\n(thing)', ha='center', va='center', fontsize=5.5, color='white') ax.add_patch(mpatches.Rectangle((3.5, 2), 2, 1.5, facecolor='#555555', edgecolor=LN, lw=0.8)) ax.text(4.5, 2.75, 'auto#2\n(thing)', ha='center', va='center', fontsize=5.5, color='white') ax.text(3, -0.3, 'klasy + instancje!', ha='center', fontsize=6, color='#555555', style='italic') plt.tight_layout() plt.savefig(os.path.join(OUTPUT_DIR, 'segmentation_types.png'), dpi=DPI, bbox_inches='tight', facecolor=BG) plt.close() print(" ✓ segmentation_types.png") # ============================================================ # PYTANIE 32: FSD and SSD visualization # ============================================================ def draw_fsd_ssd(): fig, axes = plt.subplots(1, 2, figsize=(8.27, 3.5)) fig.suptitle('Dominacja stochastyczna — FSD i SSD', fontsize=FS_TITLE, fontweight='bold', y=1.02) # FSD: CDF comparison ax = axes[0] ax.set_title('FSD: F_A(x) ≤ F_B(x) ∀x', fontsize=9, fontweight='bold') x = np.linspace(-2, 6, 200) # A ~ shifted right (better), B ~ shifted left from scipy.stats import norm F_A = norm.cdf(x, loc=2.5, scale=1.0) F_B = norm.cdf(x, loc=1.5, scale=1.0) ax.plot(x, F_A, 'k-', lw=2, label='F_A (lepsza — niżej)') ax.plot(x, F_B, 'k--', lw=2, label='F_B (gorsza — wyżej)') ax.fill_between(x, F_A, F_B, alpha=0.15, color='gray') ax.set_xlabel('x (wynik)', fontsize=8) ax.set_ylabel('F(x) = P(X ≤ x)', fontsize=8) ax.legend(fontsize=7, loc='lower right') ax.text(0, 0.8, 'A ≥_FSD B\nF_A zawsze pod F_B\n→ KAŻDY racjonalny\n wybierze A', fontsize=7, bbox=dict(boxstyle='round', facecolor=GRAY4)) ax.grid(True, alpha=0.3) ax.tick_params(labelsize=7) # SSD: CDFs can cross, but integral is less ax = axes[1] ax.set_title('SSD: ∫F_A ≤ ∫F_B ∀x (CDFs mogą się krzyżować)', fontsize=9, fontweight='bold') F_A2 = norm.cdf(x, loc=2.0, scale=0.8) F_B2 = norm.cdf(x, loc=2.0, scale=1.5) # same mean, more spread ax.plot(x, F_A2, 'k-', lw=2, label='F_A (mniej ryzyka)') ax.plot(x, F_B2, 'k--', lw=2, label='F_B (więcej ryzyka)') ax.fill_between(x, F_A2, F_B2, where=F_A2 < F_B2, alpha=0.15, color='gray') ax.fill_between(x, F_A2, F_B2, where=F_A2 >= F_B2, alpha=0.08, color='gray', hatch='///') ax.set_xlabel('x (wynik)', fontsize=8) ax.set_ylabel('F(x)', fontsize=8) ax.legend(fontsize=7, loc='lower right') ax.text(-1.5, 0.75, 'A ≥_SSD B\nCDFs się krzyżują,\nale ∫F_A ≤ ∫F_B\n→ risk-averse\n wybierze A', fontsize=7, bbox=dict(boxstyle='round', facecolor=GRAY4)) ax.grid(True, alpha=0.3) ax.tick_params(labelsize=7) plt.tight_layout() plt.savefig(os.path.join(OUTPUT_DIR, 'fsd_ssd_comparison.png'), dpi=DPI, bbox_inches='tight', facecolor=BG) plt.close() print(" ✓ fsd_ssd_comparison.png") # ============================================================ # Main # ============================================================ if __name__ == '__main__': print("Generating study diagrams...") draw_network_models() draw_vector_clock_timeline() draw_linearizability_vs_sequential() draw_paxos_flow() draw_hog_pipeline() draw_rcnn_evolution() draw_segmentation_types() draw_fsd_ssd() print(f"\nAll diagrams saved to {OUTPUT_DIR}/")