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

Snapshot statevector and stabilizer extensions #355

Merged
merged 12 commits into from
Oct 2, 2019
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@ Added
-----
- Added tests for the Fredkin gate (#357)
- Added tests for the cu1 gate (#360)
- Added tests for statevector and stabilizer snapshots (\#355)

Changed
-------
- Stabilizer snapshot returns stabilizer instead of full Clifford table (\#355)
- Signature of SnapshotStatevector and SnapshotStabilizer (\#355)
- Changed all names from tensor_network_state to matrix_product_state (\#356)
- Update device noise model to consume asymmetric readout errors from backends (\#354)
- Update device noise model to use gate_length (\#352)
Expand Down
13 changes: 6 additions & 7 deletions qiskit/providers/aer/extensions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@
Snapshot extensions for Quantum Circuits
"""

from . import snapshot
from .snapshot import Snapshot
from . import snapshot_statevector
from . import snapshot_stabilizer
from . import snapshot_density_matrix
from . import snapshot_probabilities
from . import snapshot_expectation_value
from .snapshot import *
from .snapshot_statevector import *
from .snapshot_stabilizer import *
from .snapshot_density_matrix import *
from .snapshot_probabilities import *
from .snapshot_expectation_value import *
2 changes: 2 additions & 0 deletions qiskit/providers/aer/extensions/snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@ def __init__(self,
num_clbits=0,
params=None):
"""Create new snapshot instruction.

Args:
label (str): the snapshot label for result data.
snapshot_type (str): the type of the snapshot.
num_qubits (int): the number of qubits for the snapshot type [Default: 0].
num_clbits (int): the number of classical bits for the snapshot type [Default: 0].
params (list or None): the parameters for snapshot_type [Default: None].

Raises:
ExtensionError: if snapshot label is invalid.
"""
Expand Down
55 changes: 33 additions & 22 deletions qiskit/providers/aer/extensions/snapshot_stabilizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,38 +21,49 @@
class SnapshotStabilizer(Snapshot):
"""Snapshot instruction for stabilizer method of Qasm simulator."""

def __init__(self,
label,
num_qubits=0,
num_clbits=0,
params=None):
def __init__(self, label, num_qubits=0):
"""Create a stabilizer state snapshot instruction.

super().__init__(label, 'stabilizer', num_qubits, num_clbits, params)
Args:
label (str): the snapshot label.
num_qubits (int): the instruction barrier size [Default: 0].

Raises:
ExtensionError: if snapshot is invalid.

Additional Information:
This snapshot is always performed on all qubits in a circuit.
The number of qubits parameter specifies the size of the
instruction as a barrier and should be set to the number of
qubits in the circuit.
"""
super().__init__(label, snapshot_type='stabilizer', num_qubits=num_qubits)


def snapshot_stabilizer(self, label):
"""Take a stabilizer snapshot of the simulator state.

def snapshot_stabilizer(self,
label,
qubits=None,
params=None):
"""Take a snapshot of the internal simulator representation.
Works on all qubits, and prevents reordering (like barrier).
Args:
label (str): a snapshot label to report the result
qubits (list or None): the qubits to apply snapshot to [Default: None].
params (list or None): the parameters for snapshot_type [Default: None].
label (str): a snapshot label to report the result.

Returns:
QuantumCircuit: with attached command
QuantumCircuit: with attached instruction.

Raises:
ExtensionError: malformed command
ExtensionError: if snapshot is invalid.

Additional Information:
This snapshot is always performed on all qubits in a circuit.
The number of qubits parameter specifies the size of the
instruction as a barrier and should be set to the number of
qubits in the circuit.
"""

snapshot_register = Snapshot.define_snapshot_register(self, label, qubits)
snapshot_register = Snapshot.define_snapshot_register(self, label)

return self.append(
SnapshotStabilizer(
label,
num_qubits=len(snapshot_register),
params=params), snapshot_register)
SnapshotStabilizer(label, num_qubits=len(snapshot_register)),
snapshot_register)


QuantumCircuit.snapshot_stabilizer = snapshot_stabilizer
58 changes: 35 additions & 23 deletions qiskit/providers/aer/extensions/snapshot_statevector.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,38 +21,50 @@
class SnapshotStatevector(Snapshot):
""" Snapshot instruction for statevector snapshot type """

def __init__(self,
label,
num_qubits=0,
num_clbits=0,
params=None):
def __init__(self, label, num_qubits=0):
"""Create a statevector state snapshot instruction.

super().__init__(label, 'statevector', num_qubits, num_clbits, params)
Args:
label (str): the snapshot label.
num_qubits (int): the instruction barrier size [Default: 0].

Raises:
ExtensionError: if snapshot is invalid.

Additional Information:
This snapshot is always performed on all qubits in a circuit.
The number of qubits parameter specifies the size of the
instruction as a barrier and should be set to the number of
qubits in the circuit.
"""
super().__init__(label, snapshot_type='statevector', num_qubits=num_qubits)


def snapshot_statevector(self, label):
"""Take a statevector snapshot of the simulator state.

def snapshot_statevector(self,
label,
qubits=None,
params=None):
"""Take a statevector snapshot of the internal simulator representation.
Works on all qubits, and prevents reordering (like barrier).
Args:
label (str): a snapshot label to report the result
qubits (list or None): the qubits to apply snapshot to [Default: None].
params (list or None): the parameters for snapshot_type [Default: None].
label (str): a snapshot label to report the result.

Returns:
QuantumCircuit: with attached command
QuantumCircuit: with attached instruction.

Raises:
ExtensionError: malformed command
"""
ExtensionError: if snapshot is invalid.

snapshot_register = Snapshot.define_snapshot_register(self, label, qubits)
Additional Information:
This snapshot is always performed on all qubits in a circuit.
The number of qubits parameter specifies the size of the
instruction as a barrier and should be set to the number of
qubits in the circuit.
"""
# Statevector snapshot acts as a barrier across all qubits in the
# circuit
snapshot_register = Snapshot.define_snapshot_register(self, label)

return self.append(
SnapshotStatevector(
label,
num_qubits=len(snapshot_register),
params=params), snapshot_register)
SnapshotStatevector(label, num_qubits=len(snapshot_register)),
snapshot_register)


QuantumCircuit.snapshot_statevector = snapshot_statevector
1 change: 1 addition & 0 deletions src/simulators/qasm/qasm_controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,7 @@ void QasmController::set_parallelization_circuit(const Circuit& circ,
const auto method = simulation_method(circ, noise_model, false);
switch (method) {
case Method::statevector:
case Method::stabilizer:
case Method::matrix_product_state: {
if ((noise_model.is_ideal() || !noise_model.has_quantum_errors()) &&
check_measure_sampling_opt(circ, Method::statevector).first) {
Expand Down
20 changes: 12 additions & 8 deletions src/simulators/stabilizer/pauli.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,19 +59,22 @@ Pauli::Pauli(const std::string &label) {
const auto num_qubits = label.size();
X = BV::BinaryVector(num_qubits);
Z = BV::BinaryVector(num_qubits);
// The label corresponds to tensor product order
// So the first element of label is the last qubit and vice versa
for (size_t i =0; i < num_qubits; i++) {
const auto qubit_i = num_qubits - 1 - i;
switch (label[i]) {
case 'I':
break;
case 'X':
X.set1(i);
X.set1(qubit_i);
break;
case 'Y':
X.set1(i);
Z.set1(i);
X.set1(qubit_i);
Z.set1(qubit_i);
break;
case 'Z':
Z.set1(i);
Z.set1(qubit_i);
break;
default:
throw std::invalid_argument("Invalid Pauli label");
Expand All @@ -86,13 +89,14 @@ std::string Pauli::str() const {
throw std::runtime_error("Pauli::str X and Z vectors are different length.");
std::string label;
for (size_t i =0; i < num_qubits; i++) {
if (!X[i] && !Z[i])
const auto qubit_i = num_qubits - 1 - i;
if (!X[qubit_i] && !Z[qubit_i])
label.push_back('I');
else if (X[i] && !Z[i])
else if (X[qubit_i] && !Z[qubit_i])
label.push_back('X');
else if (X[i] && Z[i])
else if (X[qubit_i] && Z[qubit_i])
label.push_back('Y');
else if (!X[i] && Z[i])
else if (!X[qubit_i] && Z[qubit_i])
label.push_back('Z');
}
return label;
Expand Down
17 changes: 16 additions & 1 deletion src/simulators/stabilizer/stabilizer_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,10 @@ class State : public Base::State<Clifford::Clifford> {
// should be left in the pre-snapshot state.
//-----------------------------------------------------------------------

// Snapshot the stabilizer state of the simulator.
// This returns a list of stabilizer generators
void snapshot_stabilizer(const Operations::Op &op, OutputData &data);

// Snapshot current qubit probabilities for a measurement (average)
void snapshot_probabilities(const Operations::Op &op,
OutputData &data,
Expand Down Expand Up @@ -424,7 +428,7 @@ void State::apply_snapshot(const Operations::Op &op,
op.name + "\'.");
switch (it->second) {
case Snapshots::stabilizer:
BaseState::snapshot_state(op, data, "stabilizer");
snapshot_stabilizer(op, data);
break;
case Snapshots::cmemory:
BaseState::snapshot_creg_memory(op, data);
Expand All @@ -446,6 +450,17 @@ void State::apply_snapshot(const Operations::Op &op,
}


void State::snapshot_stabilizer(const Operations::Op &op, OutputData &data) {
// We don't want to snapshot the full Clifford table, only the
// stabilizer part. First Convert simulator clifford table to JSON
json_t clifford = BaseState::qreg_;
// Then extract the stabilizer generator list
data.add_singleshot_snapshot("stabilizer",
op.string_params[0],
clifford["stabilizers"]);
}


void State::snapshot_probabilities(const Operations::Op &op,
OutputData &data,
bool variance) {
Expand Down
Loading