Code Walkthrough
1: Initialization
Begin by initializing the Qiskit Runtime Service using an IBM Quantum API key and connect to ibm_kyoto backend.
2. Quantum Circuit Construction
A quantum circuit is created with 127 qubits (q0, q1, ..., q126) and 127 classical bits for measurement (c0, c1, ..., c126).
This circuit will represent the quantum states of gravitational instantons.
We map instanton configurations to quantum states using rotational gates. Specifically, we apply a rotation around the Y-axis on each qubit:
RY(θi) = exp (−i(θ_i/2)σ_y)
where σ_y is the Pauli-Y matrix, and θ_i = (π/2^(i+1)) for the i-th qubit. This represents a gradual rotation with decreasing angles across the qubits, simulating the complexity of the gravitational instantons.
A sequence of Controlled-NOT (CNOT) gates is applied to entangle adjacent qubits, simulating interactions between different parts of the instanton configuration:
CNOT(q_i, q_(i+1)) = ∣0⟩⟨0∣ ⊗ I + ∣1⟩⟨1∣ ⊗ X
where I is the identity matrix, and X is the Pauli-X matrix. This step entangles each qubit with its neighbor, forming a chain of entangled states.
We introduce a unitary operation that evolves the state of each qubit, representing the evolution of the gravitational instanton over time. The unitary operation is defined as:
U = ( 0, 1
1, e^(i * (π/4)))
This unitary is applied to all qubits, simulating the quantum dynamics of the system.
To simulate the annealing process towards a stable instanton configuration, we apply another round of rotations and phase shifts:
RY(π/4) and
Z = ( 1, 0
0, -1)
The RY(π/4) gate is applied to each qubit, followed by a Z-gate, which introduces a phase flip.
3. Measurement
The final quantum state is measured by mapping the quantum state of each qubit to the corresponding classical bit. This step collapses the quantum state into a classical outcome.
4. Transpilation and Optimization
The circuit is transpiled to optimize its execution on ibm_kyoto, ensuring that the quantum operations are mapped efficiently to the hardware's physical qubits. The transpiler rearranges the qubits and gates to minimize errors and reduce circuit depth while preserving the logical operations.
An optimization level of 3 is used, which allows for aggressive optimization of the circuit to reduce the number of gates and improve fidelity.
5. Execution
The quantum circuit is executed using SamplerV2 on ibm_kyoto. The sampler performs multiple shots (8192) to gather a statistical distribution of measurement outcomes. This data represents the probability distribution of different quantum states after the instanton simulation.
6. Results Analysis
The collected counts are plotted as a histogram to visualize the distribution of the final quantum states. This plot provides insight into how the gravitational instanton configurations evolved under quantum dynamics. The raw counts and backend data are saved to a JSON file for further analysis.
Code:
# imports
import numpy as np
from qiskit import QuantumCircuit, transpile
from qiskit.circuit.library import UnitaryGate
from qiskit_ibm_runtime import QiskitRuntimeService, Session, SamplerV2
from qiskit.visualization import plot_histogram # Import for histogram plotting
import json
import logging
import matplotlib.pyplot as plt
# IBM Quantum API key
api_key = "YOUR_IBM_API_KEY"
channel = "ibm_quantum" # Typical channel for IBM Quantum services
# Initialize Qiskit Runtime Service
service = QiskitRuntimeService(channel=channel, token=api_key)
# Backend
backend = service.backend("ibm_kyoto")
# Define the quantum states for abstract gravitational instantons
qc = QuantumCircuit(127, 127) # Define 127 qubits and 127 classical bits for measurement
# Mapping instanton configurations to quantum states across 127 qubits
for i in range(127):
qc.ry(np.pi / (2**(i+1)), i) # Applying different RY rotations to simulate complexity
# Add a sequence of CNOT gates to entangle the qubits, simulating interactions
for i in range(126):
qc.cx(i, i + 1)
# Evolve the state with unitary operators simulating path integrals
unitary = UnitaryGate(np.array([[1, 0], [0, np.exp(1j * np.pi/4)]]))
for i in range(127):
qc.append(unitary, [i])
# Quantum annealing-like evolution
for qubit in range(127):
qc.ry(np.pi / 4, qubit)
qc.z(qubit)
# Measurement
qc.measure(range(127), range(127))
# Calibration data - optimizing circuit
selected_qubits = range(127) # We use all 127 qubits in this case
qc = transpile(qc, backend=backend, initial_layout=selected_qubits, optimization_level=3)
# Execution on backend with SamplerV2
with Session(service=service, backend=backend) as session:
sampler = SamplerV2(session=session)
# Run the circuit
job = sampler.run([qc], shots=8192)
job_result = job.result()
# Retrieve the classical register name
classical_register = qc.cregs[0].name
# Extract counts for the first (and only) pub result
pub_result = job_result[0].data[classical_register].get_counts()
# Save the results to JSON
results_data = {
"raw_counts": pub_result
}
file_path = '/Users/Documents/gravitational_instanton_results.json'
with open(file_path, 'w') as f:
json.dump(results_data, f, indent=4)
# Plotting the results for analysis
plot_histogram(pub_result)
plt.show()
CODE FOR VISUALS FROM RUN DATA
# imports
import json
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.spatial.distance import pdist, squareform
from sklearn.decomposition import PCA
from sklearn.manifold import MDS, TSNE
from scipy.cluster.hierarchy import dendrogram, linkage
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.animation import FuncAnimation
# Load the results from the JSON file
file_path = '/Users/Documents/gravitational_instanton_results.json'
with open(file_path, 'r') as file:
results_data = json.load(file)
# Extract the raw counts
raw_counts = results_data["raw_counts"]
# Convert the bitstrings into binary arrays
bitstrings = list(raw_counts.keys())
bitstrings_array = np.array([[int(bit) for bit in bitstring] for bitstring in bitstrings])
# Compute pairwise Hamming distances
hamming_distances = pdist(bitstrings_array, metric='hamming')
hamming_matrix = squareform(hamming_distances)
# Color scheme
plt.style.use('dark_background')
# Multidimensional Scaling (MDS) Visualization
def mds_visualization():
mds = MDS(n_components=2, dissimilarity="precomputed")
mds_coords = mds. fit_transform(hamming_matrix)
plt.figure(figsize=(10, 6))
plt.scatter(mds_coords[:, 0], mds_coords[:, 1], color='green', alpha=0.7)
plt.title('MDS of Quantum States Based on Hamming Distance', color='white')
plt.xlabel('MDS Dimension 1', color='white')
plt.ylabel('MDS Dimension 2', color='white')
plt.grid(True, color='gray')
plt.savefig('/Users/Documents/mds_visualization.png')
plt.show()
# t-SNE Visualization
def tsne_visualization():
tsne = TSNE(n_components=2, metric="hamming")
tsne_coords = tsne. fit_transform(bitstrings_array)
plt.figure(figsize=(10, 6))
plt.scatter(tsne_coords[:, 0], tsne_coords[:, 1], color='red', alpha=0.7)
plt.title('t-SNE Visualization of Quantum States', color='white')
plt.xlabel('t-SNE Dimension 1', color='white')
plt.ylabel('t-SNE Dimension 2', color='white')
plt.grid(True, color='gray')
plt.savefig('/Users/Documents/tsne_visualization.png')
plt.show()
# 3D PCA Visualization
def pca_3d_visualization():
pca_3d = PCA(n_components=3)
bitstrings_pca_3d = pca_3d.fit_transform(bitstrings_array)
fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(111, projection='3d')
ax.scatter(bitstrings_pca_3d[:, 0], bitstrings_pca_3d[:, 1], bitstrings_pca_3d[:, 2], color='blue', alpha=0.7)
ax.set_title('3D PCA of Quantum States', color='white')
ax.set_xlabel('Principal Component 1', color='white')
ax.set_ylabel('Principal Component 2', color='white')
ax.set_zlabel('Principal Component 3', color='white')
plt.savefig('/Users/Documents/pca_3d_visualization.png')
plt.show()
# Hierarchical Clustering Dendrogram
def hierarchical_clustering_dendrogram():
linked = linkage(bitstrings_array, 'ward')
plt.figure(figsize=(12, 8))
dendrogram(linked, orientation='top', distance_sort='descending', show_leaf_counts=True, color_threshold=None)
plt.title('Hierarchical Clustering Dendrogram of Quantum States', color='white')
plt.xlabel('Sample Index', color='white')
plt.ylabel('Distance', color='white')
plt.grid(True, color='gray')
plt.savefig('/Users/Documents/hierarchical_clustering_dendrogram.png')
plt.show()
# Correlation Matrix Heatmap
def correlation_matrix_heatmap():
correlation_matrix = np.corrcoef(bitstrings_array.T)
plt.figure(figsize=(12, 10))
sns.heatmap(correlation_matrix, cmap="coolwarm", cbar=True)
plt.title('Correlation Matrix Heatmap of Qubit Activations', color='white')
plt.xlabel('Qubit Index', color='white')
plt.ylabel('Qubit Index', color='white')
plt.savefig('/Users/Documents/correlation_matrix_heatmap.png')
plt.show()
# Path Integral Visualization
def path_integral_visualization():
plt.figure(figsize=(10, 6))
plt.plot(np.random.randn(100).cumsum(), color='blue', alpha=0.7)
plt.title('Path Integral Visualization', color='white')
plt.xlabel('Time', color='white')
plt.ylabel('Amplitude', color='white')
plt.grid(True, color='gray')
plt.savefig('/Users/Documents/path_integral_visualization.png')
plt.show()
# Quantum State Evolution Over Time
def quantum_state_evolution_animation():
fig, ax = plt.subplots(figsize=(10, 6))
line, = ax.plot([], [], color='green')
ax.set_xlim(0, 100)
ax.set_ylim(-2, 2)
ax.set_title('Quantum State Evolution Over Time', color='white')
ax.set_xlabel('Time', color='white')
ax.set_ylabel('Amplitude', color='white')
def animate(i):
line.set_data(np.arange(0, i), np.sin(np.arange(0, i) / 10))
return line,
ani = FuncAnimation(fig, animate, frames=100, interval=50)
ani.save('/User/Documents/quantum_state_evolution.gif', writer='imagemagick')
plt.show()
# Run all visualizations
mds_visualization()
tsne_visualization()
pca_3d_visualization()
hierarchical_clustering_dendrogram()
correlation_matrix_heatmap()
path_integral_visualization()
quantum_state_evolution_animation()
# End