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 circuit extensions #317

Merged
merged 16 commits into from
Aug 14, 2019
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
332 changes: 332 additions & 0 deletions qiskit/providers/aer/aer_snapshots.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,332 @@
# -*- coding: utf-8 -*-

# This code is part of Qiskit.
#
# (C) Copyright IBM 2018, 2019.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
"""
Simulator command to snapshot internal simulator representation.
"""

import warnings

from qiskit import QuantumCircuit
from qiskit.circuit.quantumregister import QuantumRegister
from qiskit.circuit import Instruction
from qiskit.extensions.exceptions import ExtensionError


class Snapshot(Instruction):
"""Simulator snapshot instruction."""

def __init__(self,
label,
snapshot_type='statevector',
num_qubits=0,
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.
"""
if not isinstance(label, str):
raise ExtensionError('Snapshot label must be a string.')
self._label = label
self._snapshot_type = snapshot_type
if params is None:
params = []
super().__init__('snapshot', num_qubits, num_clbits, params)

def assemble(self):
"""Assemble a QasmQobjInstruction"""
instruction = super().assemble()
instruction.label = self._label
instruction.snapshot_type = self._snapshot_type
return instruction

def inverse(self):
"""Special case. Return self."""
return Snapshot(self.num_qubits, self.num_clbits, self.params[0],
self.params[1])

@property
def snapshot_type(self):
"""Return snapshot type"""
return self._snapshot_type

@property
def label(self):
"""Return snapshot label"""
return self._label

@label.setter
def label(self, name):
"""Set snapshot label to name
Args:
name (str or None): label to assign unitary
Raises:
TypeError: name is not string or None.
"""
if isinstance(name, str):
self._label = name
else:
raise TypeError('label expects a string')


def snapshot(self,
label,
snapshot_type='statevector',
qubits=None,
params=None):
"""Take a statevector snapshot of the internal simulator representation.
kanejess marked this conversation as resolved.
Show resolved Hide resolved
Works on all qubits, and prevents reordering (like barrier).
Args:
label (str): a snapshot label to report the result
snapshot_type (str): the type of the snapshot.
qubits (list or None): the qubits to apply snapshot to [Default: None].
params (list or None): the parameters for snapshot_type [Default: None].
Returns:
QuantumCircuit: with attached command
Raises:
ExtensionError: malformed command
"""
# Convert label to string for backwards compatibility
if not isinstance(label, str):
warnings.warn(
"Snapshot label should be a string, "
"implicit conversion is deprecated.", DeprecationWarning)
label = str(label)
# If no qubits are specified we add all qubits so it acts as a barrier
# This is needed for full register snapshots like statevector
if isinstance(qubits, QuantumRegister):
qubits = qubits[:]
if not qubits:
tuples = []
if isinstance(self, QuantumCircuit):
for register in self.qregs:
tuples.append(register)
if not tuples:
raise ExtensionError('no qubits for snapshot')
qubits = []
for tuple_element in tuples:
if isinstance(tuple_element, QuantumRegister):
for j in range(tuple_element.size):
qubits.append(tuple_element[j])
else:
qubits.append(tuple_element)
return self.append(
Snapshot(
label,
snapshot_type=snapshot_type,
num_qubits=len(qubits),
params=params), qubits)


# Add to QuantumCircuit class
QuantumCircuit.snapshot = snapshot

class SnapshotStatevector(Snapshot):
""" Simulator snapshot instruction for statevector snapshot type """

def __init__(self,
label,
snapshot_type='statevector',
num_qubits=0,
num_clbits=0,
params=None):
super().__init__(label, snapshot_type, num_qubits, num_clbits, params)


def snapshot_statevector(self,
label,
snapshot_type='statevector',
qubits=None,
params=None):

# Convert label to string for backwards compatibility
if not isinstance(label, str):
warnings.warn(
"Snapshot label should be a string, "
"implicit conversion is deprecated.", DeprecationWarning)
label = str(label)
# If no qubits are specified we add all qubits so it acts as a barrier
# This is needed for full register snapshots
if isinstance(qubits, QuantumRegister):
qubits = qubits[:]
if not qubits:
tuples = []
if isinstance(self, QuantumCircuit):
for register in self.qregs:
tuples.append(register)
if not tuples:
raise ExtensionError('no qubits for snapshot')
qubits = []
for tuple_element in tuples:
if isinstance(tuple_element, QuantumRegister):
for j in range(tuple_element.size):
qubits.append(tuple_element[j])
else:
qubits.append(tuple_element)
return self.append(
SnapshotStatevector(
label,
snapshot_type=snapshot_type,
num_qubits=len(qubits),
params=params), qubits)

QuantumCircuit.snapshot_statevector = snapshot_statevector


class SnapshotStabilizer(Snapshot):
def __init__(self,
label,
snapshot_type='stabilizer',
num_qubits=0,
num_clbits=0,
params=None):
super().__init__(label, snapshot_type, num_qubits, num_clbits, params)

def snapshot_stabilizer(self,
label,
snapshot_type='stabilizer',
qubits=None,
params=None):

# Convert label to string for backwards compatibility
if not isinstance(label, str):
kanejess marked this conversation as resolved.
Show resolved Hide resolved
warnings.warn(
"Snapshot label should be a string, "
"implicit conversion is deprecated.", DeprecationWarning)
label = str(label)
# If no qubits are specified we add all qubits so it acts as a barrier
# This is needed for full register snapshots like statevector
if isinstance(qubits, QuantumRegister):
qubits = qubits[:]
if not qubits:
tuples = []
if isinstance(self, QuantumCircuit):
for register in self.qregs:
tuples.append(register)
if not tuples:
raise ExtensionError('no qubits for snapshot')
qubits = []
for tuple_element in tuples:
if isinstance(tuple_element, QuantumRegister):
for j in range(tuple_element.size):
qubits.append(tuple_element[j])
else:
qubits.append(tuple_element)
return self.append(
SnapshotStabilizer(
label,
snapshot_type=snapshot_type,
num_qubits=len(qubits),
params=params), qubits)

QuantumCircuit.snapshot_stabilizer = snapshot_stabilizer

class SnaphotDensityMatrix(Snapshot):
def __init__(self,
label,
snapshot_type='density_matrix',
num_qubits=0,
num_clbits=0,
params=None):
super().__init__(label, num_qubits, num_clbits, params)

def snapshot_density_matrix(self,
label,
snapshot_type='density_matrix',
kanejess marked this conversation as resolved.
Show resolved Hide resolved
qubits=None,
params=None):

# Convert label to string for backwards compatibility
if not isinstance(label, str):
warnings.warn(
"Snapshot label should be a string, "
"implicit conversion is deprecated.", DeprecationWarning)
label = str(label)
# If no qubits are specified we add all qubits so it acts as a barrier
# This is needed for full register snapshots
if isinstance(qubits, QuantumRegister):
qubits = qubits[:]
if not qubits:
tuples = []
if isinstance(self, QuantumCircuit):
for register in self.qregs:
tuples.append(register)
if not tuples:
raise ExtensionError('no qubits for snapshot')
qubits = []
for tuple_element in tuples:
if isinstance(tuple_element, QuantumRegister):
for j in range(tuple_element.size):
qubits.append(tuple_element[j])
else:
qubits.append(tuple_element)
return self.append(
SnapshotDensityMatrix(
label,
snapshot_type=snapshot_type,
num_qubits=len(qubits),
params=params), qubits)

QuantumCircuit.snapshot_density_matrix = snapshot_density_matrix

class SnapshotProbabilites(Snapshot):

def __init__(self,
label,
snapshot_type='probabilities',
num_qubits,
num_clbits=0,
params=None):

super().__init__(label, snapshot_type, num_qubits, num_clbits, params)

def snapshot_probabilities(self,
label,
snapshot_type='probabilities',
num_qubits,
params=None):

return self.append(
SnapshotProbabilites(
label,
snapshot_type=snapshot_type,
num_qubits,
params=params), qubits)


QuantumCircuit.snapshot_probabilities = snapshot_probabilities

'''
class SnapshotExpectationValue(Snapshot):

def __init__(self,
label,
snapshot_type='expectation_value',
num_qubits=0,
num_clbits=0,
params=None):

super().__init__(label, snapshot_type, num_qubits, num_clbits, params)

def snapshot_expectation_value():
pass

QuantumCircuit.snapshot_expectation_value = snapshot_expectation_value
'''
18 changes: 18 additions & 0 deletions qiskit/providers/aer/extensions/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2018, 2019.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

from . import snapshot
from . import snapshot_statevector
from . import snapshot_stabilizer
from . import snapshot_density_matrix
from . import snapshot_probabilities
from . import snapshot_expectation_value
Loading