Implement GPU tensor network simulator by using cuTensorNet (#1637)

* Implement tensor network simulator by using cuTensorNet

Implementing general tensor network simulator for GPU accelerated by
NVIDIA's cuTensoNet APIs of cuQuantum SDK. Any quantum circuits can
be translated into tensor network and can be simulated.
This method supports both statevector and density matrix simulations,
noise simulation can be done by single shot with density matrix
if there is no save_statevector operation.
This method supports parallelization by multiple GPUs and MPI processes
by using tensor network slicing technique.

* fix aer_simulator.py
* return values in TensorNetContractorDummy
* Fix for cuQuantum 22.11.0
* remove dependencieis to shot branching
* fix test cases, remove remaining shot-branching options
* add release note, fix available_methods to handle tensor_network
* fix available_methods
* spdlog version

---------

Co-authored-by: Hiroshi Horii <hhorii@users.noreply.github.com>
This commit is contained in:
Jun Doi 2023-01-30 11:57:34 +09:00 committed by GitHub
parent 4297171078
commit 3e34a24bf9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 4479 additions and 112 deletions

View File

@ -261,7 +261,39 @@ if(AER_THRUST_SUPPORTED)
set(AER_COMPILER_DEFINITIONS ${AER_COMPILER_DEFINITIONS} THRUST_DEVICE_SYSTEM=THRUST_DEVICE_SYSTEM_CUDA)
set(THRUST_DEPENDENT_LIBS "")
if(CUSTATEVEC_ROOT)
if(NOT DEFINED CUQUANTUM_ROOT)
if(DEFINED ENV{CUQUANTUM_ROOT})
set(CUQUANTUM_ROOT $ENV{CUQUANTUM_ROOT})
endif()
endif()
if(NOT DEFINED CUTENSOR_ROOT)
if(DEFINED ENV{CUTENSOR_ROOT})
set(CUTENSOR_ROOT $ENV{CUTENSOR_ROOT})
endif()
endif()
if(NOT DEFINED AER_ENABLE_CUQUANTUM)
if(DEFINED ENV{AER_ENABLE_CUQUANTUM})
set(AER_ENABLE_CUQUANTUM $ENV{AER_ENABLE_CUQUANTUM})
endif()
endif()
if(AER_ENABLE_CUQUANTUM)
set(AER_COMPILER_DEFINITIONS ${AER_COMPILER_DEFINITIONS} AER_CUSTATEVEC AER_CUTENSORNET)
if(DEFINED CUQUANTUM_ROOT)
set(AER_COMPILER_FLAGS "${AER_COMPILER_FLAGS} -I${CUQUANTUM_ROOT}/include")
set(THRUST_DEPENDANT_LIBS "-L${CUQUANTUM_ROOT}/lib")
endif()
if(DEFINED CUTENSOR_ROOT)
set(AER_COMPILER_FLAGS "${AER_COMPILER_FLAGS} -I${CUTENSOR_ROOT}/include")
set(THRUST_DEPENDANT_LIBS "${THRUST_DEPENDANT_LIBS} -L${CUTENSOR_ROOT}/lib/11")
endif()
if(CUQUANTUM_STATIC)
set(THRUST_DEPENDANT_LIBS "${THRUST_DEPENDANT_LIBS} -lcustatevec_static -lcutensornet_static -lcutensor -lcublas")
else()
set(THRUST_DEPENDANT_LIBS "${THRUST_DEPENDANT_LIBS} -lcustatevec -lcutensornet -lcutensor")
endif()
elseif(CUSTATEVEC_ROOT)
#TODO this is remained for backward compatibility, use CUQUANTUM_ROOT instead
set(AER_COMPILER_DEFINITIONS ${AER_COMPILER_DEFINITIONS} AER_CUSTATEVEC)
set(AER_COMPILER_FLAGS "${AER_COMPILER_FLAGS} -I${CUSTATEVEC_ROOT}/include")
if(CUSTATEVEC_STATIC)

View File

@ -648,15 +648,18 @@ Few notes on GPU builds:
Qiskit Aer now supports cuQuantum optimized Quantum computing APIs from NVIDIA®.
cuStateVec APIs can be exploited to accelerate statevector, density_matrix and unitary methods.
Supported version of cuQuantum is 0.40 or higher and required version of CUDA toolkit is 11.2 or higher.
cuTensorNet APIs can be exploited to tensor_network merthod.
This implementation requires CUDA toolkit version 11.2 or higher and Volta or Ampare architecture GPUs.
To build Qiskit Aer with cuStateVec support, please set the path to cuQuantum root directory to CUSTATEVEC_ROOT as following.
To build Qiskit Aer with cuQuantum support, please set the path to cuQuantum root directory to CUQUANTUM_ROOT
and directory to cuTensor to CUTENSOR_ROOT then set AER_ENABLE_CUQUANTUM=true.
as following.
For example,
qiskit-aer$ python ./setup.py bdist_wheel -- -DAER_THRUST_BACKEND=CUDA -DCUSTATEVEC_ROOT=path_to_cuQuantum
qiskit-aer$ python ./setup.py bdist_wheel -- -DAER_THRUST_BACKEND=CUDA -DCUQUANTUM_ROOT=path_to_cuQuantum -DCUTENSOR_ROOT=path_to_cuTENSOR -DAER_ENABLE_CUQUANTUM=true --
if you want to link cuQuantum library statically, set `CUSTATEVEC_STATIC` to setup.py.
if you want to link cuQuantum library statically, set `CUQUANTUM_STATIC` to setup.py.
Otherwise you also have to set environmental variable LD_LIBRARY_PATH to indicate path to the cuQuantum libraries.
To run with cuStateVec, set `device='GPU'` to AerSimulator option and set `cuStateVec_enable=True` to option in execute method.

View File

@ -24,7 +24,7 @@ endmacro()
macro(_use_system_libraries)
# Use system libraries
_import_aer_system_dependency(nlohmann_json 3.1.1)
_import_aer_system_dependency(spdlog 1.5.0)
_import_aer_system_dependency(spdlog 1.9.2)
if(SKBUILD)
_import_aer_system_dependency(muparserx 4.0.8)

View File

@ -119,6 +119,10 @@ class AerSimulator(AerBackend):
can simulate ideal and noisy gates, and reset, but does not support
measurement.
* ``"tensor_network"``: A tensor-network based simulation that supports
both statevector and density matrix. Currently there is only available
for GPU and accelerated by using cuTensorNet APIs of cuQuantum.
**GPU Simulation**
By default all simulation methods run on the CPU, however select methods
@ -144,6 +148,8 @@ class AerSimulator(AerBackend):
+--------------------------+---------------+
| ``superop`` | No |
+--------------------------+---------------+
| ``tensor_network`` | Yes(GPU only) |
+--------------------------+---------------+
Running a GPU simulation is done using ``device="GPU"`` kwarg during
initialization or with :meth:`set_options`. The list of supported devices
@ -262,9 +268,10 @@ class AerSimulator(AerBackend):
intermediate measurements and can greatly accelerate simulation time
on GPUs. If there are multiple GPUs on the system, shots are distributed
automatically across available GPUs. Also this option distributes multiple
shots to parallel processes of MPI (Default: True).
shots to parallel processes of MPI (Default: False).
If multiple GPUs are used for batched exectuion number of GPUs is
reported to ``batched_shots_optimization_parallel_gpus`` metadata.
``cuStateVec_enable`` is not supported for this option.
* ``batched_shots_gpu_max_qubits`` (int): This option sets the maximum
number of qubits for enabling the ``batched_shots_gpu`` option. If the
@ -395,6 +402,17 @@ class AerSimulator(AerBackend):
Possible values are "mps_swap_right" and "mps_swap_left".
(Default: "mps_swap_left")
These backend options only apply when using the ``tensor_network``
simulation method:
* ``tensor_network_num_sampling_qubits`` (int): is used to set number
of qubits to be sampled in single tensor network contraction when
using sampling measure. (Default: 10)
* ``use_cuTensorNet_autotuning`` (bool): enables auto tuning of plan
in cuTensorNet API. It takes some time for tuning, so enable if the
circuit is very large. (Default: False)
These backend options apply in circuit optimization passes:
* ``fusion_enable`` (bool): Enable fusion optimization in circuit
@ -472,6 +490,14 @@ class AerSimulator(AerBackend):
'superop': sorted([
'quantum_channel', 'qerror_loc', 'kraus', 'superop', 'save_state',
'save_superop', 'set_superop',
]),
'tensor_network': sorted([
'quantum_channel', 'qerror_loc', 'roerror', 'kraus', 'superop',
'save_state', 'save_expval', 'save_expval_var',
'save_probabilities', 'save_probabilities_dict',
'save_density_matrix', 'save_amplitudes', 'save_amplitudes_sq',
'save_statevector', 'save_statevector_dict',
'set_statevector', 'set_density_matrix'
])
}
@ -483,7 +509,8 @@ class AerSimulator(AerBackend):
_CUSTOM_INSTR['density_matrix']).union(
_CUSTOM_INSTR['matrix_product_state']).union(
_CUSTOM_INSTR['unitary']).union(
_CUSTOM_INSTR['superop']))
_CUSTOM_INSTR['superop']).union(
_CUSTOM_INSTR['tensor_network']))
_DEFAULT_CONFIGURATION = {
'backend_name': 'aer_simulator',
@ -506,7 +533,7 @@ class AerSimulator(AerBackend):
_SIMULATION_METHODS = [
'automatic', 'statevector', 'density_matrix',
'stabilizer', 'matrix_product_state', 'extended_stabilizer',
'unitary', 'superop'
'unitary', 'superop', 'tensor_network'
]
_AVAILABLE_METHODS = None
@ -524,12 +551,12 @@ class AerSimulator(AerBackend):
self._controller = aer_controller_execute()
# Update available methods and devices for class
if AerSimulator._AVAILABLE_METHODS is None:
AerSimulator._AVAILABLE_METHODS = available_methods(
self._controller, AerSimulator._SIMULATION_METHODS)
if AerSimulator._AVAILABLE_DEVICES is None:
AerSimulator._AVAILABLE_DEVICES = available_devices(
self._controller, AerSimulator._SIMULATION_DEVICES)
if AerSimulator._AVAILABLE_METHODS is None:
AerSimulator._AVAILABLE_METHODS = available_methods(
self._controller, AerSimulator._SIMULATION_METHODS, AerSimulator._AVAILABLE_DEVICES)
# Default configuration
if configuration is None:
@ -578,7 +605,7 @@ class AerSimulator(AerBackend):
blocking_enable=False,
chunk_swap_buffer_qubits=None,
# multi-shots optimization options (GPU only)
batched_shots_gpu=True,
batched_shots_gpu=False,
batched_shots_gpu_max_qubits=16,
num_threads_per_device=1,
# statevector options
@ -602,7 +629,11 @@ class AerSimulator(AerBackend):
mps_swap_direction='mps_swap_left',
chop_threshold=1e-8,
mps_parallel_threshold=14,
mps_omp_threads=1)
mps_omp_threads=1,
# tensor network options
tensor_network_num_sampling_qubits=10,
use_cuTensorNet_autotuning=False
)
def __repr__(self):
"""String representation of an AerSimulator."""

