Spaces:
Sleeping
Sleeping
| """ | |
| Atomic VSA Interactive Demo | |
| A Gradio-based demonstration of Vector Symbolic Architecture for clinical triage. | |
| """ | |
| import gradio as gr | |
| import numpy as np | |
| from typing import Dict, List, Tuple | |
| # ============================================================================ | |
| # VSA Core Implementation (Python port of Julia logic) | |
| # ============================================================================ | |
| D = 2048 # Dimensionality for demo (production uses 10,048) | |
| np.random.seed(42) | |
| class AtomRegistry: | |
| """Registry of atomic vectors (symbols).""" | |
| def __init__(self, dim: int = D): | |
| self.dim = dim | |
| self.atoms: Dict[str, np.ndarray] = {} | |
| def get_or_create(self, name: str) -> np.ndarray: | |
| if name not in self.atoms: | |
| # Create bipolar random vector {-1, +1}^D | |
| self.atoms[name] = np.random.choice([-1, 1], size=self.dim).astype(np.float32) | |
| return self.atoms[name] | |
| def __getitem__(self, name: str) -> np.ndarray: | |
| return self.get_or_create(name) | |
| # Global registry | |
| registry = AtomRegistry() | |
| def bind(a: np.ndarray, b: np.ndarray) -> np.ndarray: | |
| """BIND operation: Element-wise multiplication (⊗).""" | |
| return a * b | |
| def bundle(vectors: List[np.ndarray]) -> np.ndarray: | |
| """BUNDLE operation: Element-wise addition (⊕).""" | |
| return np.sum(vectors, axis=0) | |
| def similarity(a: np.ndarray, b: np.ndarray) -> float: | |
| """Cosine similarity between vectors.""" | |
| norm_a = np.linalg.norm(a) | |
| norm_b = np.linalg.norm(b) | |
| if norm_a == 0 or norm_b == 0: | |
| return 0.0 | |
| return float(np.dot(a, b) / (norm_a * norm_b)) | |
| def thermometer_encode(value: float, min_val: float, max_val: float, levels: int = 20) -> np.ndarray: | |
| """Thermometer encoding for continuous values.""" | |
| level_atoms = [registry.get_or_create(f"_level_{i}") for i in range(levels)] | |
| active_levels = int((value - min_val) / (max_val - min_val) * levels) | |
| active_levels = max(0, min(levels, active_levels)) | |
| if active_levels == 0: | |
| return np.zeros(D, dtype=np.float32) | |
| return bundle(level_atoms[:active_levels]) | |
| # ============================================================================ | |
| # Clinical Triage System | |
| # ============================================================================ | |
| SYMPTOMS = [ | |
| "chest_pain", "shortness_of_breath", "fever", "cough", | |
| "headache", "fatigue", "nausea", "dizziness", | |
| "abdominal_pain", "back_pain", "joint_pain", "rash", | |
| "sore_throat", "runny_nose", "muscle_ache", "chills" | |
| ] | |
| TRIAGE_CATEGORIES = { | |
| "Emergency - Cardiac": ["chest_pain", "shortness_of_breath", "dizziness"], | |
| "Urgent - Respiratory": ["shortness_of_breath", "cough", "fever", "chills"], | |
| "Urgent - Infection": ["fever", "chills", "fatigue", "muscle_ache"], | |
| "Standard - Flu-like": ["fever", "cough", "sore_throat", "runny_nose", "muscle_ache"], | |
| "Standard - GI": ["nausea", "abdominal_pain", "fever"], | |
| "Standard - Musculoskeletal": ["back_pain", "joint_pain", "muscle_ache"], | |
| "Low Priority - Minor": ["headache", "fatigue", "runny_nose"], | |
| } | |
| # Pre-build prototype vectors for each triage category | |
| PROTOTYPES: Dict[str, np.ndarray] = {} | |
| for category, symptom_list in TRIAGE_CATEGORIES.items(): | |
| molecules = [] | |
| for symptom in symptom_list: | |
| field_atom = registry[f"symptom_field"] | |
| value_atom = registry[symptom] | |
| molecules.append(bind(field_atom, value_atom)) | |
| PROTOTYPES[category] = bundle(molecules) | |
| def create_patient_vector(symptoms: List[str], vitals: Dict[str, float]) -> np.ndarray: | |
| """Create a patient record as a bundled molecule.""" | |
| molecules = [] | |
| # Encode symptoms | |
| for symptom in symptoms: | |
| if symptom in SYMPTOMS: | |
| field_atom = registry["symptom_field"] | |
| value_atom = registry[symptom] | |
| molecules.append(bind(field_atom, value_atom)) | |
| # Encode vitals with thermometer encoding | |
| if "heart_rate" in vitals: | |
| hr_encoded = thermometer_encode(vitals["heart_rate"], 40, 180) | |
| molecules.append(bind(registry["heart_rate_field"], hr_encoded)) | |
| if "temperature" in vitals: | |
| temp_encoded = thermometer_encode(vitals["temperature"], 35, 42) | |
| molecules.append(bind(registry["temperature_field"], temp_encoded)) | |
| if "blood_pressure_sys" in vitals: | |
| bp_encoded = thermometer_encode(vitals["blood_pressure_sys"], 80, 200) | |
| molecules.append(bind(registry["bp_field"], bp_encoded)) | |
| if not molecules: | |
| return np.zeros(D, dtype=np.float32) | |
| return bundle(molecules) | |
| def triage_patient(patient_vector: np.ndarray) -> List[Tuple[str, float]]: | |
| """Classify patient against triage prototypes.""" | |
| scores = [] | |
| for category, prototype in PROTOTYPES.items(): | |
| sim = similarity(patient_vector, prototype) | |
| scores.append((category, sim)) | |
| # Sort by similarity descending | |
| scores.sort(key=lambda x: x[1], reverse=True) | |
| return scores | |
| # ============================================================================ | |
| # Gradio Interface | |
| # ============================================================================ | |
| def process_triage( | |
| chest_pain: bool, shortness_of_breath: bool, fever: bool, cough: bool, | |
| headache: bool, fatigue: bool, nausea: bool, dizziness: bool, | |
| abdominal_pain: bool, back_pain: bool, joint_pain: bool, rash: bool, | |
| sore_throat: bool, runny_nose: bool, muscle_ache: bool, chills: bool, | |
| heart_rate: float, temperature: float, blood_pressure: float | |
| ) -> Tuple[str, str, str]: | |
| """Process symptoms and return triage classification.""" | |
| # Collect selected symptoms | |
| symptom_map = { | |
| "chest_pain": chest_pain, "shortness_of_breath": shortness_of_breath, | |
| "fever": fever, "cough": cough, "headache": headache, "fatigue": fatigue, | |
| "nausea": nausea, "dizziness": dizziness, "abdominal_pain": abdominal_pain, | |
| "back_pain": back_pain, "joint_pain": joint_pain, "rash": rash, | |
| "sore_throat": sore_throat, "runny_nose": runny_nose, | |
| "muscle_ache": muscle_ache, "chills": chills | |
| } | |
| selected_symptoms = [s for s, v in symptom_map.items() if v] | |
| if not selected_symptoms: | |
| return "No symptoms selected", "", "" | |
| # Create patient vector | |
| vitals = { | |
| "heart_rate": heart_rate, | |
| "temperature": temperature, | |
| "blood_pressure_sys": blood_pressure | |
| } | |
| patient_vec = create_patient_vector(selected_symptoms, vitals) | |
| # Get triage scores | |
| scores = triage_patient(patient_vec) | |
| # Format results | |
| primary = scores[0] | |
| primary_result = f"**{primary[0]}**\nSimilarity: {primary[1]:.4f}" | |
| # All scores | |
| all_scores = "\n".join([f"{cat}: {sim:.4f}" for cat, sim in scores]) | |
| # Explanation | |
| explanation = f""" | |
| **VSA Explanation:** | |
| - Patient encoded as {D}-dimensional bipolar vector | |
| - Symptoms: {', '.join(selected_symptoms)} | |
| - Heart Rate: {heart_rate} bpm → Thermometer encoded | |
| - Temperature: {temperature}°C → Thermometer encoded | |
| - Blood Pressure: {blood_pressure} mmHg → Thermometer encoded | |
| **How it works:** | |
| 1. Each symptom is BOUND (⊗) with a field identifier | |
| 2. All bound pairs are BUNDLED (⊕) into a superposition | |
| 3. Cosine similarity computed against {len(PROTOTYPES)} prototypes | |
| 4. Classification is deterministic and fully explainable | |
| """ | |
| return primary_result, all_scores, explanation | |
| def demo_bind_operation(concept_a: str, concept_b: str) -> str: | |
| """Demonstrate BIND operation.""" | |
| if not concept_a or not concept_b: | |
| return "Enter two concepts" | |
| vec_a = registry[concept_a] | |
| vec_b = registry[concept_b] | |
| bound = bind(vec_a, vec_b) | |
| # Verify self-inverse property | |
| unbound = bind(bound, vec_b) | |
| recovery_sim = similarity(unbound, vec_a) | |
| return f""" | |
| **BIND Operation: {concept_a} ⊗ {concept_b}** | |
| Vector A (first 10 dims): {vec_a[:10].astype(int).tolist()} | |
| Vector B (first 10 dims): {vec_b[:10].astype(int).tolist()} | |
| Bound (first 10 dims): {bound[:10].astype(int).tolist()} | |
| **Self-Inverse Property:** | |
| (A ⊗ B) ⊗ B = A | |
| Recovery similarity: {recovery_sim:.6f} (should be 1.0) | |
| **Orthogonality:** | |
| Sim(A, B): {similarity(vec_a, vec_b):.4f} (random vectors ≈ 0) | |
| Sim(A, Bound): {similarity(vec_a, bound):.4f} (bound dissimilar to inputs) | |
| """ | |
| def demo_bundle_operation(concepts: str) -> str: | |
| """Demonstrate BUNDLE operation.""" | |
| if not concepts: | |
| return "Enter comma-separated concepts" | |
| concept_list = [c.strip() for c in concepts.split(",") if c.strip()] | |
| if len(concept_list) < 2: | |
| return "Enter at least 2 concepts" | |
| vectors = [registry[c] for c in concept_list] | |
| bundled = bundle(vectors) | |
| # Show similarity to each component | |
| sims = [(c, similarity(bundled, registry[c])) for c in concept_list] | |
| sim_report = "\n".join([f" Sim(Bundle, {c}): {s:.4f}" for c, s in sims]) | |
| return f""" | |
| **BUNDLE Operation: {' ⊕ '.join(concept_list)}** | |
| Bundled {len(concept_list)} vectors into superposition. | |
| **Holographic Property - Bundle is similar to ALL inputs:** | |
| {sim_report} | |
| Unlike classical storage, the bundle simultaneously represents | |
| all {len(concept_list)} concepts in the same {D}-dimensional space! | |
| """ | |
| # Build the Gradio app | |
| with gr.Blocks(title="Atomic VSA Demo", theme=gr.themes.Soft()) as demo: | |
| gr.Markdown(""" | |
| # ⚛️ Atomic VSA: Interactive Demo | |
| **Physics-Inspired Hyperdimensional Computing for Explainable Clinical AI** | |
| [](https://doi.org/10.5281/zenodo.18650281) | |
| [](https://github.com/muhammadarshad/atomic-vsa-research) | |
| This demo showcases the Atomic Vector Symbolic Architecture (Atomic VSA) — | |
| a deterministic, interpretable AI framework achieving **92.5% F1** on clinical triage. | |
| """) | |
| with gr.Tabs(): | |
| # Tab 1: Clinical Triage Demo | |
| with gr.TabItem("🏥 Clinical Triage"): | |
| gr.Markdown("### Enter Patient Symptoms & Vitals") | |
| with gr.Row(): | |
| with gr.Column(): | |
| gr.Markdown("**Symptoms:**") | |
| chest_pain = gr.Checkbox(label="Chest Pain") | |
| shortness_of_breath = gr.Checkbox(label="Shortness of Breath") | |
| fever = gr.Checkbox(label="Fever") | |
| cough = gr.Checkbox(label="Cough") | |
| headache = gr.Checkbox(label="Headache") | |
| fatigue = gr.Checkbox(label="Fatigue") | |
| nausea = gr.Checkbox(label="Nausea") | |
| dizziness = gr.Checkbox(label="Dizziness") | |
| with gr.Column(): | |
| gr.Markdown("**More Symptoms:**") | |
| abdominal_pain = gr.Checkbox(label="Abdominal Pain") | |
| back_pain = gr.Checkbox(label="Back Pain") | |
| joint_pain = gr.Checkbox(label="Joint Pain") | |
| rash = gr.Checkbox(label="Rash") | |
| sore_throat = gr.Checkbox(label="Sore Throat") | |
| runny_nose = gr.Checkbox(label="Runny Nose") | |
| muscle_ache = gr.Checkbox(label="Muscle Ache") | |
| chills = gr.Checkbox(label="Chills") | |
| with gr.Column(): | |
| gr.Markdown("**Vitals:**") | |
| heart_rate = gr.Slider(40, 180, value=75, label="Heart Rate (bpm)") | |
| temperature = gr.Slider(35.0, 42.0, value=37.0, step=0.1, label="Temperature (°C)") | |
| blood_pressure = gr.Slider(80, 200, value=120, label="Systolic BP (mmHg)") | |
| triage_btn = gr.Button("🔬 Run Triage", variant="primary") | |
| with gr.Row(): | |
| primary_output = gr.Markdown(label="Primary Classification") | |
| scores_output = gr.Textbox(label="All Scores", lines=7) | |
| explanation_output = gr.Markdown(label="VSA Explanation") | |
| triage_btn.click( | |
| process_triage, | |
| inputs=[ | |
| chest_pain, shortness_of_breath, fever, cough, | |
| headache, fatigue, nausea, dizziness, | |
| abdominal_pain, back_pain, joint_pain, rash, | |
| sore_throat, runny_nose, muscle_ache, chills, | |
| heart_rate, temperature, blood_pressure | |
| ], | |
| outputs=[primary_output, scores_output, explanation_output] | |
| ) | |
| # Tab 2: VSA Operations | |
| with gr.TabItem("🧮 VSA Operations"): | |
| gr.Markdown(""" | |
| ### Explore the Algebraic Operations | |
| Atomic VSA uses two fundamental operations: | |
| - **BIND (⊗)**: Creates relational structures (self-inverse) | |
| - **BUNDLE (⊕)**: Creates holographic superpositions | |
| """) | |
| with gr.Row(): | |
| with gr.Column(): | |
| gr.Markdown("#### BIND Operation") | |
| bind_a = gr.Textbox(label="Concept A", value="HeartRate") | |
| bind_b = gr.Textbox(label="Concept B", value="115bpm") | |
| bind_btn = gr.Button("Compute BIND") | |
| bind_output = gr.Markdown() | |
| bind_btn.click(demo_bind_operation, [bind_a, bind_b], bind_output) | |
| with gr.Column(): | |
| gr.Markdown("#### BUNDLE Operation") | |
| bundle_input = gr.Textbox( | |
| label="Concepts (comma-separated)", | |
| value="fever, cough, fatigue" | |
| ) | |
| bundle_btn = gr.Button("Compute BUNDLE") | |
| bundle_output = gr.Markdown() | |
| bundle_btn.click(demo_bundle_operation, [bundle_input], bundle_output) | |
| # Tab 3: About | |
| with gr.TabItem("📄 About"): | |
| gr.Markdown(""" | |
| ## Atomic Vector Symbolic Architecture | |
| ### Key Innovation | |
| Atomic VSA applies **physics-inspired principles** to hyperdimensional computing: | |
| | Physics | Computing (AVSA) | Clinical Medicine | | |
| |---------|------------------|-------------------| | |
| | Atom | 10,048-dim vector | Semantic concept | | |
| | Proton (+) | Positive evidence | Finding FOR diagnosis | | |
| | Electron (−) | Negative evidence | Finding AGAINST diagnosis | | |
| | Molecule | BIND(a ⊗ b) | Clinical fact pair | | |
| | Superposition | BUNDLE(⊕) | Patient record | | |
| ### Performance | |
| | Metric | Result | | |
| |--------|--------| | |
| | F1 Score | 92.5% (25-category ICD-11) | | |
| | Label Recall | 91.9% (comorbidity) | | |
| | Latency | 11.97ms (p50) | | |
| | Power | 15W (edge) | | |
| ### Why VSA? | |
| - ✅ **Deterministic**: Same input → same output, always | |
| - ✅ **Interpretable**: Algebraic operations are transparent | |
| - ✅ **Efficient**: No training, no GPU required | |
| - ✅ **Green AI**: 160× lower power than neural networks | |
| ### Links | |
| - **Paper (DOI)**: [10.5281/zenodo.18650281](https://doi.org/10.5281/zenodo.18650281) | |
| - **Code**: [GitHub](https://github.com/muhammadarshad/atomic-vsa-research) | |
| - **Author**: Muhammad Arshad (marshad.dev@gmail.com) | |
| """) | |
| if __name__ == "__main__": | |
| demo.launch() | |