| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- 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()
|