Create quantum_bayes_mahalanobis.py
Browse files-------------------------------------------------------------------------------
Notas de la versi贸n refinada:
1) Se agregaron validaciones de dimensi贸n para evitar errores silenciosos.
2) Se incorpor贸 manejo de excepci贸n cuando la matriz de covarianza no es invertible,
recurriendo a la pseudo-inversa.
3) Se incluyeron docstrings en espa帽ol m谩s descriptivos para cada clase y m茅todo.
4) Se agreg贸 un argumento learning_rate al m茅todo optimize_quantum_state para mayor flexibilidad.
5) Se sali贸 del bloque de gradient y se volvi贸 a evaluar la funci贸n objetivo
para comparar si el valor mejor贸 y as铆 actualizar el mejor estado.
6) El registro de la distancia de Mahalanobis se realiza cuando sea necesario (e.g. en la funci贸n objetivo),
evitando duplicar demasiadas llamadas si no se requiere.
7) El m茅todo simulate_wave_collapse mantiene la estructura original pero con m谩s comentarios y
simplificaciones de nombres de variables.
8) Se agrega una funcion de entropia que incluye el metodo de Von Neumann para una dimendion densa cuanticamente correcta
- quantum_bayes_mahalanobis.py +503 -0
@@ -0,0 +1,503 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import tensorflow as tf
|
3 |
+
import tensorflow_probability as tfp
|
4 |
+
from scipy.spatial.distance import mahalanobis
|
5 |
+
from sklearn.covariance import EmpiricalCovariance
|
6 |
+
|
7 |
+
# Ajusta el import a tus necesidades reales:
|
8 |
+
# Se asume que en bayes_logic.py se tienen las clases BayesLogic, PRN, adem谩s de las
|
9 |
+
# funciones shannon_entropy, calculate_cosines, etc.
|
10 |
+
from bayes_logic import (
|
11 |
+
BayesLogic,
|
12 |
+
PRN,
|
13 |
+
shannon_entropy,
|
14 |
+
calculate_cosines
|
15 |
+
)
|
16 |
+
|
17 |
+
class QuantumBayesMahalanobis(BayesLogic):
|
18 |
+
"""
|
19 |
+
Clase que combina la l贸gica de Bayes con el c谩lculo de la distancia de Mahalanobis
|
20 |
+
aplicada a estados cu谩nticos, permitiendo proyecciones vectorizadas e inferencias
|
21 |
+
de coherencia/entrop铆a.
|
22 |
+
"""
|
23 |
+
def __init__(self):
|
24 |
+
"""
|
25 |
+
Constructor que inicializa el estimador de covarianza para su posterior uso.
|
26 |
+
"""
|
27 |
+
super().__init__()
|
28 |
+
self.covariance_estimator = EmpiricalCovariance()
|
29 |
+
|
30 |
+
def _get_inverse_covariance(self, data: np.ndarray) -> np.ndarray:
|
31 |
+
"""
|
32 |
+
Ajusta el estimador de covarianza con los datos y retorna la inversa de la
|
33 |
+
matriz de covarianza. Si la matriz no fuera invertible, se retorna la
|
34 |
+
pseudo-inversa (pinv).
|
35 |
+
|
36 |
+
Par谩metros:
|
37 |
+
-----------
|
38 |
+
data: np.ndarray
|
39 |
+
Datos con forma (n_muestras, n_dimensiones).
|
40 |
+
|
41 |
+
Retorna:
|
42 |
+
--------
|
43 |
+
inv_cov_matrix: np.ndarray
|
44 |
+
Inversa o pseudo-inversa de la matriz de covarianza estimada.
|
45 |
+
"""
|
46 |
+
if data.ndim != 2:
|
47 |
+
raise ValueError("Los datos deben ser una matriz bidimensional (n_muestras, n_dimensiones).")
|
48 |
+
self.covariance_estimator.fit(data)
|
49 |
+
cov_matrix = self.covariance_estimator.covariance_
|
50 |
+
try:
|
51 |
+
inv_cov_matrix = np.linalg.inv(cov_matrix)
|
52 |
+
except np.linalg.LinAlgError:
|
53 |
+
inv_cov_matrix = np.linalg.pinv(cov_matrix)
|
54 |
+
return inv_cov_matrix
|
55 |
+
|
56 |
+
def compute_quantum_mahalanobis(self,
|
57 |
+
quantum_states_A: np.ndarray,
|
58 |
+
quantum_states_B: np.ndarray) -> np.ndarray:
|
59 |
+
"""
|
60 |
+
Calcula la distancia de Mahalanobis para cada estado en 'quantum_states_B'
|
61 |
+
respecto a la distribuci贸n de 'quantum_states_A'. Retorna un arreglo 1D
|
62 |
+
con tantas distancias como filas tenga 'quantum_states_B'.
|
63 |
+
|
64 |
+
Par谩metros:
|
65 |
+
-----------
|
66 |
+
quantum_states_A: np.ndarray
|
67 |
+
Representa el conjunto de estados cu谩nticos de referencia.
|
68 |
+
Forma esperada: (n_muestras, n_dimensiones).
|
69 |
+
|
70 |
+
quantum_states_B: np.ndarray
|
71 |
+
Estados cu谩nticos para los que calcularemos la distancia
|
72 |
+
de Mahalanobis. Forma: (n_muestras, n_dimensiones).
|
73 |
+
|
74 |
+
Retorna:
|
75 |
+
--------
|
76 |
+
distances: np.ndarray
|
77 |
+
Distancias de Mahalanobis calculadas para cada entrada de B.
|
78 |
+
"""
|
79 |
+
if quantum_states_A.ndim != 2 or quantum_states_B.ndim != 2:
|
80 |
+
raise ValueError("Los estados cu谩nticos deben ser matrices bidimensionales.")
|
81 |
+
if quantum_states_A.shape[1] != quantum_states_B.shape[1]:
|
82 |
+
raise ValueError("La dimensi贸n (n_dimensiones) de A y B debe coincidir.")
|
83 |
+
|
84 |
+
inv_cov_matrix = self._get_inverse_covariance(quantum_states_A)
|
85 |
+
mean_A = np.mean(quantum_states_A, axis=0)
|
86 |
+
|
87 |
+
diff_B = quantum_states_B - mean_A # (n_samples_B, n_dims)
|
88 |
+
aux = diff_B @ inv_cov_matrix # (n_samples_B, n_dims)
|
89 |
+
dist_sqr = np.einsum('ij,ij->i', aux, diff_B) # Producto elemento a elemento y sumatoria por fila
|
90 |
+
distances = np.sqrt(dist_sqr)
|
91 |
+
return distances
|
92 |
+
|
93 |
+
def quantum_cosine_projection(self,
|
94 |
+
quantum_states: np.ndarray,
|
95 |
+
entropy: float,
|
96 |
+
coherence: float) -> tf.Tensor:
|
97 |
+
"""
|
98 |
+
Proyecta los estados cu谩nticos usando cosenos directores y calcula la
|
99 |
+
distancia de Mahalanobis entre dos proyecciones vectorizadas (A y B).
|
100 |
+
Finalmente retorna las distancias normalizadas (softmax).
|
101 |
+
|
102 |
+
Par谩metros:
|
103 |
+
-----------
|
104 |
+
quantum_states: np.ndarray
|
105 |
+
Estados cu谩nticos de entrada con forma (n_muestras, 2).
|
106 |
+
entropy: float
|
107 |
+
Entrop铆a del sistema a usar en la funci贸n calculate_cosines.
|
108 |
+
coherence: float
|
109 |
+
Coherencia del sistema a usar en la funci贸n calculate_cosines.
|
110 |
+
|
111 |
+
Retorna:
|
112 |
+
--------
|
113 |
+
normalized_distances: tf.Tensor
|
114 |
+
Tensor 1D con las distancias normalizadas (softmax).
|
115 |
+
"""
|
116 |
+
if quantum_states.shape[1] != 2:
|
117 |
+
raise ValueError("Se espera que 'quantum_states' tenga exactamente 2 columnas.")
|
118 |
+
cos_x, cos_y, cos_z = calculate_cosines(entropy, coherence)
|
119 |
+
|
120 |
+
# Proyecci贸n A: multiplicar cada columna por (cos_x, cos_y)
|
121 |
+
projected_states_A = quantum_states * np.array([cos_x, cos_y])
|
122 |
+
# Proyecci贸n B: multiplicar cada columna por (cos_x*cos_z, cos_y*cos_z)
|
123 |
+
projected_states_B = quantum_states * np.array([cos_x * cos_z, cos_y * cos_z])
|
124 |
+
|
125 |
+
# Calcular distancias de Mahalanobis vectorizadas
|
126 |
+
mahalanobis_distances = self.compute_quantum_mahalanobis(
|
127 |
+
projected_states_A,
|
128 |
+
projected_states_B
|
129 |
+
)
|
130 |
+
|
131 |
+
# Convertir a tensor y normalizar con softmax
|
132 |
+
mahalanobis_distances_tf = tf.convert_to_tensor(mahalanobis_distances, dtype=tf.float32)
|
133 |
+
normalized_distances = tf.nn.softmax(mahalanobis_distances_tf)
|
134 |
+
return normalized_distances
|
135 |
+
|
136 |
+
def calculate_quantum_posterior_with_mahalanobis(self,
|
137 |
+
quantum_states: np.ndarray,
|
138 |
+
entropy: float,
|
139 |
+
coherence: float):
|
140 |
+
"""
|
141 |
+
Calcula la probabilidad posterior usando la distancia de Mahalanobis
|
142 |
+
en proyecciones cu谩nticas e integra la l贸gica de Bayes.
|
143 |
+
|
144 |
+
Par谩metros:
|
145 |
+
-----------
|
146 |
+
quantum_states: np.ndarray
|
147 |
+
Matriz de estados cu谩nticos (n_muestras, 2).
|
148 |
+
entropy: float
|
149 |
+
Entrop铆a del sistema.
|
150 |
+
coherence: float
|
151 |
+
Coherencia del sistema.
|
152 |
+
|
153 |
+
Retorna:
|
154 |
+
--------
|
155 |
+
posterior: tf.Tensor
|
156 |
+
Probabilidad posterior calculada combinando la l贸gica bayesiana.
|
157 |
+
quantum_projections: tf.Tensor
|
158 |
+
Proyecciones cu谩nticas normalizadas (distancias softmax).
|
159 |
+
"""
|
160 |
+
quantum_projections = self.quantum_cosine_projection(
|
161 |
+
quantum_states,
|
162 |
+
entropy,
|
163 |
+
coherence
|
164 |
+
)
|
165 |
+
|
166 |
+
# Calcular covarianza en las proyecciones
|
167 |
+
tensor_projections = tf.convert_to_tensor(quantum_projections, dtype=tf.float32)
|
168 |
+
quantum_covariance = tfp.stats.covariance(tensor_projections, sample_axis=0)
|
169 |
+
|
170 |
+
# Calcular prior cu谩ntico basado en la traza de la covarianza
|
171 |
+
dim = tf.cast(tf.shape(quantum_covariance)[0], tf.float32)
|
172 |
+
quantum_prior = tf.linalg.trace(quantum_covariance) / dim
|
173 |
+
|
174 |
+
# Calcular otros componentes para la posteriori (usando m茅todos heredados de BayesLogic).
|
175 |
+
prior_coherence = self.calculate_high_coherence_prior(coherence)
|
176 |
+
joint_prob = self.calculate_joint_probability(
|
177 |
+
coherence,
|
178 |
+
1, # variable arbitraria: "evento" = 1
|
179 |
+
tf.reduce_mean(tensor_projections)
|
180 |
+
)
|
181 |
+
cond_prob = self.calculate_conditional_probability(joint_prob, quantum_prior)
|
182 |
+
posterior = self.calculate_posterior_probability(quantum_prior,
|
183 |
+
prior_coherence,
|
184 |
+
cond_prob)
|
185 |
+
return posterior, quantum_projections
|
186 |
+
|
187 |
+
def predict_quantum_state(self,
|
188 |
+
quantum_states: np.ndarray,
|
189 |
+
entropy: float,
|
190 |
+
coherence: float):
|
191 |
+
"""
|
192 |
+
Predice el siguiente estado cu谩ntico con base en la proyecci贸n y la distancia
|
193 |
+
de Mahalanobis, generando un "estado futuro".
|
194 |
+
|
195 |
+
Par谩metros:
|
196 |
+
-----------
|
197 |
+
quantum_states: np.ndarray
|
198 |
+
Estados cu谩nticos de entrada (n_muestras, 2).
|
199 |
+
entropy: float
|
200 |
+
Entrop铆a del sistema.
|
201 |
+
coherence: float
|
202 |
+
Coherencia del sistema.
|
203 |
+
|
204 |
+
Retorna:
|
205 |
+
--------
|
206 |
+
next_state_prediction: tf.Tensor
|
207 |
+
Predicci贸n del siguiente estado cu谩ntico.
|
208 |
+
posterior: tf.Tensor
|
209 |
+
Probabilidad posterior que se us贸 en la predicci贸n.
|
210 |
+
"""
|
211 |
+
posterior, projections = self.calculate_quantum_posterior_with_mahalanobis(
|
212 |
+
quantum_states,
|
213 |
+
entropy,
|
214 |
+
coherence
|
215 |
+
)
|
216 |
+
|
217 |
+
# Generar un estado futuro ponderado por la posterior
|
218 |
+
# Posterior es escalar, mientras que projections es un vector
|
219 |
+
next_state_prediction = tf.reduce_sum(
|
220 |
+
tf.multiply(projections, tf.expand_dims(posterior, -1)),
|
221 |
+
axis=0
|
222 |
+
)
|
223 |
+
return next_state_prediction, posterior
|
224 |
+
|
225 |
+
|
226 |
+
class EnhancedPRN(PRN):
|
227 |
+
"""
|
228 |
+
Extiende la clase PRN para registrar distancias de Mahalanobis y con ello
|
229 |
+
definir un 'ruido cu谩ntico' adicional en el sistema.
|
230 |
+
"""
|
231 |
+
def __init__(self, influence: float = 0.5, algorithm_type: str = None, **parameters):
|
232 |
+
"""
|
233 |
+
Constructor que permite definir la influencia y el tipo de algoritmo,
|
234 |
+
adem谩s de inicializar una lista para conservar registros promedio de
|
235 |
+
distancias de Mahalanobis.
|
236 |
+
"""
|
237 |
+
super().__init__(influence, algorithm_type, **parameters)
|
238 |
+
self.mahalanobis_records = []
|
239 |
+
|
240 |
+
def record_quantum_noise(self, probabilities: dict, quantum_states: np.ndarray):
|
241 |
+
"""
|
242 |
+
Registra un 'ruido cu谩ntico' basado en la distancia de Mahalanobis
|
243 |
+
calculada para los estados cu谩nticos.
|
244 |
+
|
245 |
+
Par谩metros:
|
246 |
+
-----------
|
247 |
+
probabilities: dict
|
248 |
+
Diccionario de probabilidades (ej. {"0": p_0, "1": p_1, ...}).
|
249 |
+
quantum_states: np.ndarray
|
250 |
+
Estados cu谩nticos (n_muestras, n_dimensiones).
|
251 |
+
|
252 |
+
Retorna:
|
253 |
+
--------
|
254 |
+
(entropy, mahal_mean): Tuple[float, float]
|
255 |
+
- Entrop铆a calculada a partir de probabilities.
|
256 |
+
- Distancia promedio de Mahalanobis.
|
257 |
+
"""
|
258 |
+
# Calculamos la entrop铆a (este m茅todo se asume en la clase base PRN o BayesLogic).
|
259 |
+
entropy = self.record_noise(probabilities)
|
260 |
+
|
261 |
+
# Ajuste del estimador de covarianza
|
262 |
+
cov_estimator = EmpiricalCovariance().fit(quantum_states)
|
263 |
+
mean_state = np.mean(quantum_states, axis=0)
|
264 |
+
inv_cov = np.linalg.pinv(cov_estimator.covariance_)
|
265 |
+
|
266 |
+
# C谩lculo vectorizado de la distancia
|
267 |
+
diff = quantum_states - mean_state
|
268 |
+
aux = diff @ inv_cov
|
269 |
+
dist_sqr = np.einsum('ij,ij->i', aux, diff)
|
270 |
+
distances = np.sqrt(dist_sqr)
|
271 |
+
mahal_mean = np.mean(distances)
|
272 |
+
|
273 |
+
def von_neumann_entropy(density_matrix: np.ndarray) -> float:
|
274 |
+
"""Calcula la entrop铆a de von Neumann para una matriz de densidad."""
|
275 |
+
# Se calculan los valores propios (eigenvalues)
|
276 |
+
eigenvalues = np.linalg.eigvalsh(density_matrix)
|
277 |
+
# Se filtran los valores propios que son cero o negativos para evitar errores en el logaritmo
|
278 |
+
non_zero_eigenvalues = eigenvalues[eigenvalues > 0]
|
279 |
+
# Se calcula la entrop铆a: S = -Tr(蟻 log(蟻)) = -危 位_i log(位_i)
|
280 |
+
entropy = -np.sum(non_zero_eigenvalues * np.log(non_zero_eigenvalues))
|
281 |
+
# Se registra la distancia promedio
|
282 |
+
self.mahalanobis_records.append(mahal_mean)
|
283 |
+
|
284 |
+
return entropy, mahal_mean
|
285 |
+
|
286 |
+
class QuantumNoiseCollapse(QuantumBayesMahalanobis):
|
287 |
+
"""
|
288 |
+
Combina la l贸gica bayesiana cu谩ntica (QuantumBayesMahalanobis) y el registro ExtendedPRN
|
289 |
+
para simular el 'colapso de onda' usando distancias de Mahalanobis como parte del ruido.
|
290 |
+
"""
|
291 |
+
def __init__(self, prn_influence: float = 0.5):
|
292 |
+
"""
|
293 |
+
Constructor que crea internamente un EnhancedPRN por defecto, con una
|
294 |
+
influencia configurable.
|
295 |
+
"""
|
296 |
+
super().__init__()
|
297 |
+
self.prn = EnhancedPRN(influence=prn_influence)
|
298 |
+
|
299 |
+
def simulate_wave_collapse(self,
|
300 |
+
quantum_states: np.ndarray,
|
301 |
+
prn_influence: float,
|
302 |
+
previous_action: int):
|
303 |
+
"""
|
304 |
+
Simula el colapso de onda incorporando ruido cu谩ntico (a trav茅s de PRN) e
|
305 |
+
integra el resultado para determinar una acci贸n bayesiana.
|
306 |
+
|
307 |
+
Par谩metros:
|
308 |
+
-----------
|
309 |
+
quantum_states: np.ndarray
|
310 |
+
Estados cu谩nticos de entrada.
|
311 |
+
prn_influence: float
|
312 |
+
Influencia del PRN en el sistema (se puede alinear con self.prn.influence).
|
313 |
+
previous_action: int
|
314 |
+
Acci贸n previa del sistema que se utiliza como condicionante.
|
315 |
+
|
316 |
+
Retorna:
|
317 |
+
--------
|
318 |
+
dict con llaves:
|
319 |
+
"collapsed_state": tf.Tensor
|
320 |
+
Representaci贸n final colapsada del estado.
|
321 |
+
"action": int
|
322 |
+
Acci贸n tomada seg煤n l贸gica bayesiana.
|
323 |
+
"entropy": float
|
324 |
+
Entrop铆a calculada.
|
325 |
+
"coherence": float
|
326 |
+
Coherencia derivada.
|
327 |
+
"mahalanobis_distance": float
|
328 |
+
Distancia promedio de Mahalanobis.
|
329 |
+
"cosines": Tuple[float, float, float]
|
330 |
+
Valores de (cos_x, cos_y, cos_z) usados en la proyecci贸n.
|
331 |
+
"""
|
332 |
+
# Diccionario de probabilidades a modo de ejemplo
|
333 |
+
probabilities = {str(i): np.sum(state) for i, state in enumerate(quantum_states)}
|
334 |
+
|
335 |
+
# Registro de entrop铆a y distancia de Mahalanobis
|
336 |
+
entropy, mahalanobis_mean = self.prn.record_quantum_noise(probabilities, quantum_states)
|
337 |
+
|
338 |
+
# C谩lculo de los cosenos directores como ejemplo de proyecci贸n
|
339 |
+
cos_x, cos_y, cos_z = calculate_cosines(entropy, mahalanobis_mean)
|
340 |
+
|
341 |
+
# Definimos coherencia a partir de la distancia de Mahalanobis y los cosenos
|
342 |
+
coherence = np.exp(-mahalanobis_mean) * (cos_x + cos_y + cos_z) / 3.0
|
343 |
+
|
344 |
+
# Llamada a un m茅todo de BayesLogic para decidir la acci贸n
|
345 |
+
bayes_probs = self.calculate_probabilities_and_select_action(
|
346 |
+
entropy=entropy,
|
347 |
+
coherence=coherence,
|
348 |
+
prn_influence=prn_influence,
|
349 |
+
action=previous_action
|
350 |
+
)
|
351 |
+
|
352 |
+
# Proyectar estados cu谩nticos
|
353 |
+
projected_states = self.quantum_cosine_projection(
|
354 |
+
quantum_states,
|
355 |
+
entropy,
|
356 |
+
coherence
|
357 |
+
)
|
358 |
+
|
359 |
+
# Ejemplo de 'colapso' multiplicando la proyecci贸n por la acci贸n que se toma
|
360 |
+
collapsed_state = tf.reduce_sum(
|
361 |
+
tf.multiply(
|
362 |
+
projected_states,
|
363 |
+
tf.cast(bayes_probs["action_to_take"], tf.float32)
|
364 |
+
)
|
365 |
+
)
|
366 |
+
|
367 |
+
return {
|
368 |
+
"collapsed_state": collapsed_state,
|
369 |
+
"action": bayes_probs["action_to_take"],
|
370 |
+
"entropy": entropy,
|
371 |
+
"coherence": coherence,
|
372 |
+
"mahalanobis_distance": mahalanobis_mean,
|
373 |
+
"cosines": (cos_x, cos_y, cos_z)
|
374 |
+
}
|
375 |
+
|
376 |
+
def objective_function_with_noise(self,
|
377 |
+
quantum_states: np.ndarray,
|
378 |
+
target_state: np.ndarray,
|
379 |
+
entropy_weight: float = 1.0) -> tf.Tensor:
|
380 |
+
"""
|
381 |
+
Funci贸n objetivo que combina fidelidad, entrop铆a y distancia de Mahalanobis
|
382 |
+
para encontrar un compromiso entre mantener la fidelidad al estado objetivo
|
383 |
+
y el ruido cu谩ntico en el sistema.
|
384 |
+
|
385 |
+
Par谩metros:
|
386 |
+
-----------
|
387 |
+
quantum_states: np.ndarray
|
388 |
+
Estados cu谩nticos actuales (n_muestras, n_dimensiones).
|
389 |
+
target_state: np.ndarray
|
390 |
+
Estado objetivo que se desea alcanzar.
|
391 |
+
entropy_weight: float
|
392 |
+
Factor que pondera la influencia de la entrop铆a en la funci贸n objetivo.
|
393 |
+
|
394 |
+
Retorna:
|
395 |
+
--------
|
396 |
+
objective_value: tf.Tensor
|
397 |
+
Valor de la funci贸n objetivo (cuanto menor, mejor).
|
398 |
+
"""
|
399 |
+
# Calcular fidelidad (simple ejemplo): |<蠄|蠁>|^2
|
400 |
+
# Suponiendo que (quantum_states y target_state) sean vectores compatibles
|
401 |
+
fidelity = tf.abs(tf.reduce_sum(quantum_states * tf.cast(target_state, quantum_states.dtype)))**2
|
402 |
+
|
403 |
+
# Registrar 'ruido': entrop铆a y distancia de Mahalanobis
|
404 |
+
probabilities = {str(i): np.sum(st) for i, st in enumerate(quantum_states)}
|
405 |
+
entropy, mahalanobis_dist = self.prn.record_quantum_noise(probabilities, quantum_states)
|
406 |
+
|
407 |
+
# Combinar m茅tricas: (1 - fidelidad) + factor * entrop铆a + penalizaci贸n por distancia
|
408 |
+
objective_value = ((1.0 - fidelity)
|
409 |
+
+ entropy_weight * entropy
|
410 |
+
+ (1.0 - np.exp(-mahalanobis_dist)))
|
411 |
+
|
412 |
+
return objective_value
|
413 |
+
|
414 |
+
def optimize_quantum_state(self,
|
415 |
+
initial_states: np.ndarray,
|
416 |
+
target_state: np.ndarray,
|
417 |
+
max_iterations: int = 100,
|
418 |
+
learning_rate: float = 0.01):
|
419 |
+
"""
|
420 |
+
Optimiza los estados cu谩nticos para acercarlos al estado objetivo,
|
421 |
+
mediante un descenso de gradiente (Adam).
|
422 |
+
|
423 |
+
Par谩metros:
|
424 |
+
-----------
|
425 |
+
initial_states: np.ndarray
|
426 |
+
Estados cu谩nticos iniciales.
|
427 |
+
target_state: np.ndarray
|
428 |
+
Estado objetivo.
|
429 |
+
max_iterations: int
|
430 |
+
N煤mero m谩ximo de iteraciones de optimizaci贸n.
|
431 |
+
learning_rate: float
|
432 |
+
Tasa de aprendizaje para Adam.
|
433 |
+
|
434 |
+
Retorna:
|
435 |
+
--------
|
436 |
+
best_states: np.ndarray
|
437 |
+
Estados optimizados que reportan el menor valor de la funci贸n objetivo.
|
438 |
+
best_objective: float
|
439 |
+
Valor final alcanzado por la funci贸n objetivo.
|
440 |
+
"""
|
441 |
+
# Convertir a tf.Variable para permitir gradientes
|
442 |
+
current_states = tf.Variable(initial_states, dtype=tf.float32)
|
443 |
+
|
444 |
+
best_objective = float('inf')
|
445 |
+
best_states = current_states.numpy().copy()
|
446 |
+
|
447 |
+
optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)
|
448 |
+
|
449 |
+
for _ in range(max_iterations):
|
450 |
+
with tf.GradientTape() as tape:
|
451 |
+
# Usar numpy() en la llamada para separar l贸gicamente la parte TF de la parte numpy
|
452 |
+
objective = self.objective_function_with_noise(current_states.numpy(), target_state)
|
453 |
+
grads = tape.gradient(objective, [current_states])
|
454 |
+
|
455 |
+
if grads[0] is None:
|
456 |
+
# Si no hay gradiente, rompe el bucle
|
457 |
+
break
|
458 |
+
|
459 |
+
optimizer.apply_gradients(zip(grads, [current_states]))
|
460 |
+
|
461 |
+
# Re-evaluar despu茅s de actualizar los par谩metros
|
462 |
+
new_objective = self.objective_function_with_noise(current_states.numpy(), target_state)
|
463 |
+
if new_objective < best_objective:
|
464 |
+
best_objective = new_objective
|
465 |
+
best_states = current_states.numpy().copy()
|
466 |
+
|
467 |
+
return best_states, best_objective
|
468 |
+
|
469 |
+
|
470 |
+
# ====================
|
471 |
+
# Ejemplo de uso
|
472 |
+
# ====================
|
473 |
+
if __name__ == "__main__":
|
474 |
+
qnc = QuantumNoiseCollapse()
|
475 |
+
|
476 |
+
# Estados cu谩nticos iniciales
|
477 |
+
initial_states = np.array([
|
478 |
+
[0.8, 0.2],
|
479 |
+
[0.9, 0.4],
|
480 |
+
[0.1, 0.7]
|
481 |
+
])
|
482 |
+
|
483 |
+
# Estado objetivo
|
484 |
+
target_state = np.array([1.0, 0.0])
|
485 |
+
|
486 |
+
# Optimizar estados
|
487 |
+
optimized_states, final_objective = qnc.optimize_quantum_state(
|
488 |
+
initial_states,
|
489 |
+
target_state,
|
490 |
+
max_iterations=100,
|
491 |
+
learning_rate=0.01
|
492 |
+
)
|
493 |
+
|
494 |
+
# Simular colapso final con la acci贸n previa (ej. 0)
|
495 |
+
final_collapse = qnc.simulate_wave_collapse(
|
496 |
+
optimized_states,
|
497 |
+
prn_influence=0.5,
|
498 |
+
previous_action=0
|
499 |
+
)
|
500 |
+
|
501 |
+
print("Estados optimizados:", optimized_states)
|
502 |
+
print("Valor final de la funci贸n objetivo:", final_objective)
|
503 |
+
print("Resultado del colapso final:", final_collapse)
|