View File

@ -92,7 +92,16 @@ BASIS_GATES = {
'u1', 'u2', 'u3', 'u', 'p', 'r', 'rx', 'ry', 'rz', 'id', 'x',
'y', 'z', 'h', 's', 'sdg', 'sx', 'sxdg', 't', 'tdg', 'swap', 'cx',
'cy', 'cz', 'cp', 'cu1', 'rxx', 'ryy',
'rzz', 'rzx', 'ccx', 'unitary', 'diagonal', 'delay', 'pauli', 'ecr',
'rzz', 'rzx', 'ccx', 'unitary', 'diagonal', 'delay', 'pauli'
]),
'tensor_network': sorted([
'u1', 'u2', 'u3', 'u', 'p', 'r', 'rx', 'ry', 'rz', 'id', 'x',
'y', 'z', 'h', 's', 'sdg', 'sx', 'sxdg', 't', 'tdg', 'swap', 'cx',
'cy', 'cz', 'csx', 'cp', 'cu', 'cu1', 'cu2', 'cu3', 'rxx', 'ryy',
'rzz', 'rzx', 'ccx', 'cswap', 'mcx', 'mcy', 'mcz', 'mcsx',
'mcp', 'mcphase', 'mcu', 'mcu1', 'mcu2', 'mcu3', 'mcrx', 'mcry', 'mcrz',
'mcr', 'mcswap', 'unitary', 'diagonal', 'multiplexer',
'initialize', 'delay', 'pauli', 'mcx_gray'
])
}
@ -104,7 +113,8 @@ BASIS_GATES[None] = BASIS_GATES['automatic'] = sorted(
BASIS_GATES['density_matrix']).union(
BASIS_GATES['matrix_product_state']).union(
BASIS_GATES['unitary']).union(
BASIS_GATES['superop']))
BASIS_GATES['superop']).union(
BASIS_GATES['tensor_network']))
def cpp_execute(controller, qobj):
@ -117,21 +127,24 @@ def cpp_execute(controller, qobj):
return controller(qobj)
def available_methods(controller, methods):
def available_methods(controller, methods, devices):
"""Check available simulation methods by running a dummy circuit."""
# Test methods are available using the controller
dummy_circ = QuantumCircuit(1)
dummy_circ.i(0)
valid_methods = []
for method in methods:
qobj = assemble(dummy_circ,
optimization_level=0,
shots=1,
method=method)
result = cpp_execute(controller, qobj)
if result.get('success', False):
valid_methods.append(method)
for device in devices:
for method in methods:
if method not in valid_methods:
qobj = assemble(dummy_circ,
optimization_level=0,
shots=1,
method=method,
device=device)
result = cpp_execute(controller, qobj)
if result.get('success', False):
valid_methods.append(method)
return tuple(valid_methods)

View File

@ -366,7 +366,8 @@ class QasmSimulator(AerBackend):
# Update available methods for class
if QasmSimulator._AVAILABLE_METHODS is None:
QasmSimulator._AVAILABLE_METHODS = available_methods(
self._controller, QasmSimulator._SIMULATION_METHODS)
self._controller, QasmSimulator._SIMULATION_METHODS,
QasmSimulator._SIMULATION_DEVICES)
# Default configuration
if configuration is None:

View File

@ -0,0 +1,13 @@
---
features:
- |
Implementing general tensor network simulator for GPU accelerated by
NVIDIA's cuTensoNet APIs of cuQuantum SDK. Any quantum circuits can
be translated into tensor network and can be simulated.
To use this simulation method, set method=tensor_network and device=GPU
This method supports both statevector and density matrix simulations,
noise simulation can be done by single shot with density matrix
if there is no save_statevector operation.
This method supports parallelization by multiple GPUs and MPI processes
by using tensor network slicing technique.
(Note : It will take very long time if the circuits is complicated.)

91
src/controllers/aer_controller.hpp Executable file → Normal file
View File

@ -59,6 +59,7 @@
#include "simulators/statevector/statevector_state.hpp"
#include "simulators/superoperator/superoperator_state.hpp"
#include "simulators/unitary/unitary_state.hpp"
#include "simulators/tensor_network/tensor_net_state.hpp"
namespace AER {
@ -112,7 +113,8 @@ protected:
stabilizer,
extended_stabilizer,
unitary,
superop
superop,
tensor_network
};
enum class Device { CPU, GPU, ThrustCPU };
@ -128,7 +130,8 @@ protected:
{Method::stabilizer, "stabilizer"},
{Method::extended_stabilizer, "extended_stabilizer"},
{Method::unitary, "unitary"},
{Method::superop, "superop"}
{Method::superop, "superop"},
{Method::tensor_network, "tensor_network"}
};
//-----------------------------------------------------------------------
@ -290,6 +293,8 @@ protected:
int_t get_max_matrix_qubits(const Circuit &circ) const;
int_t get_matrix_bits(const Operations::Op& op) const;
bool has_statevector_ops(const Circuit &circuit) const;
//-----------------------------------------------------------------------
// Parallelization Config
//-----------------------------------------------------------------------
@ -487,6 +492,8 @@ void Controller::set_config(const json_t &config) {
method_ = Method::unitary;
} else if (method == "superop") {
method_ = Method::superop;
} else if (method == "tensor_network") {
method_ = Method::tensor_network;
} else if (method != "automatic") {
throw std::runtime_error(std::string("Invalid simulation method (") +
method + std::string(")."));
@ -534,6 +541,10 @@ void Controller::set_config(const json_t &config) {
}
}
if(method_ == Method::tensor_network && sim_device_ != Device::GPU){
throw std::runtime_error("Invalid combination of simulation method and device, \"tensor_network\" only supports \"device=GPU\"");
}
std::string precision;
if (JSON::get_value(precision, "precision", config)) {
if (precision == "double") {
@ -681,7 +692,8 @@ void Controller::set_parallelization_circuit(const Circuit &circ,
break;
}
case Method::density_matrix:
case Method::superop: {
case Method::superop:
case Method::tensor_network: {
if (circ.shots == 1 || num_process_per_experiment_ > 1 ||
check_measure_sampling_opt(circ, method)) {
parallel_shots_ = 1;
@ -1157,6 +1169,17 @@ void Controller::run_circuit(const Circuit &circ, const Noise::NoiseModel &noise
case Method::matrix_product_state:
return run_circuit_helper<MatrixProductState::State>(
circ, noise, config, Method::matrix_product_state, result);
case Method::tensor_network: {
if (sim_precision_ == Precision::Double) {
return run_circuit_helper<
TensorNetwork::State<TensorNetwork::TensorNet<double>>>(
circ, noise, config, Method::tensor_network, result);
} else {
return run_circuit_helper<
TensorNetwork::State<TensorNetwork::TensorNet<float>>>(
circ, noise, config, Method::tensor_network, result);
}
}
default:
throw std::runtime_error("Controller:Invalid simulation method");
}
@ -1218,6 +1241,15 @@ size_t Controller::required_memory_mb(const Circuit &circ,
MatrixProductState::State state;
return state.required_memory_mb(circ.num_qubits, circ.ops);
}
case Method::tensor_network: {
if (sim_precision_ == Precision::Single) {
TensorNetwork::State<TensorNetwork::TensorNet<float>> state;
return state.required_memory_mb(circ.num_qubits, circ.ops);
} else {
TensorNetwork::State<TensorNetwork::TensorNet<double>> state;
return state.required_memory_mb(circ.num_qubits, circ.ops);
}
}
default:
// We shouldn't get here, so throw an exception if we do
throw std::runtime_error("Controller: Invalid simulation method");
@ -1260,6 +1292,20 @@ Transpile::Fusion Controller::transpile_fusion(Method method,
fusion_pass.threshold /= 2;
break;
}
case Method::tensor_network: {
if(opset.contains(Operations::OpType::save_statevec) || opset.contains(Operations::OpType::save_statevec_dict)){
if (fusion_pass.allow_kraus) {
// Halve default max fused qubits for Kraus noise fusion
fusion_pass.max_qubit /= 2;
}
}
else{
// Halve the default threshold and max fused qubits for density matrix
fusion_pass.threshold /= 2;
fusion_pass.max_qubit /= 2;
}
break;
}
default: {
fusion_pass.active = false;
return fusion_pass;
@ -1295,7 +1341,7 @@ void Controller::run_circuit_helper(const Circuit &circ,
result.set_config(config);
result.metadata.add(method_names_.at(method), "method");
if (method == Method::statevector || method == Method::density_matrix ||
method == Method::unitary) {
method == Method::unitary || method == Method::tensor_network) {
result.metadata.add(sim_device_name_, "device");
} else {
result.metadata.add("CPU", "device");
@ -1329,7 +1375,7 @@ void Controller::run_circuit_helper(const Circuit &circ,
result.metadata.add("readout", "noise");
}
// Superop noise sampling
else if (method == Method::density_matrix || method == Method::superop) {
else if (method == Method::density_matrix || method == Method::superop || (method == Method::tensor_network && !has_statevector_ops(circ))) {
// Sample noise using SuperOp method
opt_circ = noise.sample_noise(circ, rng, Noise::NoiseModel::Method::superop);
result.metadata.add("superop", "noise");
@ -1434,6 +1480,7 @@ void Controller::run_circuit_without_sampled_noise(Circuit &circ,
state.set_config(config);
state.set_parallelization(parallel_state_update_);
state.set_global_phase(circ.global_phase_angle);
state.enable_density_matrix(!has_statevector_ops(circ));
bool can_sample = circ.can_sample;
@ -1481,6 +1528,7 @@ void Controller::run_circuit_without_sampled_noise(Circuit &circ,
shot_state.set_config(config);
shot_state.set_parallelization(parallel_state_update_);
shot_state.set_global_phase(circ.global_phase_angle);
shot_state.enable_density_matrix(!has_statevector_ops(circ));
shot_state.set_max_matrix_qubits(max_bits);
@ -1544,6 +1592,7 @@ void Controller::run_circuit_without_sampled_noise(Circuit &circ,
par_state.set_config(config);
par_state.set_parallelization(parallel_state_update_);
par_state.set_global_phase(circ.global_phase_angle);
par_state.enable_density_matrix(!has_statevector_ops(circ));
par_state.set_distribution(num_process_per_experiment_);
par_state.set_max_matrix_qubits(max_bits );
@ -1593,6 +1642,7 @@ void Controller::run_circuit_with_sampled_noise(
state.set_config(config);
state.set_parallelization(parallel_state_update_);
state.set_global_phase(circ.global_phase_angle);
state.enable_density_matrix(!has_statevector_ops(circ));
// Transpilation for circuit noise method
auto fusion_pass = transpile_fusion(method, circ.opset(), config);
@ -1661,6 +1711,14 @@ bool Controller::check_measure_sampling_opt(const Circuit &circ,
method == Method::unitary) {
return true;
}
if(method == Method::tensor_network){
//if there are no save statevec ops, tensor network simulator runs as density matrix simulator
if((!circ.opset().contains(Operations::OpType::save_statevec)) &&
(!circ.opset().contains(Operations::OpType::save_statevec_dict)) ){
return true;
}
}
// If circuit contains a non-initial initialize that is not a full width
// instruction we can't sample
@ -1801,11 +1859,11 @@ Controller::simulation_methods(std::vector<Circuit> &circuits,
for (const auto& circ: circuits) {
auto method = automatic_simulation_method(circ, noise_model);
sim_methods.push_back(method);
if (!superop_enabled && (method == Method::density_matrix || method == Method::superop)) {
if (!superop_enabled && (method == Method::density_matrix || method == Method::superop || (method == Method::tensor_network && !has_statevector_ops(circ)) )) {
noise_model.enable_superop_method(max_parallel_threads_);
superop_enabled = true;
} else if (kraus_noise && !kraus_enabled &&
(method == Method::statevector || method == Method::matrix_product_state)) {
(method == Method::statevector || method == Method::matrix_product_state || (method == Method::tensor_network && has_statevector_ops(circ))) ) {
noise_model.enable_kraus_method(max_parallel_threads_);
kraus_enabled = true;
}
@ -1822,6 +1880,18 @@ Controller::simulation_methods(std::vector<Circuit> &circuits,
|| method_ == Method::matrix_product_state)) {
noise_model.enable_kraus_method(max_parallel_threads_);
}
else if(method_ == Method::tensor_network){
bool has_save_statevec = false;
for (const auto& circ: circuits) {
has_save_statevec |= has_statevector_ops(circ);
if(has_save_statevec)
break;
}
if(!has_save_statevec)
noise_model.enable_superop_method(max_parallel_threads_);
else if(kraus_noise)
noise_model.enable_kraus_method(max_parallel_threads_);
}
return sim_methods;
}
@ -1886,6 +1956,8 @@ bool Controller::validate_method(Method method,
return validate_state(QubitUnitary::State<>(), circ, noise_model, throw_except);
case Method::superop:
return validate_state(QubitSuperoperator::State<>(), circ, noise_model, throw_except);
case Method::tensor_network:
return validate_state(TensorNetwork::State<>(), circ, noise_model, throw_except);
case Method::automatic:
throw std::runtime_error("Cannot validate circuit for unresolved simulation method.");
}
@ -1980,6 +2052,11 @@ int_t Controller::get_max_matrix_qubits(const Circuit &circ) const
return max_bits;
}
bool Controller::has_statevector_ops(const Circuit &circ) const
{
return circ.opset().contains(Operations::OpType::save_statevec) || circ.opset().contains(Operations::OpType::save_statevec_dict) || circ.opset().contains(Operations::OpType::save_amps);
}
//-------------------------------------------------------------------------
} // end namespace AER
//-------------------------------------------------------------------------

View File

@ -229,6 +229,8 @@ public:
//set creg bit counts before initialize creg
virtual void set_num_creg_bits(uint_t num_memory, uint_t num_register){}
//can apply density matrix (without statevector output required)
virtual void enable_density_matrix(bool flg){}
//-----------------------------------------------------------------------
// Common instructions
//-----------------------------------------------------------------------
@ -255,6 +257,7 @@ protected:
int_t max_matrix_qubits_ = 0;
std::string sim_device_name_ = "CPU";
};
void Base::set_config(const json_t &config)

View File

@ -0,0 +1,282 @@
/**
* This code is part of Qiskit.
*
* (C) Copyright IBM 2018, 2019, 2023.
*
* 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.
*/
#ifndef _tensor_hpp_
#define _tensor_hpp_
#include <complex>
#include <vector>
#include "framework/types.hpp"
#include "framework/utils.hpp"
namespace AER {
namespace TensorNetwork {
//class for tensor expression
template <typename data_t>
class Tensor
{
protected:
int base_; //basis of bit, 2 for qubit, 3 for qutrit (not supported yet)
int rank_; //rank(dimension) of tensor
std::vector<int64_t> extents_; //number of elements in each rank ( = base_)
int64_t size_; //size of tensor (number of elements)
std::vector<std::complex<data_t>> tensor_; //tensor elements (row major)
std::vector<int32_t> modes_; //indices of connected tensors
reg_t qubits_; //bits for each rank
bool sp_tensor_; //this tensor is superop matrix
public:
Tensor()
{
rank_ = 0;
size_ = 0;
base_ = 2; //qubit for default
sp_tensor_ = false;
}
Tensor(Tensor<data_t>& t);
~Tensor(){}
int rank()
{
return rank_;
}
std::vector<int64_t>& extents()
{
return extents_;
}
std::vector<std::complex<data_t>>& tensor()
{
return tensor_;
}
std::vector<int32_t>& modes()
{
return modes_;
}
reg_t& qubits()
{
return qubits_;
}
//create tensor from matrix
void set(const reg_t& qubits,std::vector<std::complex<data_t>>& mat);
void set(int qubit,std::vector<std::complex<data_t>>& mat);
void set(const reg_t& qubits,std::complex<data_t>* mat, uint64_t size);
//create conjugate tensor
void set_conj(const reg_t& qubits,std::vector<std::complex<data_t>>& mat);
void set_rank(int nr);
//multiply matrix
void mult_matrix(std::vector<std::complex<data_t>>& mat);
void mult_matrix_conj(std::vector<std::complex<data_t>>& mat);
//make conjugate tensor
void conjugate_tensor(void);
bool& sp_tensor(void)
{
return sp_tensor_;
}
};
template <typename data_t>
Tensor<data_t>::Tensor(Tensor<data_t>& t)
{
base_ = t.base_;
rank_ = t.rank_;
extents_ = t.extents_;
size_ = t.size_;
tensor_ = t.tensor_;
modes_ = t.modes_;
qubits_ = t.qubits_;
sp_tensor_ = t.sp_tensor_;
}
template <typename data_t>
void Tensor<data_t>::set(const reg_t& qubits,std::vector<std::complex<data_t>>& mat)
{
tensor_ = mat;
size_ = mat.size();
rank_ = 0;
int64_t t = size_;
if(base_ == 2){
while(t > 1){
rank_++;
t >>= 1;
}
}
else{
while(t > 1){
rank_++;
t /= base_;
}
}
modes_.resize(rank_);
extents_.resize(rank_);
for(int i=0;i<rank_;i++)
extents_[i] = base_;
qubits_ = qubits;
}
template <typename data_t>
void Tensor<data_t>::set(int qubit,std::vector<std::complex<data_t>>& mat)
{
tensor_ = mat;
size_ = mat.size();
rank_ = 0;
int64_t t = size_;
if(base_ == 2){
while(t > 1){
rank_++;
t >>= 1;
}
}
else{
while(t > 1){
rank_++;
t /= base_;
}
}
modes_.resize(rank_);
extents_.resize(rank_);
for(int i=0;i<rank_;i++)
extents_[i] = base_;
qubits_.push_back(qubit);
}
template <typename data_t>
void Tensor<data_t>::set(const reg_t& qubits,std::complex<data_t>* mat, uint_t size)
{
tensor_.resize(size);
for(int i=0;i<size;i++)
tensor_[i] = mat[i];
size_ = size;
rank_ = 0;
int64_t t = size_;
if(base_ == 2){
while(t > 1){
rank_++;
t >>= 1;
}
}
else{
while(t > 1){
rank_++;
t /= base_;
}
}
modes_.resize(rank_);
extents_.resize(rank_);
for(int i=0;i<rank_;i++)
extents_[i] = base_;
qubits_ = qubits;
}
template <typename data_t>
void Tensor<data_t>::set_conj(const reg_t& qubits,std::vector<std::complex<data_t>>& mat)
{
set(qubits,mat);
for(int i=0;i<tensor_.size();i++)
tensor_[i] = std::conj(tensor_[i]);
sp_tensor_ = true;
}
template <typename data_t>
void Tensor<data_t>::set_rank(int nr)
{
rank_ = nr;
size_ = 1ull << nr;
tensor_.resize(size_);
modes_.resize(rank_);
extents_.resize(rank_);
for(int i=0;i<rank_;i++)
extents_[i] = base_;
}
template <typename data_t>
void Tensor<data_t>::mult_matrix(std::vector<std::complex<data_t>>& mat)
{
int i,j,k;
if(tensor_.size() == mat.size()){
for(i=0;i<rank_;i++){
std::vector<std::complex<data_t>> t(base_,0.0);
for(j=0;j<base_;j++){
for(k=0;k<base_;k++)
t[k] += tensor_[i+j*base_] * mat[j+k*base_];
}
for(k=0;k<base_;k++)
tensor_[i+k*base_] = t[k];
}
}
}
template <typename data_t>
void Tensor<data_t>::mult_matrix_conj(std::vector<std::complex<data_t>>& mat)
{
int i,j,k;
if(tensor_.size() == mat.size()){
for(i=0;i<rank_;i++){
std::vector<std::complex<data_t>> t(base_,0.0);
for(j=0;j<base_;j++){
for(k=0;k<base_;k++)
t[k] += tensor_[i+j*base_] * std::conj(mat[j+k*base_]);
}
for(k=0;k<base_;k++)
tensor_[i+k*base_] = t[k];
}
}
}
template <typename data_t>
void Tensor<data_t>::conjugate_tensor(void)
{
for(int i=0;i<tensor_.size();i++){
tensor_[i] = std::conj(tensor_[i]);
}
}
//------------------------------------------------------------------------------
} // end namespace TensorNet
} // end namespace AER
//------------------------------------------------------------------------------
#endif // _tensor_hpp_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,102 @@
/**
* This code is part of Qiskit.
*
* (C) Copyright IBM 2018, 2019, 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.
*/
#ifndef _tensor_net_contractor_hpp_
#define _tensor_net_contractor_hpp_
namespace AER {
namespace TensorNetwork {
#define AER_TENSOR_NET_MAX_SAMPLING 10000
template <typename data_t = double>
class TensorNetContractor {
protected:
public:
TensorNetContractor(){}
virtual ~TensorNetContractor(){}
virtual void set_device(int idev) = 0;
virtual void allocate_additional_tensors(uint_t size) = 0;
virtual void set_network(const std::vector<std::shared_ptr<Tensor<data_t>>>& tensors, bool add_sp_tensors = true) = 0;
virtual void set_additional_tensors(const std::vector<std::shared_ptr<Tensor<data_t>>>& tensors) = 0;
virtual void set_output(std::vector<int32_t>& modes,std::vector<int64_t>& extents) = 0;
virtual void update_additional_tensors(const std::vector<std::shared_ptr<Tensor<data_t>>>& tensors) = 0;
virtual void setup_contraction(bool use_autotune = false) = 0;
virtual uint_t num_slices(void) = 0;
virtual void contract(std::vector<std::complex<data_t>>& out) = 0;
virtual double contract_and_trace(uint_t num_qubits) = 0;
virtual double contract_and_sample_measure(reg_t& samples, std::vector<double> &rnds, uint_t num_qubits) = 0;
virtual void allocate_sampling_buffers(uint_t size = AER_TENSOR_NET_MAX_SAMPLING) = 0;
virtual void deallocate_sampling_buffers(void) = 0;
};
template <typename data_t = double>
class TensorNetContractorDummy : public TensorNetContractor<data_t> {
protected:
public:
TensorNetContractorDummy(){}
~TensorNetContractorDummy(){}
void set_device(int idev) override {}
void allocate_additional_tensors(uint_t size) override {}
void set_network(const std::vector<std::shared_ptr<Tensor<data_t>>>& tensors, bool add_sp_tensors = true) override {}
void set_additional_tensors(const std::vector<std::shared_ptr<Tensor<data_t>>>& tensors) override {}
void set_output(std::vector<int32_t>& modes,std::vector<int64_t>& extents) override {}
void update_additional_tensors(const std::vector<std::shared_ptr<Tensor<data_t>>>& tensors) override {}
void setup_contraction(bool use_autotune = false) override {}
uint_t num_slices(void) override
{
return 1;
}
void contract(std::vector<std::complex<data_t>>& out) override {}
double contract_and_trace(uint_t num_qubits) override
{
return 1.0;
}
double contract_and_sample_measure(reg_t& samples, std::vector<double> &rnds, uint_t num_qubits) override
{
return 1.0;
}
void allocate_sampling_buffers(uint_t size = AER_TENSOR_NET_MAX_SAMPLING) override {}
void deallocate_sampling_buffers(void) override {}
};
//------------------------------------------------------------------------------
} // end namespace TensorNetwork
} // end namespace AER
//------------------------------------------------------------------------------
#endif //_tensor_net_contractor_hpp_

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -43,6 +43,10 @@ class TestAlgorithms(SimulatorTestCase):
def _test_teleport(self, **options):
"""Test teleport circuits."""
shots = 1000
for key, val in options.items():
if 'method' == key and 'tensor_network' in val:
shots = 100
backend = self.backend(**options)
circuits = ref_algorithms.teleport_circuit()
@ -56,7 +60,7 @@ class TestAlgorithms(SimulatorTestCase):
@supported_methods(
['automatic', 'statevector', 'density_matrix',
'matrix_product_state', 'extended_stabilizer'])
'matrix_product_state', 'extended_stabilizer', 'tensor_network'])
def test_grovers(self, method, device):
"""Test grovers circuits execute."""
@ -71,7 +75,7 @@ class TestAlgorithms(SimulatorTestCase):
@supported_methods(
['automatic', 'statevector', 'density_matrix',
'matrix_product_state', 'extended_stabilizer'])
'matrix_product_state', 'extended_stabilizer', 'tensor_network'])
def test_teleport(self, method, device):
"""Test teleport circuits."""
self._test_teleport(method=method, device=device)

View File

@ -21,7 +21,7 @@ from test.terra.backends.simulator_test_case import (
SUPPORTED_METHODS = [
'automatic', 'stabilizer', 'statevector', 'density_matrix',
'matrix_product_state', 'extended_stabilizer'
'matrix_product_state', 'extended_stabilizer', 'tensor_network'
]

View File

@ -27,7 +27,7 @@ class TestConditionalGates(SimulatorTestCase):
SUPPORTED_METHODS = [
'automatic', 'stabilizer', 'statevector', 'density_matrix',
'matrix_product_state', 'extended_stabilizer'
'matrix_product_state', 'extended_stabilizer', 'tensor_network'
]
# ---------------------------------------------------------------------
@ -50,6 +50,7 @@ class TestConditionalGates(SimulatorTestCase):
"""Test conditional gate operations on 2-bit conditional register."""
shots = 100
backend = self.backend(method=method, device=device)
backend.set_options(max_parallel_experiments=0)
circuits = ref_conditionals.conditional_circuits_2bit(
final_measure=True, conditional_type='gate')
targets = ref_conditionals.conditional_counts_2bit(shots)
@ -61,9 +62,12 @@ class TestConditionalGates(SimulatorTestCase):
def test_conditional_gates_64bit(self, method, device):
"""Test conditional gate operations on 64-bit conditional register."""
shots = 100
if 'tensor_network' in method:
shots = 1
# [value of conditional register, list of condtional values]
cases = ref_conditionals.conditional_cases_64bit()
backend = self.backend(method=method, device=device)
backend.set_options(max_parallel_experiments=0)
circuits = ref_conditionals.conditional_circuits_nbit(64, cases,
final_measure=True, conditional_type='gate')
# not using hex counts because number of leading zeros in results
@ -79,8 +83,11 @@ class TestConditionalGates(SimulatorTestCase):
def test_conditional_gates_132bit(self, method, device):
"""Test conditional gate operations on 132-bit conditional register."""
shots = 100
if 'tensor_network' in method:
shots = 1
cases = ref_conditionals.conditional_cases_132bit()
backend = self.backend(method=method, device=device)
backend.set_options(max_parallel_experiments=0)
circuits = ref_conditionals.conditional_circuits_nbit(132, cases, final_measure=True,
conditional_type='gate')
targets = ref_conditionals.condtional_counts_nbit(132, cases, shots,
@ -95,7 +102,7 @@ class TestConditionalUnitary(SimulatorTestCase):
"""AerSimulator conditional unitary tests."""
SUPPORTED_METHODS = [
'automatic', 'statevector', 'density_matrix', 'matrix_product_state',
'automatic', 'statevector', 'density_matrix', 'matrix_product_state', 'tensor_network'
]
# ---------------------------------------------------------------------
@ -118,6 +125,7 @@ class TestConditionalUnitary(SimulatorTestCase):
"""Test conditional unitary operations on 2-bit conditional register."""
shots = 100
backend = self.backend(method=method, device=device)
backend.set_options(max_parallel_experiments=0)
circuits = ref_conditionals.conditional_circuits_2bit(
final_measure=True, conditional_type='unitary')
targets = ref_conditionals.conditional_counts_2bit(shots)
@ -129,8 +137,11 @@ class TestConditionalUnitary(SimulatorTestCase):
def test_conditional_unitary_64bit(self, method, device):
"""Test conditional unitary operations on 64-bit conditional register."""
shots = 100
if 'tensor_network' in method:
shots = 1
cases = ref_conditionals.conditional_cases_64bit()
backend = self.backend(method=method, device=device)
backend.set_options(max_parallel_experiments=0)
circuits = ref_conditionals.conditional_circuits_nbit(64, cases,
final_measure=True, conditional_type='unitary')
targets = ref_conditionals.condtional_counts_nbit(64, cases, shots,
@ -144,8 +155,11 @@ class TestConditionalUnitary(SimulatorTestCase):
def test_conditional_unitary_132bit(self, method, device):
"""Test conditional unitary operations on 132-bit conditional register."""
shots = 100
if 'tensor_network' in method:
shots = 1
cases = ref_conditionals.conditional_cases_132bit()
backend = self.backend(method=method, device=device)
backend.set_options(max_parallel_experiments=0)
circuits = ref_conditionals.conditional_circuits_nbit(132, cases, final_measure=True,
conditional_type='unitary')
targets = ref_conditionals.condtional_counts_nbit(132, cases, shots,
@ -160,7 +174,7 @@ class TestConditionalKraus(SimulatorTestCase):
"""AerSimulator conditional kraus tests."""
SUPPORTED_METHODS = [
'automatic', 'statevector', 'density_matrix', 'matrix_product_state',
'automatic', 'statevector', 'density_matrix', 'matrix_product_state', 'tensor_network'
]
# ---------------------------------------------------------------------
@ -183,6 +197,7 @@ class TestConditionalKraus(SimulatorTestCase):
"""Test conditional kraus operations on 2-bit conditional register."""
shots = 100
backend = self.backend(method=method, device=device)
backend.set_options(max_parallel_experiments=0)
circuits = ref_conditionals.conditional_circuits_2bit(
final_measure=True, conditional_type='kraus')
targets = ref_conditionals.conditional_counts_2bit(shots)
@ -194,8 +209,11 @@ class TestConditionalKraus(SimulatorTestCase):
def test_conditional_kraus_64bit(self, method, device):
"""Test conditional kraus operations on 64-bit conditional register."""
shots = 100
if 'tensor_network' in method:
shots = 1
cases = ref_conditionals.conditional_cases_64bit()
backend = self.backend(method=method, device=device)
backend.set_options(max_parallel_experiments=0)
circuits = ref_conditionals.conditional_circuits_nbit(64, cases,
final_measure=True, conditional_type='kraus')
targets = ref_conditionals.condtional_counts_nbit(64, cases, shots,
@ -209,8 +227,11 @@ class TestConditionalKraus(SimulatorTestCase):
def test_conditional_kraus_132bit(self, method, device):
"""Test conditional kraus operations on 132-bit conditional register."""
shots = 100
if 'tensor_network' in method:
shots = 1
cases = ref_conditionals.conditional_cases_132bit()
backend = self.backend(method=method, device=device)
backend.set_options(max_parallel_experiments=0)
circuits = ref_conditionals.conditional_circuits_nbit(132, cases, final_measure=True,
conditional_type='kraus')
targets = ref_conditionals.condtional_counts_nbit(132, cases, shots,
@ -224,7 +245,7 @@ class TestConditionalKraus(SimulatorTestCase):
class TestConditionalSuperOp(SimulatorTestCase):
"""AerSimulator conditional superop tests."""
SUPPORTED_METHODS = ['automatic', 'density_matrix']
SUPPORTED_METHODS = ['automatic', 'density_matrix', 'tensor_network']
# ---------------------------------------------------------------------
# Test conditional
@ -246,6 +267,7 @@ class TestConditionalSuperOp(SimulatorTestCase):
"""Test conditional superop operations on 2-bit conditional register."""
shots = 100
backend = self.backend(method=method, device=device)
backend.set_options(max_parallel_experiments=0)
circuits = ref_conditionals.conditional_circuits_2bit(
final_measure=True, conditional_type='superop')
targets = ref_conditionals.conditional_counts_2bit(shots)
@ -257,8 +279,11 @@ class TestConditionalSuperOp(SimulatorTestCase):
def test_conditional_superop_64bit(self, method, device):
"""Test conditional superop operations on 64-bit conditional register."""
shots = 100
if 'tensor_network' in method:
shots = 1
cases = ref_conditionals.conditional_cases_64bit()
backend = self.backend(method=method, device=device)
backend.set_options(max_parallel_experiments=0)
circuits = ref_conditionals.conditional_circuits_nbit(64, cases,
final_measure=True, conditional_type='superop')
targets = ref_conditionals.condtional_counts_nbit(64, cases, shots,
@ -272,8 +297,11 @@ class TestConditionalSuperOp(SimulatorTestCase):
def test_conditional_superop_132bit(self, method, device):
"""Test conditional superop operations on 132-bit conditional register."""
shots = 100
if 'tensor_network' in method:
shots = 1
cases = ref_conditionals.conditional_cases_132bit()
backend = self.backend(method=method, device=device)
backend.set_options(max_parallel_experiments=0)
circuits = ref_conditionals.conditional_circuits_nbit(132, cases, final_measure=True,
conditional_type='superop')
targets = ref_conditionals.condtional_counts_nbit(132, cases, shots,

View File

@ -20,7 +20,7 @@ import numpy as np
from test.terra.backends.simulator_test_case import (
SimulatorTestCase, supported_methods)
SUPPORTED_METHODS = ['automatic', 'statevector', 'matrix_product_state']
SUPPORTED_METHODS = ['automatic', 'statevector', 'matrix_product_state', 'tensor_network']
@ddt
@ -35,6 +35,8 @@ class TestInitialize(SimulatorTestCase):
"""Test AerSimulator initialize"""
backend = self.backend(method=method, device=device)
shots = 100
if 'tensor_network' in method:
shots = 10
lst = [0, 1]
init_states = [
np.array(lst),
@ -55,6 +57,8 @@ class TestInitialize(SimulatorTestCase):
"""Test AerSimulator initialize"""
backend = self.backend(method=method, device=device)
shots = 100
if 'tensor_network' in method:
shots = 10
lst = [0, 1, 0, 0]
init_states = [
np.array(lst),
@ -77,11 +81,15 @@ class TestInitialize(SimulatorTestCase):
# For statevector output we can combine deterministic and non-deterministic
# count output circuits
shots = 1000
delta=0.05
if 'tensor_network' in method:
shots = 50
delta=0.2
circuits = ref_initialize.initialize_circuits_1(final_measure=True)
targets = ref_initialize.initialize_counts_1(shots)
result = backend.run(circuits, shots=shots).result()
self.assertSuccess(result)
self.compare_counts(result, circuits, targets, delta=0.05 * shots)
self.compare_counts(result, circuits, targets, delta=delta * shots)
@supported_methods(SUPPORTED_METHODS)
def test_initialize_2(self, method, device):
@ -90,33 +98,45 @@ class TestInitialize(SimulatorTestCase):
# For statevector output we can combine deterministic and non-deterministic
# count output circuits
shots = 1000
delta=0.05
if 'tensor_network' in method:
shots = 50
delta=0.2
circuits = ref_initialize.initialize_circuits_2(final_measure=True)
targets = ref_initialize.initialize_counts_2(shots)
result = backend.run(circuits, shots=shots).result()
self.assertSuccess(result)
self.compare_counts(result, circuits, targets, delta=0.05 * shots)
self.compare_counts(result, circuits, targets, delta=delta * shots)
@supported_methods(SUPPORTED_METHODS)
def test_initialize_sampling_opt(self, method, device):
"""Test sampling optimization"""
backend = self.backend(method=method, device=device)
shots = 1000
delta=0.05
if 'tensor_network' in method:
shots = 50
delta=0.2
circuits = ref_initialize.initialize_sampling_optimization()
targets = ref_initialize.initialize_counts_sampling_optimization(shots)
result = backend.run(circuits, shots=shots).result()
self.assertSuccess(result)
self.compare_counts(result, circuits, targets, delta=0.05 * shots)
self.compare_counts(result, circuits, targets, delta=delta * shots)
@supported_methods(SUPPORTED_METHODS)
def test_initialize_entangled_qubits(self, method, device):
"""Test initialize entangled qubits"""
backend = self.backend(method=method, device=device)
shots = 1000
delta=0.05
if 'tensor_network' in method:
shots = 50
delta=0.2
circuits = ref_initialize.initialize_entangled_qubits()
targets = ref_initialize.initialize_counts_entangled_qubits(shots)
result = backend.run(circuits, shots=shots).result()
self.assertSuccess(result)
self.compare_counts(result, circuits, targets, delta=0.05 * shots)
self.compare_counts(result, circuits, targets, delta=delta * shots)
@supported_methods(SUPPORTED_METHODS)
def test_initialize_sampling_opt_enabled(self, method, device):
@ -155,7 +175,10 @@ class TestInitialize(SimulatorTestCase):
circ = QuantumCircuit(4)
circ.initialize('+-rl')
circ.save_statevector()
actual = backend.run(circ).result().get_statevector(circ)
if 'tensor_network' in method:
actual = backend.run(circ, shots=50).result().get_statevector(circ)
else:
actual = backend.run(circ).result().get_statevector(circ)
for q4, p4 in enumerate([1, 1]):
for q3, p3 in enumerate([1, -1]):

View File

@ -27,7 +27,7 @@ from test.terra.backends.simulator_test_case import (
SUPPORTED_METHODS = [
'automatic', 'stabilizer', 'statevector', 'density_matrix',
'matrix_product_state', 'extended_stabilizer'
'matrix_product_state', 'extended_stabilizer', 'tensor_network'
]
@ -91,12 +91,16 @@ class TestMeasure(SimulatorTestCase):
"""Test AerSimulator measure with non-deterministic counts without sampling"""
backend = self.backend(method=method, device=device)
shots = 4000
delta=0.05
if 'tensor_network' in method:
shots = 100
delta=0.1
circuits = ref_measure.measure_circuits_nondeterministic(
allow_sampling=False)
targets = ref_measure.measure_counts_nondeterministic(shots)
result = backend.run(circuits, shots=shots).result()
self.assertSuccess(result)
self.compare_counts(result, circuits, targets, delta=0.05 * shots)
self.compare_counts(result, circuits, targets, delta=delta * shots)
self.compare_result_metadata(result, circuits, "measure_sampling", False)
@supported_methods(SUPPORTED_METHODS)
@ -139,7 +143,7 @@ class TestMeasure(SimulatorTestCase):
targets = ref_measure.measure_counts_deterministic(shots)
result = backend.run(circuits, shots=shots).result()
self.assertSuccess(result)
sampling = (method == "density_matrix")
sampling = (method == "density_matrix" or method == "tensor_network")
self.compare_result_metadata(result, circuits, "measure_sampling", sampling)
# ---------------------------------------------------------------------
@ -192,12 +196,16 @@ class TestMeasure(SimulatorTestCase):
"""Test AerSimulator measure with non-deterministic counts"""
backend = self.backend(method=method, device=device)
shots = 4000
delta=0.05
if 'tensor_network' in method:
shots = 100
delta=0.1
circuits = ref_measure.multiqubit_measure_circuits_nondeterministic(
allow_sampling=False)
targets = ref_measure.multiqubit_measure_counts_nondeterministic(shots)
result = backend.run(circuits, shots=shots).result()
self.assertSuccess(result)
self.compare_counts(result, circuits, targets, delta=0.05 * shots)
self.compare_counts(result, circuits, targets, delta=delta * shots)
self.compare_result_metadata(result, circuits, "measure_sampling", False)
# ---------------------------------------------------------------------

View File

@ -27,7 +27,7 @@ class TestMetadata(SimulatorTestCase):
@supported_methods(
['automatic', 'statevector', 'density_matrix',
'matrix_product_state', 'extended_stabilizer'])
'matrix_product_state', 'extended_stabilizer', 'tensor_network'])
def test_single_circuit_metadata(self, method, device):
"""Test circuits with object metadata."""
backend = self.backend(method=method, device=device)
@ -40,7 +40,7 @@ class TestMetadata(SimulatorTestCase):
@supported_methods(
['automatic', 'statevector', 'density_matrix',
'matrix_product_state', 'extended_stabilizer'])
'matrix_product_state', 'extended_stabilizer', 'tensor_network'])
def test_three_circuit_metadata(self, method, device):
"""Test circuits with object metadata."""
backend = self.backend(method=method, device=device)
@ -65,7 +65,7 @@ class TestMetadata(SimulatorTestCase):
self.assertEqual(circuit2.metadata, metadata2)
@supported_methods(
['automatic', 'statevector', 'density_matrix', 'matrix_product_state'])
['automatic', 'statevector', 'density_matrix', 'matrix_product_state', 'tensor_network'])
def test_three_parameterized_circuit_metadata(self, method, device):
"""Test circuits with object metadata."""
backend = self.backend(method=method, device=device)

View File

@ -31,7 +31,7 @@ from test.terra.reference import ref_reset_noise
ALL_METHODS = [
'automatic', 'stabilizer', 'statevector', 'density_matrix',
'matrix_product_state', 'extended_stabilizer'
'matrix_product_state', 'extended_stabilizer', 'tensor_network'
]
@ -86,7 +86,7 @@ class TestNoise(SimulatorTestCase):
@supported_methods([
'automatic', 'stabilizer', 'statevector', 'density_matrix',
'matrix_product_state', 'extended_stabilizer'])
'matrix_product_state', 'extended_stabilizer', 'tensor_network'])
def test_pauli_reset_noise(self, method, device):
"""Test simulation with Pauli reset error noise model."""
backend = self.backend(method=method, device=device)
@ -137,7 +137,7 @@ class TestNoise(SimulatorTestCase):
self.compare_counts(result, [circuit], [target], delta=0.05 * shots)
@supported_methods([
'automatic', 'statevector', 'density_matrix', 'matrix_product_state'])
'automatic', 'statevector', 'density_matrix', 'matrix_product_state', 'tensor_network'])
def test_kraus_gate_noise(self, method, device):
"""Test simulation with Kraus gate error noise model."""
backend = self.backend(method=method, device=device)
@ -185,7 +185,7 @@ class TestNoise(SimulatorTestCase):
self.compare_counts(result, [ideal_circuit], [ref_target], hex_counts=False, delta=0.1 * shots)
@supported_methods([
'automatic', 'statevector', 'density_matrix', 'matrix_product_state'])
'automatic', 'statevector', 'density_matrix', 'matrix_product_state', 'tensor_network'])
def test_kraus_gate_noise_on_QFT(self, method, device):
"""Test Kraus noise on a QFT circuit"""
self._test_kraus_gate_noise_on_QFT(
@ -228,7 +228,7 @@ class TestNoise(SimulatorTestCase):
probs = {key: val / shots for key, val in result.get_counts(0).items()}
self.assertDictAlmostEqual(target_probs, probs, delta=0.1)
@supported_methods(['automatic', 'statevector', 'density_matrix'])
@supported_methods(['automatic', 'statevector', 'density_matrix', 'tensor_network'])
def test_kraus_circuit_noise(self, method, device):
"""Test simulation with Kraus quantum errors in circuit."""
backend = self.backend(method=method, device=device)

View File

@ -20,7 +20,7 @@ from test.terra.backends.simulator_test_case import (
SUPPORTED_METHODS = [
'automatic', 'statevector', 'density_matrix',
'matrix_product_state', 'extended_stabilizer'
'matrix_product_state', 'extended_stabilizer', 'tensor_network'
]

View File

@ -27,7 +27,7 @@ class TestOptions(SimulatorTestCase):
@supported_methods(
['automatic', 'stabilizer', 'statevector', 'density_matrix',
'matrix_product_state', 'extended_stabilizer'])
'matrix_product_state', 'extended_stabilizer', 'tensor_network'])
def test_seed_simulator_option_measure(self, method, device):
"""Test seed_simulator option fixes measurement outcomes"""
backend = self.backend(method=method, device=device,
@ -45,7 +45,7 @@ class TestOptions(SimulatorTestCase):
@supported_methods(
['automatic', 'stabilizer', 'statevector', 'density_matrix',
'matrix_product_state', 'extended_stabilizer'])
'matrix_product_state', 'extended_stabilizer', 'tensor_network'])
def test_seed_simulator_run_option_measure(self, method, device):
"""Test seed_simulator option fixes measurement outcomes"""
backend = self.backend(method=method, device=device)
@ -61,7 +61,7 @@ class TestOptions(SimulatorTestCase):
@supported_methods(
['automatic', 'stabilizer', 'statevector', 'density_matrix',
'matrix_product_state', 'extended_stabilizer', 'unitary', 'superop'])
'matrix_product_state', 'extended_stabilizer', 'unitary', 'superop', 'tensor_network'])
def test_method_option(self, method, device):
"""Test method option works"""
backend = self.backend(method=method, device=device)
@ -81,7 +81,7 @@ class TestOptions(SimulatorTestCase):
@supported_methods(
['automatic', 'stabilizer', 'statevector', 'density_matrix',
'matrix_product_state', 'extended_stabilizer', 'unitary', 'superop'])
'matrix_product_state', 'extended_stabilizer', 'unitary', 'superop', 'tensor_network'])
def test_device_option(self, method, device):
"""Test device option works"""
backend = self.backend(method=method, device=device)
@ -121,7 +121,7 @@ class TestOptions(SimulatorTestCase):
self.assertEqual(sorted(basis_gates1), sorted(basis_gates2))
@supported_methods(
['automatic', 'stabilizer', 'statevector', 'density_matrix',
'matrix_product_state', 'extended_stabilizer'])
'matrix_product_state', 'extended_stabilizer', 'tensor_network'])
def test_shots_option(self, method, device):
"""Test shots option is observed"""
shots = 99
@ -136,7 +136,7 @@ class TestOptions(SimulatorTestCase):
@supported_methods(
['automatic', 'stabilizer', 'statevector', 'density_matrix',
'matrix_product_state', 'extended_stabilizer'])
'matrix_product_state', 'extended_stabilizer', 'tensor_network'])
def test_shots_run_option(self, method, device):
"""Test shots option is observed"""
shots = 99

View File

@ -28,7 +28,7 @@ class TestPauliGate(SimulatorTestCase):
@supported_methods(
["automatic", "stabilizer", "statevector", "density_matrix", "matrix_product_state",
"unitary", "superop", "extended_stabilizer"], ['I', 'X', 'Y', 'Z', 'XY', 'ZXY'])
"unitary", "superop", "extended_stabilizer", "tensor_network"], ['I', 'X', 'Y', 'Z', 'XY', 'ZXY'])
def test_pauli_gate(self, method, device, pauli):
"""Test multi-qubit Pauli gate."""
pauli = qi.Pauli(pauli)

View File

@ -19,7 +19,7 @@ from test.terra.backends.simulator_test_case import (
ALL_METHODS = [
'automatic', 'stabilizer', 'statevector', 'density_matrix',
'matrix_product_state', 'extended_stabilizer'
'matrix_product_state', 'extended_stabilizer', 'tensor_network'
]
@ddt

View File

@ -64,14 +64,14 @@ class TestSaveAmplitudes(SimulatorTestCase):
self.assertTrue(np.allclose(value, target))
@supported_methods(
['automatic', 'statevector', 'matrix_product_state'], AMPLITUDES)
['automatic', 'statevector', 'matrix_product_state', 'tensor_network'], AMPLITUDES)
def test_save_amplitudes(self, method, device, params):
"""Test save_amplitudes instruction"""
self._test_save_amplitudes(
QFT(3), params, False, method=method, device=device)
@supported_methods(
['automatic', 'statevector', 'matrix_product_state', 'density_matrix'],
['automatic', 'statevector', 'matrix_product_state', 'density_matrix', 'tensor_network'],
AMPLITUDES)
def test_save_amplitudes_squared(self, method, device, params):
"""Test save_amplitudes_squared instruction"""
@ -80,7 +80,7 @@ class TestSaveAmplitudes(SimulatorTestCase):
@supported_methods(
['automatic', 'stabilizer', 'statevector', 'matrix_product_state',
'density_matrix'], AMPLITUDES)
'density_matrix', 'tensor_network'], AMPLITUDES)
def test_save_amplitudes_squared_clifford(self, method, device, params):
"""Test save_amplitudes_squared instruction for Clifford circuit"""
# Stabilizer test circuit

View File

@ -26,7 +26,7 @@ class QasmSaveDensityMatrixTests(SimulatorTestCase):
"""Test SaveDensityMatrix instruction."""
@supported_methods(['automatic', 'statevector', 'density_matrix',
'matrix_product_state'])
'matrix_product_state', 'tensor_network'])
def test_save_density_matrix(self, method, device):
"""Test save density matrix for instruction"""
backend = self.backend(method=method, device=device)
@ -54,7 +54,7 @@ class QasmSaveDensityMatrixTests(SimulatorTestCase):
self.assertEqual(value, target)
@supported_methods(['automatic', 'statevector', 'density_matrix',
'matrix_product_state'])
'matrix_product_state', 'tensor_network'])
def test_save_density_matrix_conditional(self, method, device):
"""Test conditional save density matrix instruction"""
backend = self.backend(method=method, device=device)
@ -82,7 +82,7 @@ class QasmSaveDensityMatrixTests(SimulatorTestCase):
self.assertEqual(qi.DensityMatrix(state), target[key])
@supported_methods(['automatic', 'statevector', 'density_matrix',
'matrix_product_state'])
'matrix_product_state', 'tensor_network'])
def test_save_density_matrix_pershot(self, method, device):
"""Test pershot save density matrix instruction"""
backend = self.backend(method=method, device=device)
@ -112,7 +112,7 @@ class QasmSaveDensityMatrixTests(SimulatorTestCase):
self.assertEqual(qi.DensityMatrix(state), target)
@supported_methods(['automatic', 'statevector', 'density_matrix',
'matrix_product_state'])
'matrix_product_state', 'tensor_network'])
def test_save_density_matrix_pershot_conditional(self, method, device):
"""Test pershot conditional save density matrix instruction"""
backend = self.backend(method=method, device=device)

View File

@ -64,7 +64,7 @@ class TestSaveExpectationValueTests(SimulatorTestCase):
@supported_methods(
[
'automatic', 'stabilizer', 'statevector', 'density_matrix',
'matrix_product_state'
'matrix_product_state', 'tensor_network'
],
PAULI2)
def test_save_expval_bell_pauli(self, method, device, pauli):
@ -84,7 +84,7 @@ class TestSaveExpectationValueTests(SimulatorTestCase):
@supported_methods(
[
'automatic', 'stabilizer', 'statevector', 'density_matrix',
'matrix_product_state'
'matrix_product_state', 'tensor_network'
],
PAULI2)
def test_save_expval_stabilizer_pauli(self, method, device, pauli):
@ -103,7 +103,7 @@ class TestSaveExpectationValueTests(SimulatorTestCase):
@supported_methods(
[
'automatic', 'stabilizer', 'statevector', 'density_matrix',
'matrix_product_state'
'matrix_product_state', 'tensor_network'
],
PAULI2)
def test_save_expval_var_stabilizer_pauli(self, method, device, pauli):
@ -122,7 +122,7 @@ class TestSaveExpectationValueTests(SimulatorTestCase):
@supported_methods(
[
'automatic', 'stabilizer', 'statevector', 'density_matrix',
'matrix_product_state'
'matrix_product_state', 'tensor_network'
],
[[0, 1], [1, 0], [0, 2], [2, 0], [1, 2], [2, 1]])
def test_save_expval_stabilizer_hermitian(self, method, device, qubits):
@ -140,7 +140,7 @@ class TestSaveExpectationValueTests(SimulatorTestCase):
@supported_methods(
[
'automatic', 'stabilizer', 'statevector', 'density_matrix',
'matrix_product_state'
'matrix_product_state', 'tensor_network'
], # , 'extended_stabilizer'],
[[0, 1], [1, 0], [0, 2], [2, 0], [1, 2], [2, 1]])
def test_save_expval_var_stabilizer_hermitian(self, method, device,
@ -157,7 +157,7 @@ class TestSaveExpectationValueTests(SimulatorTestCase):
device=device)
@supported_methods(
['automatic', 'statevector', 'density_matrix', 'matrix_product_state'],
['automatic', 'statevector', 'density_matrix', 'matrix_product_state', 'tensor_network'],
PAULI2)
def test_save_expval_nonstabilizer_pauli(self, method, device, pauli):
"""Test Pauli expval for non-stabilizer circuit"""
@ -173,7 +173,7 @@ class TestSaveExpectationValueTests(SimulatorTestCase):
device=device)
@supported_methods(
['automatic', 'statevector', 'density_matrix', 'matrix_product_state'],
['automatic', 'statevector', 'density_matrix', 'matrix_product_state', 'tensor_network'],
PAULI2)
def test_save_expval_var_nonstabilizer_pauli(self, method, device, pauli):
"""Test Pauli expval_var for non-stabilizer circuit"""
@ -189,7 +189,7 @@ class TestSaveExpectationValueTests(SimulatorTestCase):
device=device)
@supported_methods(
['automatic', 'statevector', 'density_matrix', 'matrix_product_state'],
['automatic', 'statevector', 'density_matrix', 'matrix_product_state', 'tensor_network'],
[[0, 1], [1, 0], [0, 2], [2, 0], [1, 2], [2, 1]])
def test_save_expval_nonstabilizer_hermitian(self, method, device, qubits):
"""Test expval for non-stabilizer circuit and Hermitian operator"""
@ -204,7 +204,7 @@ class TestSaveExpectationValueTests(SimulatorTestCase):
device=device)
@supported_methods(
['automatic', 'statevector', 'density_matrix', 'matrix_product_state'],
['automatic', 'statevector', 'density_matrix', 'matrix_product_state', 'tensor_network'],
[[0, 1], [1, 0], [0, 2], [2, 0], [1, 2], [2, 1]])
def test_save_expval_var_nonstabilizer_hermitian(self, method, device,
qubits):
@ -219,7 +219,7 @@ class TestSaveExpectationValueTests(SimulatorTestCase):
method=method,
device=device)
@supported_methods(['density_matrix'], PAULI2)
@supported_methods(['density_matrix', 'tensor_network'], PAULI2)
def test_save_expval_cptp_pauli(self, method, device, pauli):
"""Test Pauli expval for stabilizer circuit"""
SEED = 5832
@ -235,7 +235,7 @@ class TestSaveExpectationValueTests(SimulatorTestCase):
method=method,
device=device)
@supported_methods(['density_matrix'], PAULI2)
@supported_methods(['density_matrix', 'tensor_network'], PAULI2)
def test_save_expval_var_cptp_pauli(self, method, device, pauli):
"""Test Pauli expval_var for stabilizer circuit"""
SEED = 5832

View File

@ -75,7 +75,7 @@ class TestSaveProbabilities(SimulatorTestCase):
@supported_methods([
'automatic', 'statevector', 'density_matrix', 'matrix_product_state',
'stabilizer'
'stabilizer', 'tensor_network'
], [[0, 1], [1, 0], [0], [1]])
def test_save_probabilities(self, method, device, qubits):
"""Test save probabilities instruction"""
@ -83,7 +83,7 @@ class TestSaveProbabilities(SimulatorTestCase):
@supported_methods([
'automatic', 'statevector', 'density_matrix', 'matrix_product_state',
'stabilizer'
'stabilizer', 'tensor_network'
], [[0, 1], [1, 0], [0], [1]])
def test_save_probabilities_dict(self, method, device, qubits):
"""Test save probabilities dict instruction"""

View File

@ -29,7 +29,7 @@ class TestSaveState(SimulatorTestCase):
@supported_methods(['automatic', 'statevector', 'density_matrix',
'stabilizer', 'matrix_product_state',
'unitary', 'superop'])
'unitary', 'superop', 'tensor_network'])
def test_save_state(self, method, device):
"""Test save_amplitudes instruction"""
@ -40,7 +40,8 @@ class TestSaveState(SimulatorTestCase):
'density_matrix': SaveDensityMatrix,
'matrix_product_state': SaveMatrixProductState,
'unitary': SaveUnitary,
'superop': SaveSuperOp
'superop': SaveSuperOp,
'tensor_network' : SaveStatevector
}
backend = self.backend(method=method, device=device)

