Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Measurements not affecting Entropy #889

Open
isabellalimaleite opened this issue Feb 24, 2025 · 1 comment
Open

Measurements not affecting Entropy #889

isabellalimaleite opened this issue Feb 24, 2025 · 1 comment

Comments

@isabellalimaleite
Copy link

isabellalimaleite commented Feb 24, 2025

I have encountered an issue where entropy remains constant even as I introduce measurements. I expected entropy to decay as measurements destroy entanglement, but my implementation does not reflect this. I have tried different measurement strategies, including stim.Circuit.append("M"), TableauSimulator.measure(), and other built-in Stim methods, but none seem to affect the entropy.

I want to confirm that my entropy calculation is correct and understand why the measurements are not reducing the entanglement (stays constant no matter what).

Does anyone have insights into what might be going wrong? Also, if you have any example code or suggestions for implementing measurement-induced transitions in Stim, I would greatly appreciate it.

I have attached my current implementation and output for reference. Any guidance you can provide would be incredibly helpful.

`import stim
import numpy as np
import matplotlib.pyplot as plt

def create_clifford_circuit(n_qubits):
"""
Generates a stabilizer circuit with N qubits using a GHZ-like entanglement structure.
"""
circuit = stim.Circuit()

# Apply Hadamard to the first qubit
circuit.append("H", [0])

# Create an entangled GHZ-like state
for i in range(n_qubits - 1):
    circuit.append("CX", [i, i + 1])  # CNOT chain

return circuit

def compute_stabilizer_entropy(simulator, n_qubits, cut):
"""
Computes the entropy after measurements using stabilizer rank.
"""
tableau = simulator.current_inverse_tableau() ** -1 # Extract stabilizer tableau

# Get binary matrix representation of stabilizers
stabilizers = [tableau.z_output(k) for k in range(len(tableau))]
binary_matrix = np.zeros((n_qubits, 2 * n_qubits), dtype=int)

for row_idx, stabilizer in enumerate(stabilizers):
    for qubit_idx, pauli in enumerate(stabilizer):
        if pauli == 1:  # Pauli X
            binary_matrix[row_idx, qubit_idx] = 1
        elif pauli == 3:  # Pauli Z
            binary_matrix[row_idx, n_qubits + qubit_idx] = 1
        elif pauli == 2:  # Pauli Y (X+Z)
            binary_matrix[row_idx, qubit_idx] = 1
            binary_matrix[row_idx, n_qubits + qubit_idx] = 1

# Select submatrix corresponding to the chosen partition
sub_matrix = binary_matrix[:, :cut]

# Count number of stabilizers acting trivially outside A
identity_on_Ac = np.all(binary_matrix[:, cut:] == 0, axis=1)
S_A_size = np.sum(identity_on_Ac)

# Compute entropy as min(cut, N - cut)
von_neumann_entropy = min(cut, n_qubits - cut)

return von_neumann_entropy

def simulate_measurement_effects(n_qubits, cut, p_values, steps):
"""
Simulates measurement effects on entropy, measuring randomly chosen qubits.
"""
measurement_counts = np.arange(steps + 1)
results = {p: [] for p in p_values}

for p in p_values:
    simulator = stim.TableauSimulator()
    circuit = create_clifford_circuit(n_qubits)
    simulator.do(circuit)  # Initialize stabilizer state
    
    # Track entropy before any measurements
    entropy = compute_stabilizer_entropy(simulator, n_qubits, cut)
    results[p].append(entropy)

    for _ in range(steps):
        # Randomly select a qubit to measure
        qubit_to_measure = np.random.choice(n_qubits)
        if np.random.rand() < p:  # Measure with probability p
            simulator.measure(qubit_to_measure)

        # Compute new entropy
        entropy = compute_stabilizer_entropy(simulator, n_qubits, cut)
        results[p].append(entropy)

return measurement_counts, results

Define parameters

n_qubits = 10
cut = n_qubits // 2 # Subsystem A is half of the total system
p_values = [0.1, 0.3, 0.5, 0.7, 0.9] # Different measurement probabilities
steps = 20 # Number of measurement steps

Run simulation

measurement_counts, entropy_results = simulate_measurement_effects(n_qubits, cut, p_values, steps)

Plot entropy decay vs. measurement steps

plt.figure(figsize=(7, 5))
for p, entropies in entropy_results.items():
plt.plot(measurement_counts, entropies, marker='o', linestyle='-', label=f"p={p}")

plt.xlabel("Measurement Step", fontsize=12)
plt.ylabel("Von Neumann Entropy S(A)", fontsize=12)
plt.title("Entropy Decay vs. Measurement Steps", fontsize=14)
plt.legend()
plt.grid(True, linestyle="--", alpha=0.6)
plt.show()`

@Strilanc
Copy link
Collaborator

I think your entropy method is incorrectly assuming that, when a stabilizer happens to cross a cut, that indicates the system isn't separable.

For example, if a two qubit system has stabilizers:

ZZ
Z_

Then your method will claim it isn't a separable state. But the state described by those stabilizers is |00>.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants