# Distributing a GHZ state with a quantum entanglement switch

In this setup, multiple nodes (user nodes) connect to a central node (switch node) through bipartite entangled states. The switch node performs fusion operations on these shared states to create a GHZ state among the user nodes. The goal is to do the latter as memory-efficient as possible. Each of the $n$ clients can store one memory qubit in its memory buffer and one qubit at the switch side. In addition the switch's register holds a dedicated 'piecemaker' slot, a qubit in the $|+\rangle$ state, which all successful clients fuse their switch-side qubits with. We term this protocol the _piecemaker_ protocol, see [Prielinger et al., 2025](https://arxiv.org/abs/2508.14737).

In each time step, $n$ entanglement generation processes run in parallel. Upon creation of an entanglement link, it is fused with the piecemaker qubit. Once all clients went through this fusion operation, the piecemaker qubit is measured. This projects the state back to the clients, resulting in the desired shared GHZ state.
The fusion operation is performed on the switch node: let us take a client who just managed to generate a bipartite entangled state, an entangled link, with its associated qubit at the switch side. The switch executes a `CNOT` gate on the client's qubit (target) and the piecemaker qubit (control). Next, the switch measures the client qubit in the computational basis and sends the outcome to the client (in order to apply the necessary Pauli correction). This procedure merges the bipartite state into the entangled state that the piecemaker qubit is currently part of, modulo any required Pauli corrections.

NOTE: The memories residing in the nodes' `Register`s suffer from depolarizing noise, see [`Depolarization`](https://qs.quantumsavory.org/stable/API/#QuantumSavory.Depolarization).

The `setup.jl` file implements all necessary base functionality.
The other files run the simulation and generate visuals in a number of different circumstances:
1. `1_simple_run.jl` A single simulator script convenient for exploratory coding, running a number of Monte Carlo simulations;
2. `2_live_visualization_interactive.jl` A web-app version of the simulator;

Documentation:
- [The "How To" doc page on setting up this simulation](https://qs.quantumsavory.org/dev/howto/piecemakerswitch/piecemakerswitch)

### Protocol flow

```mermaid
sequenceDiagram
    participant Client1
    participant ClientN

    participant SwitchNode
    participant Log

    Note over Client1,SwitchNode: Round 1 (1 unit time)
    par Entanglement Generation
        Client1->>+SwitchNode: Try to generate entanglement
        ClientN->>+SwitchNode: Try to generate entanglement
    end

    SwitchNode->>SwitchNode: Run fusions with successful clients

    par Send Measurement Outcomes
        SwitchNode-->>-Client1: Send measurement outcomes
        SwitchNode-->>-ClientN: Send measurement outcomes
    end

    par Apply Corrections (No time cost)
        Client1->>Client1: Apply correction gates
        ClientN->>ClientN: Apply correction gates
    end

    loop Check Fusion Status (No time cost)
        SwitchNode->>SwitchNode: Check if all clients are fused
        alt All clients fused
            SwitchNode->>SwitchNode: Measure piecemaker
            SwitchNode->>SwitchNode: Compute fidelity to GHZ state
            SwitchNode->>Log: Log fidelity and time [END OF PROTOCOL]
        else
            SwitchNode->>SwitchNode: Keep checking
        end
    end
```

## TODO

The code can be slightly simplified if the `Logger` and `PiecemakerProtocol` are
turned into callable structs (e.g. subtypes of `AbstractProtocol`).
That permits slightly easier organization of configuration and log data.