import numpy as np import pandas as pd import os import sys import time from datetime import datetime import json import gc import signal import multiprocessing from multiprocessing import Pool, cpu_count from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor import psutil # Import bibliotek kwantowych from qiskit import Aer from qiskit.circuit.library import ZZFeatureMap, PauliFeatureMap, EfficientSU2 from qiskit_machine_learning.kernels import QuantumKernel from qiskit_machine_learning.algorithms import QSVC import dimod # Dodanie zalecanego zamiennika dla ZZFeatureMap from qiskit.circuit import QuantumCircuit, Parameter from qiskit.circuit.library.data_preparation import ZFeatureMap # Dodanie bibliotek do kodowania amplitudowego from qiskit.circuit import QuantumCircuit from qiskit.extensions import Initialize import scipy.linalg as la # Dodanie biblioteki UMAP import umap # Maksymalny czas trwania eksperymentu MAX_EXECUTION_TIME = 24 * 60 * 60 * 7 * 3 def timeout_handler(signum, frame): print("\n\n======= PRZEKROCZONO MAKSYMALNY CZAS WYKONANIA =======") print(f"Eksperyment został przerwany po {MAX_EXECUTION_TIME/3600:.1f} godzinach.") sys.exit(1) # Ustawienie obsługi sygnału signal.signal(signal.SIGALRM, timeout_handler) signal.alarm(MAX_EXECUTION_TIME) # ----------------- CZĘŚĆ 0: PARAMETRY KONFIGURACYJNE OPTYMALIZOWANE DLA VAST.AI ----------------- # Parametry danych DATA_FILES = [ 'dane/TCGA_GBM_LGG_Mutations_clean.csv', 'dane/TCGA_GBM_LGG_Mutations_noise_1percent_added.csv', 'dane/TCGA_GBM_LGG_Mutations_noise_5percent_added.csv', 'dane/TCGA_GBM_LGG_Mutations_noise_10percent_added.csv', 'dane/TCGA_GBM_LGG_Mutations_noise_15percent_added.csv', 'dane/TCGA_GBM_LGG_Mutations_noise_20percent_added.csv', 'dane/TCGA_GBM_LGG_Mutations_noise_1percent_substituted.csv', 'dane/TCGA_GBM_LGG_Mutations_noise_5percent_substituted.csv', 'dane/TCGA_GBM_LGG_Mutations_noise_10percent_substituted.csv', 'dane/TCGA_GBM_LGG_Mutations_noise_15percent_substituted.csv', 'dane/TCGA_GBM_LGG_Mutations_noise_20percent_substituted.csv' ] TEST_SIZE = 0.3 RANDOM_STATE = 42 # Parametry redukcji wymiarowości USE_PCA = True USE_TSNE = False USE_UMAP = False PCA_COMPONENTS = 12 TSNE_COMPONENTS = 3 TSNE_PERPLEXITY = 100 TSNE_LEARNING_RATE = 50 TSNE_MAX_ITER = 1000 UMAP_COMPONENTS = 14 UMAP_NEIGHBORS = 15 UMAP_MIN_DIST = 0.8 UMAP_METRIC = 'euclidean' EVALUATE_SILHOUETTE = False OPTIMAL_SILHOUETTE_SCORE = 0.1964 # Wybór eksperymentów do przeprowadzenia RUN_CLASSIC_SVM = False RUN_QUANTUM_SVM = True RUN_HYBRID_APPROACH = False # Parametry klasycznego SVM - OPTYMALIZOWANE DLA WIELU RDZENI SVM_PARAM_GRID = { 'C': [0.1, 1, 10, 100], 'gamma': ['scale', 'auto', 0.1, 0.01], 'kernel': ['linear', 'rbf', 'poly'] } SVM_CV = 5 # Parametry kwantowego SVM BACKEND_NAME = 'qasm_simulator' C_VALUES = [0.1, 1.0, 10.0] QSVM_CV = 10 # Parametry wyżarzania kwantowego NUM_READS = 100 QUBO_PENALTY = 10.0 # Parametry analizy cech IMPORTANCE_THRESHOLD = 0.01 # Parametry wyjściowe OUTPUT_DIR = f'wyniki/2025-08-30-2-{QSVM_CV}-fold-zFeature' # Parametry IBM Quantum Cloud USE_IBM_QUANTUM = False IBM_BACKEND = 'qasm_simulator' IBM_REAL_BACKEND = 'qasm_simulator' IBM_TOKEN = None IBM_INSTANCE = None IBM_MAX_SHOTS = 1024 IBM_OPTIMIZATION_LEVEL = 1 IBM_RESILIENCE_LEVEL = 1 # BEZPIECZNE OPTYMALIZACJE DLA VAST.AI - Z OGRANICZENIAMI def get_optimal_cpu_config(): total_cores = cpu_count() available_memory = psutil.virtual_memory().total / (1024**3) # GB print(f"=== KONFIGURACJA SYSTEMU ===") print(f"Liczba rdzeni CPU: {total_cores}") print(f"Dostępna pamięć RAM: {available_memory:.1f} GB") # BEZPIECZNA konfiguracja - maksymalnie 70% rdzeni safe_cores = int(total_cores * 0.7) if total_cores >= 200: # BEZPIECZNA konfiguracja dla 255 rdzeni n_jobs_kernel = min(30, safe_cores // 4) # 15% rdzeni dla obliczeń jądra n_jobs_svm = min(20, safe_cores // 6) # 10% rdzeni dla SVM n_jobs_parallel = min(15, safe_cores // 8) # 7% rdzeni dla równoległości print(f"Konfiguracja: BEZPIECZNA (200+ rdzeni) - OGRANICZONE WYKORZYSTANIE") print(f"Bezpieczne wykorzystanie: {n_jobs_kernel + n_jobs_svm + n_jobs_parallel}/{total_cores} rdzeni ({((n_jobs_kernel + n_jobs_svm + n_jobs_parallel)/total_cores)*100:.1f}%)") elif total_cores >= 100: # Bezpieczna konfiguracja (100-199 rdzeni) n_jobs_kernel = min(25, safe_cores // 3) n_jobs_svm = min(15, safe_cores // 5) n_jobs_parallel = min(10, safe_cores // 7) print(f"Konfiguracja: BEZPIECZNA (100+ rdzeni)") elif total_cores >= 40: # Bezpieczna konfiguracja (40-99 rdzeni) n_jobs_kernel = min(15, safe_cores // 3) n_jobs_svm = min(8, safe_cores // 5) n_jobs_parallel = min(6, safe_cores // 7) print(f"Konfiguracja: BEZPIECZNA (40+ rdzeni)") elif total_cores >= 32: # Bezpieczna konfiguracja (32-39 rdzeni) n_jobs_kernel = min(12, safe_cores // 3) n_jobs_svm = min(6, safe_cores // 5) n_jobs_parallel = min(4, safe_cores // 8) print(f"Konfiguracja: BEZPIECZNA (32+ rdzeni)") elif total_cores >= 16: # Bezpieczna konfiguracja (16-31 rdzeni) n_jobs_kernel = min(8, safe_cores // 3) n_jobs_svm = min(4, safe_cores // 4) n_jobs_parallel = min(3, safe_cores // 5) print(f"Konfiguracja: BEZPIECZNA (16+ rdzeni)") else: # Bezpieczna konfiguracja (<16 rdzeni) n_jobs_kernel = min(4, safe_cores // 3) n_jobs_svm = min(2, safe_cores // 4) n_jobs_parallel = min(2, safe_cores // 4) print(f"Konfiguracja: BEZPIECZNA (<16 rdzeni)") print(f"n_jobs_kernel: {n_jobs_kernel}") print(f"n_jobs_svm: {n_jobs_svm}") print(f"n_jobs_parallel: {n_jobs_parallel}") print(f"Bezpieczne wykorzystanie: {n_jobs_kernel + n_jobs_svm + n_jobs_parallel}/{total_cores} rdzeni") return { 'n_jobs_kernel': n_jobs_kernel, 'n_jobs_svm': n_jobs_svm, 'n_jobs_parallel': n_jobs_parallel, 'total_cores': total_cores, 'available_memory': available_memory } # Pobierz optymalną konfigurację CPU_CONFIG = get_optimal_cpu_config() # BEZPIECZNA OPTYMALIZACJA PAMIĘCI DLA VAST.AI def optimize_memory_for_large_system(): memory_gb = CPU_CONFIG['available_memory'] if memory_gb >= 200: print(f"BEZPIECZNA OPTYMALIZACJA PAMIĘCI: {memory_gb:.1f} GB") # Bezpieczne ustawienia dla dużych macierzy import numpy as np np.set_printoptions(precision=4, suppress=True) # Częstsze garbage collection dla bezpieczeństwa import gc gc.set_threshold(700, 10, 10) # Częstsze GC print("Pamięć zoptymalizowana bezpiecznie") else: print(f"Pamięć: {memory_gb:.1f} GB - standardowa optymalizacja") # Dodaj monitoring pamięci start_memory_monitoring() # Dodaj funkcje timeout i monitoring def timeout(seconds): def decorator(func): import functools @functools.wraps(func) def wrapper(*args, **kwargs): def handler(signum, frame): raise TimeoutError(f"Funkcja {func.__name__} przekroczyła limit {seconds}s") signal.signal(signal.SIGALRM, handler) signal.alarm(seconds) try: result = func(*args, **kwargs) finally: signal.alarm(0) return result return wrapper return decorator def start_memory_monitoring(): import threading def monitor_resources(): while True: try: cpu_percent = psutil.cpu_percent(interval=1) memory_percent = psutil.virtual_memory().percent if cpu_percent > 95 or memory_percent > 90: print(f"WYSOKIE WYKORZYSTANIE - CPU: {cpu_percent}%, RAM: {memory_percent}%") time.sleep(30) except Exception as e: print(f"Błąd monitoringu: {e}") time.sleep(60) # Uruchom monitoring w tle monitor_thread = threading.Thread(target=monitor_resources, daemon=True) monitor_thread.start() print("Monitoring zasobów uruchomiony") # Uruchom optymalizację pamięci optimize_memory_for_large_system() # Upewnij się, że katalog wyjściowy istnieje if not os.path.exists(OUTPUT_DIR): os.makedirs(OUTPUT_DIR) # Upewnij się, że katalog cache istnieje CACHE_DIR = 'cache' if not os.path.exists(CACHE_DIR): os.makedirs(CACHE_DIR) print(f"Utworzono katalog cache: {CACHE_DIR}") # ZAAWANSOWANY SYSTEM LOGOWANIA class Logger: def __init__(self, filename): self.terminal = sys.stdout self.log = open(filename, 'w', encoding='utf-8') self.start_time = time.time() def write(self, message): # Dodaj timestamp do każdego komunikatu timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") formatted_message = f"[{timestamp}] {message}" self.terminal.write(formatted_message) self.log.write(formatted_message) self.log.flush() def flush(self): self.terminal.flush() self.log.flush() def close(self): self.log.close() # FUNKCJA DO LOGOWANIA Z TIMESTAMPEM def log_message(message, level="INFO"): timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") formatted_message = f"[{timestamp}] [{level}] {message}\n" # Wyświetl w konsoli sys.stdout.write(formatted_message) sys.stdout.flush() # Zapisz do pliku log try: with open('qsvm_experiments.log', 'a', encoding='utf-8') as f: f.write(formatted_message) f.flush() except Exception as e: print(f"Błąd zapisu do log: {e}") # FUNKCJA DO LOGOWANIA POSTĘPU def log_progress(current, total, description="Postęp"): percentage = (current / total) * 100 timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") message = f"[{timestamp}] [PROGRESS] {description}: {current}/{total} ({percentage:.1f}%)" sys.stdout.write(f"\r{message}") sys.stdout.flush() # Zapisz do pliku log try: with open('qsvm_experiments.log', 'a', encoding='utf-8') as f: f.write(message + "\n") f.flush() except Exception as e: print(f"Błąd zapisu do log: {e}") # FUNKCJA DO LOGOWANIA BŁĘDÓW def log_error(error_message, exception=None): timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") if exception: error_details = f"[{timestamp}] [ERROR] {error_message}\nException: {str(exception)}\nTraceback: {traceback.format_exc()}" else: error_details = f"[{timestamp}] [ERROR] {error_message}" # Wyświetl w konsoli sys.stderr.write(error_details + "\n") sys.stderr.flush() # Zapisz do pliku log try: with open('qsvm_experiments.log', 'a', encoding='utf-8') as f: f.write(error_details + "\n") f.flush() except Exception as e: print(f"Błąd zapisu do log: {e}") # FUNKCJA DO LOGOWANIA WYNIKÓW def log_results(results_dict, experiment_name): timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") message = f"[{timestamp}] [RESULTS] Eksperyment: {experiment_name}\n" for key, value in results_dict.items(): if isinstance(value, (int, float)): message += f" {key}: {value}\n" elif isinstance(value, dict): message += f" {key}: {json.dumps(value, indent=2)}\n" else: message += f" {key}: {str(value)}\n" # Wyświetl w konsoli sys.stdout.write(message) sys.stdout.flush() # Zapisz do pliku log try: with open('qsvm_experiments.log', 'a', encoding='utf-8') as f: f.write(message) f.flush() except Exception as e: print(f"Błąd zapisu do log: {e}") # IMPORT TRACEBACK DLA BŁĘDÓW import traceback # Funkcja do zapisywania szczegółowych metryk def save_metrics(y_true, y_pred, model_name): from sklearn.metrics import classification_report, confusion_matrix, roc_auc_score, accuracy_score, precision_score, recall_score, f1_score accuracy = accuracy_score(y_true, y_pred) precision = precision_score(y_true, y_pred, average='weighted', zero_division=0) recall = recall_score(y_true, y_pred, average='weighted', zero_division=0) f1 = f1_score(y_true, y_pred, average='weighted', zero_division=0) try: roc_auc = roc_auc_score(y_true, y_pred) except: roc_auc = "N/A" print(f"\nSzczegółowe metryki dla modelu {model_name}:") print(f"Accuracy: {accuracy:.4f}") print(f"Precision: {precision:.4f}") print(f"Recall: {recall:.4f}") print(f"F1 Score: {f1:.4f}") print(f"ROC AUC: {roc_auc}") cm = confusion_matrix(y_true, y_pred) print("\nMacierz pomyłek:") print(cm) return { 'accuracy': accuracy, 'precision': precision, 'recall': recall, 'f1': f1, 'roc_auc': roc_auc, 'confusion_matrix': cm.tolist() } # Funkcja do zapisywania wyników pośrednich def save_results_cache(results_dict, cache_file): cache_data = { 'timestamp': datetime.now().isoformat(), 'results': results_dict } with open(cache_file, 'w') as f: json.dump(cache_data, f, indent=2) log_message(f"Zapisano cache: {cache_file}", "CACHE") # Funkcja do wczytywania wyników pośrednich def load_results_cache(cache_file): if os.path.exists(cache_file): try: with open(cache_file, 'r') as f: cache_data = json.load(f) log_message(f"Wczytano cache z: {cache_file}", "CACHE") log_message(f"Timestamp: {cache_data.get('timestamp', 'N/A')}", "CACHE") return cache_data.get('results', {}) except Exception as e: log_error(f"Błąd wczytywania cache: {e}") return { 'quantum_results': [], 'quantum_times': {}, 'completed_feature_maps': [], 'hybrid_scores': {}, 'hybrid_eval_times': {}, 'classic_svm_results': {}, 'data_preparation_cache': {}, 'kernel_cache': {} } # FUNKCJE CACHE DLA JĄDRA KWANTOWEGO def get_kernel_cache_key(X1_shape, X2_shape, feature_map_name, shots): return f"kernel_{X1_shape[0]}x{X1_shape[1]}_{X2_shape[0]}x{X2_shape[1]}_{feature_map_name}_{shots}" def save_kernel_cache(kernel_matrix, cache_key, cache_dir=CACHE_DIR): if not os.path.exists(cache_dir): os.makedirs(cache_dir) cache_file = os.path.join(cache_dir, f"{cache_key}.npy") np.save(cache_file, kernel_matrix) log_message(f"Zapisano jądro do cache: {cache_file}", "CACHE") def load_kernel_cache(cache_key, cache_dir=CACHE_DIR): cache_file = os.path.join(cache_dir, f"{cache_key}.npy") if os.path.exists(cache_file): try: kernel_matrix = np.load(cache_file) log_message(f"Wczytano jądro z cache: {cache_file}", "CACHE") return kernel_matrix except Exception as e: log_error(f"Błąd wczytywania jądra z cache: {e}") return None # FUNKCJE CACHE DLA PRZYGOTOWANIA DANYCH def get_data_cache_key(data_file, test_size, random_state, pca_components): #Generuje klucz cache dla przygotowanych danych return f"data_{os.path.basename(data_file)}_{test_size}_{random_state}_{pca_components}" def save_data_cache(data_dict, cache_key, cache_dir=CACHE_DIR): if not os.path.exists(cache_dir): os.makedirs(cache_dir) cache_file = os.path.join(cache_dir, f"{cache_key}.npz") np.savez_compressed(cache_file, **data_dict) log_message(f"Zapisano dane do cache: {cache_file}", "CACHE") def load_data_cache(cache_key, cache_dir=CACHE_DIR): cache_file = os.path.join(cache_dir, f"{cache_key}.npz") if os.path.exists(cache_file): try: data = np.load(cache_file) data_dict = {key: data[key] for key in data.files} log_message(f"Wczytano dane z cache: {cache_file}", "CACHE") return data_dict except Exception as e: log_error(f"Błąd wczytywania danych z cache: {e}") return None # FUNKCJE CACHE DLA WYNIKÓW EKSPERYMENTÓW def save_experiment_cache(experiment_name, results, cache_dir=CACHE_DIR):" if not os.path.exists(cache_dir): os.makedirs(cache_dir) cache_file = os.path.join(cache_dir, f"experiment_{experiment_name}.json") cache_data = { 'timestamp': datetime.now().isoformat(), 'experiment_name': experiment_name, 'results': results } with open(cache_file, 'w') as f: json.dump(cache_data, f, indent=2) log_message(f"Zapisano eksperyment do cache: {cache_file}", "CACHE") def load_experiment_cache(experiment_name, cache_dir=CACHE_DIR): cache_file = os.path.join(cache_dir, f"experiment_{experiment_name}.json") if os.path.exists(cache_file): try: with open(cache_file, 'r') as f: cache_data = json.load(f) log_message(f"Wczytano eksperyment z cache: {cache_file}", "CACHE") return cache_data.get('results', {}) except Exception as e: log_error(f"Błąd wczytywania eksperymentu z cache: {e}") return None # FUNKCJA DO CZYSZCZENIA CACHE def clear_cache(cache_dir=CACHE_DIR): if os.path.exists(cache_dir): import shutil shutil.rmtree(cache_dir) log_message(f"Wyczyszczono cache: {cache_dir}", "CACHE") # FUNKCJA DO SPRAWDZANIA STATUSU CACHE def check_cache_status(cache_dir=CACHE_DIR): if not os.path.exists(cache_dir): log_message("Brak katalogu cache", "CACHE") return cache_files = os.listdir(cache_dir) log_message(f"Katalog cache: {cache_dir}", "CACHE") log_message(f"Liczba plików cache: {len(cache_files)}", "CACHE") for file in cache_files: file_path = os.path.join(cache_dir, file) file_size = os.path.getsize(file_path) / (1024 * 1024) # MB file_time = datetime.fromtimestamp(os.path.getmtime(file_path)) log_message(f" - {file}: {file_size:.2f} MB, {file_time}", "CACHE") # BEZPIECZNA FUNKCJA DO RÓWNOLEGŁEGO OBLICZANIA JĄDRA KWANTOWEGO Z TIMEOUTAMI @timeout(1800) # 30 minut timeout def parallel_quantum_kernel_evaluation(X1, X2, feature_map, backend_name='qasm_simulator', shots=1024): # SPRAWDZENIE CACHE feature_map_name = feature_map.__class__.__name__ cache_key = get_kernel_cache_key(X1.shape, X2.shape, feature_map_name, shots) log_message(f"Sprawdzanie cache dla jądra: {cache_key}", "KERNEL") cached_kernel = load_kernel_cache(cache_key) if cached_kernel is not None: log_message(f"Znaleziono jądro w cache! Oszczędność: ~{X1.shape[0] * X2.shape[0] * 8 / (1024**2):.1f} MB", "KERNEL") return cached_kernel log_message(f"Brak jądra w cache - obliczanie od nowa", "KERNEL") n_jobs = CPU_CONFIG['n_jobs_kernel'] log_message(f"Bezpieczne obliczanie jądra kwantowego (n_jobs={n_jobs})", "KERNEL") log_message(f"Rozmiar danych: {X1.shape} x {X2.shape}", "KERNEL") log_message(f"Bezpieczne wykorzystanie rdzeni: {n_jobs}/{CPU_CONFIG['total_cores']} ({n_jobs/CPU_CONFIG['total_cores']*100:.1f}%)", "KERNEL") # Sprawdź rozmiar danych - ograniczenie dla bezpieczeństwa max_matrix_size = 1000 * 1000 # Maksymalnie 1M elementów if X1.shape[0] * X2.shape[0] > max_matrix_size: log_message(f"Zbyt duża macierz jądra: {X1.shape[0] * X2.shape[0]} > {max_matrix_size}", "WARNING") log_message(f"Redukcja rozmiaru danych dla bezpieczeństwa", "KERNEL") # Redukuj rozmiar danych X1 = X1[:min(500, X1.shape[0])] X2 = X2[:min(500, X2.shape[0])] # Inicjalizacja backendu try: backend = Aer.get_backend(backend_name) backend.set_options(shots=shots) except Exception as e: log_error(f"Błąd backendu: {e}, używam qasm_simulator") backend = Aer.get_backend('qasm_simulator') backend.set_options(shots=shots) # Utworzenie quantum kernel try: from qiskit.utils import QuantumInstance quantum_instance = QuantumInstance(backend=backend, shots=shots) quantum_kernel = QuantumKernel( feature_map=feature_map, quantum_instance=quantum_instance ) except Exception as e: log_error(f"Błąd tworzenia quantum kernel: {e}") return None # BEZPIECZNA OPTYMALIZACJA CHUNK SIZE chunk_size = max(1, min(X1.shape[0] // n_jobs, 5)) # Mniejsze chunki dla bezpieczeństwa kernel_matrix = np.zeros((X1.shape[0], X2.shape[0])) @timeout(300) # 5 minut timeout na chunk def compute_kernel_chunk(start_idx): end_idx = min(start_idx + chunk_size, X1.shape[0]) chunk_X1 = X1[start_idx:end_idx] try: chunk_kernel = quantum_kernel.evaluate(chunk_X1, X2) return start_idx, end_idx, chunk_kernel except Exception as e: log_error(f"Błąd obliczania chunk'a {start_idx}-{end_idx}: {e}") return start_idx, end_idx, np.zeros((end_idx - start_idx, X2.shape[0])) # Bezpieczne równoległe obliczenia from concurrent.futures import ProcessPoolExecutor, as_completed log_message(f"Używam {n_jobs} rdzeni bezpiecznie", "KERNEL") log_message(f"Chunk size: {chunk_size}", "KERNEL") log_message(f"Liczba chunk'ów: {len(range(0, X1.shape[0], chunk_size))}", "KERNEL") # BEZPIECZNA LICZBA PROCESÓW max_workers = min(n_jobs, 20) # Maksymalnie 20 procesów jednocześnie with ProcessPoolExecutor(max_workers=max_workers) as executor: futures = [] for i in range(0, X1.shape[0], chunk_size): futures.append(executor.submit(compute_kernel_chunk, i)) # Zbierz wyniki z timeoutami completed_chunks = 0 for future in as_completed(futures, timeout=1800): # 30 minut timeout try: start_idx, end_idx, chunk_kernel = future.result(timeout=300) kernel_matrix[start_idx:end_idx] = chunk_kernel completed_chunks += 1 log_message(f"Ukończono chunk {completed_chunks}/{len(futures)}", "KERNEL") except Exception as e: log_error(f"Błąd w chunk'u: {e}") continue # ZAPISZ DO CACHE log_message(f"Zapisuję jądro do cache: {cache_key}", "KERNEL") save_kernel_cache(kernel_matrix, cache_key) return kernel_matrix # OPTYMALIZOWANA FUNKCJA PRZYGOTOWANIA DANYCH Z CACHE def prepare_data(data_file): from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.decomposition import PCA from sklearn.manifold import TSNE from sklearn.metrics import silhouette_score # SPRAWDZENIE CACHE DLA DANYCH cache_key = get_data_cache_key(data_file, TEST_SIZE, RANDOM_STATE, PCA_COMPONENTS) print(f"Sprawdzanie cache dla danych: {cache_key}") cached_data = load_data_cache(cache_key) if cached_data is not None: print(f"Znaleziono dane w cache! Oszczędność czasu przygotowania.") return cached_data print(f"Brak danych w cache - przygotowanie od nowa") print(f"\n======= PRZYGOTOWANIE DANYCH =======") start_time_data = time.time() # Wczytanie danych data = pd.read_csv(data_file) print(f"Wymiary oryginalnych danych: {data.shape}") # Wydzielenie zmiennej docelowej y = data['Primary_Diagnosis'] print(f"Unikalne wartości zmiennej docelowej: {y.unique()}") print(f"Rozkład klas: {y.value_counts().to_dict()}") # Usunięcie kolumn identyfikacyjnych id_columns = ['Project', 'Case_ID'] data_processed = data.drop(id_columns + ['Grade'], axis=1) print(f"Wymiary danych po usunięciu kolumn identyfikacyjnych: {data_processed.shape}") # Przekształcenie kolumn kategorycznych na binarne print("Przekształcanie kolumn kategorycznych na binarne...") categorical_columns = data_processed.select_dtypes(include=['object']).columns.tolist() print(f"Kolumny kategoryczne do przekształcenia: {categorical_columns}") # Specjalna obsługa kolumny Age_at_diagnosis (jeśli istnieje) if 'Age_at_diagnosis' in categorical_columns: print("Znaleziono kolumnę Age_at_diagnosis - sprawdzanie formatu...") age_col = data_processed['Age_at_diagnosis'] # Sprawdź czy wartości są już numeryczne (dni) try: data_processed['Age_at_diagnosis'] = pd.to_numeric(age_col, errors='raise') print("Kolumna Age_at_diagnosis została przekształcona na numeryczną (dni).") categorical_columns.remove('Age_at_diagnosis') # Usuń z listy kolumn kategorycznych except: print("UWAGA: Kolumna Age_at_diagnosis nie jest numeryczna!") # Przekształcenie każdej kolumny kategorycznej for col in categorical_columns: unique_values = data_processed[col].unique() print(f"Kolumna {col} zawiera wartości: {unique_values}") if len(unique_values) == 2: if set(unique_values) == {'Yes', 'No'}: data_processed[col] = data_processed[col].map({'Yes': 1, 'No': 0}) elif set(unique_values) == {'Male', 'Female'}: data_processed[col] = data_processed[col].map({'Male': 1, 'Female': 0}) elif set(unique_values) == {'GBM', 'LGG'}: data_processed[col] = data_processed[col].map({'GBM': 1, 'LGG': 0}) else: data_processed[col] = pd.factorize(data_processed[col])[0] else: # Ograniczenie one-hot encoding do maksymalnie 10 kategorii MAX_CATEGORIES = 10 if len(unique_values) > MAX_CATEGORIES: print(f"Kolumna {col} ma {len(unique_values)} kategorii - używam factorize zamiast one-hot.") data_processed[col] = pd.factorize(data_processed[col])[0] else: try: data_processed[col] = pd.to_numeric(data_processed[col], errors='raise') print(f"Kolumna {col} została przekształcona na liczbową.") except: print(f"Kolumna {col} zostanie zakodowana jako one-hot ({len(unique_values)} kategorii).") dummies = pd.get_dummies(data_processed[col], prefix=col, drop_first=True) data_processed = pd.concat([data_processed, dummies], axis=1) data_processed.drop(col, axis=1, inplace=True) # Sprawdzenie, czy wszystkie dane są numeryczne non_numeric = data_processed.select_dtypes(include=['object']).columns.tolist() if non_numeric: print(f"UWAGA: Pozostały kolumny nieliczbowe: {non_numeric}") print("Usuwanie pozostałych kolumn nieliczbowych...") data_processed = data_processed.drop(non_numeric, axis=1) print(f"Wymiary danych po przekształceniu: {data_processed.shape}") # Kontrola liczby wymiarów MAX_DIMENSIONS = 27 # Maksymalna liczba wymiarów if data_processed.shape[1] > MAX_DIMENSIONS: print(f"UWAGA: Zbyt wiele wymiarów ({data_processed.shape[1]})! Maksymalnie {MAX_DIMENSIONS}.") print("Rozważ zwiększenie PCA_COMPONENTS lub ograniczenie one-hot encoding.") # Wypełnienie brakujących wartości if data_processed.isnull().sum().sum() > 0: print("Wypełnianie brakujących wartości...") data_processed.fillna(data_processed.mean(), inplace=True) # Przygotowanie danych do modelowania X = data_processed.values print(f"Wymiary danych wejściowych: {X.shape}") # Przetwarzanie cech scaler = StandardScaler() X_scaled = scaler.fit_transform(X) print(f"Wymiary danych po skalowaniu: {X_scaled.shape}") # Redukcja wymiarowości print("\n======= REDUKCJA WYMIAROWOŚCI =======") # Przygotowanie różnych wersji zredukowanych danych X_reduced_versions = {} if USE_PCA: pca_components = min(PCA_COMPONENTS, X_scaled.shape[1]) print(f"Liczba komponentów PCA: {pca_components}") pca = PCA(n_components=pca_components) X_reduced_pca = pca.fit_transform(X_scaled) print(f"Wymiary danych po redukcji PCA: {X_reduced_pca.shape}") print(f"Wyjaśniona wariancja: {sum(pca.explained_variance_ratio_):.4f}") X_reduced_versions['pca'] = X_reduced_pca if USE_TSNE: print(f"\nStosowanie t-SNE na danych skalowanych...") tsne = TSNE( n_components=TSNE_COMPONENTS, perplexity=TSNE_PERPLEXITY, learning_rate=TSNE_LEARNING_RATE, n_iter=TSNE_MAX_ITER, random_state=RANDOM_STATE ) tsne_start_time = time.time() X_reduced_tsne = tsne.fit_transform(X_scaled) tsne_end_time = time.time() tsne_time = tsne_end_time - tsne_start_time print(f"Wymiary danych po redukcji t-SNE: {X_reduced_tsne.shape}") print(f"Czas wykonania t-SNE: {tsne_time:.2f} sekund") if EVALUATE_SILHOUETTE: try: silhouette_avg = silhouette_score(X_reduced_tsne, y) print(f"Silhouette Score dla t-SNE: {silhouette_avg:.4f}") except Exception as e: print(f"Nie udało się obliczyć Silhouette Score: {str(e)}") X_reduced_versions['tsne'] = X_reduced_tsne if USE_UMAP: print(f"\nStosowanie UMAP na danych skalowanych...") umap_reducer = umap.UMAP( n_components=UMAP_COMPONENTS, n_neighbors=UMAP_NEIGHBORS, min_dist=UMAP_MIN_DIST, metric=UMAP_METRIC, random_state=RANDOM_STATE ) umap_start_time = time.time() X_reduced_umap = umap_reducer.fit_transform(X_scaled) umap_end_time = time.time() umap_time = umap_end_time - umap_start_time print(f"Wymiary danych po redukcji UMAP: {X_reduced_umap.shape}") print(f"Czas wykonania UMAP: {umap_time:.2f} sekund") if EVALUATE_SILHOUETTE: try: silhouette_avg_umap = silhouette_score(X_reduced_umap, y) print(f"Silhouette Score dla UMAP: {silhouette_avg_umap:.4f}") except Exception as e: print(f"Nie udało się obliczyć Silhouette Score dla UMAP: {str(e)}") X_reduced_versions['umap'] = X_reduced_umap # Wybór domyślnej wersji zredukowanych danych if 'pca' in X_reduced_versions: X_reduced = X_reduced_versions['pca'] print("Używanie danych zredukowanych przez PCA jako domyślnych.") elif 'umap' in X_reduced_versions: X_reduced = X_reduced_versions['umap'] print("Używanie danych zredukowanych przez UMAP jako domyślnych.") elif 'tsne' in X_reduced_versions: X_reduced = X_reduced_versions['tsne'] print("Używanie danych zredukowanych przez t-SNE jako domyślnych.") else: X_reduced = X_scaled print("Nie wybrano żadnej metody redukcji wymiarowości. Używanie oryginalnych danych skalowanych.") # Podział na zbiory treningowy i testowy X_train_reduced, X_test_reduced, y_train, y_test = train_test_split( X_reduced, y, test_size=TEST_SIZE, random_state=RANDOM_STATE ) # Podział dla oryginalnych danych X_train, X_test, _, _ = train_test_split(X, y, test_size=TEST_SIZE, random_state=RANDOM_STATE) print(f"Wymiary zbioru treningowego: {X_train_reduced.shape}") print(f"Wymiary zbioru testowego: {X_test_reduced.shape}") end_time_data = time.time() data_preparation_time = end_time_data - start_time_data print(f"\nCzas przygotowania danych: {data_preparation_time:.2f} sekund") # PRZYGOTUJ DANE DO CACHE data_dict = { 'X_train': X_train, 'X_test': X_test, 'X_train_reduced': X_train_reduced, 'X_test_reduced': X_test_reduced, 'y_train': y_train, 'y_test': y_test, 'data_processed': data_processed, 'preparation_time': data_preparation_time } # ZAPISZ DO CACHE print(f"Zapisuję dane do cache: {cache_key}") save_data_cache(data_dict, cache_key) return data_dict def run_experiment_parallel(exp_file): experiment_name = exp_file.replace('.py', '') # SPRAWDZENIE CACHE DLA EKSPERYMENTU log_message(f"Sprawdzanie cache dla eksperymentu: {experiment_name}", "EXPERIMENT") cached_results = load_experiment_cache(experiment_name) if cached_results is not None: log_message(f"Znaleziono wyniki eksperymentu w cache: {experiment_name}", "EXPERIMENT") return cached_results log_message(f"Brak wyników w cache - uruchamianie eksperymentu: {experiment_name}", "EXPERIMENT") # URUCHOM EKSPERYMENT if exp_file == 'qsvm1_zz.py': import qsvm1_zz results = qsvm1_zz.run_experiment() elif exp_file == 'qsvm2_pauli.py': import qsvm2_pauli results = qsvm2_pauli.run_experiment() elif exp_file == 'qsvm3_z.py': import qsvm3_z results = qsvm3_z.run_experiment() elif exp_file == 'qsvm4_amplitude.py': import qsvm4_amplitude results = qsvm4_amplitude.run_experiment() elif exp_file == 'qsvm5_hybrid.py': import qsvm5_hybrid results = qsvm5_hybrid.run_experiment() else: log_error(f"Nieznany eksperyment: {exp_file}") return None # ZAPISZ WYNIKI DO CACHE if results is not None: log_message(f"Zapisuję wyniki eksperymentu do cache: {experiment_name}", "EXPERIMENT") save_experiment_cache(experiment_name, results) return results def run_single_file_experiment(args): exp_file, data_file = args experiment_name = exp_file.replace('.py', '') file_name = os.path.basename(data_file).split('.')[0] log_message(f"Uruchamianie {experiment_name} na pliku: {file_name}", "FILE_EXPERIMENT") # SPRAWDZENIE CACHE DLA KOMBINACJI EKSPERYMENT+PLIK cache_key = f"{experiment_name}_{file_name}" cached_results = load_experiment_cache(cache_key) if cached_results is not None: log_message(f"Znaleziono wyniki w cache: {cache_key}", "FILE_EXPERIMENT") return (exp_file, data_file, cached_results) log_message(f"Brak wyników w cache - obliczanie: {cache_key}", "FILE_EXPERIMENT") # URUCHOM EKSPERYMENT NA POJEDYNCZYM PLIKU try: if exp_file == 'qsvm1_zz.py': import qsvm1_zz results = qsvm1_zz.run_single_file_experiment(data_file) elif exp_file == 'qsvm2_pauli.py': import qsvm2_pauli results = qsvm2_pauli.run_single_file_experiment(data_file) elif exp_file == 'qsvm3_z.py': import qsvm3_z results = qsvm3_z.run_single_file_experiment(data_file) elif exp_file == 'qsvm4_amplitude.py': import qsvm4_amplitude results = qsvm4_amplitude.run_single_file_experiment(data_file) elif exp_file == 'qsvm5_hybrid.py': import qsvm5_hybrid results = qsvm5_hybrid.run_single_file_experiment(data_file) else: log_error(f"Nieznany eksperyment: {exp_file}") return (exp_file, data_file, None) # ZAPISZ WYNIKI DO CACHE if results is not None: log_message(f"Zapisuję wyniki do cache: {cache_key}", "FILE_EXPERIMENT") save_experiment_cache(cache_key, results) return (exp_file, data_file, results) except Exception as e: log_error(f"Błąd w eksperymencie {exp_file} na pliku {data_file}: {e}") return (exp_file, data_file, None) @timeout(7200) # 2 godziny timeout na cały eksperyment def run_all_experiments_parallel(): experiment_files = [ 'qsvm3_z.py' # ZFeatureMap - ZAKOMENTOWANE # 'qsvm4_amplitude.py', # Amplitude Encoding - ZAKOMENTOWANE # 'qsvm1_zz.py', # ZZFeatureMap - ZAKOMENTOWANE # 'qsvm2_pauli.py' # PauliFeatureMap - TYLKO TEN # 'qsvm5_hybrid.py' # Hybrid Approach - ZAKOMENTOWANE ] # GENERUJ WSZYSTKIE KOMBINACJE EKSPERYMENT+PLIK all_combinations = [] for exp_file in experiment_files: for data_file in DATA_FILES: all_combinations.append((exp_file, data_file)) total_combinations = len(all_combinations) log_message(f"Łączna liczba kombinacji eksperyment+plik: {total_combinations}", "MAIN") # BEZPIECZNE WYKORZYSTANIE RDZENI n_processes = min(CPU_CONFIG['n_jobs_parallel'], total_combinations, 8) # Maksymalnie 8 procesów log_message(f"Uruchamianie {total_combinations} kombinacji z {n_processes} procesami bezpiecznie", "MAIN") log_message(f"Eksperymenty: {experiment_files}", "MAIN") log_message(f"Pliki danych: {len(DATA_FILES)}", "MAIN") log_message(f"Bezpieczne przyspieszenie: ~{n_processes/2:.1f}x", "MAIN") # Dodatkowe informacje o wydajności log_message(f"Dostępna pamięć: {CPU_CONFIG['available_memory']:.1f} GB", "MAIN") log_message(f"Bezpieczna konfiguracja rdzeni:", "MAIN") log_message(f" - Jądro kwantowe: {CPU_CONFIG['n_jobs_kernel']} rdzeni", "MAIN") log_message(f" - SVM: {CPU_CONFIG['n_jobs_svm']} rdzeni", "MAIN") log_message(f" - Równoległość: {CPU_CONFIG['n_jobs_parallel']} rdzeni", "MAIN") # Przewidywany czas dla wszystkich kombinacji log_message(f"PRZEWIDYWANY CZAS Z TIMEOUTAMI:", "MAIN") log_message(f" - Amplitude: 20-45 minut na plik (max 2h)", "MAIN") log_message(f" - ŁĄCZNIE: {total_combinations} kombinacji z timeoutami", "MAIN") # URUCHOM KOMBINACJE Z TIMEOUTAMI results = [] for i, combination in enumerate(all_combinations): try: log_message(f"Uruchamianie kombinacji {i+1}/{total_combinations}: {combination}", "MAIN") # Timeout na pojedynczą kombinację @timeout(3600) # 1 godzina na kombinację def run_single_with_timeout(): return run_single_file_experiment(combination) result = run_single_with_timeout() results.append(result) log_message(f"Ukończono kombinację {i+1}/{total_combinations}", "MAIN") except TimeoutError: log_message(f"Timeout dla kombinacji {i+1}: {combination}", "WARNING") results.append((combination[0], combination[1], None)) except Exception as e: log_error(f"Błąd w kombinacji {i+1}: {e}") results.append((combination[0], combination[1], None)) # GRUPUJ WYNIKI WG EKSPERYMENTÓW grouped_results = {} for exp_file in experiment_files: grouped_results[exp_file] = [] for exp_file, data_file, result in results: if result is not None: grouped_results[exp_file].append((data_file, result)) return grouped_results # FUNKCJA DO URACHAMIANIA KLASYCZNEGO SVM def run_classic_svm_single_file(data_file): from sklearn.svm import SVC from sklearn.model_selection import GridSearchCV, cross_val_score from sklearn.metrics import classification_report, confusion_matrix, roc_auc_score, accuracy_score, precision_score, recall_score, f1_score file_name = os.path.basename(data_file).split('.')[0] log_message(f"Uruchamianie klasycznego SVM na pliku: {file_name}", "CLASSIC_SVM") # SPRAWDZENIE CACHE DLA KLASYCZNEGO SVM cache_key = f"classic_svm_{file_name}" cached_results = load_experiment_cache(cache_key) if cached_results is not None: log_message(f"Znaleziono wyniki klasycznego SVM w cache: {cache_key}", "CLASSIC_SVM") return cached_results log_message(f"Brak wyników w cache - obliczanie klasycznego SVM: {cache_key}", "CLASSIC_SVM") try: # Przygotowanie danych data_dict = prepare_data(data_file) X_train_reduced = data_dict['X_train_reduced'] X_test_reduced = data_dict['X_test_reduced'] y_train = data_dict['y_train'] y_test = data_dict['y_test'] log_message(f"Wymiary danych treningowych: {X_train_reduced.shape}", "CLASSIC_SVM") log_message(f"Wymiary danych testowych: {X_test_reduced.shape}", "CLASSIC_SVM") # Uruchomienie klasycznego SVM z GridSearchCV start_time = time.time() # BEZPIECZNE WYKORZYSTANIE RDZENI n_jobs = min(CPU_CONFIG['n_jobs_svm'], 8) # Maksymalnie 8 rdzeni dla bezpieczeństwa log_message(f"Używam {n_jobs} rdzeni dla klasycznego SVM", "CLASSIC_SVM") grid = GridSearchCV( SVC(random_state=RANDOM_STATE), SVM_PARAM_GRID, cv=SVM_CV, scoring='accuracy', n_jobs=n_jobs, verbose=1 ) log_message("Rozpoczynam GridSearchCV dla klasycznego SVM...", "CLASSIC_SVM") grid.fit(X_train_reduced, y_train) # Najlepszy model best_model = grid.best_estimator_ best_params = grid.best_params_ best_score = grid.best_score_ # Predykcje na zbiorze testowym classic_pred = best_model.predict(X_test_reduced) end_time = time.time() classic_svm_time = end_time - start_time # Obliczenie metryk accuracy = accuracy_score(y_test, classic_pred) precision = precision_score(y_test, classic_pred, average='weighted', zero_division=0) recall = recall_score(y_test, classic_pred, average='weighted', zero_division=0) f1 = f1_score(y_test, classic_pred, average='weighted', zero_division=0) try: roc_auc = roc_auc_score(y_test, classic_pred) except: roc_auc = "N/A" # Macierz pomyłek cm = confusion_matrix(y_test, classic_pred) # Raport klasyfikacji class_report = classification_report(y_test, classic_pred, output_dict=True) # Wyniki results = { 'file_name': file_name, 'best_params': best_params, 'best_cv_score': best_score, 'test_accuracy': accuracy, 'test_precision': precision, 'test_recall': recall, 'test_f1': f1, 'test_roc_auc': roc_auc, 'confusion_matrix': cm.tolist(), 'classification_report': class_report, 'training_time': classic_svm_time, 'data_shape': X_train_reduced.shape, 'timestamp': datetime.now().isoformat() } log_message(f"Klasyczny SVM ukończony dla {file_name}:", "CLASSIC_SVM") log_message(f" - Najlepsze parametry: {best_params}", "CLASSIC_SVM") log_message(f" - Dokładność CV: {best_score:.4f}", "CLASSIC_SVM") log_message(f" - Dokładność test: {accuracy:.4f}", "CLASSIC_SVM") log_message(f" - Czas treningu: {classic_svm_time:.2f} sekund", "CLASSIC_SVM") # ZAPISZ DO CACHE log_message(f"Zapisuję wyniki klasycznego SVM do cache: {cache_key}", "CLASSIC_SVM") save_experiment_cache(cache_key, results) return results except Exception as e: log_error(f"Błąd w klasycznym SVM dla pliku {data_file}: {e}") return None # FUNKCJA DO URACHAMIANIA KLASYCZNEGO SVM NA WSZYSTKICH PLIKACH def run_classic_svm_all_files(): log_message(f"Uruchamianie klasycznego SVM na {len(DATA_FILES)} plikach", "CLASSIC_SVM_ALL") # Sprawdź które pliki istnieją existing_files = [] for data_file in DATA_FILES: if os.path.exists(data_file): existing_files.append(data_file) else: log_message(f"Plik nie istnieje: {data_file}", "WARNING") log_message(f"Znaleziono {len(existing_files)} istniejących plików", "CLASSIC_SVM_ALL") # Uruchom klasyczny SVM na wszystkich plikach results = [] for i, data_file in enumerate(existing_files): try: log_message(f"Przetwarzanie pliku {i+1}/{len(existing_files)}: {os.path.basename(data_file)}", "CLASSIC_SVM_ALL") # Timeout na pojedynczy plik @timeout(1800) # 30 minut na plik def run_single_with_timeout(): return run_classic_svm_single_file(data_file) result = run_single_with_timeout() if result is not None: results.append(result) log_message(f"Ukończono plik {i+1}/{len(existing_files)}", "CLASSIC_SVM_ALL") else: log_message(f"Błąd w pliku {i+1}/{len(existing_files)}", "CLASSIC_SVM_ALL") except TimeoutError: log_message(f"Timeout dla pliku {i+1}: {os.path.basename(data_file)}", "WARNING") except Exception as e: log_error(f"Błąd w pliku {i+1}: {e}") # Zapisanie wszystkich wyników if results: output_file = os.path.join(OUTPUT_DIR, f'wyniki_classic_svm_all_{datetime.now().strftime("%Y%m%d_%H%M%S")}.json') with open(output_file, 'w') as f: json.dump(results, f, indent=2) log_message(f"Zapisano wszystkie wyniki do: {output_file}", "CLASSIC_SVM_ALL") # Podsumowanie log_message("PODSUMOWANIE KLASYCZNEGO SVM:", "CLASSIC_SVM_ALL") for result in results: log_message(f" {result['file_name']}: {result['test_accuracy']:.4f} (czas: {result['training_time']:.1f}s)", "CLASSIC_SVM_ALL") return results if __name__ == "__main__": print("======= KONTROLER EKSPERYMENTÓW QSVM - BEZPIECZNE ZFEATUREMAP Z TIMEOUTAMI =======") print(f"BEZPIECZNA KONFIGURACJA: {CPU_CONFIG['total_cores']} rdzeni") print(f"Dostępna pamięć: {CPU_CONFIG['available_memory']:.1f} GB") print(f"BEZPIECZNA KONFIGURACJA: {CPU_CONFIG}") print("") print("Uruchamianie TYLKO PAULIFEATUREMAP z BEZPIECZNYMI timeoutami:") print(" - PauliFeatureMap (qsvm2_pauli.py) - TYLKO TEN") print(" - Amplitude Encoding (qsvm4_amplitude.py) - ZAKOMENTOWANE") print(" - ZZFeatureMap (qsvm1_zz.py) - ZAKOMENTOWANE") print(" - ZFeatureMap (qsvm3_z.py) - ZAKOMENTOWANE") print(" - Hybrid Approach (qsvm5_hybrid.py) - ZAKOMENTOWANE") print("") print("SYSTEM BEZPIECZEŃSTWA:") print(" - Timeouty na wszystkie operacje - zapobieganie zawieszeniu") print(" - Monitoring zasobów - wykrywanie przeciążenia") print(" - Ograniczone wykorzystanie rdzeni - 70% maksymalnie") print(" - Cache z timeoutami - bezpieczne zapisywanie") print("") print("SYSTEM CACHE:") print(" - Cache jądra kwantowego - oszczędność obliczeń") print(" - Cache przygotowania danych - oszczędność czasu") print(" - Cache wyników eksperymentów - wznowienie po przerwaniu") print("") print("PRZEWIDYWANE WYNIKI:") print(f" - Czas wykonania: 1-2 godziny (z timeoutami)") print(f" - Bezpieczne wykorzystanie rdzeni: {CPU_CONFIG['n_jobs_kernel'] + CPU_CONFIG['n_jobs_svm'] + CPU_CONFIG['n_jobs_parallel']}/{CPU_CONFIG['total_cores']}") print(f" - Przewidywane przyspieszenie: ~{CPU_CONFIG['total_cores']/16:.1f}x (bezpieczne)") print(" - Oszczędność dzięki cache: 50-80% przy ponownym uruchomieniu") print(" - Zero zawieszeń dzięki timeoutom") print("") # SPRAWDZENIE STATUSU CACHE print("Sprawdzanie statusu cache...") check_cache_status() print("") try: start_time = time.time() print("URUCHAMIANIE KWANTOWEGO SVM (ZFEATUREMAP)") print("Uruchamianie TYLKO PAULIFEATUREMAP z BEZPIECZNYMI timeoutami:") print(" - PauliFeatureMap (qsvm2_pauli.py) - TYLKO TEN") print(" - Amplitude Encoding (qsvm4_amplitude.py) - ZAKOMENTOWANE") print(" - ZZFeatureMap (qsvm1_zz.py) - ZAKOMENTOWANE") print(" - ZFeatureMap (qsvm3_z.py) - ZAKOMENTOWANE") print(" - Hybrid Approach (qsvm5_hybrid.py) - ZAKOMENTOWANE") print("") print("PRZEWIDYWANE WYNIKI:") print(f" - Czas wykonania: 1-2 godziny (z timeoutami)") print(f" - Bezpieczne wykorzystanie rdzeni: {CPU_CONFIG['n_jobs_kernel'] + CPU_CONFIG['n_jobs_svm'] + CPU_CONFIG['n_jobs_parallel']}/{CPU_CONFIG['total_cores']}") print(f" - Przewidywane przyspieszenie: ~{CPU_CONFIG['total_cores']/16:.1f}x (bezpieczne)") print(" - Oszczędność dzięki cache: 50-80% przy ponownym uruchomieniu") print(" - Zero zawieszeń dzięki timeoutom") print("") results = run_all_experiments_parallel() end_time = time.time() total_time = end_time - start_time print("") print("======= PAULIFEATUREMAP ZAKOŃCZONE - BEZPIECZNIE Z TIMEOUTAMI =======") print(f"Całkowity czas wykonania: {total_time/60:.1f} minut ({total_time/3600:.1f} godzin)") print(f"⚡ Średni czas na eksperyment: {total_time/1/60:.1f} minut") print(f"Bezpieczne wykorzystanie rdzeni: {CPU_CONFIG['n_jobs_kernel'] + CPU_CONFIG['n_jobs_svm'] + CPU_CONFIG['n_jobs_parallel']}/{CPU_CONFIG['total_cores']} ({((CPU_CONFIG['n_jobs_kernel'] + CPU_CONFIG['n_jobs_svm'] + CPU_CONFIG['n_jobs_parallel'])/CPU_CONFIG['total_cores'])*100:.1f}%)") print("Finalny status cache:") check_cache_status() print("PAULIFEATUREMAP ZAKOŃCZONE BEZPIECZNIE!") except TimeoutError: print("") print("======= EKSPERYMENT PRZERWANY PRZEZ TIMEOUT =======") print("Eksperyment został bezpiecznie przerwany po przekroczeniu limitu czasu") print("Wyniki częściowe zostały zapisane w cache") print("Status cache:") check_cache_status() print("Można wznowić eksperyment - cache zostanie wykorzystany") except Exception as e: print("") print("======= BŁĄD W EKSPERYMENCIE =======") print(f"Błąd: {str(e)}") print("Status cache:") check_cache_status() print("Sprawdź logi i spróbuj ponownie")