From a8500dc4c15d948ddddfcca4eeb475fb8092e51e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kasprowicz?= Date: Sat, 13 Sep 2025 01:23:15 +0000 Subject: [PATCH] Upload files to "/" --- qsvm_optimized.py | 1261 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1261 insertions(+) create mode 100644 qsvm_optimized.py diff --git a/qsvm_optimized.py b/qsvm_optimized.py new file mode 100644 index 0000000..8783401 --- /dev/null +++ b/qsvm_optimized.py @@ -0,0 +1,1261 @@ +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")