Quantum Mechanics Foundations¶
This page provides a comprehensive introduction to the quantum mechanics principles underlying QE-KGR. Understanding these concepts is crucial for effectively using quantum entangled knowledge graphs.
🌊 Quantum Mechanics Basics¶
Wave-Particle Duality¶
Quantum mechanics reveals that particles exhibit both wave and particle properties. In QE-KGR, knowledge entities are represented as quantum states that can exist in superposition - simultaneously embodying multiple characteristics.
import numpy as np
from qekgr import EntangledGraph
# A node can be in superposition of multiple states
graph = EntangledGraph(hilbert_dim=4)
# Superposition state: 60% physicist + 40% engineer
superposition_state = np.array([0.6, 0.4, 0.0, 0.0])
node = graph.add_quantum_node("Alex", state=superposition_state)
print(f"State amplitudes: {node.state_vector}")
print(f"Probabilities: {np.abs(node.state_vector)**2}")
Quantum Superposition¶
Mathematical Foundation: A quantum state |ψ⟩ can be written as a linear combination of basis states:
where \(|\alpha|^2 + |\beta|^2 + |\gamma|^2 + |\delta|^2 = 1\) (normalization condition).
In QE-KGR:
# Create superposition of entity types
alpha, beta, gamma, delta = 0.5, 0.5, 0.5, 0.5
# Normalize
norm = np.sqrt(alpha**2 + beta**2 + gamma**2 + delta**2)
superposition = np.array([alpha, beta, gamma, delta]) / norm
entity = graph.add_quantum_node("Entity", state=superposition)
print(f"Entity exists in superposition: {entity.state_vector}")
Quantum Entanglement¶
Definition: Quantum entanglement occurs when particles become correlated such that the quantum state of each particle cannot be described independently.
Mathematical Representation: For two entangled qubits: \(\(|\psi\rangle = \frac{1}{\sqrt{2}}(|00\rangle + |11\rangle)\)\)
In Knowledge Graphs:
# Create entangled relationship
graph.add_entangled_edge("Alice", "Bob",
relations=["collaborates", "friends", "co-authors"],
amplitudes=[0.8, 0.6, 0.4])
# The relationship exists in quantum superposition
# When measured, it collapses to one specific relation
edge = graph.edges[("Alice", "Bob")]
measured_relation = edge.collapse_relation()
print(f"Measured relation: {measured_relation}")
🎯 Quantum States in Knowledge Representation¶
Pure States vs Mixed States¶
Pure State: Complete quantum information, represented by state vector |ψ⟩
# Pure state - complete information
pure_state = np.array([1.0, 0.0, 0.0, 0.0]) # Definitely in state |0⟩
node_pure = graph.add_quantum_node("PureEntity", state=pure_state)
print(f"Entropy (pure): {node_pure.measure_entropy():.3f}") # Should be 0
Mixed State: Incomplete information, represented by density matrix ρ
# Mixed state - statistical mixture
# 70% probability |0⟩, 30% probability |1⟩
p0, p1 = 0.7, 0.3
density_matrix = p0 * np.outer([1,0,0,0], [1,0,0,0]) + p1 * np.outer([0,1,0,0], [0,1,0,0])
node_mixed = graph.add_quantum_node("MixedEntity", state=None)
node_mixed.density_matrix = density_matrix
print(f"Entropy (mixed): {node_mixed.measure_entropy():.3f}") # > 0
Hilbert Space Representation¶
Hilbert Space: Complex vector space with inner product, where quantum states live.
Dimensionality in QE-KGR:
- 2D: Binary characteristics (yes/no, active/inactive)
- 4D: Quaternary states (4 distinct entity types)
- 8D: Octal representation (richer quantum effects)
- 16D+: High-dimensional semantic embeddings
# Different Hilbert space dimensions
binary_graph = EntangledGraph(hilbert_dim=2) # Simple binary states
quaternary_graph = EntangledGraph(hilbert_dim=4) # Quaternary states
complex_graph = EntangledGraph(hilbert_dim=8) # Rich quantum effects
print(f"State space sizes: {2**1}, {2**2}, {2**3}")
Bloch Sphere Representation (2D Case)¶
For 2-dimensional Hilbert space, quantum states can be visualized on the Bloch sphere:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def bloch_sphere_coordinates(state_vector):
"""Convert 2D quantum state to Bloch sphere coordinates."""
if len(state_vector) != 2:
raise ValueError("Bloch sphere only for 2D states")
alpha, beta = state_vector[0], state_vector[1]
# Bloch sphere coordinates
x = 2 * np.real(alpha * np.conj(beta))
y = 2 * np.imag(alpha * np.conj(beta))
z = np.abs(alpha)**2 - np.abs(beta)**2
return x, y, z
# Example: Entity in superposition
theta = np.pi/3 # 60 degrees
entity_state = np.array([np.cos(theta/2), np.sin(theta/2)])
x, y, z = bloch_sphere_coordinates(entity_state)
print(f"Bloch coordinates: ({x:.3f}, {y:.3f}, {z:.3f})")
⚛️ Quantum Operations in Graphs¶
Quantum Gates and Unitary Operations¶
Unitary Evolution: Quantum states evolve through unitary transformations U: \(\(|\psi'⟩ = U|\psi⟩\)\)
Common Quantum Gates:
# Pauli-X gate (bit flip)
pauli_x = np.array([[0, 1], [1, 0]])
# Pauli-Y gate
pauli_y = np.array([[0, -1j], [1j, 0]])
# Pauli-Z gate (phase flip)
pauli_z = np.array([[1, 0], [0, -1]])
# Hadamard gate (creates superposition)
hadamard = np.array([[1, 1], [1, -1]]) / np.sqrt(2)
# Apply Hadamard to create superposition
initial_state = np.array([1, 0]) # |0⟩
superposition = hadamard @ initial_state
print(f"After Hadamard: {superposition}") # (|0⟩ + |1⟩)/√2
Quantum Measurements¶
Born Rule: Probability of measuring state |φ⟩ in state |ψ⟩ is |⟨φ|ψ⟩|²
def measure_state(state_vector, measurement_basis):
"""Measure quantum state in given basis."""
probabilities = np.abs(np.dot(measurement_basis.conj(), state_vector))**2
# Collapse state (measurement)
outcome = np.random.choice(len(probabilities), p=probabilities)
collapsed_state = measurement_basis[:, outcome]
return outcome, collapsed_state, probabilities
# Example measurement
state = np.array([0.6, 0.8]) # Normalized superposition
computational_basis = np.eye(2) # |0⟩, |1⟩ basis
outcome, collapsed, probs = measure_state(state, computational_basis)
print(f"Measurement outcome: {outcome}")
print(f"Collapsed state: {collapsed}")
print(f"Probabilities: {probs}")
🔗 Quantum Entanglement Theory¶
Bell States¶
Maximally Entangled States: \(\(|\Phi^+\rangle = \frac{1}{\sqrt{2}}(|00\rangle + |11\rangle)\)\) \(\(|\Phi^-\rangle = \frac{1}{\sqrt{2}}(|00\rangle - |11\rangle)\)\) \(\(|\Psi^+\rangle = \frac{1}{\sqrt{2}}(|01\rangle + |10\rangle)\)\) \(\(|\Psi^-\rangle = \frac{1}{\sqrt{2}}(|01\rangle - |10\rangle)\)\)
# Create Bell state between two entities
def create_bell_state(graph, node1_id, node2_id, bell_type="phi_plus"):
"""Create maximally entangled Bell state between two nodes."""
bell_states = {
"phi_plus": np.array([1, 0, 0, 1]) / np.sqrt(2),
"phi_minus": np.array([1, 0, 0, -1]) / np.sqrt(2),
"psi_plus": np.array([0, 1, 1, 0]) / np.sqrt(2),
"psi_minus": np.array([0, 1, -1, 0]) / np.sqrt(2)
}
entangled_state = bell_states[bell_type]
# Add maximally entangled edge
graph.add_entangled_edge(node1_id, node2_id,
relations=["quantum_correlated"],
amplitudes=[1.0])
return entangled_state
# Create Bell pair
bell_state = create_bell_state(graph, "Alice", "Bob", "phi_plus")
print(f"Bell state: {bell_state}")
Entanglement Entropy¶
Von Neumann Entropy: Measure of entanglement in quantum states \(\(S(\rho) = -\text{Tr}(\rho \log_2 \rho)\)\)
def von_neumann_entropy(density_matrix):
"""Calculate von Neumann entropy of quantum state."""
eigenvalues = np.linalg.eigvals(density_matrix)
# Remove zero eigenvalues to avoid log(0)
nonzero_eigenvals = eigenvalues[eigenvalues > 1e-12]
entropy = -np.sum(nonzero_eigenvals * np.log2(nonzero_eigenvals))
return entropy
# Compare entropies
pure_state_rho = np.outer([1,0], [1,0]) # |0⟩⟨0|
mixed_state_rho = 0.5 * np.outer([1,0], [1,0]) + 0.5 * np.outer([0,1], [0,1])
print(f"Pure state entropy: {von_neumann_entropy(pure_state_rho):.3f}")
print(f"Mixed state entropy: {von_neumann_entropy(mixed_state_rho):.3f}")
Schmidt Decomposition¶
For bipartite systems, any pure state can be written as: \(\(|\psi\rangle = \sum_i \sqrt{\lambda_i} |i_A\rangle \otimes |i_B\rangle\)\)
def schmidt_decomposition(bipartite_state, dim_A, dim_B):
"""Perform Schmidt decomposition of bipartite quantum state."""
# Reshape state vector into matrix
state_matrix = bipartite_state.reshape(dim_A, dim_B)
# Singular Value Decomposition
U, s, Vh = np.linalg.svd(state_matrix)
# Schmidt coefficients are singular values
schmidt_coeffs = s
# Schmidt rank (number of non-zero coefficients)
schmidt_rank = np.sum(s > 1e-12)
return schmidt_coeffs, schmidt_rank, U, Vh
# Example: Entangled state
entangled_state = np.array([1, 0, 0, 1]) / np.sqrt(2) # Bell state
coeffs, rank, U, Vh = schmidt_decomposition(entangled_state, 2, 2)
print(f"Schmidt coefficients: {coeffs}")
print(f"Schmidt rank: {rank}")
print(f"Entanglement: {'Yes' if rank > 1 else 'No'}")
🌊 Quantum Interference¶
Constructive and Destructive Interference¶
Amplitude Addition: When quantum paths combine, amplitudes add: \(\(A_{total} = A_1 + A_2\)\)
Probability: \(P = |A_{total}|^2 = |A_1 + A_2|^2\)
def quantum_interference_demo():
"""Demonstrate quantum interference effects."""
# Two quantum paths with different phases
amplitude_1 = 0.7 * np.exp(1j * 0) # Path 1: real amplitude
amplitude_2 = 0.7 * np.exp(1j * np.pi) # Path 2: opposite phase
# Constructive interference (same phase)
constructive = amplitude_1 + amplitude_1
prob_constructive = np.abs(constructive)**2
# Destructive interference (opposite phases)
destructive = amplitude_1 + amplitude_2
prob_destructive = np.abs(destructive)**2
print(f"Constructive interference probability: {prob_constructive:.3f}")
print(f"Destructive interference probability: {prob_destructive:.3f}")
return constructive, destructive
constructive, destructive = quantum_interference_demo()
Interference in Quantum Walks¶
from qekgr import QuantumInference
def analyze_quantum_walk_interference(graph):
"""Analyze interference patterns in quantum walks."""
inference = QuantumInference(graph)
# Perform quantum walk
walk_result = inference.quantum_walk("Alice", steps=10)
# Analyze interference pattern
interference = walk_result.interference_pattern
# Find constructive interference peaks
mean_amplitude = np.mean(np.abs(interference))
constructive_nodes = np.where(np.abs(interference) > 1.5 * mean_amplitude)[0]
print(f"Constructive interference at nodes: {constructive_nodes}")
print(f"Mean amplitude: {mean_amplitude:.3f}")
print(f"Max interference: {np.max(np.abs(interference)):.3f}")
return interference
# Analyze interference in your graph
interference_pattern = analyze_quantum_walk_interference(graph)
📊 Quantum Information Theory¶
Quantum Mutual Information¶
Classical Mutual Information: \(I(A:B) = H(A) + H(B) - H(A,B)\)
Quantum Mutual Information: \(I(\rho_{AB}) = S(\rho_A) + S(\rho_B) - S(\rho_{AB})\)
def quantum_mutual_information(joint_density_matrix, dim_A, dim_B):
"""Calculate quantum mutual information between subsystems."""
# Partial traces to get reduced density matrices
rho_A = partial_trace(joint_density_matrix, dim_B, 'B')
rho_B = partial_trace(joint_density_matrix, dim_A, 'A')
# Von Neumann entropies
S_A = von_neumann_entropy(rho_A)
S_B = von_neumann_entropy(rho_B)
S_AB = von_neumann_entropy(joint_density_matrix)
# Quantum mutual information
I_AB = S_A + S_B - S_AB
return I_AB
def partial_trace(rho, dim_trace_out, subsystem):
"""Compute partial trace of density matrix."""
if subsystem == 'A':
# Trace out subsystem A
dim_keep = rho.shape[0] // dim_trace_out
rho_B = np.zeros((dim_keep, dim_keep), dtype=complex)
for i in range(dim_trace_out):
rho_B += rho[i*dim_keep:(i+1)*dim_keep, i*dim_keep:(i+1)*dim_keep]
return rho_B
else:
# Trace out subsystem B
dim_keep = rho.shape[0] // dim_trace_out
rho_A = np.zeros((dim_keep, dim_keep), dtype=complex)
for i in range(dim_keep):
for j in range(dim_keep):
for k in range(dim_trace_out):
rho_A[i,j] += rho[i*dim_trace_out + k, j*dim_trace_out + k]
return rho_A
Quantum Discord¶
Quantum Discord: Measures quantum correlations beyond entanglement \(\(\mathcal{D}(\rho_{AB}) = I(\rho_{AB}) - \max_{\{M_k\}} I(\rho_{AB}|\{M_k\})\)\)
def quantum_discord_approximation(joint_state, dim_A, dim_B):
"""Approximate quantum discord calculation."""
# This is a simplified approximation
# Full calculation requires optimization over all possible measurements
joint_rho = np.outer(joint_state, joint_state.conj())
# Quantum mutual information
I_quantum = quantum_mutual_information(joint_rho, dim_A, dim_B)
# Classical mutual information (approximation using computational basis)
I_classical = classical_mutual_information_approx(joint_rho, dim_A, dim_B)
# Discord approximation
discord = I_quantum - I_classical
return max(0, discord) # Discord is non-negative
def classical_mutual_information_approx(joint_rho, dim_A, dim_B):
"""Approximate classical mutual information."""
# This is simplified - full calculation requires optimization
# Here we use computational basis measurement
# Extract probabilities from diagonal elements
probs_joint = np.diag(joint_rho).real
# Marginal probabilities
probs_A = np.zeros(dim_A)
probs_B = np.zeros(dim_B)
for i in range(dim_A):
for j in range(dim_B):
idx = i * dim_B + j
probs_A[i] += probs_joint[idx]
probs_B[j] += probs_joint[idx]
# Classical mutual information calculation
I_classical = 0
for i in range(dim_A):
for j in range(dim_B):
idx = i * dim_B + j
if probs_joint[idx] > 0 and probs_A[i] > 0 and probs_B[j] > 0:
I_classical += probs_joint[idx] * np.log2(probs_joint[idx] / (probs_A[i] * probs_B[j]))
return I_classical
🔄 Quantum Decoherence¶
Environmental Interaction¶
Decoherence: Loss of quantum coherence due to environmental interaction
Master Equation: \(\(\frac{d\rho}{dt} = -\frac{i}{\hbar}[H, \rho] + \mathcal{L}[\rho]\)\)
where \(\mathcal{L}[\rho]\) is the Lindblad superoperator describing decoherence.
def simulate_decoherence(initial_state, decoherence_rate, time_steps):
"""Simulate quantum decoherence over time."""
state = initial_state.copy()
density_matrix = np.outer(state, state.conj())
# Time evolution with decoherence
dt = 0.1
coherence_trace = []
for t in range(time_steps):
# Decoherence: exponential decay of off-diagonal elements
for i in range(len(state)):
for j in range(len(state)):
if i != j: # Off-diagonal elements
density_matrix[i,j] *= np.exp(-decoherence_rate * dt)
# Measure coherence (sum of off-diagonal elements)
coherence = np.sum(np.abs(density_matrix - np.diag(np.diag(density_matrix))))
coherence_trace.append(coherence)
return density_matrix, coherence_trace
# Simulate decoherence of superposition state
superposition = np.array([1, 1]) / np.sqrt(2)
final_state, coherence = simulate_decoherence(superposition, decoherence_rate=0.1, time_steps=50)
print(f"Initial coherence: {coherence[0]:.3f}")
print(f"Final coherence: {coherence[-1]:.3f}")
🎯 Applications in Knowledge Graphs¶
Quantum-Enhanced Entity Resolution¶
def quantum_entity_resolution(graph, entity1, entity2):
"""Use quantum overlap to determine if entities are the same."""
node1 = graph.nodes[entity1]
node2 = graph.nodes[entity2]
# Quantum state overlap
overlap = np.abs(np.vdot(node1.state_vector, node2.state_vector))**2
# Metadata similarity (classical)
metadata_sim = jaccard_similarity(node1.metadata, node2.metadata)
# Combined quantum-classical similarity
similarity = 0.7 * overlap + 0.3 * metadata_sim
return similarity, overlap, metadata_sim
def jaccard_similarity(dict1, dict2):
"""Calculate Jaccard similarity between two dictionaries."""
set1 = set(str(v) for v in dict1.values())
set2 = set(str(v) for v in dict2.values())
intersection = len(set1 & set2)
union = len(set1 | set2)
return intersection / union if union > 0 else 0
# Example usage
similarity, q_overlap, c_similarity = quantum_entity_resolution(graph, "Alice", "Bob")
print(f"Total similarity: {similarity:.3f}")
print(f"Quantum overlap: {q_overlap:.3f}")
print(f"Classical similarity: {c_similarity:.3f}")
Quantum Link Prediction¶
def quantum_link_prediction(graph, source, target):
"""Predict link probability using quantum interference."""
# Find all paths between source and target
paths = find_quantum_paths(graph, source, target, max_length=4)
# Calculate quantum amplitudes for each path
total_amplitude = 0
for path in paths:
path_amplitude = calculate_path_amplitude(graph, path)
total_amplitude += path_amplitude
# Link probability from quantum amplitude
link_probability = np.abs(total_amplitude)**2
return link_probability, paths
def find_quantum_paths(graph, source, target, max_length):
"""Find all quantum paths between two nodes."""
# Simplified implementation - use networkx for path finding
import networkx as nx
classical_graph = graph._graph # NetworkX representation
try:
paths = list(nx.all_simple_paths(classical_graph, source, target, max_length))
return paths[:10] # Limit to first 10 paths
except nx.NetworkXNoPath:
return []
def calculate_path_amplitude(graph, path):
"""Calculate quantum amplitude along a path."""
amplitude = 1.0 + 0j
for i in range(len(path) - 1):
edge_key = (path[i], path[i+1])
if edge_key in graph.edges:
edge = graph.edges[edge_key]
# Use mean amplitude of superposed relations
edge_amplitude = np.mean(edge.amplitudes)
amplitude *= edge_amplitude
else:
amplitude *= 0.1 # Small amplitude for missing edges
return amplitude
# Predict missing link
prob, paths = quantum_link_prediction(graph, "Alice", "Charlie")
print(f"Link prediction probability: {prob:.3f}")
print(f"Found {len(paths)} quantum paths")
📚 Further Reading¶
Textbooks¶
- Nielsen & Chuang: "Quantum Computation and Quantum Information"
- Preskill: "Lecture Notes on Quantum Computation"
- Wilde: "Quantum Information Theory"
Research Papers¶
- Quantum Walks: "Quantum walks and search algorithms" (Shenvi et al.)
- Quantum Machine Learning: "Quantum advantage in learning" (Liu et al.)
- Graph Theory: "Spectral Graph Theory" (Chung)
Online Resources¶
Understanding these quantum mechanics foundations will greatly enhance your ability to design and interpret quantum entangled knowledge graphs. The interplay between quantum superposition, entanglement, and interference creates powerful new possibilities for knowledge representation and reasoning! 🌊⚛️