import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from scipy.spatial import ConvexHull # Leer el archivo manualmente data = [] with open('resultados1.txt', 'r', encoding='utf-8') as f: header = f.readline().strip().split('\t') for line in f: values = line.strip().split('\t') if len(values) >= 9: # Asegurar que hay suficientes columnas data.append(values) # Encontrar índices de columnas tf_idx = header.index('tf') tw_idx = header.index('tw') flecha_idx = header.index('Flecha_Media') # Convertir datos a números def convert_value(x): """Convierte string a float, manejando formato con coma decimal""" try: return float(x.replace(',', '.').strip()) except: return np.nan tf_list = [] tw_list = [] flecha_list = [] for row in data: tf_val = convert_value(row[tf_idx]) tw_val = convert_value(row[tw_idx]) flecha_val = convert_value(row[flecha_idx]) if not (np.isnan(tf_val) or np.isnan(tw_val) or np.isnan(flecha_val)): tf_list.append(tf_val) tw_list.append(tw_val) flecha_list.append(flecha_val) tf = np.array(tf_list) tw = np.array(tw_list) flecha_media = np.array(flecha_list) # Función para calcular la frontera de Pareto (versión mejorada) def pareto_frontier(tf, tw, flecha): """ Calcula los puntos que pertenecen a la frontera de Pareto. Queremos minimizar tf, tw y el valor absoluto de flecha (magn itud de deflexión). Un punto es Pareto si no hay otro punto que sea mejor en todos los criterios simultáneamente. """ n = len(tf) is_pareto = np.ones(n, dtype=bool) # Usar valor absoluto de flecha para la comparación flecha_abs = np.abs(flecha) for i in range(n): for j in range(n): if i != j: # El punto j domina al punto i si es mejor (≤) en todos los criterios # y estrictamente mejor en al menos uno if (tf[j] <= tf[i] and tw[j] <= tw[i] and flecha_abs[j] <= flecha_abs[i]) and \ (tf[j] < tf[i] or tw[j] < tw[i] or flecha_abs[j] < flecha_abs[i]): is_pareto[i] = False break return is_pareto # Calcular frontera de Pareto pareto_mask = pareto_frontier(tf, tw, flecha_media) pareto_tf = tf[pareto_mask] pareto_tw = tw[pareto_mask] pareto_flecha = flecha_media[pareto_mask] print(f"Total de puntos: {len(tf)}") print(f"Puntos en la frontera de Pareto: {len(pareto_tf)}") # Crear figura 3D fig = plt.figure(figsize=(14, 10)) ax = fig.add_subplot(111, projection='3d') # Graficar todos los puntos scatter_all = ax.scatter(tf, tw, flecha_media, c='lightblue', marker='o', s=50, alpha=0.6, label='Todos los puntos') # Graficar la frontera de Pareto scatter_pareto = ax.scatter(pareto_tf, pareto_tw, pareto_flecha, c='red', marker='*', s=200, alpha=0.9, label='Frontera de Pareto') # Intentar graficar la superficie convexa de la frontera de Pareto if len(pareto_tf) >= 4: try: # Crear matriz de coordenadas para la frontera de Pareto points_pareto = np.column_stack((pareto_tf, pareto_tw, pareto_flecha)) # Calcular la envolvente convexa (convex hull) hull = ConvexHull(points_pareto) # Graficar la superficie for simplex in hull.simplices: # Crear triángulos de la superficie triangle = points_pareto[simplex] # Graficar los bordes del triángulo for i in range(3): ax.plot(triangle[[i, (i+1)%3], 0], triangle[[i, (i+1)%3], 1], triangle[[i, (i+1)%3], 2], 'r-', alpha=0.3, linewidth=0.5) except Exception as e: print(f"No se pudo graficar la superficie convexa: {e}") # Etiquetas de ejes ax.set_xlabel('tf (espesor del ala)', fontsize=12, fontweight='bold') ax.set_ylabel('tw (espesor del alma)', fontsize=12, fontweight='bold') ax.set_zlabel('Flecha_Media (deflexión)', fontsize=12, fontweight='bold') ax.set_title('Nube de Puntos 3D y Frontera de Pareto\ntf vs tw vs Flecha_Media', fontsize=14, fontweight='bold') # Leyenda ax.legend(loc='upper right', fontsize=11) # Ajustar vista ax.view_init(elev=20, azim=45) plt.tight_layout() plt.savefig('grafico_3d_pareto.png', dpi=300, bbox_inches='tight') print("\nGráfico guardado como 'grafico_3d_pareto.png'") # Mostrar detalles de los puntos de Pareto print("\n" + "="*60) print("PUNTOS EN LA FRONTERA DE PARETO:") print("="*60) print(f"{'tf':<12} {'tw':<12} {'Flecha_Media':<15}") print("-"*60) for i in range(len(pareto_tf)): print(f"{pareto_tf[i]:<12.6f} {pareto_tw[i]:<12.6f} {pareto_flecha[i]:<15.6f}") plt.show()