mirror of https://github.com/Qiskit/qiskit-aer.git
Add AerStatevector (#1590)
Add a new class AerStatevector that supports q.i.s.Statevector interface. This class uses an internal class AerState that directly access to Aer's native runtime.
This commit is contained in:
parent
329169f80c
commit
3babb7fcc2
|
@ -14,4 +14,5 @@ Qiskit Aer API Reference
|
||||||
aer_primitives
|
aer_primitives
|
||||||
aer_pulse
|
aer_pulse
|
||||||
aer_utils
|
aer_utils
|
||||||
|
aer_quantum_info
|
||||||
parallel
|
parallel
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
.. _aer-primitives:
|
.. _aer-primitives:
|
||||||
|
|
||||||
.. automodule:: qiskit.providers.aer.primitives
|
.. automodule:: qiskit_aer.primitives
|
||||||
:no-members:
|
:no-members:
|
||||||
:no-inherited-members:
|
:no-inherited-members:
|
||||||
:no-special-members:
|
:no-special-members:
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
.. _aer-quantum_info:
|
||||||
|
|
||||||
|
.. automodule:: qiskit_aer.quantum_info
|
||||||
|
:no-members:
|
||||||
|
:no-inherited-members:
|
||||||
|
:no-special-members:
|
|
@ -68,6 +68,7 @@ from .aererror import AerError
|
||||||
from .backends import *
|
from .backends import *
|
||||||
from . import library
|
from . import library
|
||||||
from . import pulse
|
from . import pulse
|
||||||
|
from . import quantum_info
|
||||||
from . import noise
|
from . import noise
|
||||||
from . import utils
|
from . import utils
|
||||||
from .version import __version__
|
from .version import __version__
|
||||||
|
|
|
@ -148,7 +148,7 @@ PYBIND11_MODULE(controller_wrappers, m) {
|
||||||
else
|
else
|
||||||
return state.probabilities(qubits);
|
return state.probabilities(qubits);
|
||||||
}, py::arg("qubits") = reg_t());
|
}, py::arg("qubits") = reg_t());
|
||||||
aer_state.def("sample_measure", &AER::AerState::sample_measure);
|
aer_state.def("sample_memory", &AER::AerState::sample_memory);
|
||||||
aer_state.def("expval_pauli", &AER::AerState::expval_pauli);
|
aer_state.def("sample_counts", &AER::AerState::sample_counts);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,4 +14,17 @@
|
||||||
=================================================
|
=================================================
|
||||||
Aer Quantum Info (:mod:`qiskit_aer.quantum_info`)
|
Aer Quantum Info (:mod:`qiskit_aer.quantum_info`)
|
||||||
=================================================
|
=================================================
|
||||||
|
|
||||||
|
.. currentmodule:: qiskit_aer.quantum_info
|
||||||
|
|
||||||
|
States
|
||||||
|
======
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:toctree: ../stubs/
|
||||||
|
|
||||||
|
AerStatevector
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from .states import AerStatevector
|
||||||
|
|
|
@ -10,8 +10,6 @@
|
||||||
# copyright notice, and modified files need to carry a notice indicating
|
# copyright notice, and modified files need to carry a notice indicating
|
||||||
# that they have been altered from the originals.
|
# that they have been altered from the originals.
|
||||||
|
|
||||||
"""
|
"""Aer Quantum States."""
|
||||||
=============================================
|
|
||||||
State (:mod:`qiskit_aer.quantum_info.states`)
|
from .aer_statevector import AerStatevector
|
||||||
=============================================
|
|
||||||
"""
|
|
||||||
|
|
|
@ -47,14 +47,17 @@ class AerState:
|
||||||
"""State that handles cpp quantum state safely"""
|
"""State that handles cpp quantum state safely"""
|
||||||
self._state = _STATE.INITIALIZING
|
self._state = _STATE.INITIALIZING
|
||||||
self._native_state = AerStateWrapper()
|
self._native_state = AerStateWrapper()
|
||||||
self._method = 'statevector'
|
|
||||||
self._init_data = None
|
self._init_data = None
|
||||||
self._moved_data = None
|
self._moved_data = None
|
||||||
self._last_qubit = -1
|
self._last_qubit = -1
|
||||||
|
self._configs = {}
|
||||||
|
|
||||||
for key, value in kwargs.items():
|
for key, value in kwargs.items():
|
||||||
self.configure(key, value)
|
self.configure(key, value)
|
||||||
|
|
||||||
|
if 'method' not in kwargs:
|
||||||
|
self.configure('method', 'statevector')
|
||||||
|
|
||||||
def _assert_initializing(self):
|
def _assert_initializing(self):
|
||||||
if self._state != _STATE.INITIALIZING:
|
if self._state != _STATE.INITIALIZING:
|
||||||
raise AerError('AerState was already initialized.')
|
raise AerError('AerState was already initialized.')
|
||||||
|
@ -108,8 +111,13 @@ class AerState:
|
||||||
raise AerError('AerState is configured with a str key')
|
raise AerError('AerState is configured with a str key')
|
||||||
if not isinstance(value, str):
|
if not isinstance(value, str):
|
||||||
value = str(value)
|
value = str(value)
|
||||||
|
self._configs[key] = value
|
||||||
self._native_state.configure(key, value)
|
self._native_state.configure(key, value)
|
||||||
|
|
||||||
|
def configuration(self):
|
||||||
|
"""return configuration"""
|
||||||
|
return self._configs.copy()
|
||||||
|
|
||||||
def initialize(self, data=None, copy=True):
|
def initialize(self, data=None, copy=True):
|
||||||
"""initialize state."""
|
"""initialize state."""
|
||||||
self._assert_initializing()
|
self._assert_initializing()
|
||||||
|
@ -120,7 +128,7 @@ class AerState:
|
||||||
elif isinstance(data, np.ndarray):
|
elif isinstance(data, np.ndarray):
|
||||||
self._initialize_with_ndarray(data, copy)
|
self._initialize_with_ndarray(data, copy)
|
||||||
else:
|
else:
|
||||||
raise AerError('unsupported init data.')
|
raise AerError(f'unsupported init data: {data.__class__}')
|
||||||
|
|
||||||
def _initialize_with_ndarray(self, data, copy):
|
def _initialize_with_ndarray(self, data, copy):
|
||||||
if AerState._is_in_use(data) and not copy:
|
if AerState._is_in_use(data) and not copy:
|
||||||
|
@ -131,7 +139,7 @@ class AerState:
|
||||||
raise AerError('length of init data must be power of two')
|
raise AerError('length of init data must be power of two')
|
||||||
|
|
||||||
if (isinstance(data, np.ndarray) and
|
if (isinstance(data, np.ndarray) and
|
||||||
self._method == 'statevector' and
|
self._configs['method'] == 'statevector' and
|
||||||
self._native_state.initialize_statevector(num_of_qubits, data, copy)):
|
self._native_state.initialize_statevector(num_of_qubits, data, copy)):
|
||||||
if not copy:
|
if not copy:
|
||||||
self._init_data = data
|
self._init_data = data
|
||||||
|
@ -186,7 +194,7 @@ class AerState:
|
||||||
self._last_qubit = allocated[len(allocated) - 1]
|
self._last_qubit = allocated[len(allocated) - 1]
|
||||||
|
|
||||||
def _assert_in_allocated_qubits(self, qubit):
|
def _assert_in_allocated_qubits(self, qubit):
|
||||||
if isinstance(qubit, list):
|
if hasattr(qubit, '__iter__'):
|
||||||
for q in qubit:
|
for q in qubit:
|
||||||
self._assert_in_allocated_qubits(q)
|
self._assert_in_allocated_qubits(q)
|
||||||
elif qubit < 0 or qubit > self._last_qubit:
|
elif qubit < 0 or qubit > self._last_qubit:
|
||||||
|
@ -195,7 +203,6 @@ class AerState:
|
||||||
@property
|
@property
|
||||||
def num_qubits(self):
|
def num_qubits(self):
|
||||||
"""return a number of allocate qubits."""
|
"""return a number of allocate qubits."""
|
||||||
self._assert_initializing()
|
|
||||||
return self._last_qubit + 1
|
return self._last_qubit + 1
|
||||||
|
|
||||||
def flush(self):
|
def flush(self):
|
||||||
|
@ -212,8 +219,8 @@ class AerState:
|
||||||
return self._native_state.last_result()
|
return self._native_state.last_result()
|
||||||
|
|
||||||
def apply_global_phase(self, phase):
|
def apply_global_phase(self, phase):
|
||||||
"""apply global phase."""
|
"""apply global phase"""
|
||||||
self._assert_allocated_or_mapped_or_moved()
|
self._assert_allocated_or_mapped()
|
||||||
self._native_state.apply_global_phase(phase)
|
self._native_state.apply_global_phase(phase)
|
||||||
|
|
||||||
def apply_unitary(self, qubits, data):
|
def apply_unitary(self, qubits, data):
|
||||||
|
@ -353,11 +360,20 @@ class AerState:
|
||||||
# retrieve probability
|
# retrieve probability
|
||||||
return self._native_state.probabilities(qubits)
|
return self._native_state.probabilities(qubits)
|
||||||
|
|
||||||
def sample_measure(self, qubits=None, shots=1024):
|
def sample_counts(self, qubits=None, shots=1024):
|
||||||
"""samples all the qubits."""
|
"""samples all the qubits."""
|
||||||
self._assert_allocated_or_mapped()
|
self._assert_allocated_or_mapped()
|
||||||
if qubits is None:
|
if qubits is None:
|
||||||
qubits = range(self._last_qubit + 1)
|
qubits = range(self._last_qubit + 1)
|
||||||
else:
|
else:
|
||||||
self._assert_in_allocated_qubits(qubits)
|
self._assert_in_allocated_qubits(qubits)
|
||||||
return self._native_state.sample_measure(qubits, shots)
|
return self._native_state.sample_counts(qubits, shots)
|
||||||
|
|
||||||
|
def sample_memory(self, qubits=None, shots=1024):
|
||||||
|
"""samples all the qubits."""
|
||||||
|
self._assert_allocated_or_mapped()
|
||||||
|
if qubits is None:
|
||||||
|
qubits = range(self._last_qubit + 1)
|
||||||
|
else:
|
||||||
|
self._assert_in_allocated_qubits(qubits)
|
||||||
|
return self._native_state.sample_memory(qubits, shots)
|
||||||
|
|
|
@ -0,0 +1,219 @@
|
||||||
|
# This code is part of Qiskit.
|
||||||
|
#
|
||||||
|
# (C) Copyright IBM 2017, 2019, 2020, 2021, 2022.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
"""
|
||||||
|
Statevector quantum state class.
|
||||||
|
"""
|
||||||
|
import copy
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from qiskit.circuit import QuantumCircuit, Instruction
|
||||||
|
from qiskit.quantum_info.states import Statevector
|
||||||
|
|
||||||
|
from qiskit_aer import AerSimulator
|
||||||
|
from .aer_state import AerState
|
||||||
|
from ...backends.aerbackend import AerError
|
||||||
|
|
||||||
|
|
||||||
|
class AerStatevector(Statevector):
|
||||||
|
"""AerStatevector class
|
||||||
|
|
||||||
|
This class inherits :class:`Statevector`, which stores probability amplitudes
|
||||||
|
in its `ndarray`. class:`AerStatevector` generates this `ndarray` by using the
|
||||||
|
same runtime with :class:`AerSimulator`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, data, dims=None, **configs):
|
||||||
|
"""
|
||||||
|
Args:
|
||||||
|
data (np.array or list or Statevector or QuantumCircuit or qiskit.circuit.Instruction):
|
||||||
|
Data from which the statevector can be constructed. This can be either a complex
|
||||||
|
vector, another statevector or a ``QuantumCircuit`` or ``Instruction``
|
||||||
|
(``Operator`` is not supportted in the current implementation). If the data is
|
||||||
|
a circuit or instruction, the statevector is constructed by assuming that all
|
||||||
|
qubits are initialized to the zero state.
|
||||||
|
dims (int or tuple or list): Optional. The subsystem dimension of
|
||||||
|
the state (See additional information).
|
||||||
|
configs (kwargs): configurations of :class:`AerSimulator`. `method` configuration must
|
||||||
|
be `statevector` or `matrix_product_state`.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
AerError: if input data is not valid.
|
||||||
|
|
||||||
|
Additional Information:
|
||||||
|
The ``dims`` kwarg is used to ``Statevector`` constructor.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if '_aer_state' in configs:
|
||||||
|
self._aer_state = configs.pop('_aer_state')
|
||||||
|
else:
|
||||||
|
if 'method' not in configs:
|
||||||
|
configs['method'] = 'statevector'
|
||||||
|
elif configs['method'] not in ('statevector', 'matrix_product_state'):
|
||||||
|
method = configs['method']
|
||||||
|
raise AerError(f'Method {method} is not supported')
|
||||||
|
if isinstance(data, (QuantumCircuit, Instruction)):
|
||||||
|
data, aer_state = AerStatevector._from_instruction(data, None, configs)
|
||||||
|
elif isinstance(data, list):
|
||||||
|
data, aer_state = AerStatevector._from_ndarray(np.array(data, dtype=complex),
|
||||||
|
configs)
|
||||||
|
elif isinstance(data, np.ndarray):
|
||||||
|
data, aer_state = AerStatevector._from_ndarray(data, configs)
|
||||||
|
elif isinstance(data, AerStatevector):
|
||||||
|
aer_state = data._aer_state
|
||||||
|
if dims is None:
|
||||||
|
dims = data._op_shape._dims_l
|
||||||
|
data = data._data.copy()
|
||||||
|
else:
|
||||||
|
raise AerError(f'Input data is not supported: type={data.__class__}, data={data}')
|
||||||
|
|
||||||
|
self._aer_state = aer_state
|
||||||
|
|
||||||
|
super().__init__(data, dims=dims)
|
||||||
|
|
||||||
|
self._result = None
|
||||||
|
self._configs = configs
|
||||||
|
|
||||||
|
def _last_result(self):
|
||||||
|
if self._result is None:
|
||||||
|
self._result = self._aer_state.last_result()
|
||||||
|
return self._result
|
||||||
|
|
||||||
|
def metadata(self):
|
||||||
|
"""Return result metadata of an operation that executed lastly."""
|
||||||
|
if self._last_result() is None:
|
||||||
|
raise AerError('AerState was not used and metdata does not exist.')
|
||||||
|
return self._last_result()['metadata']
|
||||||
|
|
||||||
|
def __copy__(self):
|
||||||
|
return copy.deepcopy(self)
|
||||||
|
|
||||||
|
def __deepcopy__(self, _memo=None):
|
||||||
|
ret = AerStatevector(self._data.copy(), **self._configs)
|
||||||
|
ret._op_shape = copy.deepcopy(self._op_shape)
|
||||||
|
ret._rng_generator = copy.deepcopy(self._rng_generator)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def conjugate(self):
|
||||||
|
return AerStatevector(np.conj(self._data), dims=self.dims())
|
||||||
|
|
||||||
|
def sample_memory(self, shots, qargs=None):
|
||||||
|
if qargs is None:
|
||||||
|
qubits = np.arange(self._aer_state.num_qubits)
|
||||||
|
else:
|
||||||
|
qubits = np.array(qargs)
|
||||||
|
self._aer_state.close()
|
||||||
|
self._aer_state = AerState(**self._aer_state.configuration())
|
||||||
|
self._aer_state.initialize(self._data, copy=False)
|
||||||
|
samples = self._aer_state.sample_memory(qubits, shots)
|
||||||
|
self._data = self._aer_state.move_to_ndarray()
|
||||||
|
return samples
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _from_ndarray(init_data, configs):
|
||||||
|
aer_state = AerState()
|
||||||
|
|
||||||
|
options = AerSimulator._default_options()
|
||||||
|
for config_key, config_value in configs.items():
|
||||||
|
if options.get(config_key):
|
||||||
|
aer_state.configure(config_key, config_value)
|
||||||
|
|
||||||
|
if len(init_data) == 0:
|
||||||
|
raise AerError('initial data must be larger than 0')
|
||||||
|
|
||||||
|
num_qubits = int(np.log2(len(init_data)))
|
||||||
|
|
||||||
|
aer_state.allocate_qubits(num_qubits)
|
||||||
|
aer_state.initialize(data=init_data)
|
||||||
|
|
||||||
|
return aer_state.move_to_ndarray(), aer_state
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_instruction(cls, instruction):
|
||||||
|
return AerStatevector(instruction)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _from_instruction(inst, init_data, configs):
|
||||||
|
aer_state = AerState()
|
||||||
|
|
||||||
|
for config_key, config_value in configs.items():
|
||||||
|
aer_state.configure(config_key, config_value)
|
||||||
|
|
||||||
|
aer_state.allocate_qubits(inst.num_qubits)
|
||||||
|
num_qubits = inst.num_qubits
|
||||||
|
|
||||||
|
if init_data is not None:
|
||||||
|
aer_state.initialize(data=init_data, copy=True)
|
||||||
|
else:
|
||||||
|
aer_state.initialize()
|
||||||
|
|
||||||
|
if isinstance(inst, QuantumCircuit) and inst.global_phase != 0:
|
||||||
|
aer_state.apply_global_phase(inst.global_phase)
|
||||||
|
|
||||||
|
if isinstance(inst, QuantumCircuit):
|
||||||
|
AerStatevector._aer_evolve_circuit(aer_state, inst, range(num_qubits))
|
||||||
|
else:
|
||||||
|
AerStatevector._aer_evolve_instruction(aer_state, inst, range(num_qubits))
|
||||||
|
|
||||||
|
return aer_state.move_to_ndarray(), aer_state
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _aer_evolve_circuit(aer_state, circuit, qubits):
|
||||||
|
"""Apply circuit into aer_state"""
|
||||||
|
for instruction in circuit.data:
|
||||||
|
if instruction.clbits:
|
||||||
|
raise AerError(
|
||||||
|
f"Cannot apply instruction with classical bits: {instruction.operation.name}"
|
||||||
|
)
|
||||||
|
inst = instruction.operation
|
||||||
|
qargs = instruction.qubits
|
||||||
|
AerStatevector._aer_evolve_instruction(aer_state, inst,
|
||||||
|
[qubits[circuit.find_bit(qarg).index]
|
||||||
|
for qarg in qargs])
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _aer_evolve_instruction(aer_state, inst, qubits):
|
||||||
|
"""Apply instruction into aer_state"""
|
||||||
|
params = inst.params
|
||||||
|
if inst.name in ['u', 'u3']:
|
||||||
|
aer_state.apply_mcu(qubits[0:len(qubits) - 1], qubits[len(qubits) - 1],
|
||||||
|
params[0], params[1], params[2])
|
||||||
|
elif inst.name in ['x', 'cx', 'ccx']:
|
||||||
|
aer_state.apply_mcx(qubits[0:len(qubits) - 1], qubits[len(qubits) - 1])
|
||||||
|
elif inst.name in ['y', 'cy']:
|
||||||
|
aer_state.apply_mcy(qubits[0:len(qubits) - 1], qubits[len(qubits) - 1])
|
||||||
|
elif inst.name in ['z', 'cz']:
|
||||||
|
aer_state.apply_mcz(qubits[0:len(qubits) - 1], qubits[len(qubits) - 1])
|
||||||
|
elif inst.name == 'unitary':
|
||||||
|
aer_state.apply_unitary(qubits, inst.params[0])
|
||||||
|
elif inst.name == 'diagonal':
|
||||||
|
aer_state.apply_diagonal(qubits, inst.params[0])
|
||||||
|
elif inst.name == 'reset':
|
||||||
|
aer_state.apply_reset(qubits)
|
||||||
|
else:
|
||||||
|
definition = inst.definition
|
||||||
|
if definition is inst:
|
||||||
|
raise AerError('cannot decompose ' + inst.name)
|
||||||
|
if not definition:
|
||||||
|
raise AerError('cannot decompose ' + inst.name)
|
||||||
|
AerStatevector._aer_evolve_circuit(aer_state, definition, qubits)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_label(cls, label):
|
||||||
|
return AerStatevector(Statevector.from_label(label)._data)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def from_int(i, dims):
|
||||||
|
size = np.product(dims)
|
||||||
|
state = np.zeros(size, dtype=complex)
|
||||||
|
state[i] = 1.0
|
||||||
|
return AerStatevector(state, dims=dims)
|
|
@ -292,15 +292,14 @@ public:
|
||||||
// Return M sampled outcomes for Z-basis measurement of specified qubits
|
// Return M sampled outcomes for Z-basis measurement of specified qubits
|
||||||
// The input is a length M list of random reals between [0, 1) used for
|
// The input is a length M list of random reals between [0, 1) used for
|
||||||
// generating samples.
|
// generating samples.
|
||||||
virtual std::unordered_map<uint_t, uint_t> sample_measure(const reg_t &qubits, uint_t shots);
|
// The returned value is unordered sampled outcomes
|
||||||
|
virtual std::vector<std::string> sample_memory(const reg_t &qubits, uint_t shots);
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
// Return M sampled outcomes for Z-basis measurement of specified qubits
|
||||||
// Expectation Values
|
// The input is a length M list of random reals between [0, 1) used for
|
||||||
//-----------------------------------------------------------------------
|
// generating samples.
|
||||||
|
// The returned value is a map from outcome to its number of samples.
|
||||||
// Return the expectation value of an N-qubit Pauli matrix.
|
virtual std::unordered_map<uint_t, uint_t> sample_counts(const reg_t &qubits, uint_t shots);
|
||||||
// The Pauli is input as a length N string of I,X,Y,Z characters.
|
|
||||||
virtual double expval_pauli(const reg_t &qubits, const std::string &pauli);
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
// Operation management
|
// Operation management
|
||||||
|
@ -866,7 +865,7 @@ void AerState::apply_mcu(const reg_t &qubits, const double theta, const double p
|
||||||
op.type = Operations::OpType::gate;
|
op.type = Operations::OpType::gate;
|
||||||
op.name = "mcu";
|
op.name = "mcu";
|
||||||
op.qubits = qubits;
|
op.qubits = qubits;
|
||||||
op.params = {theta, phi, lambda};
|
op.params = {theta, phi, lambda, 0.0};
|
||||||
|
|
||||||
buffer_op(std::move(op));
|
buffer_op(std::move(op));
|
||||||
}
|
}
|
||||||
|
@ -1037,7 +1036,21 @@ std::vector<double> AerState::probabilities(const reg_t &qubits) {
|
||||||
return ((DataMap<ListData, rvector_t>)last_result_.data).value()["s"].value()[0];
|
return ((DataMap<ListData, rvector_t>)last_result_.data).value()["s"].value()[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<uint_t, uint_t> AerState::sample_measure(const reg_t &qubits, uint_t shots) {
|
std::vector<std::string> AerState::sample_memory(const reg_t &qubits, uint_t shots) {
|
||||||
|
assert_initialized();
|
||||||
|
|
||||||
|
flush_ops();
|
||||||
|
|
||||||
|
std::vector<std::string> ret;
|
||||||
|
ret.reserve(shots);
|
||||||
|
std::vector<reg_t> samples = state_->sample_measure(qubits, shots, rng_);
|
||||||
|
for (auto& sample : samples) {
|
||||||
|
ret.push_back(Utils::int2string(Utils::reg2int(sample, 2), 2, qubits.size()));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_map<uint_t, uint_t> AerState::sample_counts(const reg_t &qubits, uint_t shots) {
|
||||||
assert_initialized();
|
assert_initialized();
|
||||||
|
|
||||||
flush_ops();
|
flush_ops();
|
||||||
|
@ -1059,15 +1072,6 @@ std::unordered_map<uint_t, uint_t> AerState::sample_measure(const reg_t &qubits,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
double AerState::expval_pauli(const reg_t &qubits, const std::string &pauli) {
|
|
||||||
assert_initialized();
|
|
||||||
|
|
||||||
flush_ops();
|
|
||||||
|
|
||||||
return state_->expval_pauli(qubits, pauli);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
// Operation management
|
// Operation management
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
|
|
|
@ -85,12 +85,12 @@ class TestAerState(common.QiskitAerTestCase):
|
||||||
state1 = AerState(seed_simulator=2222)
|
state1 = AerState(seed_simulator=2222)
|
||||||
state1.allocate_qubits(4)
|
state1.allocate_qubits(4)
|
||||||
state1.initialize(init_state.data, copy=True)
|
state1.initialize(init_state.data, copy=True)
|
||||||
sample1 = state1.sample_measure()
|
sample1 = state1.sample_counts()
|
||||||
sv1 = state1.move_to_ndarray()
|
sv1 = state1.move_to_ndarray()
|
||||||
|
|
||||||
state2 = AerState(seed_simulator=2222)
|
state2 = AerState(seed_simulator=2222)
|
||||||
state2.initialize(sv1, copy=False)
|
state2.initialize(sv1, copy=False)
|
||||||
sample2 = state2.sample_measure()
|
sample2 = state2.sample_counts()
|
||||||
sv2 = state2.move_to_ndarray()
|
sv2 = state2.move_to_ndarray()
|
||||||
state2.close()
|
state2.close()
|
||||||
|
|
||||||
|
@ -447,7 +447,7 @@ class TestAerState(common.QiskitAerTestCase):
|
||||||
state = AerState(seed_simulator=11111)
|
state = AerState(seed_simulator=11111)
|
||||||
state.allocate_qubits(5)
|
state.allocate_qubits(5)
|
||||||
state.initialize(init_state.data)
|
state.initialize(init_state.data)
|
||||||
actual = state.sample_measure()
|
actual = state.sample_counts()
|
||||||
|
|
||||||
for key, value in actual.items():
|
for key, value in actual.items():
|
||||||
key_str = f"{key:05b}"
|
key_str = f"{key:05b}"
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue