Skip to content

Simulator Interfaces #281

@ajavadia

Description

@ajavadia

Summary:

This issue is regarding the way we expose simulator backends to the user. From a user's perspective, it would make sense to group these simulators by functionality. This is separate from how they are actually implemented "under the hood". Functionally, we have the following simulators:

  1. qasm_simulator: This is to mimic how things are done in a real experiment.
    • To be meaningful, it should contain measurements (measure qr->cr) as the result will only be a bit-string, similar to experiment results. No measurement means you just read out 0s.
    • It can contain reset and if.
    • Multiple measurements to the same classical register will rewrite the bits.
    • It can include 1 or many shots. At the end, the returned result will be a histogram of the classical register for that many shots.
result = {
    "data": {
        "counts": {
            "00010": 40,
            "00111": 24
        }
    }
    ...
}
  1. wavefunction_simulator: This is for obtaining wavefunction from qubit registers.
    • The wavefunction can be requested by a snapshot qr->sr command, where qr is the register to be queried and sr is a (to-be-implemented) snapshot_register (or wavefunction_register).
    • It does not need measurements. Including them will collapse the wavefunction.
    • For the first implementation, we can disable measure, if and shots.
    • Later, we may include them, but then we have to return a list of possible snapshot outcomes for each snapshot_register.
result = {
    "data": {
        "snapshots": {
            "sr1": [0.5+0.5J, 0, 0, -0.707J],
            "sr2": [0.2, 0.1, 0.25+0.25J, 0.908J]
        }
    }
    ...
}
  1. unitary_simulator: for getting the 2^n x 2^n unitary matrix equivalent of the circuit.
    • measure, if and shots are disabled.
result = {
        "data": {
            'unitary': array([
                [-0.5, 0.5, 0.5, 0.5],
                [0.5, 0.5, 0.5, -0.5],
                [0.5, 0.5, -0.5, 0.5],
                [0.5, -0.5, 0.5, 0.5]
            ])
        }
    }
    ...
}
  1. stabilizer_simulator: for efficient simulation of stabilizer circuits, according to Gottesman's paper.
    • snapshot qr->sr will record the 2n+1 X 2n dimensional matrix of a clifford tableau.
result = {
        "data": {
            'tableu': array([
                [1, 0, 0, 0, 0],
                [0, 1, 0, 0, 0],
                [0, 0, 1, 0, 0],
                [0, 0, 0, 1, 0]
            ]),
        }
    }
    ...
}
  1. tgate_simulator: for fast simulation of circuits dominated by Clifford gates with relatively few T gates, according to Bravyi and Gosset's paper

Expected Behavior

Implementation optimizations:

a. There are currently 3 implementations for qasm simulator: python, c++ and an external one by projectq. We should make the c++ one the standard local_qasm_simulator, and call the others local_qasm_simulator_py, local_qasm_simulator_projectq. There isn't really any reason for the latter 2 to be exposed through get_available_backends(), but someone who knows they absolutely want to use one of them can know they exist through documentation.

b. For the local_qasm_simulator, if there are no intermediate measures, then the compiler should be smart and not call local_qasm_simulator many times. Instead, it should call the local_wavefunction_simulator, then sample the output wavefunction to produce the counts histogram. Similarly, if there is an intermediate measure but that qubit is not modified later (it can be a control), then the measurement should be commuted to the end and the whole simulation, again, only done once.

c. For the local_qasm_simulator, if the circuit is entirely made up of CNOT, Hadamard, Phase, the compiler should be smart and call the local_stabalizer_simulator which is much more scalable. Similarly for a Clifford-dominated circuit with some Ts, it should call the local_tgate_simulator.

Current Behavior

  • The name local_qiskit_simulator (as opposed to local_qasm_simulator) has to go.
  • The implicit way of getting wavefunctions by setting shots=1 has to go.
  • The current local_clifford_simulator should be called local_stabilizer_simulator. A local_clifford_simulator will be added later.

Context

This is a summary of some discussions with @jaygambetta, @awcross1, @levbishop. Everyone, please comment if you have any thoughts, and feel free to correct any mistakes by editing my comment.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions