diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 555bbb9a6d..840476f306 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -70,12 +70,12 @@ jobs: with: python-version: 3.8 - name: Install deps - run: python -m pip install -U cibuildwheel==1.7.0 + run: python -m pip install -U cibuildwheel==1.7.1 - name: Build Wheels env: CIBW_BEFORE_ALL_LINUX: "yum install -y https://archives.fedoraproject.org/pub/archive/epel/6/x86_64/epel-release-6-8.noarch.rpm && yum install -y openblas-devel" CIBW_BEFORE_BUILD: "pip install -U virtualenv pybind11" - CIBW_SKIP: "cp27-* cp34-* cp35-* cp39-* pp*" + CIBW_SKIP: "cp27-* cp34-* cp35-* pp*" CIBW_MANYLINUX_X86_64_IMAGE: "quay.io/pypa/manylinux2010_x86_64:2020-12-03-912b0de" CIBW_MANYLINUX_I686_IMAGE: "quay.io/pypa/manylinux2010_i686:2020-12-03-912b0de" CIBW_TEST_COMMAND: "python3 {project}/tools/verify_wheels.py" diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 2ad5c1f7a0..af0a05a75c 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -18,7 +18,7 @@ jobs: python-version: '3.7' - name: Install cibuildwheel run: | - python -m pip install cibuildwheel==1.5.5 + python -m pip install cibuildwheel==1.7.1 - name: Build wheels env: CIBW_BEFORE_ALL_LINUX: "yum install -y https://archives.fedoraproject.org/pub/archive/epel/6/x86_64/epel-release-6-8.noarch.rpm && yum install -y openblas-devel" @@ -74,14 +74,14 @@ jobs: python-version: '3.7' - name: Install cibuildwheel run: | - python -m pip install cibuildwheel==1.5.5 + python -m pip install cibuildwheel==1.7.1 - name: Build wheels env: - CIBW_BEFORE_ALL: "yum install -y yum-utils wget && wget https://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel6-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm && rpm -i cuda-repo-rhel6-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm && yum clean all && yum -y install cuda-10-1 && yum install -y https://archives.fedoraproject.org/pub/archive/epel/6/x86_64/epel-release-6-8.noarch.rpm" + CIBW_BEFORE_ALL: "yum install -y yum-utils wget && wget https://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel6-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm && rpm -i cuda-repo-rhel6-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm && yum clean all && yum -y install cuda-10-1" CIBW_BEFORE_BUILD: "pip install -U Cython pip virtualenv pybind11 && yum install -y openblas-devel" CIBW_SKIP: "cp27-* cp34-* cp35-* *-manylinux_i686 pp*" - CIBW_MANYLINUX_X86_64_IMAGE: "quay.io/pypa/manylinux2010_x86_64:2020-12-03-912b0de" - CIBW_MANYLINUX_I686_IMAGE: "quay.io/pypa/manylinux2010_i686:2020-12-03-912b0de" + CIBW_MANYLINUX_X86_64_IMAGE: "quay.io/pypa/manylinux2010_x86_64:latest" + CIBW_MANYLINUX_I686_IMAGE: "quay.io/pypa/manylinux2010_i686:latest" CIBW_ENVIRONMENT: QISKIT_AER_PACKAGE_NAME=qiskit-aer-gpu AER_THRUST_BACKEND=CUDA CUDACXX=/usr/local/cuda/bin/nvcc CIBW_TEST_COMMAND: "python3 {project}/tools/verify_wheels.py" CIBW_TEST_REQUIRES: "git+https://github.com/Qiskit/qiskit-terra.git" diff --git a/.github/workflows/tests_linux.yml b/.github/workflows/tests_linux.yml index ccb2523f74..28387c7d31 100644 --- a/.github/workflows/tests_linux.yml +++ b/.github/workflows/tests_linux.yml @@ -42,7 +42,7 @@ jobs: needs: ["lint"] strategy: matrix: - python-version: [3.6, 3.7, 3.8] + python-version: [3.6, 3.7, 3.8, 3.9] platform: [ { os: "ubuntu-latest", python-architecture: "x64" }, ] @@ -86,7 +86,7 @@ jobs: timeout-minutes: 25 strategy: matrix: - python-version: [3.6, 3.7, 3.8] + python-version: [3.6, 3.7, 3.8, 3.9] os: ["ubuntu-latest"] env: AER_THRUST_BACKEND: OMP diff --git a/.github/workflows/tests_mac.yml b/.github/workflows/tests_mac.yml index 44045d0b74..5d7b2e4d70 100644 --- a/.github/workflows/tests_mac.yml +++ b/.github/workflows/tests_mac.yml @@ -42,7 +42,7 @@ jobs: needs: ["lint"] strategy: matrix: - python-version: [3.6, 3.7, 3.8] + python-version: [3.6, 3.7, 3.8, 3.9] platform: [ { os: "macOS-latest", python-architecture: "x64"}, ] @@ -80,7 +80,7 @@ jobs: timeout-minutes: 25 strategy: matrix: - python-version: [3.6, 3.7, 3.8] + python-version: [3.6, 3.7, 3.8, 3.9] os: ["macOS-latest"] env: AER_THRUST_BACKEND: OMP diff --git a/.github/workflows/tests_windows.yml b/.github/workflows/tests_windows.yml index 4e1a8e01d4..3b95d868ea 100644 --- a/.github/workflows/tests_windows.yml +++ b/.github/workflows/tests_windows.yml @@ -43,7 +43,7 @@ jobs: timeout-minutes: 25 strategy: matrix: - python-version: [3.6, 3.7, 3.8] + python-version: [3.6, 3.7, 3.8, 3.9] os: ["windows-latest"] env: AER_THRUST_BACKEND: OMP diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c52bf7a92..00b1c34f66 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,12 +47,9 @@ option(BUILD_TESTS "Specify whether we want to build tests or not" FALSE) # Allow disabling conan for downstream package managers. Requires all libraries to be present in path # Default is value of environment variable if defined or ON -if(DEFINED ENV{DISABLE_CONAN}) - set(_DISABLE_CONAN_DEFAULT ENV{DISABLE_CONAN}) -else() - set(_DISABLE_CONAN_DEFAULT OFF) +if(NOT DEFINED DISABLE_CONAN AND DEFINED ENV{DISABLE_CONAN}) + set(DISABLE_CONAN $ENV{DISABLE_CONAN}) endif() -option(DISABLE_CONAN "Disable Conan package manager to find dependencies. If disabled, you must have all dependencies present on your system." ${_DISABLE_CONAN_DEFAULT}) include(CTest) include(compiler_utils) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 1f1f7b4299..df12da9d61 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -140,6 +140,8 @@ stages: python.version: '3.7' Python38: python.version: '3.8' + Python39: + python.version: '3.9' variables: PIP_CACHE_DIR: $(Pipeline.Workspace)/.pip steps: @@ -229,6 +231,8 @@ stages: python.version: '3.7' Python38: python.version: '3.8' + Python39: + python.version: '3.9' variables: PIP_CACHE_DIR: $(Pipeline.Workspace)/.pip steps: @@ -243,7 +247,7 @@ stages: source activate qiskit-aer conda update --yes -n base conda conda config --add channels conda-forge - conda install --yes --quiet --name qiskit-aer python=$(python.version) numpy cmake pip setuptools pybind11 cython scipy + conda install --yes --quiet --name qiskit-aer python=$(python.version) numpy cmake pip setuptools wheel pybind11 cython scipy displayName: Create Anaconda environments - bash: | set -x @@ -255,7 +259,7 @@ stages: set -x set -e source activate qiskit-aer - pip install -U setuptools wheel + pip install -U setuptools pip install dist/*tar.gz pip install git+https://github.com/Qiskit/qiskit-terra python tools/verify_wheels.py diff --git a/docs/conf.py b/docs/conf.py index 49d0d093f6..0b99fefe5d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -46,7 +46,7 @@ # The short X.Y version version = '' # The full version, including alpha/beta/rc tags -release = '0.7.2' +release = '0.7.3' # -- General configuration --------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index 0e00e6d818..ec661b6de5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,2 +1,3 @@ [build-system] -requires = ["setuptools", "wheel", "urllib3<1.26", "conan>=1.22.2", "scikit-build", "cmake!=3.17.1,!=3.17.0", "ninja", "pybind11>2.4", "Cython>0.27.1"] +requires = ["setuptools", "wheel", "urllib3<1.26", "conan>=1.22.2", "scikit-build", + "cmake!=3.17.1,!=3.17.0", "ninja", "pybind11>2.4", "Cython>0.27.1", "numpy>1.16.3"] diff --git a/qiskit/providers/aer/VERSION.txt b/qiskit/providers/aer/VERSION.txt index 7486fdbc50..f38fc5393f 100644 --- a/qiskit/providers/aer/VERSION.txt +++ b/qiskit/providers/aer/VERSION.txt @@ -1 +1 @@ -0.7.2 +0.7.3 diff --git a/qiskit/providers/aer/backends/qasm_simulator.py b/qiskit/providers/aer/backends/qasm_simulator.py index bdaef1059c..adcdacb261 100644 --- a/qiskit/providers/aer/backends/qasm_simulator.py +++ b/qiskit/providers/aer/backends/qasm_simulator.py @@ -257,15 +257,18 @@ class QasmSimulator(AerBackend): 'max_shots': int(1e6), 'description': 'A C++ QasmQobj simulator with noise', 'coupling_map': None, - 'basis_gates': [ + 'basis_gates': sorted([ 'u1', 'u2', 'u3', 'u', 'p', 'r', 'rx', 'ry', 'rz', 'id', 'x', 'y', 'z', 'h', 's', 'sdg', 'sx', 't', 'tdg', 'swap', 'cx', 'cy', 'cz', 'csx', 'cp', 'cu1', 'cu2', 'cu3', 'rxx', 'ryy', 'rzz', 'rzx', 'ccx', 'cswap', 'mcx', 'mcy', 'mcz', 'mcsx', 'mcp', 'mcu1', 'mcu2', 'mcu3', 'mcrx', 'mcry', 'mcrz', 'mcr', 'mcswap', 'unitary', 'diagonal', 'multiplexer', - 'initialize', 'kraus', 'roerror', 'delay' - ], + 'initialize', 'delay', + # Custom instructions + 'kraus', 'roerror', 'snapshot' + ]), + 'custom_instructions': sorted(['roerror', 'kraus', 'snapshot']), 'gates': [] } @@ -291,6 +294,9 @@ def __init__(self, if configuration is None: configuration = self._method_configuration() + elif not hasattr(configuration, 'custom_instructions'): + configuration.custom_instructions = [] + super().__init__(configuration, properties=properties, available_methods=QasmSimulator._AVAILABLE_METHODS, @@ -312,6 +318,12 @@ def from_backend(cls, backend, **options): name = configuration.backend_name configuration.backend_name = 'qasm_simulator({})'.format(name) + # Basis gates and Custom instructions + basis_gates = set(configuration.basis_gates) + custom_instr = cls._DEFAULT_CONFIGURATION['custom_instructions'] + configuration.custom_instructions = sorted(custom_instr) + configuration.basis_gates = sorted(basis_gates.union(custom_instr)) + # Use automatic noise model if none is provided if 'noise_model' not in options: noise_model = NoiseModel.from_backend(backend) @@ -348,7 +360,10 @@ def _set_option(self, key, value): # If key is noise_model we also change the simulator config # to use the noise_model basis gates by default. if key == 'noise_model' and value is not None: - self._set_configuration_option('basis_gates', value.basis_gates) + basis_gates = set(self._configuration.basis_gates) # Method basis gates + intersection = basis_gates.intersection(value.basis_gates) + self._check_basis_gates(basis_gates, value.basis_gates, intersection) + self._set_option('basis_gates', intersection) # If key is method we update our configurations if key == 'method': @@ -356,19 +371,38 @@ def _set_option(self, key, value): self._set_configuration_option('description', method_config.description) self._set_configuration_option('backend_name', method_config.backend_name) self._set_configuration_option('n_qubits', method_config.n_qubits) - - # Take intersection of method basis gates and noise model basis gates - # if there is a noise model which has already set the basis gates - basis_gates = method_config.basis_gates + self._set_configuration_option('custom_instructions', + method_config.custom_instructions) + # Take intersection of method basis gates with configuration + # basis gates and noise model basis gates + basis_gates = set(self._configuration.basis_gates) + basis_gates = basis_gates.intersection(method_config.basis_gates) if 'noise_model' in self.options: - noise_basis_gates = self.options['noise_model'].basis_gates - basis_gates = list( - set(basis_gates).intersection(noise_basis_gates)) - self._set_configuration_option('basis_gates', basis_gates) + noise_gates = self.options['noise_model'].basis_gates + intersection = basis_gates.intersection(noise_gates) + self._check_basis_gates(basis_gates, noise_gates, intersection) + basis_gates = intersection + self._set_option('basis_gates', basis_gates) + + # When setting basis gates always append custom simulator instructions for + # the current method + if key == 'basis_gates': + value = sorted(set(value).union(self.configuration().custom_instructions)) # Set all other options from AerBackend super()._set_option(key, value) + @staticmethod + def _check_basis_gates(method_gates, noise_gates, intersection=None): + """Check if intersection of method basis gates and noise basis gates is empty""" + if intersection is None: + intersection = set(method_gates).intersection(noise_gates) + if not intersection: + logger.warning( + "The intersection of NoiseModel basis gates (%s) and " + "backend basis gates (%s) is empty", + sorted(noise_gates), sorted(method_gates)) + def _validate(self, qobj): """Semantic validations of the qobj which cannot be done via schemas. @@ -409,38 +443,41 @@ def _method_configuration(method=None): ]: config.n_qubits = config.n_qubits // 2 config.description = 'A C++ QasmQobj density matrix simulator with noise' - config.basis_gates = [ + config.custom_instructions = sorted(['roerror', 'snapshot', 'kraus', 'superop']) + config.basis_gates = sorted([ 'u1', 'u2', 'u3', 'u', 'p', 'r', 'rx', 'ry', 'rz', 'id', 'x', 'y', 'z', 'h', 's', 'sdg', 'sx', 't', 'tdg', 'swap', 'cx', - 'cy', 'cz', 'cp', 'cu1', 'rxx', 'ryy', - 'rzz', 'rzx', 'ccx', 'unitary', 'diagonal', 'kraus', 'superop' - 'roerror', 'delay' - ] + 'cy', 'cz', 'cp', 'cu1', 'rxx', 'ryy', 'rzz', 'rzx', 'ccx', + 'unitary', 'diagonal', 'delay', + ] + config.custom_instructions) # Matrix product state method elif method == 'matrix_product_state': config.description = 'A C++ QasmQobj matrix product state simulator with noise' - config.basis_gates = [ + config.custom_instructions = sorted(['roerror', 'snapshot', 'kraus']) + config.basis_gates = sorted([ 'u1', 'u2', 'u3', 'u', 'p', 'cp', 'cx', 'cz', 'id', 'x', 'y', 'z', 'h', 's', - 'sdg', 'sx', 't', 'tdg', 'swap', 'ccx', 'unitary', 'roerror', 'delay' - ] + 'sdg', 'sx', 't', 'tdg', 'swap', 'ccx', 'unitary', 'delay' + ] + config.custom_instructions) # Stabilizer method elif method == 'stabilizer': config.n_qubits = 5000 # TODO: estimate from memory config.description = 'A C++ QasmQobj Clifford stabilizer simulator with noise' - config.basis_gates = [ + config.custom_instructions = sorted(['roerror', 'snapshot']) + config.basis_gates = sorted([ 'id', 'x', 'y', 'z', 'h', 's', 'sdg', 'sx', 'cx', 'cy', 'cz', - 'swap', 'roerror', 'delay' - ] + 'swap', 'delay', + ] + config.custom_instructions) # Extended stabilizer method elif method == 'extended_stabilizer': config.n_qubits = 63 # TODO: estimate from memory config.description = 'A C++ QasmQobj ranked stabilizer simulator with noise' - config.basis_gates = [ + config.custom_instructions = sorted(['roerror', 'snapshot']) + config.basis_gates = sorted([ 'cx', 'cz', 'id', 'x', 'y', 'z', 'h', 's', 'sdg', 'sx', 'swap', - 'u0', 'u1', 'p', 'ccx', 'ccz', 'roerror', 'delay' - ] + 'u0', 'u1', 'p', 'ccx', 'ccz', 'delay' + ] + config.custom_instructions) return config diff --git a/qiskit/providers/aer/noise/noise_model.py b/qiskit/providers/aer/noise/noise_model.py index 4b89f41a46..9a6af556f7 100644 --- a/qiskit/providers/aer/noise/noise_model.py +++ b/qiskit/providers/aer/noise/noise_model.py @@ -93,12 +93,12 @@ class NoiseModel: # Checks for standard 1-3 qubit instructions _1qubit_instructions = set([ - "x90", "u1", "u2", "u3", "U", "id", "x", "y", "z", "h", "s", "sdg", - "t", "tdg", "r", "rx", "ry", "rz", "p" - ]) - _2qubit_instructions = set(["cx", "cy", "cz", "swap", "rxx", "ryy", "rzz", - "rzx", "cu1", "cu2", "cu3", "cp"]) - _3qubit_instructions = set(["ccx", "cswap"]) + 'u1', 'u2', 'u3', 'u', 'p', 'r', 'rx', 'ry', 'rz', 'id', 'x', + 'y', 'z', 'h', 's', 'sdg', 'sx', 't', 'tdg']) + _2qubit_instructions = set([ + 'swap', 'cx', 'cy', 'cz', 'csx', 'cp', 'cu1', 'cu2', 'cu3', 'rxx', + 'ryy', 'rzz', 'rzx']) + _3qubit_instructions = set(['ccx', 'cswap']) def __init__(self, basis_gates=None): """Initialize an empty noise model. @@ -271,15 +271,20 @@ def from_backend(cls, backend, """ if isinstance(backend, BaseBackend): properties = backend.properties() + basis_gates = backend.configuration().basis_gates if not properties: raise NoiseError('Qiskit backend {} does not have a ' 'BackendProperties'.format(backend)) elif isinstance(backend, BackendProperties): properties = backend + basis_gates = set() + for prop in properties.gates: + basis_gates.add(prop.gate) + basis_gates = list(basis_gates) else: raise NoiseError('{} is not a Qiskit backend or' ' BackendProperties'.format(backend)) - noise_model = NoiseModel() + noise_model = NoiseModel(basis_gates=basis_gates) # Add single-qubit readout errors if readout_error: diff --git a/releasenotes/notes/add-python3.9-83b3b4e5c3d59571.yaml b/releasenotes/notes/add-python3.9-83b3b4e5c3d59571.yaml new file mode 100644 index 0000000000..dd4629c5cf --- /dev/null +++ b/releasenotes/notes/add-python3.9-83b3b4e5c3d59571.yaml @@ -0,0 +1,10 @@ +--- +features: + - | + Python 3.9 support has been added in this release. You can now run Qiskit + Aer using Python 3.9 without building from source. +deprecations: + - | + Python 3.6 support has been deprecated and will be removed in a future + release. When support is removed you will need to upgrade the Python + version you're using to Python 3.7 or above. diff --git a/releasenotes/notes/fix-backend-noise-model-f22e9d6254d70852.yaml b/releasenotes/notes/fix-backend-noise-model-f22e9d6254d70852.yaml new file mode 100644 index 0000000000..4bccf758cf --- /dev/null +++ b/releasenotes/notes/fix-backend-noise-model-f22e9d6254d70852.yaml @@ -0,0 +1,11 @@ +--- +fixes: + - | + Fixes issue with setting :class:`~qiskit.providers.aer.QasmSimulator` + basis gates when using ``"method"`` and ``"noise_model"`` options + together, and when using them with a simulator constructed using + :meth:`~qiskit.providers.aer.QasmSimulator.from_backend`. Now the + listed basis gates will be the intersection of gates supported by + the backend configuration, simulation method, and noise model basis + gates. If the intersection of the noise model basis gates and + simulator basis gates is empty a warning will be logged. diff --git a/releasenotes/notes/fix-c-if-large-register-79d6649395e57ff5.yaml b/releasenotes/notes/fix-c-if-large-register-79d6649395e57ff5.yaml new file mode 100644 index 0000000000..384a52439a --- /dev/null +++ b/releasenotes/notes/fix-c-if-large-register-79d6649395e57ff5.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + Fixes a bug that resulted in `c_if` not working when the + width of the conditional register was greater than 64. See + `#1077 `. diff --git a/releasenotes/notes/fix-noise-basis-gates-ecdfa43394ff78e3.yaml b/releasenotes/notes/fix-noise-basis-gates-ecdfa43394ff78e3.yaml new file mode 100644 index 0000000000..5c9edc2253 --- /dev/null +++ b/releasenotes/notes/fix-noise-basis-gates-ecdfa43394ff78e3.yaml @@ -0,0 +1,11 @@ +--- +fixes: + - | + Fixes bug in + :meth:`~qiskit.providers.aer.noise.NoiseModel.from_backend` and + :meth:`~qiskit.providers.aer.QasmSimulator.from_backend` where + :attr:`~qiskit.providers.aer.noise.NoiseModel.basis_gates` was set + incorrectly for IBMQ devices with basis gate set + ``['id', 'rz', 'sx', 'x', 'cx']``. Now the noise model will always + have the same basis gates as the backend basis gates regardless of + whether those instructions have errors in the noise model or not. diff --git a/releasenotes/notes/fix-truncation-85010290548c2d16.yaml b/releasenotes/notes/fix-truncation-85010290548c2d16.yaml new file mode 100644 index 0000000000..3fddd50ae2 --- /dev/null +++ b/releasenotes/notes/fix-truncation-85010290548c2d16.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + Fixes a bug when applying truncation in the matrix product state method of the QasmSimulator. + diff --git a/setup.py b/setup.py index cf88f2b5e9..b71bd40de6 100644 --- a/setup.py +++ b/setup.py @@ -42,6 +42,11 @@ except ImportError: subprocess.call([sys.executable, '-m', 'pip', 'install', 'pybind11>=2.4']) +try: + from numpy import array +except ImportError: + subprocess.call([sys.executable, '-m', 'pip', 'install', 'numpy>=1.16.3']) + from skbuild import setup @@ -111,6 +116,7 @@ "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", "Topic :: Scientific/Engineering", ], python_requires=">=3.6", diff --git a/src/framework/creg.hpp b/src/framework/creg.hpp index f386173432..2144fa9b29 100755 --- a/src/framework/creg.hpp +++ b/src/framework/creg.hpp @@ -178,13 +178,20 @@ void ClassicalRegister::apply_bfunc(const Operations::Op &op) { } else { // We need to use big ints so we implement the bit-mask via the binary string // representation rather than using a big integer class - std::string mask_bin = Utils::hex2bin(mask); // has 0b prefix while creg_register_ doesn't - size_t length = std::min(mask_bin.size() - 2, creg_register_.size()); // -2 to remove 0b + std::string mask_bin = Utils::hex2bin(mask, false); + size_t length = std::min(mask_bin.size(), creg_register_.size()); std::string masked_val = std::string(length, '0'); for (size_t rev_pos = 0; rev_pos < length; rev_pos++) { masked_val[length - 1 - rev_pos] = (mask_bin[mask_bin.size() - 1 - rev_pos] & creg_register_[creg_register_.size() - 1 - rev_pos]); } + // remove leading 0's + size_t end_i = masked_val.find('1'); + if (end_i == std::string::npos) + masked_val = "0"; + else + masked_val.erase(0, end_i); + masked_val = Utils::bin2hex(masked_val); // convert to hex string // Using string comparison to compare to target value compared = masked_val.compare(target_val); diff --git a/src/framework/utils.hpp b/src/framework/utils.hpp index 52fe60ff7f..d7a2ac87a4 100755 --- a/src/framework/utils.hpp +++ b/src/framework/utils.hpp @@ -1015,7 +1015,7 @@ std::string hex2bin(std::string str, bool prefix) { // We go via long integer conversion, so we process 64-bit chunks at // a time - const size_t block = 8; + const size_t block = 16; const size_t len = str.size(); const size_t chunks = len / block; const size_t remain = len % block; @@ -1024,7 +1024,9 @@ std::string hex2bin(std::string str, bool prefix) { std::string bin = (prefix) ? "0b" : ""; // Start with remain - bin += int2string(std::stoull(str.substr(0, remain), nullptr, 16), 2); + if (remain != 0) + bin += int2string(std::stoull(str.substr(0, remain), nullptr, 16), 2); + for (size_t j=0; j < chunks; ++j) { std::string part = int2string(std::stoull(str.substr(remain + j * block, block), nullptr, 16), 2, 64); bin += part; diff --git a/src/simulators/matrix_product_state/svd.cpp b/src/simulators/matrix_product_state/svd.cpp index 73ab95d5e0..fb7a0151a6 100644 --- a/src/simulators/matrix_product_state/svd.cpp +++ b/src/simulators/matrix_product_state/svd.cpp @@ -124,11 +124,11 @@ void reduce_zeros(cmatrix_t &U, rvector_t &S, cmatrix_t &V, if (new_SV_num < SV_num) { double sum=0; for (uint_t i=0; i THRESHOLD) { for (uint_t i=0; i= 64) registers +# ========================================================================== + +def conditional_cases_64bit(): + """Test cases for conditional on 64-bit registers.""" + # [value of conditional register, list of condtional values] + return [ + (0, [0, 1, 2**63]), + (1, [1, 2**63]), + (2**32, [2**32, 0, 2**31]), + (2**32-1, [2**32-1, 0, 0xffffffff00000000]), + (2**64-1, [2**64-1, 0]), + (2337843, [2337843, 0]), + ] + + +def conditional_cases_132bit(): + """Test cases for conditional on 132-bit registers.""" + # [value of conditional register, list of condtional values] + return [ + (0, [0, 1]), + (1, [1, 0, 2**131]), + (2**131, [2**131, 1]), + (2**132-1, [2**132-1, 0, 1]), + ] + + +def conditional_circuits_nbit(n, cases, final_measure=True, + conditional_type='gate'): + """Conditional gates on n bit classical register. + Args: + n(int): width of conditional register + cases(list): list of tuples `(register_value, condtional_values)` + where register_value is the value of n-bit conditional + register, and conditional_values is a list of conditional + values for each test case. + Eg. [(0, [0, 1])] would return a list of two circuits, + the conditional register will store a value of 0 when + the condtional instruction conditioned is applied for both, + but conditioned value is 0 and 1 for the first and second + repectively. + """ + circuits = [] + qr = QuantumRegister(1) + cond = ClassicalRegister(n, 'cond') + if final_measure: + cr = ClassicalRegister(1, 'meas') + regs = (qr, cr, cond) + else: + regs = (qr, cond) + + for reg_val, cond_vals in cases: + # bit string for value in conditional register + bin_reg_val = bin(reg_val)[2:] + str_n = len(bin_reg_val) + + for cond_val in cond_vals: + circuit = QuantumCircuit(*regs) + + # encode reg_val into conditional register + circuit.x(qr) + for i, c in enumerate(bin_reg_val): + if c == '1': + circuit.measure(qr[0], cond[str_n-i-1]) + circuit.x(qr) + + # apply x to qr[0] if cond register has value cond_val + add_conditional_x(circuit, qr[0], cond, cond_val, conditional_type) + if final_measure: + circuit.measure(qr, cr) + circuits.append(circuit) + return circuits + + +def condtional_counts_nbit(n, cases, shots, hex_counts=True): + """n-bit condtional circuits reference counts.""" + targets = [] + for reg_val, cond_vals in cases: + for cond_val in cond_vals: + cr = 1 if reg_val == cond_val else 0 + if hex_counts: + key = '{:#x}'.format(reg_val * 2 + cr) + else: + key = '{} {}'.format(bin(reg_val)[2:].zfill(n), str(cr)) + targets.append({key: shots}) + return targets + + +def conditional_statevector_nbit(cases): + """n-bit conditional circuits reference statevector.""" + targets = [] + for reg_val, cond_vals in cases: + for cond_val in cond_vals: + if reg_val == cond_val: + targets.append(np.array([0, 1])) + else: + targets.append(np.array([1, 0])) + return targets diff --git a/tox.ini b/tox.ini index 96f8d7dcb5..1145705ef6 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] minversion = 2.1 -envlist = py36, py37, py38, lint +envlist = py36, py37, py38, py39, lint skipsdist = True [testenv]