View File

@ -25,7 +25,7 @@ class TestSaveStatevector(SimulatorTestCase):
"""SaveStatevector instruction tests."""
@supported_methods(['automatic', 'statevector', 'matrix_product_state',
'extended_stabilizer'])
'extended_stabilizer', 'tensor_network'])
def test_save_statevector(self, method, device):
"""Test save statevector instruction"""
backend = self.backend(method=method, device=device)
@ -54,7 +54,7 @@ class TestSaveStatevector(SimulatorTestCase):
self.assertEqual(value, target)
@supported_methods(['automatic', 'statevector', 'matrix_product_state',
'extended_stabilizer'])
'extended_stabilizer', 'tensor_network'])
def test_save_statevector_conditional(self, method, device):
"""Test conditional save statevector instruction"""
@ -85,7 +85,7 @@ class TestSaveStatevector(SimulatorTestCase):
self.assertEqual(vec, target[key])
@supported_methods(['automatic', 'statevector', 'matrix_product_state',
'extended_stabilizer'])
'extended_stabilizer', 'tensor_network'])
def test_save_statevector_pershot(self, method, device):
"""Test pershot save statevector instruction"""
backend = self.backend(method=method, device=device)
@ -117,7 +117,7 @@ class TestSaveStatevector(SimulatorTestCase):
self.assertEqual(vec, target)
@supported_methods(['automatic', 'statevector', 'matrix_product_state',
'extended_stabilizer'])
'extended_stabilizer', 'tensor_network'])
def test_save_statevector_pershot_conditional(self, method, device):
"""Test pershot conditional save statevector instruction"""

View File

@ -29,7 +29,7 @@ def statevec_as_dict(data):
class TestSaveStatevectorDict(SimulatorTestCase):
"""Test SaveStatevectorDict instruction."""
@supported_methods(['automatic', 'statevector'])
@supported_methods(['automatic', 'statevector', 'tensor_network'])
def test_save_statevector_dict(self, method, device):
"""Test save statevector for instruction"""
@ -58,7 +58,7 @@ class TestSaveStatevectorDict(SimulatorTestCase):
value = simdata[label]
self.assertDictAlmostEqual(value, target)
@supported_methods(['automatic', 'statevector'])
@supported_methods(['automatic', 'statevector', 'tensor_network'])
def test_save_statevector_conditional(self, method, device):
"""Test conditional save statevector instruction"""
@ -87,7 +87,7 @@ class TestSaveStatevectorDict(SimulatorTestCase):
self.assertIn(key, target)
self.assertDictAlmostEqual(vec, target[key])
@supported_methods(['automatic', 'statevector'])
@supported_methods(['automatic', 'statevector', 'tensor_network'])
def test_save_statevector_dict_pershot(self, method, device):
"""Test pershot save statevector instruction"""
@ -119,7 +119,7 @@ class TestSaveStatevectorDict(SimulatorTestCase):
for vec in value:
self.assertDictAlmostEqual(vec, target)
@supported_methods(['automatic', 'statevector'])
@supported_methods(['automatic', 'statevector', 'tensor_network'])
def test_save_statevector_dict_pershot_conditional(
self, method, device):
"""Test pershot conditional save statevector instruction"""

View File

@ -70,7 +70,7 @@ class TestSetState(SimulatorTestCase):
value = simdata[label]
self.assertEqual(value, target)
@supported_methods(['automatic', 'statevector'], [1, 2, 3])
@supported_methods(['automatic', 'statevector', 'tensor_network'], [1, 2, 3])
def test_set_statevector(self, method, device, num_qubits):
"""Test SetStatevector for instruction"""
backend = self.backend(method=method, device=device)
@ -93,7 +93,7 @@ class TestSetState(SimulatorTestCase):
value = simdata[label]
self.assertEqual(value, target)
@supported_methods(['automatic', 'density_matrix'], [1, 2, 3])
@supported_methods(['automatic', 'density_matrix', 'tensor_network'], [1, 2, 3])
def test_set_density_matrix(self, method, device, num_qubits):
"""Test SetDensityMatrix instruction"""
backend = self.backend(method=method, device=device)

View File

@ -154,7 +154,7 @@ class TestGates(SimulatorTestCase):
@supported_methods(
["automatic", "stabilizer", "statevector", "density_matrix", "matrix_product_state",
"unitary", "superop"],
"unitary", "superop", "tensor_network"],
CLIFFORD_GATES_DICT)
def test_clifford_gate(self, method, device, gate):
"""Test Clifford standard gates."""
@ -170,7 +170,7 @@ class TestGates(SimulatorTestCase):
@supported_methods(
["automatic", "statevector", "density_matrix", "matrix_product_state",
"unitary", "superop"],
"unitary", "superop", "tensor_network"],
NONCLIFFORD_GATES_DICT)
def test_nonclifford_gate(self, method, device, gate):
"""Test non-Clifford standard gates."""
@ -184,7 +184,7 @@ class TestGates(SimulatorTestCase):
self._test_gate(gate, NONCLIFFORD_GATES_DICT, method=method, device=device,
blocking_qubits=2, max_parallel_threads=1)
@supported_methods(["automatic", "statevector", "unitary"], MC_GATES_DICT)
@supported_methods(["automatic", "statevector", "unitary", "tensor_network"], MC_GATES_DICT)
def test_multictrl_gate(self, method, device, gate):
"""Test multi-controlled standard gates."""
self._test_gate(gate, MC_GATES_DICT, method=method, device=device)

View File

@ -17,7 +17,7 @@ from test.terra.backends.simulator_test_case import (
ALL_METHODS = [
'automatic', 'stabilizer', 'statevector', 'density_matrix',
'matrix_product_state', 'extended_stabilizer'
'matrix_product_state', 'extended_stabilizer', 'tensor_network'
]
@ddt

View File

@ -29,7 +29,7 @@ from test.terra.backends.simulator_test_case import (
class TestUnitaryGates(SimulatorTestCase):
"""AerSimulator unitary gate tests."""
METHODS = ["automatic", "statevector", "density_matrix", "matrix_product_state"]
METHODS = ["automatic", "statevector", "density_matrix", "matrix_product_state", "tensor_network"]
# ---------------------------------------------------------------------
# Test unitary gate qobj instruction

View File

@ -33,6 +33,9 @@ class TestQasmSimulator(SimulatorTestCase):
# GPU_cuStateVec is converted to GPU
if device == "GPU_cuStateVec":
device = "GPU"
# GPU_batch is converted to GPU
if device == "GPU_batch":
device = "GPU"
legacy_method = f"{method}_{device.lower()}"
backend.set_options(method=legacy_method)
self.assertEqual(backend.options.method, method)

View File

@ -37,6 +37,9 @@ class SimulatorTestCase(QiskitAerTestCase):
if 'device' == key and 'cuStateVec' in val:
sim_options['device'] = 'GPU'
sim_options['cuStateVec_enable'] = True
elif 'device' == key and 'batch' in val:
sim_options['device'] = 'GPU'
sim_options['batched_shots_gpu'] = True
else:
sim_options[key] = val
return self.BACKEND(**sim_options)
@ -77,17 +80,25 @@ def _method_device(methods):
#add special test device for cuStateVec if available
cuStateVec = check_cuStateVec(available_devices)
gpu_methods = ['statevector', 'density_matrix', 'unitary']
gpu_methods = ['statevector', 'density_matrix', 'unitary', 'tensor_network']
data_args = []
for method in methods:
if method in gpu_methods:
for device in available_devices:
data_args.append((method, device))
#add test cases for cuStateVec if available using special device = 'GPU_cuStateVec'
#'GPU_cuStateVec' is used only inside tests not available in Aer
#and this is converted to "device='GPU'" and option "cuStateVec_enalbe = True" is added
if cuStateVec:
data_args.append((method, 'GPU_cuStateVec'))
if 'tensor_network' == method:
for device in available_devices:
if device == 'GPU':
data_args.append((method, 'GPU'))
else:
for device in available_devices:
data_args.append((method, device))
if device == 'GPU':
#add batched optimization test for GPU
data_args.append((method, 'GPU_batch'))
#add test cases for cuStateVec if available using special device = 'GPU_cuStateVec'
#'GPU_cuStateVec' is used only inside tests not available in Aer
#and this is converted to "device='GPU'" and option "cuStateVec_enalbe = True" is added
if cuStateVec and 'tensor_network' != method:
data_args.append((method, 'GPU_cuStateVec'))
else:
data_args.append((method, 'CPU'))
return data_args