diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9b3540e299..d8ac259592 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -62,7 +62,7 @@ jobs: shell: bash - name: Run qobj run: | - pip install -U qiskit + pip install -U qiskit-terra python tools/generate_qobj.py cd out Release/qasm_simulator ../qobj.json | python ../tools/verify_standalone_results.py @@ -109,7 +109,7 @@ jobs: shell: bash - name: Run qobj run: | - pip install -U qiskit + pip install -U qiskit-terra python tools/generate_qobj.py cd out /usr/bin/mpirun.openmpi -host localhost:2 -np 2 Release/qasm_simulator ../qobj.json | python ../tools/verify_standalone_results.py @@ -132,7 +132,7 @@ jobs: uses: microsoft/setup-msbuild@v1.0.2 if: runner.os == 'Windows' - name: Install deps - run: python -m pip install -U cibuildwheel==2.16.2 + run: python -m pip install -U cibuildwheel==2.11.2 - name: Build Wheels env: AER_CMAKE_OPENMP_BUILD: 1 @@ -152,7 +152,7 @@ jobs: with: python-version: 3.8 - name: Install deps - run: python -m pip install -U cibuildwheel==2.16.2 + run: python -m pip install -U cibuildwheel==2.11.2 - name: Build Wheels env: CIBW_ARCHS_MACOS: arm64 diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index c5cc5e9a03..fc5b9877d2 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -10,37 +10,39 @@ jobs: matrix: os: ["macOS-latest", "ubuntu-latest", "windows-2019"] runs-on: ${{ matrix.os }} - environment: release steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 name: Install Python with: python-version: '3.8' - name: Install cibuildwheel run: | - python -m pip install cibuildwheel==2.16.2 + python -m pip install cibuildwheel==2.11.2 - name: Build wheels env: AER_CMAKE_OPENMP_BUILD: 1 run: python -m cibuildwheel --output-dir wheelhouse - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v2 with: path: ./wheelhouse/*.whl - name: publish-shared-wheels + - name: Publish Wheels + env: + TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} + TWINE_USERNAME: qiskit + run : | + pip install -U twine + twine upload wheelhouse/* build_wheels_aarch64: name: Build wheels on ${{ matrix.os }} runs-on: ${{ matrix.os }} - environment: release - permissions: - id-token: write strategy: fail-fast: false matrix: os: [ubuntu-latest] steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 name: Install Python with: python-version: '3.8' @@ -53,78 +55,73 @@ jobs: platforms: all - name: Install cibuildwheel run: | - python -m pip install cibuildwheel==2.16.2 + python -m pip install cibuildwheel==2.11.2 twine - name: Build wheels run: | python -m cibuildwheel --output-dir wheelhouse env: CIBW_BEFORE_ALL_LINUX: "yum install -y https://dl.fedoraproject.org/pub/epel/7/aarch64/Packages/e/epel-release-7-12.noarch.rpm && yum install -y openblas-devel" CIBW_ARCHS_LINUX: aarch64 - CIBW_TEST_SKIP: "cp38* cp39* cp310* cp311*" - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v2 with: path: ./wheelhouse/*.whl - - name: Publish package distributions to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - packages-dir: wheelhouse + - name: Upload to PyPI + run: twine upload ./wheelhouse/*.whl + env: + TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} + TWINE_USERNAME: qiskit wheel-arm64-macos: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: ["macOS-latest"] - environment: release steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v2 - name: Set up Python Python 3.8 - uses: actions/setup-python@v4 + uses: actions/setup-python@v2 with: python-version: 3.8 - name: Install deps - run: python -m pip install -U cibuildwheel==2.16.2 + run: python -m pip install -U cibuildwheel==2.11.2 twine - name: Build Wheels env: CIBW_ARCHS_MACOS: arm64 run: cibuildwheel --output-dir wheelhouse - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v2 with: path: ./wheelhouse/*.whl - name: publish-shared-wheels + - name: Upload to PyPI + run: twine upload ./wheelhouse/*.whl + env: + TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} + TWINE_USERNAME: qiskit sdist: name: Publish qiskit-aer sdist runs-on: ubuntu-latest - environment: release - permissions: - id-token: write steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 name: Install Python with: python-version: '3.8' - name: Install Deps - run: pip install -U scikit-build wheel + run: pip install -U twine wheel - name: Build Artifacts run: | python setup.py sdist shell: bash - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v2 with: path: ./dist/qiskit* - - name: Publish package distributions to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - packages-dir: dist + - name: Publish to PyPi + env: + TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} + TWINE_USERNAME: qiskit + run: twine upload dist/qiskit* gpu-build-cuda11: name: Build qiskit-aer-gpu-cu11 wheels - strategy: - matrix: - os: ["ubuntu-latest"] - runs-on: ${{ matrix.os }} - environment: release - permissions: - id-token: write + runs-on: ubuntu-latest steps: - name: Maximize build space uses: easimon/maximize-build-space@master @@ -135,39 +132,37 @@ jobs: remove-android: 'true' remove-haskell: 'true' remove-codeql: 'true' - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + remove-docker-images: 'true' + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 name: Install Python with: python-version: '3.8' - name: Install cibuildwheel run: | - python -m pip install cibuildwheel==2.16.2 + python -m pip install cibuildwheel==2.11.2 - name: Build wheels env: CIBW_BEFORE_ALL: "yum install -y yum-utils wget && wget -q https://developer.download.nvidia.com/compute/cuda/11.8.0/local_installers/cuda-repo-rhel7-11-8-local-11.8.0_520.61.05-1.x86_64.rpm && rpm -i cuda-repo-rhel7-11-8-local-11.8.0_520.61.05-1.x86_64.rpm && yum clean all && yum -y install cuda && yum -y install openblas-devel && yum-config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/rhel7/x86_64/cuda-rhel7.repo && yum clean all" CIBW_BEFORE_BUILD : "pip install nvidia-cuda-runtime-cu11 nvidia-cublas-cu11 nvidia-cusolver-cu11 nvidia-cusparse-cu11 cuquantum-cu11" - CIBW_SKIP: "*-manylinux_i686 pp* cp36* cp37* *musllinux*" + CIBW_SKIP: "*-manylinux_i686 pp* cp36* *musllinux*" CIBW_ENVIRONMENT: QISKIT_AER_PACKAGE_NAME=qiskit-aer-gpu-cu11 QISKIT_AER_CUDA_MAJOR=11 CMAKE_VERBOSE_MAKEFILE=true AER_THRUST_BACKEND=CUDA CUDACXX=/usr/local/cuda/bin/nvcc AER_CUDA_ARCH="7.0 7.2 7.5 8.0 8.6 8.7" AER_PYTHON_CUDA_ROOT=/opt/_internal AER_CIBUILD=true CIBW_REPAIR_WHEEL_COMMAND: 'auditwheel repair --exclude libcudart.so.11.0 --exclude libcustatevec.so.1 --exclude libcutensornet.so.2 --exclude libcutensor.so.1 --exclude libcutensorMg.so.1 --exclude libcusolver.so.11 --exclude libcusolverMg.so.11 --exclude libcusparse.so.11 --exclude libcublas.so.11 --exclude libcublasLt.so.11 -w {dest_dir} {wheel}' run: | python -m cibuildwheel --output-dir wheelhouse - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v2 with: path: ./wheelhouse/*.whl - - name: Publish package distributions to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - packages-dir: wheelhouse + - name: Publish Wheels + env: + TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} + TWINE_USERNAME: qiskit + run : | + pip install -U twine + twine upload wheelhouse/* gpu-build-cuda12: name: Build qiskit-aer-gpu-cu12 wheels - strategy: - matrix: - os: ["ubuntu-latest"] - runs-on: ${{ matrix.os }} - environment: release - permissions: - id-token: write + runs-on: ubuntu-latest steps: - name: Maximize build space uses: easimon/maximize-build-space@master @@ -178,43 +173,44 @@ jobs: remove-android: 'true' remove-haskell: 'true' remove-codeql: 'true' - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + remove-docker-images: 'true' + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 name: Install Python with: python-version: '3.8' - name: Install cibuildwheel run: | - python -m pip install cibuildwheel==2.16.2 + python -m pip install cibuildwheel==2.11.2 - name: Build wheels env: - CIBW_BEFORE_ALL: "yum install -y yum-utils wget && wget -q https://developer.download.nvidia.com/compute/cuda/12.2.2/local_installers/cuda-repo-rhel7-12-2-local-12.2.2_535.104.05-1.x86_64.rpm && rpm -i cuda-repo-rhel7-12-2-local-12.2.2_535.104.05-1.x86_64.rpm && yum clean all && yum -y install nvidia-driver-latest-dkms && yum -y install cuda && yum -y install openblas-devel && yum-config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/rhel7/x86_64/cuda-rhel7.repo && yum clean all" - CIBW_BEFORE_BUILD : "pip install nvidia-cuda-runtime-cu12 nvidia-nvjitlink-cu12 nvidia-cublas-cu12 nvidia-cusolver-cu12 nvidia-cusparse-cu12 cuquantum-cu12" - CIBW_SKIP: "*-manylinux_i686 pp* cp36* cp37* *musllinux*" + CIBW_BEFORE_ALL: "yum install -y yum-utils wget && wget -q https://developer.download.nvidia.com/compute/cuda/12.1.1/local_installers/cuda-repo-rhel7-12-1-local-12.1.1_530.30.02-1.x86_64.rpm && rpm -i cuda-repo-rhel7-12-1-local-12.1.1_530.30.02-1.x86_64.rpm && yum clean all && yum -y install cuda && yum -y install openblas-devel && yum-config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/rhel7/x86_64/cuda-rhel7.repo && yum clean all" + CIBW_BEFORE_BUILD : "pip install nvidia-cuda-runtime-cu12 nvidia-cublas-cu12 nvidia-cusolver-cu12 nvidia-cusparse-cu12 cuquantum-cu12" + CIBW_SKIP: "*-manylinux_i686 pp* cp36* *musllinux*" CIBW_ENVIRONMENT: QISKIT_AER_PACKAGE_NAME=qiskit-aer-gpu QISKIT_AER_CUDA_MAJOR=12 CMAKE_VERBOSE_MAKEFILE=true AER_THRUST_BACKEND=CUDA CUDACXX=/usr/local/cuda/bin/nvcc AER_CUDA_ARCH="7.0 7.2 7.5 8.0 8.6 8.7 9.0" AER_PYTHON_CUDA_ROOT=/opt/_internal AER_CIBUILD=true CIBW_REPAIR_WHEEL_COMMAND: 'auditwheel repair --exclude libcudart.so.12 --exclude libcustatevec.so.1 --exclude libcutensornet.so.2 --exclude libcutensor.so.1 --exclude libcutensorMg.so.1 --exclude libcusolver.so.11 --exclude libcusolverMg.so.11 --exclude libcusolver.so.12 --exclude libcusolverMg.so.12 --exclude libcusparse.so.12 --exclude libcublas.so.12 --exclude libcublasLt.so.12 --exclude libnvJitLink.so.12 -w {dest_dir} {wheel}' run: | python -m cibuildwheel --output-dir wheelhouse - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v2 with: path: ./wheelhouse/*.whl - - name: Publish package distributions to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - packages-dir: wheelhouse + - name: Publish Wheels + env: + TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} + TWINE_USERNAME: qiskit + run : | + pip install -U twine + twine upload wheelhouse/* build_wheels_s390x: name: Build wheels on s390x runs-on: ${{ matrix.os }} - environment: release - permissions: - id-token: write strategy: fail-fast: false matrix: os: [ubuntu-latest] steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 name: Install Python with: python-version: '3.8' @@ -226,31 +222,31 @@ jobs: with: platforms: all - name: Build wheels - uses: pypa/cibuildwheel@v2.16.2 + uses: pypa/cibuildwheel@v2.11.2 env: CIBW_ARCHS_LINUX: s390x CIBW_TEST_SKIP: "cp*" CIBW_BEFORE_ALL: "yum install -y epel-release && yum install -y openblas-devel" - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v2 with: path: ./wheelhouse/*.whl - - name: Publish package distributions to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - packages-dir: wheelhouse + - name: Install twine + run: python -m pip install twine + - name: Upload to PyPI + run: twine upload ./wheelhouse/*.whl + env: + TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} + TWINE_USERNAME: qiskit build_wheels_ppc64le: name: Build wheels on ppc64le runs-on: ${{ matrix.os }} - environment: release - permissions: - id-token: write strategy: fail-fast: false matrix: os: [ubuntu-latest] steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 name: Install Python with: python-version: '3.8' @@ -262,31 +258,18 @@ jobs: with: platforms: all - name: Build wheels - uses: pypa/cibuildwheel@v2.16.2 + uses: pypa/cibuildwheel@v2.11.2 env: CIBW_ARCHS_LINUX: ppc64le CIBW_TEST_SKIP: "cp*" CIBW_BEFORE_ALL: "yum install -y epel-release && yum install -y openblas-devel" - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v2 with: path: ./wheelhouse/*.whl - - name: Publish package distributions to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - packages-dir: wheelhouse - publish-shared-wheels: - name: Publish shared wheels - runs-on: ubuntu-latest - needs: [wheel-build, wheel-arm64-macos] - environment: release - permissions: - id-token: write - steps: - - uses: actions/download-artifact@v3 - with: - path: deploy - name: publish-shared-wheels - - name: Publish package distributions to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - packages-dir: deploy + - name: Install twine + run: python -m pip install twine + - name: Upload to PyPI + run: twine upload ./wheelhouse/*.whl + env: + TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }} + TWINE_USERNAME: qiskit diff --git a/.github/workflows/docs-publish.yml b/.github/workflows/docs-publish.yml index eb922217d0..6c5ffaae34 100644 --- a/.github/workflows/docs-publish.yml +++ b/.github/workflows/docs-publish.yml @@ -21,13 +21,10 @@ jobs: python -m pip install --upgrade pip pip install -U virtualenv setuptools wheel tox sudo apt-get install graphviz pandoc build-essential libopenblas-dev - - name: Build docs + - name: Build and publish env: + encrypted_rclone_key: ${{ secrets.encrypted_rclone_key }} + encrypted_rclone_iv: ${{ secrets.encrypted_rclone_iv }} QISKIT_DOCS_BUILD_TUTORIALS: 'always' - run: tox -edocs - - name: Bypass Jekyll Processing # Necessary for setting the correct css path - run: touch docs/_build/html/.nojekyll - - name: Deploy - uses: JamesIves/github-pages-deploy-action@v4 - with: - folder: docs/_build/html/ + run: | + tools/deploy_documentation.sh diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 192e7bcd07..da877479ac 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -72,9 +72,9 @@ jobs: git clone https://github.com/Qiskit/qiskit-tutorials --depth=1 python -m pip install --upgrade pip wheel pip install -U -r requirements-dev.txt -c constraints.txt - pip install -c constraints.txt git+https://github.com/Qiskit/qiskit + pip install -c constraints.txt git+https://github.com/Qiskit/qiskit-terra pip install -c constraints.txt . - pip install -U "qiskit-ibmq-provider" "z3-solver" "qiskit-ignis" "qiskit-aqua" "pyscf<1.7.4" "matplotlib>=3.3.0" jupyter pylatexenc nbsphinx cvxpy qiskit-sphinx-theme -c constraints.txt + pip install -U "qiskit-ibmq-provider" "z3-solver" "qiskit-ignis" "qiskit-aqua" "pyscf<1.7.4" "matplotlib<3.3.0" jupyter pylatexenc nbsphinx cvxpy qiskit-sphinx-theme -c constraints.txt sudo apt install -y graphviz pandoc libopenblas-dev pip check shell: bash diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2bd6e3020c..091baf8282 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -32,7 +32,7 @@ jobs: run: | set -e pip install -U pip wheel - pip install -U -c constraints.txt -r requirements-dev.txt qiskit numpy scipy + pip install -U -c constraints.txt -r requirements-dev.txt qiskit-terra numpy scipy shell: bash - name: Run clang-format run: | @@ -49,7 +49,7 @@ jobs: needs: ["lint"] strategy: matrix: - python-version: [3.8, 3.9, "3.10", '3.11', "3.12.0"] + python-version: [3.8, 3.9, "3.10", '3.11'] platform: [ { os: "ubuntu-latest", python-architecture: "x64" }, ] @@ -182,8 +182,8 @@ jobs: - name: Install Aer run: | set -e - python -I -m build --wheel --config-setting=--build-option=-DTEST_JSON=1 - pip install -U dist/*.whl + python -I -m build --wheel --config-setting=--build-option=-- --config-setting=--build-option=-DTEST_JSON=1 + pip install --find-links=dist qiskit-aer - name: Run Tests run: | set -e diff --git a/CMakeLists.txt b/CMakeLists.txt index 424185d7cc..25641659cd 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,34 +11,6 @@ cmake_minimum_required(VERSION 3.8 FATAL_ERROR) file(STRINGS "qiskit_aer/VERSION.txt" VERSION_NUM) -# For ROCm builds we need to make sure the CXX and HIP compilers match and are clang. -# We should do this before the project() call to make sure the compiler options are -# properly assessed. -if(AER_THRUST_BACKEND STREQUAL "ROCM") - - if(DEFINED ENV{ROCM_PATH}) - set(ROCM_PATH "$ENV{ROCM_PATH}") - else() - set(ROCM_PATH "/opt/rocm") - endif() - - if(NOT DEFINED CMAKE_HIP_COMPILER) - if(DEFINED ENV{CMAKE_HIP_COMPILER}) - set(CMAKE_HIP_COMPILER "$ENV{CMAKE_HIP_COMPILER}") - else() - set(CMAKE_HIP_COMPILER "${ROCM_PATH}/llvm/bin/clang++") - endif() - endif() - - if(NOT DEFINED CMAKE_CXX_COMPILER) - if(DEFINED ENV{CMAKE_CXX_COMPILER}) - set(CMAKE_CXX_COMPILER "$ENV{CMAKE_CXX_COMPILER}") - else() - set(CMAKE_CXX_COMPILER "${CMAKE_HIP_COMPILER}") - endif() - endif() -endif() - # Add CUDA to the project if needed. set(EXTRA_LANGUAGES "") if(AER_THRUST_BACKEND STREQUAL "CUDA") @@ -78,8 +50,6 @@ endif() option(STATIC_LINKING "Specify if we want statically link the executable (for redistribution mainly)" FALSE) option(BUILD_TESTS "Specify whether we want to build tests or not" FALSE) -option(USE_BUNDLED_BLAS_WIN "Use the bundled openblas library on Windows when - not using AER_BLAS_LIB_PATH" TRUE) # 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 @@ -233,13 +203,21 @@ else() if(APPLE) message(STATUS "Looking for Apple BLAS & Lapack library...") set(BLA_VENDOR "Apple") - else() - message(STATUS "Looking for OpenBLAS library...") - if(NOT BLA_VENDOR) - set(BLA_VENDOR "OpenBLAS") - endif() + elseif(MKL) + message(STATUS "Looking for MKL library...") + find_package(MKL CONFIG REQUIRED) + if (MKL_FOUND) + message(STATUS "MKL Found") + set(BLA_VENDOR Intel10_64ilp) + add_compile_definitions(MKL) + endif() + else() + message(STATUS "Looking for OpenBLAS library...") + if(NOT BLA_VENDOR) + set(BLA_VENDOR "OpenBLAS") + endif() endif() - if(WIN32 AND USE_BUNDLED_BLAS_WIN) + if(WIN32) message(STATUS "Uncompressing OpenBLAS static library...") set(WIN_ARCH "win64" ) if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4") # Checking if win32 build @@ -406,96 +384,6 @@ if(AER_THRUST_SUPPORTED) set(AER_COMPILER_DEFINITIONS ${AER_COMPILER_DEFINITIONS} AER_THRUST_CPU=TRUE) # We don't need to add OMP because it's already an AER dependency set(THRUST_DEPENDENT_LIBS "") - elseif(AER_THRUST_BACKEND STREQUAL "ROCM") - # - # Build with GPU support with ROCm - # - - # Assert that the C++ and compilers are Clang to enable ROCm builds. - if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") - message(FATAL_ERROR - "The compiler for ROCm builds must be Clang. Set CMAKE_CXX_COMPILER to /llvm/bin/clang++") - endif() - - # GDB debug information is what is needed for runs enabled with ROCm. - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -ggdb") - - # Leverage AER_ROCM_ARCH to specify the relevant targets and send the ROCm default ones to - # the background by marking them as advanced. We need to set the architectures in advance - # of attemting to find HIP to leverage the package machinery. - - string(REPLACE " " ";" AER_ROCM_ARCH_LIST ${AER_ROCM_ARCH}) - set(GPU_TARGETS ${AER_ROCM_ARCH_LIST} CACHE INTERNAL "GPU targets to compile for") - set(AMDGPU_TARGETS ${AER_ROCM_ARCH_LIST} CACHE INTERNAL "AMD GPU targets to compile for") - set(CMAKE_HIP_ARCHITECTURES ${AER_ROCM_ARCH_LIST}) - - mark_as_advanced(GPU_TARGETS) - mark_as_advanced(AMDGPU_TARGETS) - mark_as_advanced(CMAKE_HIP_ARCHITECTURES) - message(STATUS "ROCm build targeting GPU Architectures: ${GPU_TARGETS}") - - message(STATUS "ROCm assumed path: ${ROCM_PATH}") - list(APPEND CMAKE_PREFIX_PATH ${ROCM_PATH}/hip ${ROCM_PATH}) - list(APPEND CMAKE_MODULE_PATH ${ROCM_PATH}/hip/cmake ${ROCM_PATH}) - - include(CheckLanguage) - check_language(HIP) - - # Find HIP in config mode as the module mode may not provide the hip:: targets. We can use module mode - # if we had hip libraries as they invoke the config package. - find_package(HIP CONFIG) - if(HIP_FOUND) - message(STATUS "Found HIP: " ${HIP_VERSION}) - else() - message(FATAL_ERROR "Could not find HIP.") - endif() - - list(APPEND AER_LIBRARIES hip::device) - - # Add definitions so that dependencies are properly determined. - # TODO: investigate the need for THRUST_DEVICE_SYSTEM=THRUST_DEVICE_SYSTEM_CUDA - list(APPEND ROCM_EXTRA_DEFS AER_THRUST_GPU AER_THRUST_ROCM THRUST_DEVICE_SYSTEM=THRUST_DEVICE_SYSTEM_HIP) - - # Add -D prefix to all defs as that is what ROCM_EXTRA_* expect to be set to. - list(TRANSFORM ROCM_EXTRA_DEFS PREPEND -D) - add_definitions(${ROCM_EXTRA_DEFS}) - list(APPEND ROCM_EXTRA_FLAGS ${ROCM_EXTRA_DEFS}) - list(APPEND ROCM_EXTRA_FLAGS -isystem${ROCM_PATH}/include; -I${AER_SIMULATOR_CPP_SRC_DIR} ; -isystem${AER_SIMULATOR_CPP_SRC_DIR}/third-party/headers; -ffast-math; -fPIC) - - if(CMAKE_BUILD_TYPE STREQUAL "Debug") - list(APPEND ROCM_EXTRA_FLAGS -O0) - else() - list(APPEND ROCM_EXTRA_FLAGS -O3) - endif() - - if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") - list(APPEND ROCM_EXTRA_FLAGS -g; -ggdb) - endif() - - # Add some warning flags to allow existing code to go through with clang. - list(APPEND ROCM_EXTRA_FLAGS -ferror-limit=3 - -Wno-unused-lambda-capture - -Wno-bitwise-instead-of-logical - -Wno-inconsistent-missing-override - -Wno-cast-align - -Wno-float-equal - -Wno-unused-variable - -Wno-unused-but-set-variable - -Wno-switch - -Wno-writable-strings - -Wno-shadow - -Wno-delete-non-abstract-non-virtual-dtor - -Wno-pessimizing-move - -Wno-return-type-c-linkage - -Wno-overloaded-virtual - -Wno-braced-scalar-init) - - - if(AER_ENABLE_CUQUANTUM) - message(WARNING "Implementation of cuQuantum is not available for ROCm builds.") - endif() - else() message(STATUS "No Thrust supported backend") set(AER_THRUST_SUPPORTED FALSE) @@ -514,7 +402,6 @@ endif() if(AER_DEBUG) set(AER_COMPILER_DEFINITIONS ${AER_COMPILER_DEFINITIONS} AER_DEBUG) - set(AER_COMPILER_FLAGS "${AER_COMPILER_FLAGS} -g") endif() if(TEST_JSON) @@ -583,35 +470,6 @@ else() # Standalone build RUNTIME_OUTPUT_DIRECTORY_DEBUG Debug RUNTIME_OUTPUT_DIRECTORY_RELEASE Release) endfunction() - - function(build_rocm target src_file is_exec) - # ROCm is only supported in x86_64 devices so it should be safe to leverage AVX2. - set(SIMD_SOURCE_FILE "${PROJECT_SOURCE_DIR}/src/simulators/statevector/qv_avx2.cpp") - - set_source_files_properties( - ${SIMD_SOURCE_FILE} - ${src_file} - PROPERTIES LANGUAGE CXX) - - if(${is_exec}) - add_executable(${target} ${src_file} ${SIMD_SOURCE_FILE}) - else() - add_library(${target} ${src_file} ${SIMD_SOURCE_FILE}) - endif() - - target_compile_options(${target} PRIVATE ${ROCM_EXTRA_FLAGS} ${SIMD_FLAGS_LIST}) - target_compile_definitions(${target} PRIVATE ${ROCM_EXTRA_DEFS} ${AER_COMPILER_DEFINITIONS}) - - target_link_libraries(${target} PRIVATE ${AER_LIBRARIES}) - - set_target_properties(${target} PROPERTIES - LINKER_LANGUAGE CXX - CXX_STANDARD 14 - COMPILE_FLAGS ${AER_COMPILER_FLAGS} - LINK_FLAGS ${AER_LINKER_FLAGS} - RUNTIME_OUTPUT_DIRECTORY_DEBUG Debug - RUNTIME_OUTPUT_DIRECTORY_RELEASE Release) - endfunction() function(build_cpu target src_file is_exec) if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64" OR CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "amd64") @@ -655,8 +513,6 @@ else() # Standalone build set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) if(CUDA_FOUND AND AER_THRUST_BACKEND STREQUAL "CUDA") build_cuda(qasm_simulator ${AER_SIMULATOR_SOURCE} TRUE) - elseif(HIP_FOUND AND AER_THRUST_BACKEND STREQUAL "ROCM") - build_rocm(qasm_simulator ${AER_SIMULATOR_SOURCE} TRUE) else() build_cpu(qasm_simulator ${AER_SIMULATOR_SOURCE} TRUE) endif() @@ -667,8 +523,6 @@ else() # Standalone build set(AER_RUNTIME_SOURCE "${PROJECT_SOURCE_DIR}/contrib/runtime/aer_runtime.cpp") if(CUDA_FOUND AND AER_THRUST_BACKEND STREQUAL "CUDA") build_cuda(aer ${AER_RUNTIME_SOURCE} FALSE) - elseif(HIP_FOUND AND AER_THRUST_BACKEND STREQUAL "ROCM") - build_rocm(aer ${AER_RUNTIME_SOURCE} FALSE) else() build_cpu(aer ${AER_RUNTIME_SOURCE} FALSE) endif() diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4f39f0b9b7..5e11aa1bc1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,7 +5,7 @@ included in the Qiskit documentation: https://qiskit.org/documentation/contributing_to_qiskit.html -## Contributing to Aer +## Contributing to Qiskit Aer In addition to the general guidelines, there are specific details for contributing to Aer. These are documented below. @@ -105,33 +105,33 @@ look something like:: ```yaml features: - | - Introduced a new feature ``foo``, that adds support for doing something to - ``AerProvider`` objects. It can be used by using the ``foo`` function, + Introduced a new feature foo, that adds support for doing something to + ``QuantumCircuit`` objects. It can be used by using the foo function, for example:: - from qiskit_aer import foo - from qiskit_aer import AerProvider - foo(AerProvider()) + from qiskit import foo + from qiskit import QuantumCircuit + foo(QuantumCircuit()) - | - The ``qiskit_aer.AerProvider`` module has a new method ``foo()``. This is - the equivalent of calling the ``qiskit_aer.foo()`` to do something to your - ``AerProvider``. This is the equivalent of running ``qiskit_aer.foo()`` on - your provider, but it has the convenience of running it natively on + The ``qiskit.QuantumCircuit`` module has a new method ``foo()``. This is + the equivalent of calling the ``qiskit.foo()`` to do something to your + QuantumCircuit. This is the equivalent of running ``qiskit.foo()`` on + your circuit, but provides the convenience of running it natively on an object. For example:: - from qiskit_aer import AerProvider + from qiskit import QuantumCircuit - provider = AerProvider() - provider.foo() + circ = QuantumCircuit() + circ.foo() deprecations: - | - The ``qiskit_aer.bar`` module has been deprecated and will be removed in a + The ``qiskit.bar`` module has been deprecated and will be removed in a future release. Its sole function, ``foobar()`` has been superseded by the - ``qiskit_aer.foo()`` function which provides similar functionality but with + ``qiskit.foo()`` function which provides similar functionality but with more accurate results and better performance. You should update your calls - ``qiskit_aer.bar.foobar()`` calls to ``qiskit_aer.foo()``. + ``qiskit.bar.foobar()`` calls to ``qiskit.foo()``. ``` You can also look at other release notes for other examples. @@ -180,7 +180,7 @@ it has been tagged:: At release time, ``reno report`` is used to generate the release notes for the release and the output will be submitted as a pull request to the documentation repository's [release notes file]( -https://github.com/Qiskit/qiskit-aer/blob/master/docs/release_notes.rst) +https://github.com/Qiskit/qiskit/blob/master/docs/release_notes.rst) #### Building release notes locally @@ -193,7 +193,7 @@ particular will be located at `docs/_build/html/release_notes.html` ## Style and lint -Aer uses 3 tools for verifying code formatting and lint checking. The +Qiskit Aer uses 3 tools for verifying code formatting and lint checking. The first tool is [black](https://github.com/psf/black) which is a Python code formatting tool that will automatically update the code formatting to a consistent style. The second tool is [pylint](https://www.pylint.org/) which is a code linter @@ -211,7 +211,7 @@ any error you will have to fix these issues by manually updating your code. ### Development Cycle -The development cycle for Aer is all handled in the open using +The development cycle for qiskit-aer is all handled in the open using the project boards in GitHub for project management. We use milestones in GitHub to track work for specific releases. The features or other changes that we want to include in a release will be tagged and discussed in GitHub. @@ -222,12 +222,12 @@ previous version in the release notes. * `main`: -The main branch is used for development of the next version of Aer. +The main branch is used for development of the next version of qiskit-aer. It will be updated frequently and should not be considered stable. The API can and will change on main as we introduce and refine new features. * `stable/*` branches: -Branches under `stable/*` are used to maintain released versions of `qiskit-aer`. +Branches under `stable/*` are used to maintain released versions of qiskit-aer. It contains the version of the code corresponding to the latest release for that minor version on pypi. For example, stable/0.4 contains the code for the 0.4.0 release on pypi. The API on these branches are stable and the only changes @@ -235,7 +235,7 @@ merged to it are bugfixes. ### Release cycle -When it is time to release a new minor version of `qiskit-aer`, we will: +When it is time to release a new minor version of qiskit-aer, we will: 1. Create a new tag with the version number and push it to github 2. Change the `main` version to the next release version. @@ -268,7 +268,7 @@ window $ conda activate QiskitDevEnv ``` -- Clone the `Aer` repo via *git*. +- Clone the `Qiskit Aer` repo via *git*. ``` $ git clone https://github.com/Qiskit/qiskit-aer ``` @@ -301,7 +301,7 @@ You're now ready to build from source! Follow the instructions for your platform ### Linux -Aer is officially supported on Red Hat, CentOS, Fedora, and Ubuntu distributions, as long as you can install a GCC version that is C++14 compatible and a few dependencies we need. +Qiskit is officially supported on Red Hat, CentOS, Fedora, and Ubuntu distributions, as long as you can install a GCC version that is C++14 compatible and a few dependencies we need. #### Dependencies @@ -635,12 +635,10 @@ options we have on `Aer` to CMake, we use its native mechanism: ### Building with GPU support -Aer can exploit GPU's horsepower to accelerate some simulations, specially the larger ones. -GPU access is supported either via CUDA® (NVIDIA® chipset) or ROCm® (AMD® GPUs). - -#### Building with CUDA® support -To build with CUDA® support, you need to have CUDA® >= 11.2 preinstalled. See install instructions [here](https://developer.nvidia.com/cuda-toolkit-archive). -Please note that we only support CUDA® GPU acceleration on Linux platforms at the moment. +Qiskit Aer can exploit GPU's horsepower to accelerate some simulations, specially the larger ones. +GPU access is supported via CUDA® (NVIDIA® chipset), so to build with GPU support, you need +to have CUDA® >= 11.2 preinstalled. See install instructions [here](https://developer.nvidia.com/cuda-toolkit-archive) +Please note that we only support GPU acceleration on Linux platforms at the moment. Once CUDA® is properly installed, you only need to set a flag so the build system knows what to do: @@ -666,18 +664,18 @@ or This will reduce the amount of compilation time when, for example, the architecture auto detection fails and the build system compiles all common architectures. -Few notes on CUDA® GPU builds: +Few notes on GPU builds: 1. Building takes considerable more time than non-GPU build, so be patient :) 2. CUDA® >= 11.2 imposes the restriction of building with g++ version not newer than 8 3. We don't need NVIDIA® drivers for building, but we need them for running simulations 4. Only Linux platforms are supported -Aer now supports cuQuantum optimized Quantum computing APIs from NVIDIA®. +Qiskit Aer now supports cuQuantum optimized Quantum computing APIs from NVIDIA®. cuStateVec APIs can be exploited to accelerate statevector, density_matrix and unitary methods. 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. -Before building Aer with cuQuantum support, install required components via pip install as following. +Before building Qiskit Aer with cuQuantum support, install required components via pip install as following. qiskit-aer$ pip install nvidia-cuda-runtime-cu11 nvidia-cublas-cu11 nvidia-cusolver-cu11 nvidia-cusparse-cu11 cuquantum-cu11 @@ -708,66 +706,16 @@ Also you can accelrate density matrix and unitary matrix simulations as well. sim = AerSimulator(method='density_matrix', device='GPU') results = execute(circuit,sim,cuStateVec_enable=True).result() ``` -#### Building with ROCm® support -ROCm® support has been added matching the CUDA® implementation based -on the `thrust` library. This enables Aer to run on AMD® GPUs, -including the AMD® Instinct GPU line based on the CDNA architecture. -ROCm® only support linux platforms. - -To build the standalone version, the following should be sufficient: - -``` -cmake -G Ninja \ - -DCMAKE_INSTALL_PREFIX= \ - -DSKBUILD=FALSE \ - -DAER_THRUST_BACKEND=ROCM \ - -DAER_MPI= \ - -DAER_ROCM_ARCH= \ - -DCMAKE_BUILD_TYPE=Release \ - -DBUILD_TESTS=True -ninja install -``` -Alternatively, and possibly preferred for most use cases, you can create a Python -wheel file that you can install as part of your Python environemnt: -``` -cd - -QISKIT_AER_PACKAGE_NAME='qiskit-aer-gpu-rocm' \ - python3 setup.py bdist_wheel -- \ - -DAER_THRUST_BACKEND=ROCM \ - -DAER_MPI= \ - -DAER_ROCM_ARCH= -pip install --force-reinstall dist/qiskit_aer_gpu_rocm-*.whl -``` - -In both cases, the host system needs to have a functional ROCm® instalation and -the environment variable `ROCM_PATH` set pointing to the ROCm® instalation folder if -that is not the default `/opt/rocm`. -Depending on how your Python environment is set, you might need to install -Aer's required development modules: -``` -cd -pip install -r requirements-dev.txt -``` -To leverage the ROCm® implementations no code changes are needed on top of one -already does for CUDA®. Running with cuStateVec, for instance, requires set -`device='GPU'` to AerSimulator option and set `cuStateVec_enable=True` option, -similarly to what is done for CUDA®: - -``` -sim = AerSimulator(method='statevector', device='GPU') -results = execute(circuit,sim,cuStateVec_enable=True).result() -``` ### Building with MPI support -Aer can parallelize its simulation on the cluster systems by using MPI. +Qiskit Aer can parallelize its simulation on the cluster systems by using MPI. This can extend available memory space to simulate quantum circuits with larger number of qubits and also can accelerate the simulation by parallel computing. To use MPI support, any MPI library (i.e. OpenMPI) should be installed and configured on the system. -Aer supports MPI both with and without GPU support. Currently following simulation methods are supported to be parallelized by MPI. +Qiskit Aer supports MPI both with and without GPU support. Currently following simulation methods are supported to be parallelized by MPI. - statevector - density_matrix @@ -795,7 +743,7 @@ For example, ### Running with multiple-GPUs and/or multiple nodes -Aer parallelizes simulations by distributing quantum states into distributed memory space. +Qiskit Aer parallelizes simulations by distributing quantum states into distributed memory space. To decrease data transfer between spaces the distributed states are managed as chunks that is a sub-state for smaller qubits than the input circuits. For example, @@ -809,7 +757,7 @@ And the (noiseless) swap gates are inserted to exchange data. Please refer to this paper (https://arxiv.org/abs/2102.02957) for more detailed algorithm and implementation of parallel simulation. So to simulate by using multiple GPUs or multiple nodes on the cluster, following configurations should be set to backend options. -(If there is not enough memory to simulate the input circuit, Aer automatically set following options, but it is recommended to explicitly set them) +(If there is not enough memory to simulate the input circuit, Qiskit Aer automatically set following options, but it is recommended to explicitly set them) - blocking_enable @@ -828,13 +776,13 @@ circ.measure_all() result = execute(circ, sim, shots=100, blocking_enable=True, blocking_qubits=23).result() ``` -To run Aer with Python script with MPI parallelization, MPI executer such as mpirun should be used to submit a job on the cluster. Following example shows how to run Python script using 4 processes by using mpirun. +To run Qiskit Aer with Python script with MPI parallelization, MPI executer such as mpirun should be used to submit a job on the cluster. Following example shows how to run Python script using 4 processes by using mpirun. ``` mpirun -np 4 python example.py ``` -MPI_Init function is called inside Aer, so you do not have to manage MPI processes in Python script. +MPI_Init function is called inside Qiskit Aer, so you do not have to manage MPI processes in Python script. Following metadatas are useful to find on which process is this script running. - num_mpi_processes : shows number of processes using for this simulation @@ -855,9 +803,9 @@ myrank = meta['mpi_rank'] Multiple shots are also distributed to multiple nodes when setting `device=GPU` and `batched_shots_gpu=True`. The results are distributed to each processes. -Note : In the script, make sure that the same random seed should be used for all processes so that the consistent circuits and parameters are passed to Aer. To do so add following option to the script. +Note : In the script, make sure that the same random seed should be used for all processes so that the consistent circuits and parameters are passed to Qiskit Aer. To do so add following option to the script. ``` -from qiskit_algorithms.utils import algorithm_globals +from qiskit.utils import algorithm_globals algorithm_globals.random_seed = consistent_seed_to_all_processes ``` @@ -966,16 +914,6 @@ These are the flags: Default: No value. Example: ``python ./setup.py bdist_wheel -- -DAER_BLAS_LIB_PATH=/path/to/look/for/blas/`` -* USE_BUNDLED_BLAS_WIN - - Tells CMake to use the bundled OpenBLAS library vendored into the source code when building on Windows. - When this option is set to `False`, CMake will use its standard method to search for the BLAS library aginst which to link instead of using the vendored version. - The `AER_BLAS_LIB_PATH` option takes precedence over this option. - - Values: True|False - Default: True - Example: ``python ./setup.py bdist_wheel -- -DUSE_BUNDLED_BLAS_WIN=FALSE`` - * BUILD_TESTS It will tell the build system to build C++ tests along with the simulator. @@ -1059,10 +997,10 @@ These are the flags: Code contributions are expected to include tests that provide coverage for the changes being made. -We have two types of tests in the codebase: Qiskit integration tests and +We have two types of tests in the codebase: Qiskit Terra integration tests and Standalone integration tests. -For Qiskit integration tests, you first need to build and install the Qiskit Python extension, and then run ``unittest`` Python framework. +For Qiskit Terra integration tests, you first need to build and install the Qiskit Python extension, and then run `unittest` Python framework. ``` qiskit-aer$ pip install . @@ -1177,7 +1115,7 @@ After this, you can step through the code and continue with your debug session a ## Dealing with the git blame ignore list -In the ``Qiskit/qiskit-aer`` repository we maintain a list of commits for git blame to +In the qiskit-aer repository we maintain a list of commits for git blame to ignore. This is mostly commits that are code style changes that don't change the functionality but just change the code formatting (for example, when we migrated to use black for code formatting). This file, `.git-blame-ignore-revs` diff --git a/README.md b/README.md index b579bd3a7a..458d3bc21d 100755 --- a/README.md +++ b/README.md @@ -1,19 +1,17 @@ -# Aer - high performance quantum circuit simulation for Qiskit +# Qiskit Aer -[![License](https://img.shields.io/github/license/Qiskit/qiskit-aer.svg?style=popout-square)](https://opensource.org/licenses/Apache-2.0) -[![Build](https://github.com/Qiskit/qiskit-aer/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/Qiskit/qiskit-aer/actions/workflows/build.yml) -[![Tests](https://github.com/Qiskit/qiskit-aer/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/Qiskit/qiskit-aer/actions/workflows/tests.yml) -[![](https://img.shields.io/github/release/Qiskit/qiskit-aer.svg?style=popout-square)](https://github.com/Qiskit/qiskit-aer/releases) -[![](https://img.shields.io/pypi/dm/qiskit-aer.svg?style=popout-square)](https://pypi.org/project/qiskit-aer/) +[![License](https://img.shields.io/github/license/Qiskit/qiskit-aer.svg?style=popout-square)](https://opensource.org/licenses/Apache-2.0)[![Build Status](https://img.shields.io/travis/com/Qiskit/qiskit-aer/master.svg?style=popout-square)](https://travis-ci.com/Qiskit/qiskit-aer)[![](https://img.shields.io/github/release/Qiskit/qiskit-aer.svg?style=popout-square)](https://github.com/Qiskit/qiskit-aer/releases)[![](https://img.shields.io/pypi/dm/qiskit-aer.svg?style=popout-square)](https://pypi.org/project/qiskit-aer/) -**Aer** is a high performance simulator for quantum circuits written in Qiskit, that includes realistic noise models. +**Qiskit** is an open-source framework for working with noisy quantum computers at the level of pulses, circuits, and algorithms. + +Qiskit is made up of elements that work together to enable quantum computing. This element is **Aer**, which provides high-performance quantum computing simulators with realistic noise models. ## Installation -We encourage installing Aer via the pip tool (a python package manager): +We encourage installing Qiskit via the pip tool (a python package manager). The following command installs the core Qiskit components, including Aer. ```bash -pip install qiskit-aer +pip install qiskit qiskit-aer ``` Pip will handle all dependencies automatically for us, and you will always install the latest (and well-tested) version. @@ -45,8 +43,8 @@ that have CUDA support, you will have to build from source. You can refer to the [contributing guide](CONTRIBUTING.md#building-with-gpu-support) for instructions on doing this. -## Simulating your first Qiskit circuit with Aer -Now that you have Aer installed, you can start simulating quantum circuits with noise. Here is a basic example: +## Simulating your first quantum program with Qiskit Aer +Now that you have Qiskit Aer installed, you can start simulating quantum circuits with noise. Here is a basic example: ``` $ python @@ -89,19 +87,20 @@ print('Counts(noise):', counts_noise) ## Contribution Guidelines -If you'd like to contribute to Aer, please take a look at our +If you'd like to contribute to Qiskit, please take a look at our [contribution guidelines](CONTRIBUTING.md). This project adheres to Qiskit's [code of conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. We use [GitHub issues](https://github.com/Qiskit/qiskit-aer/issues) for tracking requests and bugs. Please use our [slack](https://qiskit.slack.com) for discussion and simple questions. To join our Slack community use the [link](https://qiskit.slack.com/join/shared_invite/zt-fybmq791-hYRopcSH6YetxycNPXgv~A#/). For questions that are more suited for a forum, we use the Qiskit tag in the [Stack Exchange](https://quantumcomputing.stackexchange.com/questions/tagged/qiskit). ## Next Steps -Now you're set up and ready to check out some of the other examples from the [Aer documentation](https://qiskit.org/ecosystem/aer/). +Now you're set up and ready to check out some of the other examples from our +[Qiskit IQX Tutorials](https://github.com/Qiskit/qiskit-tutorials/tree/master/tutorials/simulators) or [Qiskit Community Tutorials](https://github.com/Qiskit/qiskit-community-tutorials/tree/master/aer) repositories. ## Authors and Citation -Aer is the work of [many people](https://github.com/Qiskit/qiskit-aer/graphs/contributors) who contribute to the project at different levels. -If you use Qiskit, please cite as per the included [BibTeX file](https://github.com/Qiskit/qiskit/blob/main/CITATION.bib). +Qiskit Aer is the work of [many people](https://github.com/Qiskit/qiskit-aer/graphs/contributors) who contribute +to the project at different levels. If you use Qiskit, please cite as per the included [BibTeX file](https://github.com/Qiskit/qiskit-terra/blob/main/CITATION.bib). ## License diff --git a/cmake/conan.cmake b/cmake/conan.cmake index e413c3f326..b27dc33b41 100644 --- a/cmake/conan.cmake +++ b/cmake/conan.cmake @@ -55,8 +55,6 @@ function(_get_msvc_ide_version result) set(${result} 15 PARENT_SCOPE) elseif(NOT MSVC_VERSION VERSION_LESS 1920 AND MSVC_VERSION VERSION_LESS 1930) set(${result} 16 PARENT_SCOPE) - elseif(NOT MSVC_VERSION VERSION_LESS 1930 AND MSVC_VERSION VERSION_LESS 1940) - set(${result} 17 PARENT_SCOPE) else() message(FATAL_ERROR "Conan: Unknown MSVC compiler version [${MSVC_VERSION}]") endif() diff --git a/cmake/conan_utils.cmake b/cmake/conan_utils.cmake index aefd4f8540..e19d6a41a6 100644 --- a/cmake/conan_utils.cmake +++ b/cmake/conan_utils.cmake @@ -70,7 +70,7 @@ macro(setup_conan) endif() # Headers includes - if(AER_THRUST_BACKEND AND NOT AER_THRUST_BACKEND STREQUAL "CUDA" AND NOT AER_THRUST_BACKEND STREQUAL "ROCM") + if(AER_THRUST_BACKEND AND NOT AER_THRUST_BACKEND STREQUAL "CUDA") set(AER_SIMULATOR_CPP_EXTERNAL_LIBS ${AER_SIMULATOR_CPP_EXTERNAL_LIBS} ${CONAN_INCLUDE_DIRS_THRUST}) endif() diff --git a/constraints.txt b/constraints.txt index a76d3881db..1f3bd7a329 100644 --- a/constraints.txt +++ b/constraints.txt @@ -1,5 +1,12 @@ pylint==2.4.4 astroid==2.3.3 +six>1.10,<=1.14 +numpy>=1.16.3,<1.25 +scipy>=1.0 +# stevedore, used by Terra currently (as of 3.4.0) issues deprecation warnings +# with modern importlib-metadata (4.8.1). importlib-metadata is only needed on +# Python <3.8. +importlib-metadata==4.6.4 # Jinja2 3.1.0 is incompatible with sphinx and/or jupyter until they are updated # to work with the new jinja version (the jinja maintainers aren't going to diff --git a/contrib/runtime/aer_runtime.cpp b/contrib/runtime/aer_runtime.cpp index 6961bac30e..784a626d51 100644 --- a/contrib/runtime/aer_runtime.cpp +++ b/contrib/runtime/aer_runtime.cpp @@ -139,7 +139,7 @@ void aer_apply_tdg(void *handler, uint_t qubit) { // sqrt(NOT) gate void aer_apply_sx(void *handler, uint_t qubit) { AER::AerState *state = reinterpret_cast(handler); - state->apply_mcsx({qubit}); + state->apply_mcrx({qubit}, -M_PI / 4.0); }; // Rotation around X-axis diff --git a/docs/_templates/autosummary/class.rst b/docs/_templates/autosummary/class.rst index f819fa6703..e4d661a008 100644 --- a/docs/_templates/autosummary/class.rst +++ b/docs/_templates/autosummary/class.rst @@ -11,27 +11,39 @@ :no-members: :no-inherited-members: :no-special-members: - :show-inheritance: -{% block attributes_summary %} + {% block attributes_summary %} {% if attributes %} + .. rubric:: Attributes - {% for item in all_attributes %} - {%- if not item.startswith('_') %} - .. autoattribute:: {{ name }}.{{ item }} - {%- endif -%} - {%- endfor %} + + .. autosummary:: + :toctree: ../stubs/ + {% for item in all_attributes %} + {%- if not item.startswith('_') %} + {{ name }}.{{ item }} + {%- endif -%} + {%- endfor %} {% endif %} -{% endblock %} + {% endblock %} -{% block methods_summary %} + {% block methods_summary %} {% if methods %} + .. rubric:: Methods + + .. autosummary:: + :toctree: ../stubs/ {% for item in all_methods %} {%- if not item.startswith('_') or item in ['__call__', '__mul__', '__getitem__', '__len__'] %} - .. automethod:: {{ name }}.{{ item }} + {{ name }}.{{ item }} + {%- endif -%} + {%- endfor %} + {% for item in inherited_members %} + {%- if item in ['__call__', '__mul__', '__getitem__', '__len__'] %} + {{ name }}.{{ item }} {%- endif -%} {%- endfor %} {% endif %} -{% endblock %} \ No newline at end of file + {% endblock %} diff --git a/docs/_templates/autosummary/class_no_inherited_members.rst b/docs/_templates/autosummary/class_no_inherited_members.rst deleted file mode 100644 index 6ed7e5c62d..0000000000 --- a/docs/_templates/autosummary/class_no_inherited_members.rst +++ /dev/null @@ -1,41 +0,0 @@ -{# This is identical to class.rst, except for the filtering of the inherited_members. -#} - -{% if referencefile %} -.. include:: {{ referencefile }} -{% endif %} - -{{ objname }} -{{ underline }} - -.. currentmodule:: {{ module }} - -.. autoclass:: {{ objname }} - :no-members: - :no-inherited-members: - :no-special-members: - :show-inheritance: - -{% block attributes_summary %} - {% if attributes %} - .. rubric:: Attributes - {% for item in all_attributes %} - {%- if not item.startswith('_') %} - .. autoattribute:: {{ name }}.{{ item }} - {%- endif -%} - {%- endfor %} - {% endif %} -{% endblock %} - -{% block methods_summary %} - {% if methods %} - .. rubric:: Methods - {% for item in all_methods %} - {%- if item not in inherited_members %} - {%- if not item.startswith('_') or item in ['__call__', '__mul__', '__getitem__', '__len__'] %} - .. automethod:: {{ name }}.{{ item }} - {%- endif -%} - {%- endif -%} - {%- endfor %} - - {% endif %} -{% endblock %} \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index 0a7e0af317..9f4cb9514f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -45,9 +45,9 @@ author = 'Qiskit Development Team' # The short X.Y version -version = '0.14.0' +version = '0.13.0' # The full version, including alpha/beta/rc tags -release = '0.14.0' +release = '0.13.0' templates_path = ['_templates'] @@ -74,7 +74,7 @@ 'sphinx.ext.intersphinx', 'nbsphinx', "sphinx_design", - 'qiskit_sphinx_theme', + 'qiskit_sphinx_theme' ] # ----------------------------------------------------------------------------- @@ -138,11 +138,19 @@ # a list of builtin themes. # -html_theme = "qiskit-ecosystem" -html_title = f"{project} {release}" +html_theme = "qiskit_sphinx_theme" +html_logo = 'images/logo.png' +#html_sidebars = {'**': ['globaltoc.html']} html_last_updated_fmt = '%Y/%m/%d' +html_theme_options = { + 'logo_only': True, + 'display_version': True, + 'prev_next_buttons_location': 'bottom', + 'style_external_links': True, +} + autoclass_content = 'both' intersphinx_mapping = { "matplotlib": ("https://matplotlib.org/stable/", None), diff --git a/docs/index.rst b/docs/index.rst index 6235a75d09..4c45d3da72 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -15,7 +15,6 @@ https://github.com/Qiskit/qiskit-aer .. toctree:: :hidden: - Home Getting Started API Documentation Tutorials diff --git a/docs/tutorials/1_aer_provider.ipynb b/docs/tutorials/1_aer_provider.ipynb index 0921311439..9e165a5701 100755 --- a/docs/tutorials/1_aer_provider.ipynb +++ b/docs/tutorials/1_aer_provider.ipynb @@ -772,7 +772,7 @@ { "data": { "text/html": [ - "

Version Information

Qiskit SoftwareVersion
qiskit0.24.0.dev0+dba2eff
qiskit-aer0.11.2
qiskit-ignis0.7.1
qiskit-ibmq-provider0.20.0
qiskit0.41.0
System information
Python version3.8.11
Python compilerClang 12.0.5 (clang-1205.0.22.11)
Python builddefault, Jul 27 2021 10:46:38
OSDarwin
CPUs8
Memory (Gb)64.0
Wed Feb 15 14:35:41 2023 JST
" + "

Version Information

Qiskit SoftwareVersion
qiskit-terra0.24.0.dev0+dba2eff
qiskit-aer0.11.2
qiskit-ignis0.7.1
qiskit-ibmq-provider0.20.0
qiskit0.41.0
System information
Python version3.8.11
Python compilerClang 12.0.5 (clang-1205.0.22.11)
Python builddefault, Jul 27 2021 10:46:38
OSDarwin
CPUs8
Memory (Gb)64.0
Wed Feb 15 14:35:41 2023 JST
" ], "text/plain": [ "" diff --git a/docs/tutorials/2_device_noise_simulation.ipynb b/docs/tutorials/2_device_noise_simulation.ipynb index 518ee69899..aef129393c 100755 --- a/docs/tutorials/2_device_noise_simulation.ipynb +++ b/docs/tutorials/2_device_noise_simulation.ipynb @@ -210,7 +210,7 @@ { "data": { "text/html": [ - "

Version Information

Qiskit SoftwareVersion
qiskit0.22.0.dev0+397a639
qiskit-aer0.10.4
System information
Python version3.10.4
Python compilerClang 12.0.0
Python buildmain, Mar 31 2022 03:38:35
OSDarwin
CPUs2
Memory (Gb)8.0
Thu Jul 14 10:20:15 2022 +08
" + "

Version Information

Qiskit SoftwareVersion
qiskit-terra0.22.0.dev0+397a639
qiskit-aer0.10.4
System information
Python version3.10.4
Python compilerClang 12.0.0
Python buildmain, Mar 31 2022 03:38:35
OSDarwin
CPUs2
Memory (Gb)8.0
Thu Jul 14 10:20:15 2022 +08
" ], "text/plain": [ "" diff --git a/docs/tutorials/3_building_noise_models.ipynb b/docs/tutorials/3_building_noise_models.ipynb index 572e4564a5..771fbff7fe 100644 --- a/docs/tutorials/3_building_noise_models.ipynb +++ b/docs/tutorials/3_building_noise_models.ipynb @@ -845,7 +845,7 @@ { "data": { "text/html": [ - "

Version Information

Qiskit SoftwareVersion
qiskit0.24.0.dev0+dba2eff
qiskit-aer0.11.2
qiskit-ibmq-provider0.19.2
qiskit0.40.0
System information
Python version3.8.11
Python compilerClang 12.0.5 (clang-1205.0.22.11)
Python builddefault, Jul 27 2021 10:46:38
OSDarwin
CPUs8
Memory (Gb)64.0
Tue Feb 07 10:30:00 2023 JST
" + "

Version Information

Qiskit SoftwareVersion
qiskit-terra0.24.0.dev0+dba2eff
qiskit-aer0.11.2
qiskit-ibmq-provider0.19.2
qiskit0.40.0
System information
Python version3.8.11
Python compilerClang 12.0.5 (clang-1205.0.22.11)
Python builddefault, Jul 27 2021 10:46:38
OSDarwin
CPUs8
Memory (Gb)64.0
Tue Feb 07 10:30:00 2023 JST
" ], "text/plain": [ "" diff --git a/docs/tutorials/5_noise_transformation.ipynb b/docs/tutorials/5_noise_transformation.ipynb index ba8d9034a2..9b9547c7db 100755 --- a/docs/tutorials/5_noise_transformation.ipynb +++ b/docs/tutorials/5_noise_transformation.ipynb @@ -318,7 +318,7 @@ { "data": { "text/html": [ - "

Version Information

Qiskit SoftwareVersion
qiskit0.24.0.dev0+dba2eff
qiskit-aer0.11.2
qiskit-ignis0.7.1
qiskit-ibmq-provider0.20.0
qiskit0.41.0
System information
Python version3.8.11
Python compilerClang 12.0.5 (clang-1205.0.22.11)
Python builddefault, Jul 27 2021 10:46:38
OSDarwin
CPUs8
Memory (Gb)64.0
Wed Feb 15 14:17:23 2023 JST
" + "

Version Information

Qiskit SoftwareVersion
qiskit-terra0.24.0.dev0+dba2eff
qiskit-aer0.11.2
qiskit-ignis0.7.1
qiskit-ibmq-provider0.20.0
qiskit0.41.0
System information
Python version3.8.11
Python compilerClang 12.0.5 (clang-1205.0.22.11)
Python builddefault, Jul 27 2021 10:46:38
OSDarwin
CPUs8
Memory (Gb)64.0
Wed Feb 15 14:17:23 2023 JST
" ], "text/plain": [ "" diff --git a/pyproject.toml b/pyproject.toml index 5543b9f5f2..8bcfe1bdce 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,7 @@ build-backend = "setuptools.build_meta" manylinux-x86_64-image = "manylinux2014" manylinux-i686-image = "manylinux2014" skip = "pp* cp36* cp37* *musllinux*" -test-skip = "cp310-win32 cp310-manylinux_i686 cp311-win32 cp311-manylinux_i686 cp312-win32 cp312-manylinux_i686" +test-skip = "cp310-win32 cp310-manylinux_i686 cp311-win32 cp311-manylinux_i686" test-command = "python {project}/tools/verify_wheels.py" # We need to use pre-built versions of Numpy and Scipy in the tests; they have a # tendency to crash if they're installed from source by `pip install`, and since @@ -30,7 +30,7 @@ before-all = "yum install -y openblas-devel" environment = { CMAKE_GENERATOR = "Visual Studio 16 2019"} [[tool.cibuildwheel.overrides]] -select = "cp3{8,9,10,11,12}-manylinux_i686" +select = "cp3{8,9,10,11}-manylinux_i686" before-all = "yum install -y wget && bash {project}/tools/install_openblas_i686.sh && bash {project}/tools/install_rust.sh" [tool.black] diff --git a/qiskit_aer/VERSION.txt b/qiskit_aer/VERSION.txt index a803cc227f..54d1a4f2a4 100644 --- a/qiskit_aer/VERSION.txt +++ b/qiskit_aer/VERSION.txt @@ -1 +1 @@ -0.14.0 +0.13.0 diff --git a/qiskit_aer/__init__.py b/qiskit_aer/__init__.py index ae552a3e40..0c3aac5b18 100644 --- a/qiskit_aer/__init__.py +++ b/qiskit_aer/__init__.py @@ -78,8 +78,8 @@ if sys.version_info < (3, 8): warnings.warn( - "Using Aer with Python 3.7 is deprecated as of the 0.12.0 release. " - "Support for running Aer with Python 3.7 will be removed in a future " + "Using Qiskit Aer with Python 3.7 is deprecated as of the 0.12.0 release. " + "Support for running Qiskit Aer with Python 3.7 will be removed in a future " "release", DeprecationWarning, ) diff --git a/qiskit_aer/aererror.py b/qiskit_aer/aererror.py index 596439d607..d1ffa74eab 100644 --- a/qiskit_aer/aererror.py +++ b/qiskit_aer/aererror.py @@ -11,7 +11,7 @@ # that they have been altered from the originals. """ -Exception for errors raised by Aer simulators backends. +Exception for errors raised by Qiskit Aer simulators backends. """ from qiskit import QiskitError diff --git a/qiskit_aer/aerprovider.py b/qiskit_aer/aerprovider.py index 915adc8e55..3f1b08e98a 100644 --- a/qiskit_aer/aerprovider.py +++ b/qiskit_aer/aerprovider.py @@ -11,7 +11,7 @@ # that they have been altered from the originals. # pylint: disable=invalid-name -"""Provider for Aer backends.""" +"""Provider for Qiskit Aer backends.""" from qiskit.providers import ProviderV1 as Provider @@ -24,7 +24,7 @@ class AerProvider(Provider): - """Provider for Aer backends.""" + """Provider for Qiskit Aer backends.""" _BACKENDS = None diff --git a/qiskit_aer/backends/aer_compiler.py b/qiskit_aer/backends/aer_compiler.py index bbb2e18a25..4909f73537 100644 --- a/qiskit_aer/backends/aer_compiler.py +++ b/qiskit_aer/backends/aer_compiler.py @@ -21,10 +21,8 @@ from concurrent.futures import Executor import numpy as np -from qiskit.circuit import QuantumCircuit, Clbit, ClassicalRegister, ParameterExpression -from qiskit.circuit.classical.expr import Expr, Unary, Binary, Var, Value, ExprVisitor, iter_vars -from qiskit.circuit.classical.types import Bool, Uint -from qiskit.circuit.library import Initialize +from qiskit.circuit import QuantumCircuit, Clbit, ParameterExpression +from qiskit.extensions import Initialize from qiskit.providers.options import Options from qiskit.pulse import Schedule, ScheduleBlock from qiskit.circuit.controlflow import ( @@ -42,21 +40,7 @@ from qiskit_aer.noise import NoiseModel # pylint: disable=import-error, no-name-in-module -from qiskit_aer.backends.controller_wrappers import ( - AerUnaryExpr, - AerUnaryOp, - AerBinaryExpr, - AerBinaryOp, - AerUintValue, - AerBoolValue, - AerUint, - AerBool, - AerCast, - AerVar, - AerCircuit, - AerConfig, -) - +from qiskit_aer.backends.controller_wrappers import AerCircuit, AerConfig from .backend_utils import circuit_optypes from ..library.control_flow_instructions import AerMark, AerJump @@ -99,9 +83,7 @@ def compile(self, circuits, basis_gates=None, optypes=None): circuit = self._inline_initialize(circuit, compiled_optypes[idx]) if self._is_dynamic(circuit, compiled_optypes[idx]): compiled_circ = transpile( - self._inline_circuit(circuit, None, None), - basis_gates=basis_gates, - optimization_level=0, + self._inline_circuit(circuit, None, None), basis_gates=basis_gates ) compiled_circuits.append(compiled_circ) # Recompute optype for compiled circuit @@ -217,36 +199,12 @@ def _inline_circuit(self, circ, continue_label, break_label, bit_map=None): return ret - def _convert_jump_conditional(self, cond_tuple, bit_map): + def _convert_c_if_args(self, cond_tuple, bit_map): """Convert a condition tuple according to the wire map.""" - if isinstance(cond_tuple, Expr): - return cond_tuple - elif isinstance(cond_tuple[0], Clbit): + if isinstance(cond_tuple[0], Clbit): return (bit_map[cond_tuple[0]], cond_tuple[1]) - elif isinstance(cond_tuple[0], ClassicalRegister): - # ClassicalRegister conditions should already be in the outer circuit. - return cond_tuple - elif isinstance(cond_tuple[0], Var): - if isinstance(cond_tuple[0].var, Clbit): - expr = Var(bit_map[cond_tuple[0].var], cond_tuple[0].type) - elif isinstance(cond_tuple[0].var, ClassicalRegister): - expr = Var([bit_map[clbit] for clbit in cond_tuple[0].var], cond_tuple[0].type) - else: - raise AerError( - f"jump condition does not support this tyep of Var: {cond_tuple[0]}." - ) - return (expr, cond_tuple[1]) - - raise AerError(f"jump condition does not support {cond_tuple[0].__class__}.") - - def _list_clbit_from_expr(self, bit_map, expr): - ret = set() - for var in iter_vars(expr): - if isinstance(var.var, Clbit): - ret.add(bit_map[var.var]) - elif isinstance(var.var, ClassicalRegister): - ret.update(bit_map[bit] for bit in var.var) - return ret + # ClassicalRegister conditions should already be in the outer circuit. + return cond_tuple def _inline_for_loop_op(self, instruction, parent, bit_map): """inline for_loop body while iterating its indexset""" @@ -271,7 +229,7 @@ def _inline_for_loop_op(self, instruction, parent, bit_map): continue_label = f"{loop_name}_{index}" inlined_body = self._inline_circuit(body, continue_label, break_label, inner_bit_map) if loop_parameter is not None: - inlined_body = inlined_body.assign_parameters({loop_parameter: index}) + inlined_body = inlined_body.bind_parameters({loop_parameter: index}) parent.append(inlined_body, qargs, cargs) parent.append(AerMark(continue_label, len(qargs), len(cargs)), qargs, cargs) @@ -280,7 +238,7 @@ def _inline_for_loop_op(self, instruction, parent, bit_map): def _inline_while_loop_op(self, instruction, parent, bit_map): """inline while_loop body with jump and mark instructions""" - condition_tuple = self._convert_jump_conditional(instruction.operation.condition, bit_map) + condition_tuple = self._convert_c_if_args(instruction.operation.condition, bit_map) (body,) = instruction.operation.params self._last_flow_id += 1 @@ -304,20 +262,23 @@ def _inline_while_loop_op(self, instruction, parent, bit_map): ) qargs = [bit_map[q] for q in instruction.qubits] cargs = [bit_map[c] for c in instruction.clbits] - - if isinstance(condition_tuple, Expr): - mark_cargs = self._list_clbit_from_expr(bit_map, condition_tuple) - elif isinstance(condition_tuple[0], Clbit): - mark_cargs = {bit_map[condition_tuple[0]]} - else: - mark_cargs = {bit_map[c] for c in condition_tuple[0]} - mark_cargs = set(cargs).union(mark_cargs) - set(instruction.clbits) - - c_if_args = self._convert_jump_conditional(condition_tuple, bit_map) + mark_cargs = cargs.copy() + mark_cargs.extend( + bit_map[c] + for c in ( + ( + {condition_tuple[0]} + if isinstance(condition_tuple[0], Clbit) + else set(condition_tuple[0]) + ) + - set(instruction.clbits) + ) + ) + c_if_args = self._convert_c_if_args(condition_tuple, bit_map) parent.append(AerMark(continue_label, len(qargs), len(mark_cargs)), qargs, mark_cargs) parent.append( - AerJump(loop_start_label, len(qargs), len(mark_cargs)).set_conditional(c_if_args), + AerJump(loop_start_label, len(qargs), len(mark_cargs)).c_if(*c_if_args), qargs, mark_cargs, ) @@ -343,18 +304,22 @@ def _inline_if_else_op(self, instruction, continue_label, break_label, parent, b else: if_else_label = if_end_label - c_if_args = self._convert_jump_conditional(condition_tuple, bit_map) + c_if_args = self._convert_c_if_args(condition_tuple, bit_map) qargs = [bit_map[q] for q in instruction.qubits] cargs = [bit_map[c] for c in instruction.clbits] - - if isinstance(condition_tuple, Expr): - mark_cargs = self._list_clbit_from_expr(bit_map, condition_tuple) - elif isinstance(condition_tuple[0], Clbit): - mark_cargs = {bit_map[condition_tuple[0]]} - else: - mark_cargs = {bit_map[c] for c in condition_tuple[0]} - mark_cargs = set(cargs).union(mark_cargs) - set(instruction.clbits) + mark_cargs = cargs.copy() + mark_cargs.extend( + bit_map[c] + for c in ( + ( + {condition_tuple[0]} + if isinstance(condition_tuple[0], Clbit) + else set(condition_tuple[0]) + ) + - set(instruction.clbits) + ) + ) true_bit_map = { inner: bit_map[outer] @@ -365,9 +330,7 @@ def _inline_if_else_op(self, instruction, continue_label, break_label, parent, b } parent.append( - AerJump(if_true_label, len(qargs), len(mark_cargs)).set_conditional(c_if_args), - qargs, - mark_cargs, + AerJump(if_true_label, len(qargs), len(mark_cargs)).c_if(*c_if_args), qargs, mark_cargs ) parent.append(AerJump(if_else_label, len(qargs), len(mark_cargs)), qargs, mark_cargs) parent.append(AerMark(if_true_label, len(qargs), len(mark_cargs)), qargs, mark_cargs) @@ -403,14 +366,11 @@ def _inline_switch_case_op(self, instruction, continue_label, break_label, paren qargs = [bit_map[q] for q in instruction.qubits] cargs = [bit_map[c] for c in instruction.clbits] - - if isinstance(instruction.operation.target, Clbit): - target_clbits = {bit_map[instruction.operation.target]} - elif isinstance(instruction.operation.target, Expr): - target_clbits = self._list_clbit_from_expr(bit_map, instruction.operation.target) - else: - target_clbits = {bit_map[c] for c in instruction.operation.target} - mark_cargs = set(cargs).union(target_clbits) - set(instruction.clbits) + mark_cargs = ( + set(cargs + [bit_map[instruction.operation.target]]) + if isinstance(instruction.operation.target, Clbit) + else set(cargs + [bit_map[c] for c in instruction.operation.target]) + ) - set(instruction.clbits) switch_end_label = f"{switch_name}_end" case_default_label = None @@ -423,9 +383,7 @@ def _inline_switch_case_op(self, instruction, continue_label, break_label, paren case_data = CaseData( label=f"{switch_name}_{i}", args_list=[ - self._convert_jump_conditional( - (instruction.operation.target, switch_val), bit_map - ) + self._convert_c_if_args((instruction.operation.target, switch_val), bit_map) if switch_val != CASE_DEFAULT else [] for switch_val in case[0] @@ -449,17 +407,8 @@ def _inline_switch_case_op(self, instruction, continue_label, break_label, paren for case_data in case_data_list: for case_args in case_data.args_list: if len(case_args) > 0: - if isinstance(case_args[0], Expr): - case_args = Binary( - Binary.Op.EQUAL, - case_args[0], - Value(case_args[1], case_args[0].type), - Bool(), - ) parent.append( - AerJump(case_data.label, len(qargs), len(mark_cargs)).set_conditional( - case_args - ), + AerJump(case_data.label, len(qargs), len(mark_cargs)).c_if(*case_args), qargs, mark_cargs, ) @@ -537,13 +486,11 @@ def compile_circuit(circuits, basis_gates=None, optypes=None): "chop_threshold": (float, np.floating), "mps_parallel_threshold": (int, np.integer), "mps_omp_threads": (int, np.integer), - "mps_lapack": (bool, np.bool_), "tensor_network_num_sampling_qubits": (int, np.integer), "use_cuTensorNet_autotuning": (bool, np.bool_), "parameterizations": (list), "fusion_parallelization_threshold": (int, np.integer), "target_gpus": (list), - "runtime_parameter_bind_enable": (bool, np.bool_), } @@ -631,11 +578,7 @@ def assemble_circuit(circuit: QuantumCircuit): for creg in circuit.cregs: creg_sizes.append([creg.name, creg.size]) - is_conditional = any( - getattr(inst.operation, "condition_expr", None) - or getattr(inst.operation, "condition", None) - for inst in circuit.data - ) + is_conditional = any(getattr(inst.operation, "condition", None) for inst in circuit.data) header = QobjExperimentHeader( n_qubits=num_qubits, @@ -662,7 +605,6 @@ def assemble_circuit(circuit: QuantumCircuit): # to the conditional instruction to map the creg ?= val condition # onto a gating register bit. conditional_reg = -1 - conditional_expr = None if hasattr(inst.operation, "condition") and inst.operation.condition: ctrl_reg, ctrl_val = inst.operation.condition mask = 0 @@ -679,124 +621,16 @@ def assemble_circuit(circuit: QuantumCircuit): aer_circ.bfunc(f"0x{mask:X}", f"0x{val:X}", "==", conditional_reg) num_of_aer_ops += 1 max_conditional_idx += 1 - elif hasattr(inst.operation, "condition_expr") and inst.operation.condition_expr: - conditional_expr = inst.operation.condition_expr num_of_aer_ops += _assemble_op( - circuit, - aer_circ, - inst, - qubit_indices, - clbit_indices, - is_conditional, - conditional_reg, - conditional_expr, + aer_circ, inst, qubit_indices, clbit_indices, is_conditional, conditional_reg ) index_map.append(num_of_aer_ops - 1) return aer_circ, index_map -def _assemble_type(expr_type): - if isinstance(expr_type, Uint): - return AerUint(expr_type.width) - elif isinstance(expr_type, Bool): - return AerBool() - else: - raise AerError(f"unknown type: {expr_type.__class__}") - - -def _assemble_clbit_indices(circ, c): - if isinstance(c, (ClassicalRegister, list)): - return [circ.find_bit(cbit).index for cbit in c] - elif isinstance(c, Clbit): - return [circ.find_bit(c).index] - else: - raise AerError(f"unknown clibt list: {c.__class__}") - - -def _assemble_unary_operator(op): - if op is Unary.Op.BIT_NOT: - return AerUnaryOp.BitNot - elif op is Unary.Op.LOGIC_NOT: - return AerUnaryOp.LogicNot - else: - raise AerError(f"unknown op: {op}") - - -_BINARY_OP_MAPPING = { - Binary.Op.BIT_AND: AerBinaryOp.BitAnd, - Binary.Op.BIT_OR: AerBinaryOp.BitOr, - Binary.Op.BIT_XOR: AerBinaryOp.BitXor, - Binary.Op.LOGIC_AND: AerBinaryOp.LogicAnd, - Binary.Op.LOGIC_OR: AerBinaryOp.LogicOr, - Binary.Op.EQUAL: AerBinaryOp.Equal, - Binary.Op.NOT_EQUAL: AerBinaryOp.NotEqual, - Binary.Op.LESS: AerBinaryOp.Less, - Binary.Op.LESS_EQUAL: AerBinaryOp.LessEqual, - Binary.Op.GREATER: AerBinaryOp.Greater, - Binary.Op.GREATER_EQUAL: AerBinaryOp.GreaterEqual, -} - - -def _assemble_binary_operator(op): - if op in _BINARY_OP_MAPPING: - return _BINARY_OP_MAPPING[op] - else: - raise AerError(f"unknown op: {op}") - - -class _AssembleExprImpl(ExprVisitor): - """Convert from Expr objects to corresponding objects.""" - - def __init__(self, circuit): - self.circuit = circuit - - def visit_value(self, node, /): - """return Aer's value types.""" - # pylint: disable=unused-variable - if isinstance(node.type, Uint): - return AerUintValue(node.type.width, node.value) - elif isinstance(node.type, Bool): - return AerBoolValue(node.value) - else: - raise AerError(f"invalid value type is specified: {node.type.__class__}") - - def visit_var(self, node, /): - return AerVar(_assemble_type(node.type), _assemble_clbit_indices(self.circuit, node.var)) - - def visit_cast(self, node, /): - return AerCast(_assemble_type(node.type), node.operand.accept(self)) - - def visit_unary(self, node, /): - return AerUnaryExpr(_assemble_unary_operator(node.op), node.operand.accept(self)) - - def visit_binary(self, node, /): - return AerBinaryExpr( - _assemble_binary_operator(node.op), - node.left.accept(self), - node.right.accept(self), - ) - - def visit_generic(self, node, /): - raise AerError(f"unsupported expression is used: {node.__class__}") - - -def _check_no_conditional(inst_name, conditional_reg): - if conditional_reg >= 0: - raise AerError(f"instruction {inst_name} does not support conditional") - - -def _assemble_op( - circ, - aer_circ, - inst, - qubit_indices, - clbit_indices, - is_conditional, - conditional_reg, - conditional_expr, -): +def _assemble_op(aer_circ, inst, qubit_indices, clbit_indices, is_conditional, conditional_reg): operation = inst.operation qubits = [qubit_indices[qubit] for qubit in inst.qubits] clbits = [clbit_indices[clbit] for clbit in inst.clbits] @@ -812,8 +646,6 @@ def _assemble_op( copied = True params[i] = 0.0 - aer_cond_expr = conditional_expr.accept(_AssembleExprImpl(circ)) if conditional_expr else None - num_of_aer_ops = 1 # fmt: off if name in { @@ -823,33 +655,28 @@ def _assemble_op( "rx", "rxx", "ry", "ryy", "rz", "rzx", "rzz", "s", "sdg", "swap", "sx", "sxdg", "t", "tdg", "u", "x", "y", "z", "u1", "u2", "u3", "cu", "cu1", "cu2", "cu3", }: - aer_circ.gate(name, qubits, params, [], conditional_reg, aer_cond_expr, - label if label else name) + aer_circ.gate(name, qubits, params, [], conditional_reg, label if label else name) elif name == "measure": if is_conditional: aer_circ.measure(qubits, clbits, clbits) else: aer_circ.measure(qubits, clbits, []) elif name == "reset": - aer_circ.reset(qubits, conditional_reg) + aer_circ.reset(qubits) elif name == "diagonal": - aer_circ.diagonal(qubits, params, conditional_reg, label if label else "diagonal") + aer_circ.diagonal(qubits, params, label if label else "diagonal") elif name == "unitary": - aer_circ.unitary(qubits, params[0], conditional_reg, aer_cond_expr, - label if label else "unitary") + aer_circ.unitary(qubits, params[0], conditional_reg, label if label else "unitary") elif name == "pauli": - aer_circ.gate(name, qubits, [], params, conditional_reg, aer_cond_expr, - label if label else name) + aer_circ.gate(name, qubits, [], params, conditional_reg, label if label else name) elif name == "initialize": - _check_no_conditional(name, conditional_reg) aer_circ.initialize(qubits, params) elif name == "roerror": - _check_no_conditional(name, conditional_reg) aer_circ.roerror(qubits, params) elif name == "multiplexer": - aer_circ.multiplexer(qubits, params, conditional_reg, aer_cond_expr, label if label else name) + aer_circ.multiplexer(qubits, params, conditional_reg, label if label else name) elif name == "kraus": - aer_circ.kraus(qubits, params, conditional_reg, aer_cond_expr) + aer_circ.kraus(qubits, params, conditional_reg) elif name in { "save_statevector", "save_statevector_dict", @@ -863,13 +690,10 @@ def _assemble_op( "save_state", "save_stabilizer", }: - _check_no_conditional(name, conditional_reg) aer_circ.save_state(qubits, name, operation._subtype, label if label else name) elif name in {"save_amplitudes", "save_amplitudes_sq"}: - _check_no_conditional(name, conditional_reg) aer_circ.save_amplitudes(qubits, name, params, operation._subtype, label if label else name) elif name in ("save_expval", "save_expval_var"): - _check_no_conditional(name, conditional_reg) paulis = [] coeff_reals = [] coeff_imags = [] @@ -887,35 +711,27 @@ def _assemble_op( label if label else name, ) elif name == "set_statevector": - _check_no_conditional(name, conditional_reg) aer_circ.set_statevector(qubits, params) elif name == "set_unitary": - _check_no_conditional(name, conditional_reg) aer_circ.set_unitary(qubits, params) elif name == "set_density_matrix": - _check_no_conditional(name, conditional_reg) aer_circ.set_density_matrix(qubits, params) elif name == "set_stabilizer": - _check_no_conditional(name, conditional_reg) aer_circ.set_clifford(qubits, params) elif name == "set_superop": - _check_no_conditional(name, conditional_reg) aer_circ.set_superop(qubits, params) elif name == "set_matrix_product_state": - _check_no_conditional(name, conditional_reg) aer_circ.set_matrix_product_state(qubits, params) elif name == "superop": - aer_circ.superop(qubits, params[0], conditional_reg, aer_cond_expr) + aer_circ.superop(qubits, params[0], conditional_reg) elif name == "barrier": - _check_no_conditional(name, conditional_reg) num_of_aer_ops = 0 elif name == "jump": - aer_circ.jump(qubits, params, conditional_reg, aer_cond_expr) + aer_circ.jump(qubits, params, conditional_reg) elif name == "mark": - _check_no_conditional(name, conditional_reg) aer_circ.mark(qubits, params) elif name == "qerror_loc": - aer_circ.set_qerror_loc(qubits, label if label else name, conditional_reg, aer_cond_expr) + aer_circ.set_qerror_loc(qubits, label if label else name, conditional_reg) elif name in ("for_loop", "while_loop", "if_else"): raise AerError( "control-flow instructions must be converted " f"to jump and mark instructions: {name}" diff --git a/qiskit_aer/backends/aer_simulator.py b/qiskit_aer/backends/aer_simulator.py index 9638bd8a71..d34cf1ef27 100644 --- a/qiskit_aer/backends/aer_simulator.py +++ b/qiskit_aer/backends/aer_simulator.py @@ -10,7 +10,7 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. """ -Aer qasm simulator backend. +Qiskit Aer qasm simulator backend. """ import copy @@ -31,7 +31,7 @@ BASIS_GATES, ) -# pylint: disable=import-error, no-name-in-module, abstract-method +# pylint: disable=import-error, no-name-in-module from .controller_wrappers import aer_controller_execute logger = logging.getLogger(__name__) @@ -318,12 +318,6 @@ class AerSimulator(AerBackend): * ``accept_distributed_results`` (bool): This option enables storing results independently in each process (Default: None). - * ``runtime_parameter_bind_enable`` (bool): If this option is True - parameters are bound at runtime by using multi-shots without constructing - circuits for each parameters. For GPU this option can be used with - ``batched_shots_gpu`` to run with multiple parameters in a batch. - (Default: False). - These backend options only apply when using the ``"statevector"`` simulation method: @@ -448,9 +442,6 @@ class AerSimulator(AerBackend): * ``mps_omp_threads`` (int): This option sets the number of OMP threads (Default: 1). - * ``mps_lapack`` (bool): This option indicates to compute the SVD function - using OpenBLAS/Lapack interface (Default: False). - These backend options only apply when using the ``tensor_network`` simulation method: @@ -519,8 +510,6 @@ class AerSimulator(AerBackend): "while_loop", "break_loop", "continue_loop", - "reset", - "switch_case", ] ), "density_matrix": sorted( @@ -543,8 +532,6 @@ class AerSimulator(AerBackend): "while_loop", "break_loop", "continue_loop", - "reset", - "switch_case", ] ), "matrix_product_state": sorted( @@ -569,8 +556,6 @@ class AerSimulator(AerBackend): "while_loop", "break_loop", "continue_loop", - "reset", - "switch_case", ] ), "stabilizer": sorted( @@ -592,8 +577,6 @@ class AerSimulator(AerBackend): "while_loop", "break_loop", "continue_loop", - "reset", - "switch_case", ] ), "extended_stabilizer": sorted( @@ -602,7 +585,6 @@ class AerSimulator(AerBackend): "qerror_loc", "roerror", "save_statevector", - "reset", ] ), "unitary": sorted( @@ -610,7 +592,6 @@ class AerSimulator(AerBackend): "save_state", "save_unitary", "set_unitary", - "reset", ] ), "superop": sorted( @@ -622,7 +603,6 @@ class AerSimulator(AerBackend): "save_state", "save_superop", "set_superop", - "reset", ] ), "tensor_network": sorted( @@ -644,8 +624,6 @@ class AerSimulator(AerBackend): "save_statevector_dict", "set_statevector", "set_density_matrix", - "reset", - "switch_case", ] ), } @@ -698,17 +676,17 @@ class AerSimulator(AerBackend): _AVAILABLE_DEVICES = None - def __init__( - self, configuration=None, properties=None, provider=None, target=None, **backend_options - ): + def __init__(self, configuration=None, properties=None, provider=None, **backend_options): self._controller = aer_controller_execute() # Update available methods and devices for class if AerSimulator._AVAILABLE_DEVICES is None: - AerSimulator._AVAILABLE_DEVICES = available_devices(self._controller) + AerSimulator._AVAILABLE_DEVICES = available_devices( + self._controller, AerSimulator._SIMULATION_DEVICES + ) if AerSimulator._AVAILABLE_METHODS is None: AerSimulator._AVAILABLE_METHODS = available_methods( - AerSimulator._SIMULATION_METHODS, AerSimulator._AVAILABLE_DEVICES + self._controller, AerSimulator._SIMULATION_METHODS, AerSimulator._AVAILABLE_DEVICES ) # Default configuration @@ -720,11 +698,7 @@ def __init__( self._cached_basis_gates = self._BASIS_GATES["automatic"] super().__init__( - configuration, - properties=properties, - provider=provider, - target=target, - backend_options=backend_options, + configuration, properties=properties, provider=provider, backend_options=backend_options ) @classmethod @@ -788,12 +762,9 @@ def _default_options(cls): chop_threshold=1e-8, mps_parallel_threshold=14, mps_omp_threads=1, - mps_lapack=False, # tensor network options tensor_network_num_sampling_qubits=10, use_cuTensorNet_autotuning=False, - # parameter binding - runtime_parameter_bind_enable=False, ) def __repr__(self): @@ -805,7 +776,7 @@ def __repr__(self): pad = " " * (len(self.__class__.__name__) + 1) return f"{display[:-1]}\n{pad}noise_model={repr(noise_model)})" - def _name(self): + def name(self): """Format backend name string for simulator""" name = self._configuration.backend_name method = getattr(self.options, "method", None) @@ -820,11 +791,6 @@ def _name(self): def from_backend(cls, backend, **options): """Initialize simulator from backend.""" if isinstance(backend, BackendV2): - if backend.description is None: - description = "created by AerSimulator.from_backend" - else: - description = backend.description - configuration = QasmBackendConfiguration( backend_name=f"'aer_simulator({backend.name})", backend_version=backend.backend_version, @@ -839,10 +805,8 @@ def from_backend(cls, backend, **options): max_shots=int(1e6), coupling_map=list(backend.coupling_map.get_edges()), max_experiments=backend.max_circuits, - description=description, ) properties = target_to_backend_properties(backend.target) - target = backend.target elif isinstance(backend, BackendV1): # Get configuration and properties from backend configuration = copy.copy(backend.configuration()) @@ -851,8 +815,6 @@ def from_backend(cls, backend, **options): # Customize configuration name name = configuration.backend_name configuration.backend_name = f"aer_simulator({name})" - - target = None else: raise TypeError( "The backend argument requires a BackendV2 or BackendV1 object, " @@ -869,7 +831,7 @@ def from_backend(cls, backend, **options): options["noise_model"] = noise_model # Initialize simulator - sim = cls(configuration=configuration, properties=properties, target=target, **options) + sim = cls(configuration=configuration, properties=properties, **options) return sim def available_methods(self): @@ -896,7 +858,7 @@ def configuration(self): ] config.basis_gates = self._cached_basis_gates + config.custom_instructions # Update simulator name - config.backend_name = self._name() + config.backend_name = self.name() return config def _execute_circuits(self, aer_circuits, noise_model, config): diff --git a/qiskit_aer/backends/aerbackend.py b/qiskit_aer/backends/aerbackend.py index 36545ffe8c..7266572ae9 100644 --- a/qiskit_aer/backends/aerbackend.py +++ b/qiskit_aer/backends/aerbackend.py @@ -10,7 +10,7 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. """ -Aer qasm simulator backend. +Qiskit Aer qasm simulator backend. """ import copy @@ -23,22 +23,19 @@ from qiskit.circuit import QuantumCircuit, ParameterExpression, Delay from qiskit.compiler import assemble -from qiskit.providers import BackendV2 as Backend -from qiskit.providers import convert_to_target +from qiskit.providers import BackendV1 as Backend from qiskit.providers.models import BackendStatus from qiskit.pulse import Schedule, ScheduleBlock from qiskit.qobj import QasmQobj, PulseQobj from qiskit.result import Result -from qiskit.transpiler import CouplingMap from ..aererror import AerError from ..jobs import AerJob, AerJobSet, split_qobj from ..noise.noise_model import NoiseModel, QuantumErrorLocation from ..noise.errors.quantum_error import QuantumChannelInstruction from .aer_compiler import compile_circuit, assemble_circuits, generate_aer_config from .backend_utils import format_save_type, circuit_optypes -from .name_mapping import NAME_MAPPING -# pylint: disable=import-error, no-name-in-module, abstract-method +# pylint: disable=import-error, no-name-in-module from .controller_wrappers import AerConfig # Logger @@ -46,10 +43,10 @@ class AerBackend(Backend, ABC): - """Aer Backend class.""" + """Qiskit Aer Backend class.""" def __init__( - self, configuration, properties=None, provider=None, target=None, backend_options=None + self, configuration, properties=None, defaults=None, backend_options=None, provider=None ): """Aer class for backends. @@ -60,8 +57,8 @@ def __init__( Args: configuration (BackendConfiguration): backend configuration. properties (BackendProperties or None): Optional, backend properties. + defaults (PulseDefaults or None): Optional, backend pulse defaults. provider (Provider): Optional, provider responsible for this backend. - target (Target): initial target for backend backend_options (dict or None): Optional set custom backend options. Raises: @@ -70,31 +67,21 @@ def __init__( # Init configuration and provider in Backend configuration.simulator = True configuration.local = True - super().__init__( - provider=provider, - name=configuration.backend_name, - description=configuration.description, - backend_version=configuration.backend_version, - ) + super().__init__(configuration, provider=provider) - # Initialize backend properties + # Initialize backend properties and pulse defaults. self._properties = properties - self._configuration = configuration + self._defaults = defaults - # Custom option values for config, properties + # Custom option values for config, properties, and defaults self._options_configuration = {} + self._options_defaults = {} self._options_properties = {} - self._target = target - self._mapping = NAME_MAPPING # Set options from backend_options dictionary if backend_options is not None: self.set_options(**backend_options) - # build coupling map - if self.configuration().coupling_map is not None: - self._coupling_map = CouplingMap(self.configuration().coupling_map) - def _convert_circuit_binds(self, circuit, binds, idx_map): parameterizations = [] @@ -316,7 +303,7 @@ def configuration(self): for key, val in self._options_configuration.items(): setattr(config, key, val) # If config has custom instructions add them to - # basis gates to include them for the qiskit transpiler + # basis gates to include them for the terra transpiler if hasattr(config, "custom_instructions"): config.basis_gates = config.basis_gates + config.custom_instructions return config @@ -333,25 +320,28 @@ def properties(self): setattr(properties, key, val) return properties - @property - def max_circuits(self): - if hasattr(self.configuration(), "max_experiments"): - return self.configuration().max_experiments - else: - return None + def defaults(self): + """Return the simulator backend pulse defaults. - @property - def target(self): - if self._target is not None: - return self._target + Returns: + PulseDefaults: The backend pulse defaults or ``None`` if the + backend does not support pulse. + """ + defaults = copy.copy(self._defaults) + for key, val in self._options_defaults.items(): + setattr(defaults, key, val) + return defaults - return convert_to_target(self.configuration(), self.properties(), None, NAME_MAPPING) + @classmethod + def _default_options(cls): + pass def clear_options(self): """Reset the simulator options to default values.""" self._options = self._default_options() self._options_configuration = {} self._options_properties = {} + self._options_defaults = {} def status(self): """Return backend status. @@ -360,7 +350,7 @@ def status(self): BackendStatus: the status of the backend. """ return BackendStatus( - backend_name=self.name, + backend_name=self.name(), backend_version=self.configuration().backend_version, operational=True, pending_jobs=0, @@ -398,7 +388,7 @@ def _execute_qobj_job(self, qobj, job_id="", format_result=True): # Validate output if not isinstance(output, dict): - logger.error("%s: simulation failed.", self.name) + logger.error("%s: simulation failed.", self.name()) if output: logger.error("Output: %s", output) raise AerError("simulation terminated without returning valid output.") @@ -406,7 +396,7 @@ def _execute_qobj_job(self, qobj, job_id="", format_result=True): # Format results output["job_id"] = job_id output["date"] = datetime.datetime.now().isoformat() - output["backend_name"] = self.name + output["backend_name"] = self.name() output["backend_version"] = self.configuration().backend_version # Push metadata to experiment headers @@ -464,7 +454,7 @@ def _execute_circuits_job( # Validate output if not isinstance(output, dict): - logger.error("%s: simulation failed.", self.name) + logger.error("%s: simulation failed.", self.name()) if output: logger.error("Output: %s", output) raise AerError("simulation terminated without returning valid output.") @@ -472,7 +462,7 @@ def _execute_circuits_job( # Format results output["job_id"] = job_id output["date"] = datetime.datetime.now().isoformat() - output["backend_name"] = self.name + output["backend_name"] = self.name() output["backend_version"] = self.configuration().backend_version # Push metadata to experiment headers @@ -692,6 +682,8 @@ def set_option(self, key, value): self._set_configuration_option(key, value) elif hasattr(self._properties, key): self._set_properties_option(key, value) + elif hasattr(self._defaults, key): + self._set_defaults_option(key, value) else: if not hasattr(self._options, key): raise AerError(f"Invalid option {key}") @@ -723,15 +715,15 @@ def _set_properties_option(self, key, value): elif key in self._options_properties: self._options_properties.pop(key) + def _set_defaults_option(self, key, value): + """Special handling for setting backend defaults options.""" + if value is not None: + self._options_defaults[key] = value + elif key in self._options_defaults: + self._options_defaults.pop(key) + def __repr__(self): """String representation of an AerBackend.""" name = self.__class__.__name__ - display = f"'{self.name}'" + display = f"'{self.name()}'" return f"{name}({display})" - - def get_translation_stage_plugin(self): - """use custom translation method to avoid gate exchange""" - if self._target is None: - return "aer_backend_plugin" - else: - return None diff --git a/qiskit_aer/backends/backend_utils.py b/qiskit_aer/backends/backend_utils.py index fe9b71dc14..717f0a4b59 100644 --- a/qiskit_aer/backends/backend_utils.py +++ b/qiskit_aer/backends/backend_utils.py @@ -12,21 +12,20 @@ # pylint: disable=invalid-name """ -Aer simulator backend utils +Qiskit Aer simulator backend utils """ import os from math import log2 - -import psutil +from qiskit.utils import local_hardware_info from qiskit.circuit import QuantumCircuit +from qiskit.compiler import assemble from qiskit.qobj import QasmQobjInstruction from qiskit.result import ProbDistribution from qiskit.quantum_info import Clifford - from .compatibility import Statevector, DensityMatrix, StabilizerState, Operator, SuperOp # Available system memory -SYSTEM_MEMORY_GB = psutil.virtual_memory().total / (1024**3) +SYSTEM_MEMORY_GB = local_hardware_info()["memory"] # Max number of qubits for complex double statevector # given available system memory @@ -212,9 +211,6 @@ "delay", "pauli", "ecr", - "rx", - "ry", - "rz", ] ), "extended_stabilizer": sorted( @@ -440,23 +436,40 @@ def cpp_execute_circuits(controller, aer_circuits, noise_model, config): return controller.execute(aer_circuits, noise_model, config) -def available_methods(methods, devices): - """Check available simulation 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: - if method == "tensor_network": - if "GPU" in devices: - valid_methods.append(method) - else: - 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_qobj(controller, qobj) + if result.get("success", False): + valid_methods.append(method) return tuple(valid_methods) -def available_devices(controller): - """return available simulation devices""" - dev = controller.available_devices() - return tuple(dev) +def available_devices(controller, devices): + """Check available simulation devices by running a dummy circuit.""" + # Test methods are available using the controller + dummy_circ = QuantumCircuit(1) + dummy_circ.i(0) + + valid_devices = [] + for device in devices: + qobj = assemble( + dummy_circ, optimization_level=0, shots=1, method="statevector", device=device + ) + result = cpp_execute_qobj(controller, qobj) + if result.get("success", False): + valid_devices.append(device) + return tuple(valid_devices) def add_final_save_instruction(qobj, state): diff --git a/qiskit_aer/backends/name_mapping.py b/qiskit_aer/backends/name_mapping.py deleted file mode 100644 index 5af58e3b07..0000000000 --- a/qiskit_aer/backends/name_mapping.py +++ /dev/null @@ -1,304 +0,0 @@ -# This code is part of Qiskit. -# -# (C) Copyright IBM 2018, 2019. -# -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. - -# pylint: disable=invalid-name -""" -Qiskit Aer simulator name mapping for Target object -""" -from qiskit.circuit import ControlledGate, Parameter -from qiskit.circuit.reset import Reset -from qiskit.circuit.library import ( - U2Gate, - RGate, - CYGate, - CZGate, - CSXGate, - CU3Gate, - CSwapGate, - PauliGate, - DiagonalGate, - UnitaryGate, - MCPhaseGate, - MCXGate, - CRXGate, - CRYGate, - CRZGate, - MCU1Gate, - MCXGrayCode, - Initialize, - UCGate, -) -from qiskit.circuit.controlflow import ( - IfElseOp, - WhileLoopOp, - ForLoopOp, - ContinueLoopOp, - BreakLoopOp, - SwitchCaseOp, -) -from qiskit.quantum_info.operators.channel.kraus import Kraus -from qiskit.quantum_info.operators.channel import SuperOp -from qiskit.quantum_info.operators.channel.quantum_channel import QuantumChannel - -from ..library import ( - SaveExpectationValue, - SaveAmplitudes, - SaveStatevectorDict, - SaveSuperOp, - SaveClifford, - SaveMatrixProductState, - SaveDensityMatrix, - SaveProbabilities, - SaveStatevector, - SetDensityMatrix, - SetUnitary, - SaveState, - SetMatrixProductState, - SaveUnitary, - SetSuperOp, - SaveExpectationValueVariance, - SaveStabilizer, - SetStatevector, - SetStabilizer, - SaveAmplitudesSquared, - SaveProbabilitiesDict, -) -from ..noise.errors import ReadoutError -from ..noise.noise_model import QuantumErrorLocation - - -class MCSXGate(ControlledGate): - """mcsx gate""" - - def __init__(self, num_ctrl_qubits, ctrl_state=None): - super().__init__( - "mcsx", - 1 + num_ctrl_qubits, - [], - None, - num_ctrl_qubits, - ctrl_state=ctrl_state, - base_gate=CSXGate(), - ) - - -class MCYGate(ControlledGate): - """mcy gate""" - - def __init__(self, num_ctrl_qubits, ctrl_state=None): - super().__init__( - "mcy", - 1 + num_ctrl_qubits, - [], - None, - num_ctrl_qubits, - ctrl_state=ctrl_state, - base_gate=CYGate(), - ) - - -class MCZGate(ControlledGate): - """mcz gate""" - - def __init__(self, num_ctrl_qubits, ctrl_state=None): - super().__init__( - "mcz", - 1 + num_ctrl_qubits, - [], - None, - num_ctrl_qubits, - ctrl_state=ctrl_state, - base_gate=CZGate(), - ) - - -class MCRXGate(ControlledGate): - """mcrx gate""" - - def __init__(self, theta, num_ctrl_qubits, ctrl_state=None): - super().__init__( - "mcrx", - 1 + num_ctrl_qubits, - [theta], - None, - num_ctrl_qubits, - ctrl_state=ctrl_state, - base_gate=CRXGate(theta), - ) - - -class MCRYGate(ControlledGate): - """mcry gate""" - - def __init__(self, theta, num_ctrl_qubits, ctrl_state=None): - super().__init__( - "mcry", - 1 + num_ctrl_qubits, - [theta], - None, - num_ctrl_qubits, - ctrl_state=ctrl_state, - base_gate=CRYGate(theta), - ) - - -class MCRZGate(ControlledGate): - """mcrz gate""" - - def __init__(self, theta, num_ctrl_qubits, ctrl_state=None): - super().__init__( - "mcrz", - 1 + num_ctrl_qubits, - [theta], - None, - num_ctrl_qubits, - ctrl_state=ctrl_state, - base_gate=CRZGate(theta), - ) - - -class MCRGate(ControlledGate): - """mcr gate""" - - def __init__(self, theta, phi, num_ctrl_qubits, ctrl_state=None): - super().__init__( - "mcr", - 1 + num_ctrl_qubits, - [theta, phi], - None, - num_ctrl_qubits, - ctrl_state=ctrl_state, - base_gate=RGate(theta, phi), - ) - - -class MCU2Gate(ControlledGate): - """mcu2 gate""" - - def __init__(self, theta, lam, num_ctrl_qubits, ctrl_state=None): - super().__init__( - "mcu2", - 1 + num_ctrl_qubits, - [theta, lam], - None, - num_ctrl_qubits, - ctrl_state=ctrl_state, - base_gate=U2Gate(theta, lam), - ) - - -class MCU3Gate(ControlledGate): - """mcu3 gate""" - - def __init__(self, theta, lam, phi, num_ctrl_qubits, ctrl_state=None): - super().__init__( - "mcu3", - 1 + num_ctrl_qubits, - [theta, phi, lam], - None, - num_ctrl_qubits, - ctrl_state=ctrl_state, - base_gate=CU3Gate(theta, phi, lam), - ) - - -class MCUGate(ControlledGate): - """mcu gate""" - - def __init__(self, theta, lam, phi, num_ctrl_qubits, ctrl_state=None): - super().__init__( - "mcu", - 1 + num_ctrl_qubits, - [theta, phi, lam], - None, - num_ctrl_qubits, - ctrl_state=ctrl_state, - base_gate=CU3Gate(theta, phi, lam), - ) - - -class MCSwapGate(ControlledGate): - """mcswap gate""" - - def __init__(self, num_ctrl_qubits, ctrl_state=None): - super().__init__( - "mcswap", - 2 + num_ctrl_qubits, - [], - None, - num_ctrl_qubits, - ctrl_state=ctrl_state, - base_gate=CSwapGate(), - ) - - -PHI = Parameter("phi") -LAM = Parameter("lam") -NAME_MAPPING = { - "cu2": U2Gate(PHI, LAM).control(), - "pauli": PauliGate, - "diagonal": DiagonalGate, - "unitary": UnitaryGate, - "mcsx": MCSXGate, - "mcp": MCPhaseGate, - "mcphase": MCPhaseGate, - "mcu": MCUGate, - "mcu1": MCU1Gate, - "mcu2": MCU2Gate, - "mcu3": MCU3Gate, - "mcx": MCXGate, - "mcy": MCYGate, - "mcz": MCZGate, - "mcr": MCRGate, - "mcrx": MCRXGate, - "mcry": MCRYGate, - "mcrz": MCRZGate, - "mcx_gray": MCXGrayCode, - "mcswap": MCSwapGate, - "multiplexer": UCGate, - "kraus": Kraus, - "superop": SuperOp, - "initialize": Initialize, - "quantum_channel": QuantumChannel, - "save_expval": SaveExpectationValue, - "save_amplitudes": SaveAmplitudes, - "roerror": ReadoutError, - "save_statevector_dict": SaveStatevectorDict, - "save_superop": SaveSuperOp, - "save_clifford": SaveClifford, - "save_matrix_product_state": SaveMatrixProductState, - "save_density_matrix": SaveDensityMatrix, - "save_probabilities": SaveProbabilities, - "if_else": IfElseOp, - "while_loop": WhileLoopOp, - "for_loop": ForLoopOp, - "switch_case": SwitchCaseOp, - "break_loop": BreakLoopOp, - "continue_loop": ContinueLoopOp, - "save_statevector": SaveStatevector, - "set_density_matrix": SetDensityMatrix, - "qerror_loc": QuantumErrorLocation, - "set_unitary": SetUnitary, - "save_state": SaveState, - "set_matrix_product_state": SetMatrixProductState, - "save_unitary": SaveUnitary, - "set_superop": SetSuperOp, - "save_expval_var": SaveExpectationValueVariance, - "save_stabilizer": SaveStabilizer, - "set_statevector": SetStatevector, - "set_stabilizer": SetStabilizer, - "save_amplitudes_sq": SaveAmplitudesSquared, - "save_probabilities_dict": SaveProbabilitiesDict, - "save_probs_ket": SaveProbabilitiesDict, - "save_probs": SaveProbabilities, - "reset": Reset(), -} diff --git a/qiskit_aer/backends/plugin/__init__.py b/qiskit_aer/backends/plugin/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/qiskit_aer/backends/plugin/aer_backend_plugin.py b/qiskit_aer/backends/plugin/aer_backend_plugin.py deleted file mode 100644 index 73be26fcef..0000000000 --- a/qiskit_aer/backends/plugin/aer_backend_plugin.py +++ /dev/null @@ -1,126 +0,0 @@ -# This code is part of Qiskit. -# -# (C) Copyright IBM 2018, 2019. -# -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. -""" -Aer simulator backend transpiler plug-in -""" -from qiskit.transpiler.preset_passmanagers.plugin import PassManagerStagePlugin -from qiskit.transpiler import PassManager, TransformationPass -from qiskit.transpiler.passes import BasisTranslator -from qiskit.transpiler.passes import UnitarySynthesis -from qiskit.transpiler.passes import HighLevelSynthesis -from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel -from qiskit.circuit.library.standard_gates import get_standard_gate_name_mapping -from qiskit.circuit.measure import Measure -from qiskit.circuit.library import Barrier -from qiskit.circuit import ControlFlowOp -from qiskit.converters import circuit_to_dag -from qiskit_aer.backends.name_mapping import NAME_MAPPING - - -class AerBackendRebuildGateSetsFromCircuit(TransformationPass): - """custom translation class to rebuild basis gates with gates in circuit""" - - def __init__(self, config, opt_lvl): - super().__init__() - self.config = config - if opt_lvl is None: - self.optimization_level = 1 - else: - self.optimization_level = opt_lvl - self.qiskit_inst_name_map = get_standard_gate_name_mapping() - self.qiskit_inst_name_map["barrier"] = Barrier - - def _add_ops(self, dag, ops: set): - num_unsupported_ops = 0 - opnodes = dag.op_nodes() - if opnodes is None: - return num_unsupported_ops - - for node in opnodes: - if isinstance(node.op, ControlFlowOp): - for block in node.op.blocks: - num_unsupported_ops += self._add_ops(circuit_to_dag(block), ops) - if node.name in self.qiskit_inst_name_map: - ops.add(node.name) - elif node.name in self.config.target: - ops.add(node.name) - else: - num_unsupported_ops = num_unsupported_ops + 1 - return num_unsupported_ops - - def run(self, dag): - # do nothing for higher optimization level - if self.optimization_level > 1: - return dag - if self.config is None or self.config.target is None: - return dag - - # search ops in supported name mapping - ops = set() - num_unsupported_ops = self._add_ops(dag, ops) - - # if there are some unsupported node (i.e. RealAmplitudes) do nothing - if num_unsupported_ops > 0 or len(ops) < 1: - return dag - - # clear all instructions in target - self.config.target._gate_map.clear() - self.config.target._gate_name_map.clear() - self.config.target._qarg_gate_map.clear() - self.config.target._global_operations.clear() - - # rebuild gate sets from circuit - for name in ops: - if name in self.qiskit_inst_name_map: - self.config.target.add_instruction(self.qiskit_inst_name_map[name], name=name) - else: - self.config.target.add_instruction(NAME_MAPPING[name], name=name) - if "measure" not in ops: - self.config.target.add_instruction(Measure()) - self.config.basis_gates = list(self.config.target.operation_names) - - return dag - - -# This plugin should not be used outside of simulator -# TODO : this plugin should be moved to optimization stage plugin -# if Qiskit will have custom optimizaiton stage plugin interface -# in that case just return pass without Optimize1qGatesDecomposition -class AerBackendPlugin(PassManagerStagePlugin): - """custom passmanager to avoid unnecessary gate changes""" - - def pass_manager(self, pass_manager_config, optimization_level=None) -> PassManager: - return PassManager( - [ - UnitarySynthesis( - pass_manager_config.basis_gates, - approximation_degree=pass_manager_config.approximation_degree, - coupling_map=pass_manager_config.coupling_map, - backend_props=pass_manager_config.backend_properties, - plugin_config=pass_manager_config.unitary_synthesis_plugin_config, - method=pass_manager_config.unitary_synthesis_method, - target=pass_manager_config.target, - ), - HighLevelSynthesis( - hls_config=pass_manager_config.hls_config, - coupling_map=pass_manager_config.coupling_map, - target=pass_manager_config.target, - use_qubit_indices=True, - equivalence_library=sel, - basis_gates=pass_manager_config.basis_gates, - ), - BasisTranslator(sel, pass_manager_config.basis_gates, pass_manager_config.target), - AerBackendRebuildGateSetsFromCircuit( - config=pass_manager_config, opt_lvl=optimization_level - ), - ] - ) diff --git a/qiskit_aer/backends/qasm_simulator.py b/qiskit_aer/backends/qasm_simulator.py index a36731403a..1901fa066f 100644 --- a/qiskit_aer/backends/qasm_simulator.py +++ b/qiskit_aer/backends/qasm_simulator.py @@ -10,7 +10,7 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. """ -Aer qasm simulator backend. +Qiskit Aer qasm simulator backend. """ import copy @@ -33,7 +33,7 @@ map_legacy_method_config, ) -# pylint: disable=import-error, no-name-in-module, abstract-method +# pylint: disable=import-error, no-name-in-module from .controller_wrappers import aer_controller_execute logger = logging.getLogger(__name__) @@ -388,7 +388,6 @@ class QasmSimulator(AerBackend): "set_statevector", "set_density_matrix", "set_stabilizer", - "reset", ] ) @@ -444,6 +443,7 @@ def __init__(self, configuration=None, properties=None, provider=None, **backend # Update available methods for class if QasmSimulator._AVAILABLE_METHODS is None: QasmSimulator._AVAILABLE_METHODS = available_methods( + self._controller, QasmSimulator._SIMULATION_METHODS, QasmSimulator._SIMULATION_DEVICES, ) @@ -527,7 +527,6 @@ def _default_options(cls): chop_threshold=1e-8, mps_parallel_threshold=14, mps_omp_threads=1, - mps_lapack=False, ) @classmethod diff --git a/qiskit_aer/backends/statevector_simulator.py b/qiskit_aer/backends/statevector_simulator.py index 9c2b67a87d..e7affcf1c7 100644 --- a/qiskit_aer/backends/statevector_simulator.py +++ b/qiskit_aer/backends/statevector_simulator.py @@ -10,14 +10,13 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. """ -Aer statevector simulator backend. +Qiskit Aer statevector simulator backend. """ import copy import logging from warnings import warn - -import psutil +from qiskit.utils import local_hardware_info from qiskit.providers.options import Options from qiskit.providers.models import QasmBackendConfiguration @@ -36,7 +35,7 @@ add_final_save_op, ) -# pylint: disable=import-error, no-name-in-module, abstract-method +# pylint: disable=import-error, no-name-in-module from .controller_wrappers import aer_controller_execute # Logger @@ -231,7 +230,6 @@ class StatevectorSimulator(AerBackend): "save_amplitudes_sq", "save_state", "set_statevector", - "reset", ] ), "gates": [], @@ -254,7 +252,9 @@ def __init__(self, configuration=None, properties=None, provider=None, **backend self._controller = aer_controller_execute() if StatevectorSimulator._AVAILABLE_DEVICES is None: - StatevectorSimulator._AVAILABLE_DEVICES = available_devices(self._controller) + StatevectorSimulator._AVAILABLE_DEVICES = available_devices( + self._controller, StatevectorSimulator._SIMULATION_DEVICES + ) if configuration is None: configuration = QasmBackendConfiguration.from_dict( @@ -354,7 +354,7 @@ def _validate(self, qobj): 1. Set shots=1. 2. Check number of qubits will fit in local memory. """ - name = self.name + name = self.name() if getattr(qobj.config, "noise_model", None) is not None: raise AerError(f"{name} does not support noise.") @@ -363,7 +363,7 @@ def _validate(self, qobj): if n_qubits > max_qubits: raise AerError( f"Number of qubits ({n_qubits}) is greater than max ({max_qubits}) " - f'for "{name}" with {int(psutil.virtual_memory().total / (1024**3))} GB system memory.' + f'for "{name}" with {int(local_hardware_info()["memory"])} GB system memory.' ) if qobj.config.shots != 1: diff --git a/qiskit_aer/backends/unitary_simulator.py b/qiskit_aer/backends/unitary_simulator.py index ef1337173c..190a3eb508 100644 --- a/qiskit_aer/backends/unitary_simulator.py +++ b/qiskit_aer/backends/unitary_simulator.py @@ -12,13 +12,12 @@ # pylint: disable=invalid-name """ -Aer Unitary Simulator Backend. +Qiskit Aer Unitary Simulator Backend. """ import copy import logging from warnings import warn - -import psutil +from qiskit.utils import local_hardware_info from qiskit.providers.options import Options from qiskit.providers.models import QasmBackendConfiguration @@ -37,7 +36,7 @@ map_legacy_method_config, ) -# pylint: disable=import-error, no-name-in-module, abstract-method +# pylint: disable=import-error, no-name-in-module from .controller_wrappers import aer_controller_execute # Logger @@ -219,7 +218,7 @@ class UnitarySimulator(AerBackend): "pauli", ] ), - "custom_instructions": sorted(["save_unitary", "save_state", "set_unitary", "reset"]), + "custom_instructions": sorted(["save_unitary", "save_state", "set_unitary"]), "gates": [], } @@ -240,7 +239,9 @@ def __init__(self, configuration=None, properties=None, provider=None, **backend self._controller = aer_controller_execute() if UnitarySimulator._AVAILABLE_DEVICES is None: - UnitarySimulator._AVAILABLE_DEVICES = available_devices(self._controller) + UnitarySimulator._AVAILABLE_DEVICES = available_devices( + self._controller, UnitarySimulator._SIMULATION_DEVICES + ) if configuration is None: configuration = QasmBackendConfiguration.from_dict( @@ -340,7 +341,7 @@ def _validate(self, qobj): 2. No measurements or reset 3. Check number of qubits will fit in local memory. """ - name = self.name + name = self.name() if getattr(qobj.config, "noise_model", None) is not None: raise AerError(f"{name} does not support noise.") @@ -350,7 +351,7 @@ def _validate(self, qobj): raise AerError( f"Number of qubits ({n_qubits}) is greater than " f'max ({max_qubits}) for "{name}" with ' - f"{int(psutil.virtual_memory().total / (1024**3))} GB system memory." + f"{int(local_hardware_info()['memory'])} GB system memory." ) if qobj.config.shots != 1: logger.info('"%s" only supports 1 shot. Setting shots=1.', name) diff --git a/qiskit_aer/backends/wrappers/CMakeLists.txt b/qiskit_aer/backends/wrappers/CMakeLists.txt index c20917fc9e..0430fc42d2 100644 --- a/qiskit_aer/backends/wrappers/CMakeLists.txt +++ b/qiskit_aer/backends/wrappers/CMakeLists.txt @@ -38,20 +38,6 @@ if(AER_THRUST_BACKEND STREQUAL "CUDA") nvcc_add_compiler_options(${AER_COMPILER_FLAGS_STRIPPED} AER_COMPILER_FLAGS_OUT) set_target_properties(controller_wrappers PROPERTIES COMPILE_FLAGS "${AER_COMPILER_FLAGS_OUT}") enable_language(CUDA) -elseif(AER_THRUST_BACKEND STREQUAL "ROCM") - - if(NOT DEFINED SIMD_SOURCE_FILE) - message(FATAL_ERROR "ROCm supported target machines are expected to be SIMD-enabled.") - endif() - - set_source_files_properties( - bindings.cc - ${SIMD_SOURCE_FILE} - PROPERTIES LANGUAGE CXX) - - target_compile_options(controller_wrappers PRIVATE ${ROCM_EXTRA_FLAGS} ${SIMD_FLAGS_LIST}) - target_compile_definitions(controller_wrappers PRIVATE ${ROCM_EXTRA_DEFS} ${AER_COMPILER_DEFINITIONS}) - set_target_properties(controller_wrappers PROPERTIES COMPILE_FLAGS "${AER_COMPILER_FLAGS}") else() if(DEFINED SIMD_SOURCE_FILE) string(REPLACE ";" " " SIMD_FLAGS "${SIMD_FLAGS_LIST}") diff --git a/qiskit_aer/backends/wrappers/aer_circuit_binding.hpp b/qiskit_aer/backends/wrappers/aer_circuit_binding.hpp index 943f579693..12f3eeba5a 100644 --- a/qiskit_aer/backends/wrappers/aer_circuit_binding.hpp +++ b/qiskit_aer/backends/wrappers/aer_circuit_binding.hpp @@ -40,100 +40,6 @@ using namespace AER; template void bind_aer_circuit(MODULE m) { - - py::enum_(m, "AerUnaryOp", py::arithmetic()) - .value("BitNot", Operations::UnaryOp::BitNot) - .value("LogicNot", Operations::UnaryOp::LogicNot) - .export_values(); - - py::enum_(m, "AerBinaryOp", py::arithmetic()) - .value("BitAnd", Operations::BinaryOp::BitAnd) - .value("BitOr", Operations::BinaryOp::BitOr) - .value("BitXor", Operations::BinaryOp::BitXor) - .value("LogicAnd", Operations::BinaryOp::LogicAnd) - .value("LogicOr", Operations::BinaryOp::LogicOr) - .value("Equal", Operations::BinaryOp::Equal) - .value("NotEqual", Operations::BinaryOp::NotEqual) - .value("Less", Operations::BinaryOp::Less) - .value("LessEqual", Operations::BinaryOp::LessEqual) - .value("Greater", Operations::BinaryOp::Greater) - .value("GreaterEqual", Operations::BinaryOp::GreaterEqual) - .export_values(); - - py::class_> - aer_scalar_type(m, "AerScalarType"); - - py::class_> - aer_uint(m, "AerUint"); - aer_uint.def( - py::init([](const uint_t width) { return new Operations::Uint(width); })); - - py::class_> - aer_bool(m, "AerBool"); - aer_bool.def(py::init([]() { return new Operations::Bool(); })); - - py::class_> aer_expr( - m, "AerExpr"); - - aer_expr.def("eval_bool", &Operations::CExpr::eval_bool); - aer_expr.def("eval_uint", &Operations::CExpr::eval_uint); - - py::class_> - aer_cast_expr(m, "AerCast"); - aer_cast_expr.def( - py::init([](const std::shared_ptr type, - const std::shared_ptr expr) { - return new Operations::CastExpr(type, expr); - })); - - py::class_> - aer_var_expr(m, "AerVar"); - aer_var_expr.def( - py::init([](const std::shared_ptr type, - const std::vector cbit_idxs) { - return new Operations::VarExpr(type, cbit_idxs); - })); - - py::class_> - aer_val_expr(m, "AerValue"); - - py::class_> - aer_uint_expr(m, "AerUintValue"); - aer_uint_expr.def(py::init([](const size_t width, const uint_t val) { - return new Operations::UintValue(width, val); - })); - - py::class_> - aer_bool_expr(m, "AerBoolValue"); - aer_bool_expr.def( - py::init([](const bool val) { return new Operations::BoolValue(val); })); - - py::class_> - aer_unary_expr(m, "AerUnaryExpr"); - aer_unary_expr.def( - py::init([](const Operations::UnaryOp op, - const std::shared_ptr expr) { - return new Operations::UnaryExpr(op, expr); - })); - - py::class_> - aer_binary_expr(m, "AerBinaryExpr"); - aer_binary_expr.def( - py::init([](const Operations::BinaryOp op, - const std::shared_ptr left, - const std::shared_ptr right) { - return new Operations::BinaryExpr(op, left, right); - })); - py::class_> aer_circuit(m, "AerCircuit"); aer_circuit.def(py::init()); aer_circuit.def("__repr__", [](const Circuit &circ) { @@ -143,7 +49,7 @@ void bind_aer_circuit(MODULE m) { << ", num_registers=" << circ.num_registers; ss << ", ops={"; - for (uint_t i = 0; i < circ.ops.size(); ++i) + for (auto i = 0; i < circ.ops.size(); ++i) if (i == 0) ss << circ.ops[i]; else diff --git a/qiskit_aer/backends/wrappers/aer_controller_binding.hpp b/qiskit_aer/backends/wrappers/aer_controller_binding.hpp index ea3b48dfae..67e057c74f 100644 --- a/qiskit_aer/backends/wrappers/aer_controller_binding.hpp +++ b/qiskit_aer/backends/wrappers/aer_controller_binding.hpp @@ -56,11 +56,6 @@ class ControllerExecutor { return AerToPy::to_python( controller_execute(circuits, noise_model, config)); } - - py::object available_devices() { - T controller; - return AerToPy::to_python(controller.available_devices()); - } }; template @@ -105,11 +100,6 @@ void bind_aer_controller(MODULE m) { return self.execute(circuits, noise_model_native, config); }); - aer_ctrl.def("available_devices", - [aer_ctrl](ControllerExecutor &self) { - return self.available_devices(); - }); - py::class_ aer_config(m, "AerConfig"); aer_config.def(py::init()); aer_config.def_readwrite("shots", &Config::shots); @@ -242,7 +232,6 @@ void bind_aer_controller(MODULE m) { aer_config.def_readwrite("mps_parallel_threshold", &Config::mps_parallel_threshold); aer_config.def_readwrite("mps_omp_threads", &Config::mps_omp_threads); - aer_config.def_readwrite("mps_lapack", &Config::mps_lapack); // # tensor network options aer_config.def_readwrite("tensor_network_num_sampling_qubits", &Config::tensor_network_num_sampling_qubits); @@ -423,14 +412,6 @@ void bind_aer_controller(MODULE m) { "target_gpus", [](const Config &config) { return config.target_gpus.val; }, [](Config &config, reg_t val) { config.target_gpus.value(val); }); - aer_config.def_property( - "runtime_parameter_bind_enable", - [](const Config &config) { - return config.runtime_parameter_bind_enable.val; - }, - [](Config &config, bool val) { - config.runtime_parameter_bind_enable.value(val); - }); aer_config.def(py::pickle( [](const AER::Config &config) { @@ -478,7 +459,6 @@ void bind_aer_controller(MODULE m) { write_value(30, config.chop_threshold), write_value(41, config.mps_parallel_threshold), write_value(42, config.mps_omp_threads), - write_value(101, config.mps_lapack), write_value(43, config.tensor_network_num_sampling_qubits), write_value(44, config.use_cuTensorNet_autotuning), write_value(45, config.library_dir), @@ -520,12 +500,11 @@ void bind_aer_controller(MODULE m) { 79, config.extended_stabilizer_norm_estimation_default_samples), write_value(80, config.shot_branching_enable), write_value(81, config.shot_branching_sampling_enable), - write_value(82, config.target_gpus), - write_value(83, config.runtime_parameter_bind_enable)); + write_value(82, config.target_gpus)); }, [](py::tuple t) { AER::Config config; - if (t.size() != 84) + if (t.size() != 82) throw std::runtime_error("Invalid serialization format."); read_value(t, 0, config.shots); @@ -573,7 +552,6 @@ void bind_aer_controller(MODULE m) { read_value(t, 30, config.chop_threshold); read_value(t, 41, config.mps_parallel_threshold); read_value(t, 42, config.mps_omp_threads); - read_value(t, 101, config.mps_lapack); read_value(t, 43, config.tensor_network_num_sampling_qubits); read_value(t, 44, config.use_cuTensorNet_autotuning); read_value(t, 45, config.library_dir); @@ -616,7 +594,6 @@ void bind_aer_controller(MODULE m) { read_value(t, 80, config.shot_branching_enable); read_value(t, 81, config.shot_branching_sampling_enable); read_value(t, 82, config.target_gpus); - read_value(t, 83, config.runtime_parameter_bind_enable); return config; })); } diff --git a/qiskit_aer/backends/wrappers/aer_state_binding.hpp b/qiskit_aer/backends/wrappers/aer_state_binding.hpp index c3dd880bf4..45dd55bcbf 100644 --- a/qiskit_aer/backends/wrappers/aer_state_binding.hpp +++ b/qiskit_aer/backends/wrappers/aer_state_binding.hpp @@ -130,8 +130,8 @@ void bind_aer_state(MODULE m) { size_t mat_len = (1UL << qubits.size()); auto ptr = values.unchecked<2>(); cmatrix_t mat(mat_len, mat_len); - for (uint_t i = 0; i < mat_len; ++i) - for (uint_t j = 0; j < mat_len; ++j) + for (auto i = 0; i < mat_len; ++i) + for (auto j = 0; j < mat_len; ++j) mat(i, j) = ptr(i, j); state.apply_unitary(qubits, mat); }); @@ -144,10 +144,10 @@ void bind_aer_state(MODULE m) { size_t mat_size = (1UL << control_qubits.size()); auto ptr = values.unchecked<3>(); std::vector mats; - for (uint_t i = 0; i < mat_size; ++i) { + for (auto i = 0; i < mat_size; ++i) { cmatrix_t mat(mat_len, mat_len); - for (uint_t j = 0; j < mat_len; ++j) - for (uint_t k = 0; k < mat_len; ++k) + for (auto j = 0; j < mat_len; ++j) + for (auto k = 0; k < mat_len; ++k) mat(j, k) = ptr(i, j, k); mats.push_back(mat); } diff --git a/qiskit_aer/jobs/aerjob.py b/qiskit_aer/jobs/aerjob.py index c457a60e67..7f309a51a5 100644 --- a/qiskit_aer/jobs/aerjob.py +++ b/qiskit_aer/jobs/aerjob.py @@ -25,7 +25,7 @@ class AerJob(Job): - """AerJob class for Aer Simulators.""" + """AerJob class for Qiskit Aer Simulators.""" def __init__( self, diff --git a/qiskit_aer/jobs/aerjobset.py b/qiskit_aer/jobs/aerjobset.py index f9fcce866c..ce3d3d6229 100644 --- a/qiskit_aer/jobs/aerjobset.py +++ b/qiskit_aer/jobs/aerjobset.py @@ -37,7 +37,7 @@ class AerJobSet(Job): - """A set of :class:`~AerJob` classes for Aer simulators. + """A set of :class:`~AerJob` classes for Qiskit Aer simulators. An instance of this class is returned when you submit experiments with executor option. It provides methods that allow you to interact diff --git a/qiskit_aer/library/control_flow_instructions/jump.py b/qiskit_aer/library/control_flow_instructions/jump.py index af411edf54..2239e17a8a 100644 --- a/qiskit_aer/library/control_flow_instructions/jump.py +++ b/qiskit_aer/library/control_flow_instructions/jump.py @@ -14,7 +14,6 @@ """ from qiskit.circuit import Instruction -from qiskit.circuit.classical.expr import Expr class AerJump(Instruction): @@ -28,19 +27,3 @@ class AerJump(Instruction): def __init__(self, jump_to, num_qubits, num_clbits=0): super().__init__("jump", num_qubits, num_clbits, [jump_to]) - self.condition_expr = None - - def set_conditional(self, cond): - """Set condition to perform this jump instruction. - - Args: - cond (Expr or tuple): `Expr` to call `eval_bool` or tuple for `c_if` - - Returns: - AerJump: jump instruction added specified condition - """ - if isinstance(cond, Expr): - self.condition_expr = cond - else: - self.c_if(*cond) - return self diff --git a/qiskit_aer/library/default_qubits.py b/qiskit_aer/library/default_qubits.py index 971a8cc0d9..bc446e73f9 100644 --- a/qiskit_aer/library/default_qubits.py +++ b/qiskit_aer/library/default_qubits.py @@ -14,6 +14,7 @@ """ from qiskit.circuit import QuantumRegister +from qiskit.extensions.exceptions import ExtensionError def default_qubits(circuit, qubits=None): @@ -26,7 +27,7 @@ def default_qubits(circuit, qubits=None): [Default: None] Raises: - ValueError: if default qubits fails. + ExtensionError: if default qubits fails. Returns: list: qubits list. @@ -36,9 +37,9 @@ def default_qubits(circuit, qubits=None): # This is needed for full register snapshots like statevector if isinstance(qubits, QuantumRegister): qubits = qubits[:] - if qubits is None: + if not qubits: qubits = list(circuit.qubits) if len(qubits) == 0: - raise ValueError("no qubits for snapshot") + raise ExtensionError("no qubits for snapshot") return qubits diff --git a/qiskit_aer/library/save_instructions/save_amplitudes.py b/qiskit_aer/library/save_instructions/save_amplitudes.py index 5d01945fba..bcc12383d1 100644 --- a/qiskit_aer/library/save_instructions/save_amplitudes.py +++ b/qiskit_aer/library/save_instructions/save_amplitudes.py @@ -14,6 +14,7 @@ """ from qiskit.circuit import QuantumCircuit +from qiskit.extensions.exceptions import ExtensionError from .save_data import SaveSingleData, SaveAverageData from ..default_qubits import default_qubits @@ -36,7 +37,7 @@ def __init__(self, num_qubits, params, label="amplitudes", pershot=False, condit [Default: False]. Raises: - ValueError: if params is invalid for the specified number of qubits. + ExtensionError: if params is invalid for the specified number of qubits. """ params = _format_amplitude_params(params, num_qubits) super().__init__( @@ -77,7 +78,7 @@ def __init__( [Default: False]. Raises: - ValueError: if params is invalid for the specified number of qubits. + ExtensionError: if params is invalid for the specified number of qubits. """ params = _format_amplitude_params(params, num_qubits) super().__init__( @@ -108,7 +109,7 @@ def save_amplitudes(self, params, label="amplitudes", pershot=False, conditional QuantumCircuit: with attached instruction. Raises: - ValueError: if params is invalid for the specified number of qubits. + ExtensionError: if params is invalid for the specified number of qubits. """ qubits = default_qubits(self) instr = SaveAmplitudes( @@ -138,7 +139,7 @@ def save_amplitudes_squared( QuantumCircuit: with attached instruction. Raises: - ValueError: if params is invalid for the specified number of qubits. + ExtensionError: if params is invalid for the specified number of qubits. """ qubits = default_qubits(self) instr = SaveAmplitudesSquared( @@ -160,7 +161,7 @@ def _format_amplitude_params(params, num_qubits=None): else: params = [int(i, 2) for i in params] if num_qubits and max(params) >= 2**num_qubits: - raise ValueError("Param values contain a state larger than the number of qubits") + raise ExtensionError("Param values contain a state larger than the number of qubits") return params diff --git a/qiskit_aer/library/save_instructions/save_data.py b/qiskit_aer/library/save_instructions/save_data.py index a98e88e12f..cb86edd94e 100644 --- a/qiskit_aer/library/save_instructions/save_data.py +++ b/qiskit_aer/library/save_instructions/save_data.py @@ -16,6 +16,7 @@ import copy from qiskit.circuit import Instruction +from qiskit.extensions.exceptions import ExtensionError class SaveData(Instruction): @@ -38,17 +39,19 @@ def __init__(self, name, num_qubits, label, subtype="single", params=None): [Default: None]. Raises: - TypeError: if the subtype string is invalid. + ExtensionError: if the subtype string is invalid. Additional Information: The supported subtypes are 'single', 'list', 'c_list', 'average', 'c_average', 'accum', 'c_accum'. """ if subtype not in self._allowed_subtypes: - raise TypeError("Invalid data subtype for SaveData instruction.") + raise ExtensionError("Invalid data subtype for SaveData instruction.") if not isinstance(label, str): - raise TypeError(f"Invalid label for save data instruction, {label} must be a string.") + raise ExtensionError( + f"Invalid label for save data instruction, {label} must be a string." + ) if params is None: params = {} diff --git a/qiskit_aer/library/save_instructions/save_expectation_value.py b/qiskit_aer/library/save_instructions/save_expectation_value.py index c3e4f8f6ab..27bcad9da0 100644 --- a/qiskit_aer/library/save_instructions/save_expectation_value.py +++ b/qiskit_aer/library/save_instructions/save_expectation_value.py @@ -16,6 +16,7 @@ from numpy import allclose from qiskit.quantum_info import Pauli, SparsePauliOp, Operator from qiskit.circuit import QuantumCircuit +from qiskit.extensions.exceptions import ExtensionError from .save_data import SaveAverageData @@ -50,8 +51,7 @@ def __init__( values [Default: False]. Raises: - ValueError: if the input operator is not Hermitian. - TypeError: if the input operator is of invalid type. + ExtensionError: if the input operator is invalid or not Hermitian. .. note:: @@ -64,7 +64,7 @@ def __init__( elif not isinstance(operator, SparsePauliOp): operator = SparsePauliOp.from_operator(Operator(operator)) if not allclose(operator.coeffs.imag, 0): - raise ValueError("Input operator is not Hermitian.") + raise ExtensionError("Input operator is not Hermitian.") params = _expval_params(operator, variance=False) super().__init__( "save_expval", @@ -109,8 +109,7 @@ def __init__( values [Default: False]. Raises: - ValueError: if the input operator is not Hermitian. - TypeError: if the input operator is of invalid type. + ExtensionError: if the input operator is invalid or not Hermitian. .. note:: @@ -123,7 +122,7 @@ def __init__( elif not isinstance(operator, SparsePauliOp): operator = SparsePauliOp.from_operator(Operator(operator)) if not allclose(operator.coeffs.imag, 0): - raise ValueError("Input operator is not Hermitian.") + raise ExtensionError("Input operator is not Hermitian.") params = _expval_params(operator, variance=True) super().__init__( "save_expval_var", @@ -143,7 +142,7 @@ def _expval_params(operator, variance=False): elif not isinstance(operator, SparsePauliOp): operator = SparsePauliOp.from_operator(Operator(operator)) if not isinstance(operator, SparsePauliOp): - raise TypeError("Invalid input operator") + raise ExtensionError("Invalid input operator") params = {} @@ -197,8 +196,7 @@ def save_expectation_value( QuantumCircuit: with attached instruction. Raises: - ValueError: if the input operator is not Hermitian. - TypeError: if the input operator is of invalid type. + ExtensionError: if the input operator is invalid or not Hermitian. .. note:: @@ -239,8 +237,7 @@ def save_expectation_value_variance( QuantumCircuit: with attached instruction. Raises: - ValueError: if the input operator is not Hermitian. - TypeError: if the input operator is of invalid type. + ExtensionError: if the input operator is invalid or not Hermitian. .. note:: diff --git a/qiskit_aer/library/set_instructions/set_density_matrix.py b/qiskit_aer/library/set_instructions/set_density_matrix.py index eb3afbf68d..08b013e1aa 100644 --- a/qiskit_aer/library/set_instructions/set_density_matrix.py +++ b/qiskit_aer/library/set_instructions/set_density_matrix.py @@ -14,6 +14,7 @@ """ from qiskit.circuit import QuantumCircuit, Instruction +from qiskit.extensions.exceptions import ExtensionError from qiskit.quantum_info import DensityMatrix from ..default_qubits import default_qubits @@ -30,7 +31,7 @@ def __init__(self, state): state (DensityMatrix): a density matrix. Raises: - ValueError: if the input density matrix is not valid. + ExtensionError: if the input density matrix is not valid. .. note:: @@ -41,7 +42,7 @@ def __init__(self, state): if not isinstance(state, DensityMatrix): state = DensityMatrix(state) if not state.num_qubits or not state.is_valid(): - raise ValueError("The input state is not valid") + raise ExtensionError("The input state is not valid") super().__init__("set_density_matrix", state.num_qubits, 0, [state.data]) @@ -55,8 +56,8 @@ def set_density_matrix(self, state): QuantumCircuit: with attached instruction. Raises: - ValueError: If the density matrix is the incorrect size for the - current circuit. + ExtensionError: If the density matrix is the incorrect size for the + current circuit. .. note: @@ -66,7 +67,7 @@ def set_density_matrix(self, state): if not isinstance(state, DensityMatrix): state = DensityMatrix(state) if not state.num_qubits or state.num_qubits != len(qubits): - raise ValueError( + raise ExtensionError( "The size of the density matrix for the set state" " instruction must be equal to the number of qubits" f" in the circuit (state.num_qubits ({state.num_qubits})" diff --git a/qiskit_aer/library/set_instructions/set_matrix_product_state.py b/qiskit_aer/library/set_instructions/set_matrix_product_state.py index fcd50e0dd3..1546c842f1 100644 --- a/qiskit_aer/library/set_instructions/set_matrix_product_state.py +++ b/qiskit_aer/library/set_instructions/set_matrix_product_state.py @@ -14,6 +14,7 @@ """ from qiskit.circuit import QuantumCircuit, Instruction +from qiskit.extensions.exceptions import ExtensionError from ..default_qubits import default_qubits @@ -51,7 +52,7 @@ def set_matrix_product_state(self, state): QuantumCircuit: with attached instruction. Raises: - ValueError: If the structure of the state is incorrect + ExtensionError: If the structure of the state is incorrect .. note: @@ -59,21 +60,21 @@ def set_matrix_product_state(self, state): """ qubits = default_qubits(self) if not isinstance(state, tuple) or len(state) != 2: - raise ValueError( + raise ExtensionError( "The input matrix product state is not valid. Should be a list of 2 elements" ) if not isinstance(state[0], list) or not isinstance(state[1], list): - raise ValueError( + raise ExtensionError( "The first element of the input matrix product state is not valid. Should be a list." ) if len(state[0]) != len(state[1]) + 1: - raise ValueError( + raise ExtensionError( "The input matrix product state is not valid. " "Length of q_reg vector should be 1 more than length of lambda_reg" ) for elem in state[0]: if not isinstance(elem, tuple) or len(elem) != 2: - raise ValueError( + raise ExtensionError( "The input matrix product state is not valid." "The first element should be a list of length 2" ) diff --git a/qiskit_aer/library/set_instructions/set_stabilizer.py b/qiskit_aer/library/set_instructions/set_stabilizer.py index 60400f4586..7767560f41 100644 --- a/qiskit_aer/library/set_instructions/set_stabilizer.py +++ b/qiskit_aer/library/set_instructions/set_stabilizer.py @@ -14,6 +14,7 @@ """ from qiskit.circuit import QuantumCircuit, Instruction +from qiskit.extensions.exceptions import ExtensionError from qiskit.quantum_info import StabilizerState, Clifford from ..default_qubits import default_qubits @@ -52,8 +53,8 @@ def set_stabilizer(self, state): QuantumCircuit: with attached instruction. Raises: - ValueError: If the state is the incorrect size for the - current circuit. + ExtensionError: If the state is the incorrect size for the + current circuit. .. note: @@ -65,7 +66,7 @@ def set_stabilizer(self, state): if not isinstance(state, Clifford): state = Clifford(state) if state.num_qubits != len(qubits): - raise ValueError( + raise ExtensionError( "The size of the Clifford for the set_stabilizer" " instruction must be equal to the number of qubits" f" in the circuit (state.num_qubits ({state.num_qubits})" diff --git a/qiskit_aer/library/set_instructions/set_statevector.py b/qiskit_aer/library/set_instructions/set_statevector.py index 25671d5e39..25603cecc5 100644 --- a/qiskit_aer/library/set_instructions/set_statevector.py +++ b/qiskit_aer/library/set_instructions/set_statevector.py @@ -14,6 +14,7 @@ """ from qiskit.circuit import QuantumCircuit, Instruction +from qiskit.extensions.exceptions import ExtensionError from qiskit.quantum_info import Statevector from ..default_qubits import default_qubits @@ -30,7 +31,7 @@ def __init__(self, state): state (Statevector): a statevector. Raises: - ValueError: if the input is not a valid state. + ExtensionError: if the input is not a valid state. .. note:: @@ -41,7 +42,7 @@ def __init__(self, state): if not isinstance(state, Statevector): state = Statevector(state) if not state.num_qubits or not state.is_valid(): - raise ValueError("The input statevector is not valid") + raise ExtensionError("The input statevector is not valid") super().__init__("set_statevector", state.num_qubits, 0, [state.data]) @@ -55,8 +56,8 @@ def set_statevector(self, state): QuantumCircuit: with attached instruction. Raises: - ValueError: If the state is the incorrect size for the - current circuit. + ExtensionError: If the state is the incorrect size for the + current circuit. .. note: @@ -66,7 +67,7 @@ def set_statevector(self, state): if not isinstance(state, Statevector): state = Statevector(state) if not state.num_qubits or state.num_qubits != len(qubits): - raise ValueError( + raise ExtensionError( "The size of the statevector for the set_statevector" " instruction must be equal to the number of qubits" f" in the circuit (state.num_qubits ({state.num_qubits})" diff --git a/qiskit_aer/library/set_instructions/set_superop.py b/qiskit_aer/library/set_instructions/set_superop.py index f7e26066d4..0538e5f2dd 100644 --- a/qiskit_aer/library/set_instructions/set_superop.py +++ b/qiskit_aer/library/set_instructions/set_superop.py @@ -14,6 +14,7 @@ """ from qiskit.circuit import QuantumCircuit, Instruction +from qiskit.extensions.exceptions import ExtensionError from qiskit.quantum_info import SuperOp from ..default_qubits import default_qubits @@ -30,7 +31,7 @@ def __init__(self, state): state (QuantumChannel): A CPTP quantum channel. Raises: - ValueError: if the input QuantumChannel is not CPTP. + ExtensionError: if the input QuantumChannel is not CPTP. .. note:: @@ -41,7 +42,7 @@ def __init__(self, state): if not isinstance(state, SuperOp): state = SuperOp(state) if not state.num_qubits or not state.is_cptp(): - raise ValueError("The input quantum channel is not CPTP") + raise ExtensionError("The input quantum channel is not CPTP") super().__init__("set_superop", state.num_qubits, 0, [state.data]) @@ -55,8 +56,9 @@ def set_superop(self, state): QuantumCircuit: with attached instruction. Raises: - ValueError: If the state is the incorrect size for the current circuit. - ValueError: if the input QuantumChannel is not CPTP. + ExtensionError: If the state is the incorrect size for the + current circuit. + ExtensionError: if the input QuantumChannel is not CPTP. .. note: @@ -66,7 +68,7 @@ def set_superop(self, state): if not isinstance(state, SuperOp): state = SuperOp(state) if not state.num_qubits or state.num_qubits != len(qubits): - raise ValueError( + raise ExtensionError( "The size of the quantum channel for the set_superop" " instruction must be equal to the number of qubits" f" in the circuit (state.num_qubits ({state.num_qubits})" diff --git a/qiskit_aer/library/set_instructions/set_unitary.py b/qiskit_aer/library/set_instructions/set_unitary.py index 9c0fa785e6..ab8e261cdc 100644 --- a/qiskit_aer/library/set_instructions/set_unitary.py +++ b/qiskit_aer/library/set_instructions/set_unitary.py @@ -14,6 +14,7 @@ """ from qiskit.circuit import QuantumCircuit, Instruction +from qiskit.extensions.exceptions import ExtensionError from qiskit.quantum_info import Operator from ..default_qubits import default_qubits @@ -30,7 +31,7 @@ def __init__(self, state): state (Operator): A unitary matrix. Raises: - ValueError: if the input matrix is not state. + ExtensionError: if the input matrix is not state. .. note:: @@ -41,7 +42,7 @@ def __init__(self, state): if not isinstance(state, Operator): state = Operator(state) if not state.num_qubits or not state.is_unitary(): - raise ValueError("The input matrix is not unitary") + raise ExtensionError("The input matrix is not unitary") super().__init__("set_unitary", state.num_qubits, 0, [state.data]) @@ -55,8 +56,9 @@ def set_unitary(self, state): QuantumCircuit: with attached instruction. Raises: - ValueError: If the state is the incorrect size for the current circuit. - ValueError: if the input matrix is not unitary. + ExtensionError: If the state is the incorrect size for the + current circuit. + ExtensionError: if the input matrix is not unitary. .. note: @@ -66,7 +68,7 @@ def set_unitary(self, state): if not isinstance(state, Operator): state = Operator(state) if not state.num_qubits or state.num_qubits != len(qubits): - raise ValueError( + raise ExtensionError( "The size of the unitary matrix for the set_unitary" " instruction must be equal to the number of qubits" f" in the circuit (state.num_qubits ({state.num_qubits})" diff --git a/qiskit_aer/noise/device/models.py b/qiskit_aer/noise/device/models.py index adc5927bae..4be3bf7283 100644 --- a/qiskit_aer/noise/device/models.py +++ b/qiskit_aer/noise/device/models.py @@ -171,15 +171,12 @@ def basic_device_gate_errors( ) # Generate custom gate time dict - # Units used in the following computation: ns (time), Hz (frequency), mK (temperature). custom_times = {} relax_params = [] if thermal_relaxation: # If including thermal relaxation errors load - # T1 [ns], T2 [ns], and frequency [GHz] values from properties + # T1, T2, and frequency values from properties relax_params = thermal_relaxation_values(properties) - # Unit conversion: GHz -> Hz - relax_params = [(t1, t2, freq * 1e9) for t1, t2, freq in relax_params] # If we are specifying custom gate times include # them in the custom times dict if gate_lengths: @@ -210,7 +207,7 @@ def basic_device_gate_errors( # Get relaxation error if thermal_relaxation: relax_error = _device_thermal_relaxation_error( - qubits, relax_time, relax_params, temperature + qubits, relax_time, relax_params, temperature, thermal_relaxation ) # Get depolarizing error channel @@ -242,8 +239,6 @@ def _basic_device_target_gate_errors( Note that, in the resulting error list, non-Gate instructions (e.g. Reset) will have no gate errors while they may have thermal relaxation errors. Exceptionally, Measure instruction will have no errors, neither gate errors nor relaxation errors. - - Note: Units in use: Time [s], Frequency [Hz], Temperature [mK] """ errors = [] for op_name, inst_prop_dic in target.items(): @@ -334,14 +329,12 @@ def _device_depolarizing_error(qubits, error_param, relax_error=None): return None -def _device_thermal_relaxation_error(qubits, gate_time, relax_params, temperature): - """Construct a thermal_relaxation_error for device. - - Expected units: frequency in relax_params [Hz], temperature [mK]. - Note that gate_time and T1/T2 in relax_params must be in the same time unit. - """ +def _device_thermal_relaxation_error( + qubits, gate_time, relax_params, temperature, thermal_relaxation=True +): + """Construct a thermal_relaxation_error for device""" # Check trivial case - if gate_time is None or gate_time == 0: + if not thermal_relaxation or gate_time is None or gate_time == 0: return None # Construct a tensor product of single qubit relaxation errors @@ -375,7 +368,7 @@ def _truncate_t2_value(t1, t2): def _excited_population(freq, temperature): - """Return excited state population from freq [Hz] and temperature [mK].""" + """Return excited state population from freq [GHz] and temperature [mK].""" if freq is None or temperature is None: return 0 population = 0 @@ -386,10 +379,10 @@ def _excited_population(freq, temperature): # Boltzman constant kB = 8.617333262e-5 (eV/K) # Planck constant h = 4.135667696e-15 (eV.s) # qubit temperature temperatue = T (mK) - # qubit frequency frequency = f (Hz) - # excited state population = 1/(1+exp((h*f)/(kb*T*1e-3))) + # qubit frequency frequency = f (GHz) + # excited state population = 1/(1+exp((h*f*1e9)/(kb*T*1e-3))) # See e.g. Phys. Rev. Lett. 114, 240501 (2015). - exp_param = exp((47.99243 * 1e-9 * freq) / abs(temperature)) + exp_param = exp((47.99243 * freq) / abs(temperature)) population = 1 / (1 + exp_param) if temperature < 0: # negative temperate implies |1> is thermal ground diff --git a/qiskit_aer/noise/errors/quantum_error.py b/qiskit_aer/noise/errors/quantum_error.py index 3989a5020d..59d65c469f 100644 --- a/qiskit_aer/noise/errors/quantum_error.py +++ b/qiskit_aer/noise/errors/quantum_error.py @@ -10,7 +10,7 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. """ -Quantum error class for Aer noise model +Quantum error class for Qiskit Aer noise model """ import copy import numbers @@ -19,10 +19,10 @@ import numpy as np -from qiskit.circuit import QuantumCircuit, Instruction, QuantumRegister, Reset +from qiskit.circuit import QuantumCircuit, Instruction, QuantumRegister from qiskit.circuit.exceptions import CircuitError -from qiskit.circuit.library.generalized_gates import PauliGate, UnitaryGate -from qiskit.circuit.library.standard_gates import IGate, XGate, YGate, ZGate +from qiskit.circuit.library.generalized_gates import PauliGate +from qiskit.circuit.library.standard_gates import IGate from qiskit.exceptions import QiskitError from qiskit.quantum_info.operators.base_operator import BaseOperator from qiskit.quantum_info.operators.channel import Kraus, SuperOp @@ -35,7 +35,7 @@ class QuantumError(BaseOperator, TolerancesMixin): """ - Quantum error class for Aer noise model + Quantum error class for Qiskit Aer noise model .. warning:: The init interface for this class is not finalized and may @@ -345,63 +345,6 @@ def to_dict(self): } return error - @staticmethod - def from_dict(error): - """Implement current error from a dictionary.""" - # check if dictionary - if not isinstance(error, dict): - raise NoiseError("error is not a dictionary") - # check expected keys "type, id, operations, instructions, probabilities" - if ( - ("type" not in error) - or ("id" not in error) - or ("operations" not in error) - or ("instructions" not in error) - or ("probabilities" not in error) - ): - raise NoiseError("erorr dictionary not containing expected keys") - error_instructions = error["instructions"] - error_probabilities = error["probabilities"] - - if len(error_instructions) != len(error_probabilities): - raise NoiseError("probabilities not matching with instructions") - # parse instructions and turn to noise_ops - noise_ops = [] - for idx, inst in enumerate(error_instructions): - noise_elem = [] - for elem in inst: - inst_name = elem["name"] - inst_qubits = elem["qubits"] - - if inst_name == "x": - noise_elem.append((XGate(), inst_qubits)) - elif inst_name == "id": - noise_elem.append((IGate(), inst_qubits)) - elif inst_name == "y": - noise_elem.append((YGate(), inst_qubits)) - elif inst_name == "z": - noise_elem.append((ZGate(), inst_qubits)) - elif inst_name == "kraus": - if "params" not in inst[0]: - raise NoiseError("kraus does not have a parameter value") - noise_elem.append((Kraus(inst[0]["params"]), inst_qubits)) - elif inst_name == "reset": - noise_elem.append((Reset(), inst_qubits)) - elif inst_name == "measure": - raise NoiseError("instruction 'measure' not supported") - elif inst_name == "unitary": - if "params" not in inst[0]: - raise NoiseError("unitary does not have a parameter value") - noise_elem.append((UnitaryGate(inst[0]["params"][0]), inst_qubits)) - else: - raise NoiseError("error gate for instruction not recognized") - - noise_ops.append((noise_elem, error_probabilities[idx])) - - error_obj = QuantumError(noise_ops) - - return error_obj - def compose(self, other, qargs=None, front=False): if not isinstance(other, QuantumError): other = QuantumError(other) diff --git a/qiskit_aer/noise/errors/readout_error.py b/qiskit_aer/noise/errors/readout_error.py index ef37dcbfc4..8374e6736c 100644 --- a/qiskit_aer/noise/errors/readout_error.py +++ b/qiskit_aer/noise/errors/readout_error.py @@ -10,7 +10,7 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. """ -Readout error class for Aer noise model. +Readout error class for Qiskit Aer noise model. """ import copy @@ -25,7 +25,7 @@ class ReadoutError: """ - Readout error class for Aer noise model. + Readout error class for Qiskit Aer noise model. """ # pylint: disable=invalid-name @@ -348,8 +348,3 @@ def __sub__(self, other): def __neg__(self): raise NotImplementedError("'ReadoutError' does not support negation.") - - @property - def num_qubits(self): - """Return the number of qubits.""" - return self._number_of_qubits diff --git a/qiskit_aer/noise/errors/standard_errors.py b/qiskit_aer/noise/errors/standard_errors.py index 69b182f280..c9d85eddf4 100644 --- a/qiskit_aer/noise/errors/standard_errors.py +++ b/qiskit_aer/noise/errors/standard_errors.py @@ -10,7 +10,7 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. """ -Standard quantum computing error channels for Aer. +Standard quantum computing error channels for Qiskit Aer. """ import itertools as it @@ -19,8 +19,8 @@ from qiskit.circuit import Reset from qiskit.circuit.library.standard_gates import IGate, XGate, ZGate -from qiskit.circuit.library.generalized_gates import UnitaryGate from qiskit.exceptions import QiskitError +from qiskit.extensions import UnitaryGate from qiskit.quantum_info.operators import Pauli from qiskit.quantum_info.operators.channel import Choi, Kraus from qiskit.quantum_info.operators.predicates import is_identity_matrix diff --git a/qiskit_aer/noise/noise_model.py b/qiskit_aer/noise/noise_model.py index 1223b0b8ea..a32fcc2020 100644 --- a/qiskit_aer/noise/noise_model.py +++ b/qiskit_aer/noise/noise_model.py @@ -10,7 +10,7 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. """ -Noise model class for Aer simulators. +Noise model class for Qiskit Aer simulators. """ import copy import json @@ -23,7 +23,8 @@ from qiskit.circuit import Instruction, Delay from qiskit.circuit import QuantumCircuit from qiskit.circuit import Reset -from qiskit.circuit.library.generalized_gates import PauliGate, UnitaryGate +from qiskit.circuit.library.generalized_gates import PauliGate +from qiskit.extensions import UnitaryGate from qiskit.providers import QubitProperties from qiskit.providers.exceptions import BackendPropertyError from qiskit.providers.models import BackendProperties @@ -77,7 +78,7 @@ def __init__(self, qerror): class NoiseModel: - """Noise model class for Aer simulators. + """Noise model class for Qiskit Aer simulators. This class is used to represent noise model for the :class:`~qiskit_aer.QasmSimulator`. It can be used to construct diff --git a/qiskit_aer/noise/noiseerror.py b/qiskit_aer/noise/noiseerror.py index 291d6fa33b..cc3e5244c6 100644 --- a/qiskit_aer/noise/noiseerror.py +++ b/qiskit_aer/noise/noiseerror.py @@ -11,7 +11,7 @@ # that they have been altered from the originals. """ -Exception for errors raised by Aer noise module. +Exception for errors raised by Qiskit Aer noise module. """ from qiskit import QiskitError diff --git a/qiskit_aer/primitives/estimator.py b/qiskit_aer/primitives/estimator.py index d4f9f65790..cf30e065d8 100644 --- a/qiskit_aer/primitives/estimator.py +++ b/qiskit_aer/primitives/estimator.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2022, 2023. +# (C) Copyright IBM 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 @@ -18,11 +18,13 @@ from collections import defaultdict from collections.abc import Sequence +from copy import copy from warnings import warn import numpy as np from qiskit.circuit import ParameterExpression, QuantumCircuit from qiskit.compiler import transpile +from qiskit.opflow import PauliSumOp from qiskit.primitives import BaseEstimator, EstimatorResult from qiskit.primitives.primitive_job import PrimitiveJob from qiskit.primitives.utils import _circuit_key, _observable_key, init_observable @@ -30,15 +32,6 @@ from qiskit.quantum_info import Pauli, PauliList from qiskit.quantum_info.operators.base_operator import BaseOperator from qiskit.result.models import ExperimentResult -from qiskit.transpiler import CouplingMap, PassManager -from qiskit.transpiler.passes import ( - ApplyLayout, - EnlargeWithAncilla, - FullAncillaAllocation, - Optimize1qGatesDecomposition, - SetLayout, -) -from qiskit.utils import deprecate_func from .. import AerError, AerSimulator @@ -91,7 +84,7 @@ def __init__( transpile_options: Options passed to transpile. run_options: Options passed to run. approximation: If True, it calculates expectation values with normal distribution - approximation. Note that this appproximation ignores readout errors. + approximation. skip_transpilation: If True, transpilation is skipped. abelian_grouping: Whether the observable should be grouped into commuting. If approximation is True, this parameter is ignored and assumed to be False. @@ -112,15 +105,7 @@ def __init__( self._transpile_options = Options() if transpile_options is not None: self._transpile_options.update_options(**transpile_options) - if not approximation: - warn( - "Option approximation=False is deprecated as of qiskit-aer 0.13. " - "It will be removed no earlier than 3 months after the release date. " - "Instead, use BackendEstimator from qiskit.primitives.", - DeprecationWarning, - stacklevel=3, - ) - self._approximation = approximation + self.approximation = approximation self._skip_transpilation = skip_transpilation self._cache: dict[tuple[tuple[int], tuple[int], bool], tuple[dict, dict]] = {} self._transpiled_circuits: dict[int, QuantumCircuit] = {} @@ -129,34 +114,6 @@ def __init__( self._observable_ids: dict[tuple, int] = {} self._abelian_grouping = abelian_grouping - @property - @deprecate_func( - since="0.13", - package_name="qiskit-aer", - is_property=True, - ) - def approximation(self): - """The approximation property""" - return self._approximation - - @approximation.setter - @deprecate_func( - since="0.13", - package_name="qiskit-aer", - is_property=True, - ) - def approximation(self, approximation): - """Setter for approximation""" - if not approximation: - warn( - "Option approximation=False is deprecated as of qiskit-aer 0.13. " - "It will be removed no earlier than 3 months after the release date. " - "Instead, use BackendEstimator from qiskit.primitives.", - DeprecationWarning, - stacklevel=3, - ) - self._approximation = approximation - def _call( self, circuits: Sequence[int], @@ -168,7 +125,7 @@ def _call( if seed is not None: run_options.setdefault("seed_simulator", seed) - if self._approximation: + if self.approximation: return self._compute_with_approximation( circuits, observables, parameter_values, run_options, seed ) @@ -178,7 +135,7 @@ def _call( def _run( self, circuits: Sequence[QuantumCircuit], - observables: Sequence[BaseOperator], + observables: Sequence[BaseOperator | PauliSumOp], parameter_values: Sequence[Sequence[float]], **run_options, ) -> PrimitiveJob: @@ -223,7 +180,7 @@ def _compute(self, circuits, observables, parameter_values, run_options): ) # Key for cache - key = (tuple(circuits), tuple(observables), self._approximation) + key = (tuple(circuits), tuple(observables), self.approximation) # Create expectation value experiments. if key in self._cache: # Use a cache @@ -346,20 +303,11 @@ def _create_meas_circuit(self, basis: Pauli, circuit_index: int): meas_circuit.h(qarg) meas_circuit.measure(qarg, clbit) meas_circuit.metadata = {"basis": basis} - if self._skip_transpilation: return meas_circuit - - layout = self._layouts[circuit_index] - passmanager = PassManager([SetLayout(layout)]) - opt1q = Optimize1qGatesDecomposition(target=self._backend.target) - passmanager.append(opt1q) - if isinstance(self._backend.coupling_map, CouplingMap): - coupling_map = self._backend.coupling_map - passmanager.append(FullAncillaAllocation(coupling_map)) - passmanager.append(EnlargeWithAncilla()) - passmanager.append(ApplyLayout()) - return passmanager.run(meas_circuit) + transpile_opts = copy(self._transpile_options) + transpile_opts.update_options(initial_layout=self._layouts[circuit_index]) + return transpile(meas_circuit, self._backend, **transpile_opts.__dict__) @staticmethod def _combine_circs(circuit: QuantumCircuit, meas_circuits: list[QuantumCircuit]): @@ -421,7 +369,7 @@ def _compute_with_approximation( self, circuits, observables, parameter_values, run_options, seed ): # Key for cache - key = (tuple(circuits), tuple(observables), self._approximation) + key = (tuple(circuits), tuple(observables), self.approximation) shots = run_options.pop("shots", None) # Create expectation value experiments. @@ -440,16 +388,20 @@ def _compute_with_approximation( self._transpile_circuits(circuits) experiment_manager = _ExperimentManager() for i, j, value in zip(circuits, observables, parameter_values): - self._validate_parameter_length(value, i) if (i, j) in experiment_manager.keys: - key_index = experiment_manager.keys.index((i, j)) - circuit = experiment_manager.experiment_circuits[key_index] + self._validate_parameter_length(value, i) + experiment_manager.append( + key=(i, j), + parameter_bind=dict(zip(self._parameters[i], value)), + ) else: + self._validate_parameter_length(value, i) circuit = ( self._circuits[i].copy() if self._skip_transpilation else self._transpiled_circuits[i].copy() ) + observable = self._observables[j] if shots is None: circuit.save_expectation_value(observable, self._layouts[i]) @@ -458,11 +410,11 @@ def _compute_with_approximation( circuit.save_expectation_value( pauli, self._layouts[i], label=str(term_ind) ) - experiment_manager.append( - key=(i, j), - parameter_bind=dict(zip(self._parameters[i], value)), - experiment_circuit=circuit, - ) + experiment_manager.append( + key=(i, j), + parameter_bind=dict(zip(self._parameters[i], value)), + experiment_circuit=circuit, + ) self._cache[key] = experiment_manager result = self._backend.run( @@ -670,22 +622,24 @@ def __len__(self): @property def experiment_indices(self): """indices of experiments""" - return np.argsort(sum(self._input_indices, [])).tolist() + return sum(self._input_indices, []) def append( self, key: tuple[int, int], parameter_bind: dict[ParameterExpression, float], - experiment_circuit: QuantumCircuit, + experiment_circuit: QuantumCircuit | None = None, ): """append experiments""" - if key in self.keys and parameter_bind: + if experiment_circuit is not None: + self.experiment_circuits.append(experiment_circuit) + + if key in self.keys: key_index = self.keys.index(key) for k, vs in self.parameter_binds[key_index].items(): vs.append(parameter_bind[k]) self._input_indices[key_index].append(self._num_experiment) else: - self.experiment_circuits.append(experiment_circuit) self.keys.append(key) self.parameter_binds.append({k: [v] for k, v in parameter_bind.items()}) self._input_indices.append([self._num_experiment]) diff --git a/qiskit_aer/primitives/sampler.py b/qiskit_aer/primitives/sampler.py index 7f06124289..8f6538e2b3 100644 --- a/qiskit_aer/primitives/sampler.py +++ b/qiskit_aer/primitives/sampler.py @@ -18,8 +18,7 @@ from collections.abc import Sequence -import numpy as np -from qiskit.circuit import ParameterExpression, QuantumCircuit +from qiskit.circuit import QuantumCircuit from qiskit.compiler import transpile from qiskit.exceptions import QiskitError from qiskit.primitives import BaseSampler, SamplerResult @@ -94,30 +93,25 @@ def _call( is_shots_none = "shots" in run_options and run_options["shots"] is None self._transpile(circuits, is_shots_none) - experiment_manager = _ExperimentManager() + experiments = [] + parameter_binds = [] for i, value in zip(circuits, parameter_values): if len(value) != len(self._parameters[i]): raise QiskitError( f"The number of values ({len(value)}) does not match " f"the number of parameters ({len(self._parameters[i])})." ) - - experiment_manager.append( - key=i, - parameter_bind=dict(zip(self._parameters[i], value)), - experiment_circuit=self._transpiled_circuits[(i, is_shots_none)], - ) + parameter_binds.append({k: [v] for k, v in zip(self._parameters[i], value)}) + experiments.append(self._transpiled_circuits[(i, is_shots_none)]) result = self._backend.run( - experiment_manager.experiment_circuits, - parameter_binds=experiment_manager.parameter_binds, - **run_options, + experiments, parameter_binds=parameter_binds, **run_options ).result() # Postprocessing metadata = [] quasis = [] - for i in experiment_manager.experiment_indices: + for i in range(len(experiments)): if is_shots_none: probabilities = result.data(i)["probabilities"] num_qubits = result.results[i].metadata["num_qubits"] @@ -198,40 +192,3 @@ def _transpile(self, circuit_indices: Sequence[int], is_shots_none: bool): ) for i, circuit in zip(to_handle, circuits): self._transpiled_circuits[(i, is_shots_none)] = circuit - - -class _ExperimentManager: - def __init__(self): - self.keys: list[int] = [] - self.experiment_circuits: list[QuantumCircuit] = [] - self.parameter_binds: list[dict[ParameterExpression, list[float]]] = [] - self._input_indices: list[list[int]] = [] - self._num_experiment: int = 0 - - def __len__(self): - return self._num_experiment - - @property - def experiment_indices(self): - """indices of experiments""" - return np.argsort(sum(self._input_indices, [])).tolist() - - def append( - self, - key: tuple[int, int], - parameter_bind: dict[ParameterExpression, float], - experiment_circuit: QuantumCircuit, - ): - """append experiments""" - if parameter_bind and key in self.keys: - key_index = self.keys.index(key) - for k, vs in self.parameter_binds[key_index].items(): - vs.append(parameter_bind[k]) - self._input_indices[key_index].append(self._num_experiment) - else: - self.experiment_circuits.append(experiment_circuit) - self.keys.append(key) - self.parameter_binds.append({k: [v] for k, v in parameter_bind.items()}) - self._input_indices.append([self._num_experiment]) - - self._num_experiment += 1 diff --git a/qiskit_aer/quantum_info/states/aer_statevector.py b/qiskit_aer/quantum_info/states/aer_statevector.py index eac02af221..fa4acf321e 100644 --- a/qiskit_aer/quantum_info/states/aer_statevector.py +++ b/qiskit_aer/quantum_info/states/aer_statevector.py @@ -260,10 +260,10 @@ def _aer_evolve_instruction(aer_state, inst, qubits, basis_gates=None): pass else: applied = False - elif inst.name == "reset": - aer_state.apply_reset(qubits) elif inst.name == "kraus": aer_state.apply_kraus(qubits, inst.params) + elif inst.name == "reset": + aer_state.apply_reset(qubits) elif inst.name == "barrier": pass else: diff --git a/releasenotes/notes/0.13/add-rocm-support-db991e3c2f2ca455.yaml b/releasenotes/notes/0.13/add-rocm-support-db991e3c2f2ca455.yaml deleted file mode 100644 index 621c2ce60c..0000000000 --- a/releasenotes/notes/0.13/add-rocm-support-db991e3c2f2ca455.yaml +++ /dev/null @@ -1,40 +0,0 @@ ---- -features: - - | - ROCm support has been added matching the existing CUDA implementation based - on the ``thrust`` library. This enables Qiskit-Aer to run on AMD GPUs, - including the AMD Instinct GPU line based on the CDNA architecture. To build - the standalone version, the following should be sufficient:: - - cmake -G Ninja \ - -DCMAKE_INSTALL_PREFIX= \ - -DSKBUILD=FALSE \ - -DAER_THRUST_BACKEND=ROCM \ - -DAER_MPI= \ - -DAER_ROCM_ARCH= \ - -DCMAKE_BUILD_TYPE=Release \ - -DBUILD_TESTS=True - ninja install - - Alternatively, and possibly preferred for most use cases, you can create a Python - wheel file that you can install as part of your Python environemnt:: - - cd - - QISKIT_AER_PACKAGE_NAME='qiskit-aer-gpu-rocm' \ - python3 setup.py bdist_wheel -- \ - -DAER_THRUST_BACKEND=ROCM \ - -DAER_MPI= \ - -DAER_ROCM_ARCH= - - pip install --force-reinstall dist/qiskit_aer_gpu_rocm-*.whl - - In both cases, the host system needs to have a functional ROCm instalation and - the environment variable ``ROCM_PATH`` set pointing to the ROCm instalation folder if - that is not the default ``/opt/rocm``. - Depending on how your Python environment is set, you might need to install - Qiskit-Aer's required development modules:: - - cd - pip install -r requirements-dev.txt - diff --git a/releasenotes/notes/0.13/add_executor-ba4870f86ed5d8ec.yaml b/releasenotes/notes/0.13/add_executor-ba4870f86ed5d8ec.yaml deleted file mode 100644 index e1088061fa..0000000000 --- a/releasenotes/notes/0.13/add_executor-ba4870f86ed5d8ec.yaml +++ /dev/null @@ -1,30 +0,0 @@ ---- -features: - - | - This release restructures ``State`` classes. - Adding circuit executor classes that runs a circuit and manages multiple - states for multi-shots simulations or multi-chunk simulations for large - number of qubits. - Previously ``StateChunk`` class manages multiple chunks for multi-shots or - multi-chunk simulations but now ``State`` class only has one state - and all the parallelization codes are moved to ``Executor`` classes. - Now all ``State`` classes are independent from parallelization. - Also some of the functions in ``Aer::Controller`` class are moved to - ``CircuitExecutor::Executor`` class. - - | - Shot-branching technique that accelerates dynamic circuits simulations - is implemented with restructured ``Executor`` classes. - Shot-branching is currently applicable to statevector, density_matrix - and tensor_network methods. - Shot-branching provides dynamic distribution of multi-shots - by branching states when applying dynamic operations - (measure, reset, initialize, noises) - By default ``shot_branching_enable`` is disabled. - And by setting ``shot_branching_sampling_enable``, final measures will be - done by sampling measure that will speed up to get counts for multiple shots - sharing the same state. - - | - New option for GPU simulation ``target_gpus`` is added. - A list of GPUs used for the simulation can be set by this option. - Without this option, all the available GPUs are used. - For example, if there is 4 GPUs, ``target_gpus=[0, 2]`` will use 2 GPUs. diff --git a/releasenotes/notes/0.13/aer-runtime-api-exposed-wrong-sx-op-dadae6cf0787e169.yaml b/releasenotes/notes/0.13/aer-runtime-api-exposed-wrong-sx-op-dadae6cf0787e169.yaml deleted file mode 100644 index dfa6aa127c..0000000000 --- a/releasenotes/notes/0.13/aer-runtime-api-exposed-wrong-sx-op-dadae6cf0787e169.yaml +++ /dev/null @@ -1,9 +0,0 @@ ---- -fixes: - - | - Aer runtime api (from contrib) exposed the wrong sx operation, - implemented with a rx. The implementation is changed now by - adding AerState::apply_mcsx and calling it from aer_apply_sx. - This way the api has the same behavior as the documentation - states and also how the sx gate behaves in python. - Fix for: https://github.com/Qiskit/qiskit-aer/issues/1925 diff --git a/releasenotes/notes/0.13/estimator-order-bug-a341d82075f47046.yaml b/releasenotes/notes/0.13/estimator-order-bug-a341d82075f47046.yaml deleted file mode 100644 index ffd8d90f6b..0000000000 --- a/releasenotes/notes/0.13/estimator-order-bug-a341d82075f47046.yaml +++ /dev/null @@ -1,5 +0,0 @@ ---- -upgrade: - - | - Fixed a bug that caused results to be incorrectly ordered or errors in - :class:`~.Estimator` with ``approximation=True``. diff --git a/releasenotes/notes/0.13/fix-aer-vector-alignment-aace6e14342c002e.yaml b/releasenotes/notes/0.13/fix-aer-vector-alignment-aace6e14342c002e.yaml deleted file mode 100644 index 0434e30fc7..0000000000 --- a/releasenotes/notes/0.13/fix-aer-vector-alignment-aace6e14342c002e.yaml +++ /dev/null @@ -1,10 +0,0 @@ ---- -fixes: - - | - Change ``AER::Vector`` object alignement to 64-byte. In some cases, it is used to - initialize ``AER:QV::QubitVector`` objects by moving storage ownership to these - objects. As the code assumes that ``AER:QV::QubitVector`` storage is at least - 32-byte aligned for AVX2 load instructions, this change enforces the same alignement - requirements for both ``AER::Vector`` and ``AER:QV::QubitVector`` objects so that - one doesn't get into segmentation faults. - \ No newline at end of file diff --git a/releasenotes/notes/0.13/fix-compiling-issue-in-release-with-vc++-47500a37841cfaa8.yaml b/releasenotes/notes/0.13/fix-compiling-issue-in-release-with-vc++-47500a37841cfaa8.yaml deleted file mode 100644 index f874dd78c0..0000000000 --- a/releasenotes/notes/0.13/fix-compiling-issue-in-release-with-vc++-47500a37841cfaa8.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -fixes: - - | - Fixes an issue when compiling a release version on windows with vc++, - also unrolls a for, avoiding an unnecessary switch inside it. - The fix is for https://github.com/Qiskit/qiskit-aer/issues/1918 - - diff --git a/releasenotes/notes/0.13/fix-excitation-population-6af281a61f659dda.yaml b/releasenotes/notes/0.13/fix-excitation-population-6af281a61f659dda.yaml deleted file mode 100644 index 874f9b3455..0000000000 --- a/releasenotes/notes/0.13/fix-excitation-population-6af281a61f659dda.yaml +++ /dev/null @@ -1,6 +0,0 @@ ---- -fixes: - - | - Fixed a bug where :meth:`~.NoiseModel.from_backend` with ``BackendV2`` and non-zero ``temperature`` - produces relaxation noises with incorrect excitation population. - Fixed `#1937 `__. diff --git a/releasenotes/notes/0.13/fix_matplotlib_dependency-5b8ba26da6a98e3a.yaml b/releasenotes/notes/0.13/fix_matplotlib_dependency-5b8ba26da6a98e3a.yaml deleted file mode 100644 index 01433b8ee3..0000000000 --- a/releasenotes/notes/0.13/fix_matplotlib_dependency-5b8ba26da6a98e3a.yaml +++ /dev/null @@ -1,4 +0,0 @@ ---- -fixes: - - | - Fix the version of matplotlib required by seaborn diff --git a/releasenotes/notes/0.13/fix_mps_extstabilizer_required_memory-f4fb0aebfeeb68e2.yaml b/releasenotes/notes/0.13/fix_mps_extstabilizer_required_memory-f4fb0aebfeeb68e2.yaml deleted file mode 100644 index 38026d8e88..0000000000 --- a/releasenotes/notes/0.13/fix_mps_extstabilizer_required_memory-f4fb0aebfeeb68e2.yaml +++ /dev/null @@ -1,10 +0,0 @@ ---- -fixes: - - | - State::set_config was not called before calling State::required_memory_mb. - Extended stabilizer uses parameter from config to calculate required memory - so size was not correct before this fix. - Now Config is passed to required_memory_mb function. - - State::required_memory_mb for MPS method returned wrong memory size. - This fix adds memory size estimation by calculating max bond dimension. diff --git a/releasenotes/notes/0.13/fix_omp_nested_performance-a3d55f3e85366a5b.yaml b/releasenotes/notes/0.13/fix_omp_nested_performance-a3d55f3e85366a5b.yaml deleted file mode 100644 index 50a19f6be9..0000000000 --- a/releasenotes/notes/0.13/fix_omp_nested_performance-a3d55f3e85366a5b.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -fixes: - - | - OpenMP nested parallel simulation for parallel experiments + parallel state - update was very slow because gate fusion uses unitary simulator inside - and it used omp parallel region. This fix remove parallel region in - gate fusion and improve performance of nested parallel simulations diff --git a/releasenotes/notes/0.13/fix_stabilizer_measure-49f9b4261dfaa4d3.yaml b/releasenotes/notes/0.13/fix_stabilizer_measure-49f9b4261dfaa4d3.yaml deleted file mode 100644 index 6a0132329c..0000000000 --- a/releasenotes/notes/0.13/fix_stabilizer_measure-49f9b4261dfaa4d3.yaml +++ /dev/null @@ -1,4 +0,0 @@ ---- -fixes: - - | - This release fixes an issue in measurement function of stabilizer simulator diff --git a/releasenotes/notes/0.13/latest-vc++-compilation-fixes-555601315e7e821b.yaml b/releasenotes/notes/0.13/latest-vc++-compilation-fixes-555601315e7e821b.yaml deleted file mode 100644 index 10ca356b1c..0000000000 --- a/releasenotes/notes/0.13/latest-vc++-compilation-fixes-555601315e7e821b.yaml +++ /dev/null @@ -1,11 +0,0 @@ ---- -fixes: - - | - Adresses two opened issues, one about replacing a char* parameter to a - const char*, another one for adding support for the latest vc++ in - conan.cmake - Changes: - Passing const char* to a char* parameter in CacheBlocking::insert_sim_op call: #1905 - https://github.com/Qiskit/qiskit-aer/issues/1905 - Add support for the latest VC++ in conan.cmake #1906: - https://github.com/Qiskit/qiskit-aer/issues/1906 diff --git a/releasenotes/notes/0.13/quantum_error_from_dict-8188a864109edd67.yaml b/releasenotes/notes/0.13/quantum_error_from_dict-8188a864109edd67.yaml deleted file mode 100644 index 87ab89e115..0000000000 --- a/releasenotes/notes/0.13/quantum_error_from_dict-8188a864109edd67.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -features: - - | - Implements from_dict() method for QuantumError. This takes a dictionary - and checks if style is the one from to_dict() method. If any mismatches - are determined then NoiseError is raised. Else dict is parsed and a new - QuantumError with noise_ops created. diff --git a/releasenotes/notes/0.13/release_0.13.0-456c0b054ea30a1b.yaml b/releasenotes/notes/0.13/release_0.13.0-456c0b054ea30a1b.yaml deleted file mode 100644 index 702a966853..0000000000 --- a/releasenotes/notes/0.13/release_0.13.0-456c0b054ea30a1b.yaml +++ /dev/null @@ -1,22 +0,0 @@ ---- -prelude: > - Here are highlights of the Aer 0.13.0 release: - - Aer's backend is now backendV2. - - Introducing shot-branching optimization that accelerates dynamic circuits - simulations. By using `shot_branching_enable=True`, multi-shots - simulation starts with single state and state will be branched with - attached shots dynamically. This option is available for `statevector`, - `density_matrix` and `tensor_network` methods. - - Adding support for classical expressions used for branch operations. - - Introducing runtime parameter binding that accelerates parameterized - circuits simulations on GPU. With `runtime_parameter_bind_enable=True` - and `batched_shots_gpu=True`, this optimization will be enabled on GPU. - This optimization can be used with Aer primitives. - - Fix dynamic link library path for GPU binary distributions. - - Now Aer supports AMD's GPUs based on ROCm (building from source code only) diff --git a/releasenotes/notes/0.13/runtime_parameter_binding-d2c57255f02729a1.yaml b/releasenotes/notes/0.13/runtime_parameter_binding-d2c57255f02729a1.yaml deleted file mode 100644 index 04573f93f7..0000000000 --- a/releasenotes/notes/0.13/runtime_parameter_binding-d2c57255f02729a1.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -features: - - | - A runtime parameter binding option is implemented to bind paramters at - runtime to a single circuit instead running multiple circuits as input. - An option ``runtime_parameter_bind_enable=True`` enables this feature and - for GPU, ``batched_shots_gpu=True`` should be also set to speed up - simulating parameterized circuit. diff --git a/releasenotes/notes/0.13/sampler-performance-81e1649ec4657aad.yaml b/releasenotes/notes/0.13/sampler-performance-81e1649ec4657aad.yaml deleted file mode 100644 index 5b8e1f2778..0000000000 --- a/releasenotes/notes/0.13/sampler-performance-81e1649ec4657aad.yaml +++ /dev/null @@ -1,5 +0,0 @@ ---- -upgrade: - - | - Improved performance when the same circuits and multiple parameters are passed to - :class:`~.Sampler`. diff --git a/releasenotes/notes/0.13/skip-cuda-requirements-927ddce79b9e7108.yaml b/releasenotes/notes/0.13/skip-cuda-requirements-927ddce79b9e7108.yaml deleted file mode 100644 index 77ead1090e..0000000000 --- a/releasenotes/notes/0.13/skip-cuda-requirements-927ddce79b9e7108.yaml +++ /dev/null @@ -1,23 +0,0 @@ ---- -prelude: > - Build environment variable was added to enable building Qiskit-Aer without the CUDA - requirements. The new variable is ``QISKIT_ADD_CUDA_REQUIREMENTS`` and can be set to - False/No/Off or True/Yes/On. By default, it is assumed True. - -features: - - | - A new environment variable ``QISKIT_ADD_CUDA_REQUIREMENTS`` can be sed to control - whether or not build the Python package for Qiskit-Aer with CUDA requirements. This - flag can be set to False/No/Off or True/Yes/On. By default it is assumed True. This - is useful in case a CUDA instalation is already available on the system where - Qiskit-Aer will run. Not including the requirements results in a smaller footprint - and facilitates leveraging different CUDA installs for development purposes. - The new flag can used like:: - - cd - - QISKIT_AER_PACKAGE_NAME='qiskit-aer-gpu' \ - QISKIT_AER_CUDA_MAJOR=$CUDA_MAJOR \ - QISKIT_ADD_CUDA_REQUIREMENTS=False \ - python3 setup.py bdist_wheel -- \ - -DAER_THRUST_BACKEND=CUDA ... diff --git a/releasenotes/notes/0.13/stabilizer_rotation-8ce2effd9578ee0a.yaml b/releasenotes/notes/0.13/stabilizer_rotation-8ce2effd9578ee0a.yaml deleted file mode 100644 index 2202d0c817..0000000000 --- a/releasenotes/notes/0.13/stabilizer_rotation-8ce2effd9578ee0a.yaml +++ /dev/null @@ -1,9 +0,0 @@ ---- -upgrade: - - | - Adding support of rotation gates (rx, ry and rz gates) to stabilizer method - when input theta is multiple of pi/2. - If ``method=automatic`` is specified (this is default), if all the input - theta of rotation gates are multiple of pi/2 ``method=stabilizer`` - is selected. Of when user sets ``method=stabilizer`` and any of theta - is not multiple of pi/2, Aer raises an exception. diff --git a/releasenotes/notes/0.13/support_backend_v2-9eeb4690199b01d1.yaml b/releasenotes/notes/0.13/support_backend_v2-9eeb4690199b01d1.yaml deleted file mode 100644 index 2579d71794..0000000000 --- a/releasenotes/notes/0.13/support_backend_v2-9eeb4690199b01d1.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -features: - - | - Update Aer Backend to BackendV2. Refer to `#1681`. - BackendV2 is differs from BackendV1 in the following points: backend.name() changes to backend.name string attribute, - the configuration attribute no longer exists, and the options attribute is added. For more information about BackendV2 is - `here`. \ No newline at end of file diff --git a/releasenotes/notes/0.13/support_c_if_reset-1f0b8e84948fb3fc.yaml b/releasenotes/notes/0.13/support_c_if_reset-1f0b8e84948fb3fc.yaml deleted file mode 100644 index ea0d00edcd..0000000000 --- a/releasenotes/notes/0.13/support_c_if_reset-1f0b8e84948fb3fc.yaml +++ /dev/null @@ -1,6 +0,0 @@ ---- -features: - - | - ``c_if`` is supportted of ``reset`` instruction and an exception - is thrown if `c_if` is called for an instruction that does not - support ``c_if``. diff --git a/releasenotes/notes/0.13/support_classical_expr-dd621e5c0fd23a15.yaml b/releasenotes/notes/0.13/support_classical_expr-dd621e5c0fd23a15.yaml deleted file mode 100644 index 11269398cb..0000000000 --- a/releasenotes/notes/0.13/support_classical_expr-dd621e5c0fd23a15.yaml +++ /dev/null @@ -1,10 +0,0 @@ ---- -features: - - | - Support ``qiskit.circuit.classical.expr.Expr`` introduced in Qiskit 0.44. - If a circuit includes unsupported expression which will be introduced in Qiskit 0.45 - or later, ``AerError`` is thrown. Objects of sub-classes of ``Expr`` are converted to - corresponding sub-classes of ``AER::Operations::CExpr`` in C++ and evaluated. - In addition, ``AER::Operations::RegComparison`` in ``bfunc`` operation is replaced - with corresponding binary operations. - diff --git a/releasenotes/notes/0.13/support_switch_transpilation-67e16241b94faa86.yaml b/releasenotes/notes/0.13/support_switch_transpilation-67e16241b94faa86.yaml deleted file mode 100644 index 0704fbc314..0000000000 --- a/releasenotes/notes/0.13/support_switch_transpilation-67e16241b94faa86.yaml +++ /dev/null @@ -1,5 +0,0 @@ ---- -issues: - - | - Though Aer supports ``switch`` for several methods, transpilation of circuits with ``switch`` has been failed. - This commit enables such transpilation by adding ``switch_case`` operations into basis gates. diff --git a/releasenotes/notes/add-mkl-as-blas-backend-in-MPS-fd4bec4ab1f24b35.yaml b/releasenotes/notes/add-mkl-as-blas-backend-in-MPS-fd4bec4ab1f24b35.yaml new file mode 100644 index 0000000000..ba05c5ebe8 --- /dev/null +++ b/releasenotes/notes/add-mkl-as-blas-backend-in-MPS-fd4bec4ab1f24b35.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Support compile using Intel MKL as BLAS backend, and using its functions + in the MPS simulation method. diff --git a/releasenotes/notes/add-py312-795ffe7d68f41c73.yaml b/releasenotes/notes/add-py312-795ffe7d68f41c73.yaml deleted file mode 100644 index a7244cd1fd..0000000000 --- a/releasenotes/notes/add-py312-795ffe7d68f41c73.yaml +++ /dev/null @@ -1,4 +0,0 @@ ---- -features: - - | - Added support for running qiskit-aer with Python 3.12. diff --git a/releasenotes/notes/0.13/add_executor-a03f2d23cf6f4ca9.yaml b/releasenotes/notes/add_executor-a03f2d23cf6f4ca9.yaml similarity index 100% rename from releasenotes/notes/0.13/add_executor-a03f2d23cf6f4ca9.yaml rename to releasenotes/notes/add_executor-a03f2d23cf6f4ca9.yaml diff --git a/releasenotes/notes/0.13/avoid_copy_of_config-7f7891864c1a1bd0.yaml b/releasenotes/notes/avoid_copy_of_config-7f7891864c1a1bd0.yaml similarity index 100% rename from releasenotes/notes/0.13/avoid_copy_of_config-7f7891864c1a1bd0.yaml rename to releasenotes/notes/avoid_copy_of_config-7f7891864c1a1bd0.yaml diff --git a/releasenotes/notes/0.13/avoid_kernel_crash_in_mac_from_blas_error-bd5b836a23f2e3ee.yaml b/releasenotes/notes/avoid_kernel_crash_in_mac_from_blas_error-bd5b836a23f2e3ee.yaml similarity index 100% rename from releasenotes/notes/0.13/avoid_kernel_crash_in_mac_from_blas_error-bd5b836a23f2e3ee.yaml rename to releasenotes/notes/avoid_kernel_crash_in_mac_from_blas_error-bd5b836a23f2e3ee.yaml diff --git a/releasenotes/notes/0.13/check_param_length-eb69cd92825bbca4.yaml b/releasenotes/notes/check_param_length-eb69cd92825bbca4.yaml similarity index 100% rename from releasenotes/notes/0.13/check_param_length-eb69cd92825bbca4.yaml rename to releasenotes/notes/check_param_length-eb69cd92825bbca4.yaml diff --git a/releasenotes/notes/0.13/check_parameter_binds_exist-9d52c665d5f94dde.yaml b/releasenotes/notes/check_parameter_binds_exist-9d52c665d5f94dde.yaml similarity index 100% rename from releasenotes/notes/0.13/check_parameter_binds_exist-9d52c665d5f94dde.yaml rename to releasenotes/notes/check_parameter_binds_exist-9d52c665d5f94dde.yaml diff --git a/releasenotes/notes/compute-svd-with-lapack-3ee992d371d653d1.yaml b/releasenotes/notes/compute-svd-with-lapack-3ee992d371d653d1.yaml index f861b6fbab..1fbeba519b 100644 --- a/releasenotes/notes/compute-svd-with-lapack-3ee992d371d653d1.yaml +++ b/releasenotes/notes/compute-svd-with-lapack-3ee992d371d653d1.yaml @@ -2,7 +2,10 @@ features: - | Replace Qiskit SVD function with OpenBLAS/LAPACK SVD functions ``zgesvd`` - and ``zgesdd``. By default ``zgesvd`` is used. Performance of ``zgesdd`` is better than - that of ``zgesvd`` on large matrices, whereas ``zgesvd`` performs better on small matrices. - User can use ``zgesdd`` function + and ``zgesdd``. By default ``zgesvd`` is used, but performace decrease with + big matrices. On the other hand, ``zgesdd`` has bad performance with small + matrices, and better with big matrices. User can use ``zgesdd`` function setting the environment variable ``QISKIT_LAPACK_SVD=DC``. +other: + - | + Performance may decrease depending on the SVD method used. diff --git a/releasenotes/notes/0.13/correct_measure_in_state_controller-a92692fd7083c476.yaml b/releasenotes/notes/correct_measure_in_state_controller-a92692fd7083c476.yaml similarity index 100% rename from releasenotes/notes/0.13/correct_measure_in_state_controller-a92692fd7083c476.yaml rename to releasenotes/notes/correct_measure_in_state_controller-a92692fd7083c476.yaml diff --git a/releasenotes/notes/0.13/defer-backend-gathering-773d0ed8092c24d9.yaml b/releasenotes/notes/defer-backend-gathering-773d0ed8092c24d9.yaml similarity index 100% rename from releasenotes/notes/0.13/defer-backend-gathering-773d0ed8092c24d9.yaml rename to releasenotes/notes/defer-backend-gathering-773d0ed8092c24d9.yaml diff --git a/releasenotes/notes/0.13/do_not_modify_metadata-60bb4b88707bd021.yaml b/releasenotes/notes/do_not_modify_metadata-60bb4b88707bd021.yaml similarity index 100% rename from releasenotes/notes/0.13/do_not_modify_metadata-60bb4b88707bd021.yaml rename to releasenotes/notes/do_not_modify_metadata-60bb4b88707bd021.yaml diff --git a/releasenotes/notes/0.13/enhancement_ecr_for_stabilizer_simulator-00110a1b39d35054.yaml b/releasenotes/notes/enhancement_ecr_for_stabilizer_simulator-00110a1b39d35054.yaml similarity index 100% rename from releasenotes/notes/0.13/enhancement_ecr_for_stabilizer_simulator-00110a1b39d35054.yaml rename to releasenotes/notes/enhancement_ecr_for_stabilizer_simulator-00110a1b39d35054.yaml diff --git a/releasenotes/notes/0.13/estimator-performance-da83a59b9fd69086.yaml b/releasenotes/notes/estimator-performance-da83a59b9fd69086.yaml similarity index 100% rename from releasenotes/notes/0.13/estimator-performance-da83a59b9fd69086.yaml rename to releasenotes/notes/estimator-performance-da83a59b9fd69086.yaml diff --git a/releasenotes/notes/0.13/estimator-variance-type-2b04ff7bcd305920.yaml b/releasenotes/notes/estimator-variance-type-2b04ff7bcd305920.yaml similarity index 100% rename from releasenotes/notes/0.13/estimator-variance-type-2b04ff7bcd305920.yaml rename to releasenotes/notes/estimator-variance-type-2b04ff7bcd305920.yaml diff --git a/releasenotes/notes/0.13/fix-cuStateVec_enable-0936f2269466e3be.yaml b/releasenotes/notes/fix-cuStateVec_enable-0936f2269466e3be.yaml similarity index 100% rename from releasenotes/notes/0.13/fix-cuStateVec_enable-0936f2269466e3be.yaml rename to releasenotes/notes/fix-cuStateVec_enable-0936f2269466e3be.yaml diff --git a/releasenotes/notes/0.13/fix-none-handling-in-noise-model-34fcc9a3e3cbdf6f.yaml b/releasenotes/notes/fix-none-handling-in-noise-model-34fcc9a3e3cbdf6f.yaml similarity index 100% rename from releasenotes/notes/0.13/fix-none-handling-in-noise-model-34fcc9a3e3cbdf6f.yaml rename to releasenotes/notes/fix-none-handling-in-noise-model-34fcc9a3e3cbdf6f.yaml diff --git a/releasenotes/notes/0.13/fix-none-t2-handling-in-noise-model-5b712adf3569eccd.yaml b/releasenotes/notes/fix-none-t2-handling-in-noise-model-5b712adf3569eccd.yaml similarity index 100% rename from releasenotes/notes/0.13/fix-none-t2-handling-in-noise-model-5b712adf3569eccd.yaml rename to releasenotes/notes/fix-none-t2-handling-in-noise-model-5b712adf3569eccd.yaml diff --git a/releasenotes/notes/0.13/fix-number-qubits-a417ca6afa64264f.yaml b/releasenotes/notes/fix-number-qubits-a417ca6afa64264f.yaml similarity index 100% rename from releasenotes/notes/0.13/fix-number-qubits-a417ca6afa64264f.yaml rename to releasenotes/notes/fix-number-qubits-a417ca6afa64264f.yaml diff --git a/releasenotes/notes/0.13/fix_aer_state_initialize_api-0c2c237a606648ef.yaml b/releasenotes/notes/fix_aer_state_initialize_api-0c2c237a606648ef.yaml similarity index 100% rename from releasenotes/notes/0.13/fix_aer_state_initialize_api-0c2c237a606648ef.yaml rename to releasenotes/notes/fix_aer_state_initialize_api-0c2c237a606648ef.yaml diff --git a/releasenotes/notes/fix_aerbackend-7e9a74f8219315dc.yaml b/releasenotes/notes/fix_aerbackend-7e9a74f8219315dc.yaml deleted file mode 100644 index f2cf556195..0000000000 --- a/releasenotes/notes/fix_aerbackend-7e9a74f8219315dc.yaml +++ /dev/null @@ -1,13 +0,0 @@ ---- -fixes: - - | - Fixes AerBackend issues caused by upgading to BackendV2 in 0.13.0 release - and fix test failures for Qiskit 0.45 release. - - For issue #1987, added description if backend given by from_backend does not - have description. - - For issue #1988, added building coupling map from option. - - For issue #1982, added custome pass maneger to rebuild basis gates from - input circuits to prevent unnecessary gate changes diff --git a/releasenotes/notes/fix_automethod_stabilizer-90963b34bd5b4439.yaml b/releasenotes/notes/fix_automethod_stabilizer-90963b34bd5b4439.yaml deleted file mode 100644 index 92c8c46c03..0000000000 --- a/releasenotes/notes/fix_automethod_stabilizer-90963b34bd5b4439.yaml +++ /dev/null @@ -1,9 +0,0 @@ ---- -fixes: - - | - Fixed `stabilizer` was selected with `method="automatic" ` when simulating - circuits with rotational gates with noise models for small number of qubits - even it is faster to calculate with `density_matrix` method. - This fix checks if `density_matrix` method with noise model is faster or not - at first and then check using `stabilizer` method. - This is side effect of implementing rotational gates in stabilizer PR #1938 diff --git a/releasenotes/notes/fix_basis_gates-5edf9708e3eec097.yaml b/releasenotes/notes/fix_basis_gates-5edf9708e3eec097.yaml deleted file mode 100644 index 6fa974b2e8..0000000000 --- a/releasenotes/notes/fix_basis_gates-5edf9708e3eec097.yaml +++ /dev/null @@ -1,5 +0,0 @@ ---- -fixes: - - | - Fixed basis gates sets of Aer backend, moved `reset` and `switch_case` - to custom instructions. diff --git a/releasenotes/notes/fix_batch_shots-837c066d8b993a2d.yaml b/releasenotes/notes/fix_batch_shots-837c066d8b993a2d.yaml deleted file mode 100644 index 3e3ef26134..0000000000 --- a/releasenotes/notes/fix_batch_shots-837c066d8b993a2d.yaml +++ /dev/null @@ -1,5 +0,0 @@ ---- -fixes: - - | - Fixed GPU batched shots optimization and GPU runtime parameter binding - failures caused by wrong checking of return condition diff --git a/releasenotes/notes/0.13/fix_cuQuantum_libpath-90d24880cd9a9ea8.yaml b/releasenotes/notes/fix_cuQuantum_libpath-90d24880cd9a9ea8.yaml similarity index 100% rename from releasenotes/notes/0.13/fix_cuQuantum_libpath-90d24880cd9a9ea8.yaml rename to releasenotes/notes/fix_cuQuantum_libpath-90d24880cd9a9ea8.yaml diff --git a/releasenotes/notes/0.13/fix_cuQuantum_static-ad132d742a64a3d5.yaml b/releasenotes/notes/fix_cuQuantum_static-ad132d742a64a3d5.yaml similarity index 100% rename from releasenotes/notes/0.13/fix_cuQuantum_static-ad132d742a64a3d5.yaml rename to releasenotes/notes/fix_cuQuantum_static-ad132d742a64a3d5.yaml diff --git a/releasenotes/notes/fix_extstabilizer_thread_safety-c85e926c7ecb8dfb.yaml b/releasenotes/notes/fix_extstabilizer_thread_safety-c85e926c7ecb8dfb.yaml deleted file mode 100644 index 2551b8bc47..0000000000 --- a/releasenotes/notes/fix_extstabilizer_thread_safety-c85e926c7ecb8dfb.yaml +++ /dev/null @@ -1,6 +0,0 @@ -fixes: - - | - Extended stabilizer simulation was sharing a single copy of RngEngine amongst - parallelized states in ``ExtendedStabilizer::State::apply_ops_parallel``, - leading to thread safety issue. Now, a new RngEngine is seeded for each parallel - state. \ No newline at end of file diff --git a/releasenotes/notes/fix_for_daily_tests-3fa9df70fb3e53ee.yaml b/releasenotes/notes/fix_for_daily_tests-3fa9df70fb3e53ee.yaml deleted file mode 100644 index 784cda289f..0000000000 --- a/releasenotes/notes/fix_for_daily_tests-3fa9df70fb3e53ee.yaml +++ /dev/null @@ -1,9 +0,0 @@ ---- -fixes: - - | - Removed deprecate function test in - test.terra.states.test_aer_statevector.TestAerStatevector.test_number_to_latex_terms - - Sorted the output properties in - test.terra.noise.test_device_models.test_basic_device_gate_errors_from_target_and_properties - to compare correctly. diff --git a/releasenotes/notes/0.13/fix_gpu_binary-1b5b162dff76060d.yaml b/releasenotes/notes/fix_gpu_binary-1b5b162dff76060d.yaml similarity index 100% rename from releasenotes/notes/0.13/fix_gpu_binary-1b5b162dff76060d.yaml rename to releasenotes/notes/fix_gpu_binary-1b5b162dff76060d.yaml diff --git a/releasenotes/notes/fix_initialize_with_global_phase-56d529cd9c09c2fa.yaml b/releasenotes/notes/fix_initialize_with_global_phase-56d529cd9c09c2fa.yaml deleted file mode 100644 index 565a5a0174..0000000000 --- a/releasenotes/notes/fix_initialize_with_global_phase-56d529cd9c09c2fa.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -fixes: - - | - When applying `initialize`, global phase was not multiplied to state. - This fix multiplies global phase to `initialize` operation. - Also this fix applies global phase to `matrix_product_state` method, - which did not use global phase. diff --git a/releasenotes/notes/0.13/fix_mpi_procs-68b76c11fe7a6b8e.yaml b/releasenotes/notes/fix_mpi_procs-68b76c11fe7a6b8e.yaml similarity index 100% rename from releasenotes/notes/0.13/fix_mpi_procs-68b76c11fe7a6b8e.yaml rename to releasenotes/notes/fix_mpi_procs-68b76c11fe7a6b8e.yaml diff --git a/releasenotes/notes/0.13/fix_omp_nested-a554de2e7fd2a2d6.yaml b/releasenotes/notes/fix_omp_nested-a554de2e7fd2a2d6.yaml similarity index 100% rename from releasenotes/notes/0.13/fix_omp_nested-a554de2e7fd2a2d6.yaml rename to releasenotes/notes/fix_omp_nested-a554de2e7fd2a2d6.yaml diff --git a/releasenotes/notes/0.13/fix_param_binding_for_pram_circuit-50e64efbedaec8fd.yaml b/releasenotes/notes/fix_param_binding_for_pram_circuit-50e64efbedaec8fd.yaml similarity index 100% rename from releasenotes/notes/0.13/fix_param_binding_for_pram_circuit-50e64efbedaec8fd.yaml rename to releasenotes/notes/fix_param_binding_for_pram_circuit-50e64efbedaec8fd.yaml diff --git a/releasenotes/notes/0.13/fix_parameter_indexing-f29f19568270d002.yaml b/releasenotes/notes/fix_parameter_indexing-f29f19568270d002.yaml similarity index 100% rename from releasenotes/notes/0.13/fix_parameter_indexing-f29f19568270d002.yaml rename to releasenotes/notes/fix_parameter_indexing-f29f19568270d002.yaml diff --git a/releasenotes/notes/0.13/fix_qobj_run-8ea657a93ce9acd2.yaml b/releasenotes/notes/fix_qobj_run-8ea657a93ce9acd2.yaml similarity index 100% rename from releasenotes/notes/0.13/fix_qobj_run-8ea657a93ce9acd2.yaml rename to releasenotes/notes/fix_qobj_run-8ea657a93ce9acd2.yaml diff --git a/releasenotes/notes/0.13/fix_required_memory_mb-7aeafa0fe553b85a.yaml b/releasenotes/notes/fix_required_memory_mb-7aeafa0fe553b85a.yaml similarity index 100% rename from releasenotes/notes/0.13/fix_required_memory_mb-7aeafa0fe553b85a.yaml rename to releasenotes/notes/fix_required_memory_mb-7aeafa0fe553b85a.yaml diff --git a/releasenotes/notes/fix_sample_measure_roerr-747b955aa2bf778c.yaml b/releasenotes/notes/fix_sample_measure_roerr-747b955aa2bf778c.yaml deleted file mode 100644 index a36e891c3d..0000000000 --- a/releasenotes/notes/fix_sample_measure_roerr-747b955aa2bf778c.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -fixes: - - | - Fixes order of applying read out error in sampling measure - in circuit executors. Ordering is reversed to fit to the older verison - of Aer. - Also fixed check of bacth execution. diff --git a/releasenotes/notes/fix_simulator_init_gpu-597afb3d5241ed66.yaml b/releasenotes/notes/fix_simulator_init_gpu-597afb3d5241ed66.yaml deleted file mode 100644 index de2340b854..0000000000 --- a/releasenotes/notes/fix_simulator_init_gpu-597afb3d5241ed66.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -fixes: - - | - This fix changes `device` query method from running simple circuit to - search devices from C++ binary to prevent initializing GPUs at - initialization phase and simulation methods are listed in Python code. - Aer built with GPU support will not initialize when `device=CPU` is used. - And only initialize and access GPUs defined in `target_gpus` option. diff --git a/releasenotes/notes/fix_stabilizer_ry_gate-07538d8a2462c09d.yaml b/releasenotes/notes/fix_stabilizer_ry_gate-07538d8a2462c09d.yaml deleted file mode 100644 index 66c10e1191..0000000000 --- a/releasenotes/notes/fix_stabilizer_ry_gate-07538d8a2462c09d.yaml +++ /dev/null @@ -1,4 +0,0 @@ ---- -fixes: - - | - fixed ry gate for stabilizer method, PI/2 and PI3/2 was inverted diff --git a/releasenotes/notes/fix_test_for_Qiskit0.45.2-e0544949be8e77fb.yaml b/releasenotes/notes/fix_test_for_Qiskit0.45.2-e0544949be8e77fb.yaml deleted file mode 100644 index db24067919..0000000000 --- a/releasenotes/notes/fix_test_for_Qiskit0.45.2-e0544949be8e77fb.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -fixes: - - | - Fixes test cases failed due to upgrade of Qiskit. - - Removed importing Aer from qiskit. - - QuantumCircuit.diagonal was deprecated, using circuit.library.Diagonal instead diff --git a/releasenotes/notes/fix_transpiler_lvl_for_dynamic_circuit-4ead3b497bbcc632.yaml b/releasenotes/notes/fix_transpiler_lvl_for_dynamic_circuit-4ead3b497bbcc632.yaml deleted file mode 100644 index e42a2b33c1..0000000000 --- a/releasenotes/notes/fix_transpiler_lvl_for_dynamic_circuit-4ead3b497bbcc632.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -fixes: - - | - For dynamic circuits, aer_compiler calls transpiler without optimizaiton - level. Because id gates are removed by transpiler, noise applied id gates - did not work correctly. This fix adds optimization_level=0 not to remove - id gates of dynamic circuits diff --git a/releasenotes/notes/0.13/implicit_cast_for_arguments-a3c671db2fff6f17.yaml b/releasenotes/notes/implicit_cast_for_arguments-a3c671db2fff6f17.yaml similarity index 100% rename from releasenotes/notes/0.13/implicit_cast_for_arguments-a3c671db2fff6f17.yaml rename to releasenotes/notes/implicit_cast_for_arguments-a3c671db2fff6f17.yaml diff --git a/releasenotes/notes/parallel-probabilistic-measurement-mps-ec00a896a0322213.yaml b/releasenotes/notes/parallel-probabilistic-measurement-mps-ec00a896a0322213.yaml deleted file mode 100644 index 1ed6a7ba01..0000000000 --- a/releasenotes/notes/parallel-probabilistic-measurement-mps-ec00a896a0322213.yaml +++ /dev/null @@ -1,5 +0,0 @@ ---- -upgrade: - - | - Improve performance in MPS measurement method ``matrix_product_state::sample_measure_all`` - by parallelizing the shots. diff --git a/releasenotes/notes/0.13/primitives-grouping-index-bug-56f69afbdc3e86a0.yaml b/releasenotes/notes/primitives-grouping-index-bug-56f69afbdc3e86a0.yaml similarity index 100% rename from releasenotes/notes/0.13/primitives-grouping-index-bug-56f69afbdc3e86a0.yaml rename to releasenotes/notes/primitives-grouping-index-bug-56f69afbdc3e86a0.yaml diff --git a/releasenotes/notes/psutil-added-ffb2a4b5956fa03d.yaml b/releasenotes/notes/psutil-added-ffb2a4b5956fa03d.yaml deleted file mode 100644 index 34939eafd2..0000000000 --- a/releasenotes/notes/psutil-added-ffb2a4b5956fa03d.yaml +++ /dev/null @@ -1,9 +0,0 @@ ---- -upgrade: - - | - Added `psutil `__ as a dependency for - Qiskit Aer. This is used to determine the amount of physical resources - available. ``psutil`` is currently a dependency of Qiskit, which is a - requirement for Qiskit Aer, so ``psutil`` was effectively already required - for any ``qiskit-aer`` installation. But, as qiskit-aer is now using it - directly is now a direct dependency for ``qiskit-aer``. diff --git a/releasenotes/notes/remove-opflow-estimator-a3b64cfe8a4fd6b3.yaml b/releasenotes/notes/remove-opflow-estimator-a3b64cfe8a4fd6b3.yaml deleted file mode 100644 index f79a41724c..0000000000 --- a/releasenotes/notes/remove-opflow-estimator-a3b64cfe8a4fd6b3.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -upgrade: - - | - The :meth:`qiskit_aer.primitives.Estimator.run` method no longer supports - ``observables`` input arguments of type ``PauliSumOp``. The ``PauliSumOp`` - class was deprecated in Qiskit 0.44 and will be removed in Qiskit 1.0. - Alternative types that you can use instead of ``PauliSumOp`` are - :class:`qiskit.quantum_info.SparsePauliOp` or :class:`qiskit.quantum_info.Pauli`. diff --git a/releasenotes/notes/0.13/remove_aer_circuit_from_metadata-e4fe09029c1a3a3c.yaml b/releasenotes/notes/remove_aer_circuit_from_metadata-e4fe09029c1a3a3c.yaml similarity index 100% rename from releasenotes/notes/0.13/remove_aer_circuit_from_metadata-e4fe09029c1a3a3c.yaml rename to releasenotes/notes/remove_aer_circuit_from_metadata-e4fe09029c1a3a3c.yaml diff --git a/releasenotes/notes/0.13/remove_pulse_simulator-f8de2f6d380f446a.yaml b/releasenotes/notes/remove_pulse_simulator-f8de2f6d380f446a.yaml similarity index 100% rename from releasenotes/notes/0.13/remove_pulse_simulator-f8de2f6d380f446a.yaml rename to releasenotes/notes/remove_pulse_simulator-f8de2f6d380f446a.yaml diff --git a/releasenotes/notes/remove_qiskit_test-777882fa1591b6e7.yaml b/releasenotes/notes/remove_qiskit_test-777882fa1591b6e7.yaml deleted file mode 100644 index a66f7d10d6..0000000000 --- a/releasenotes/notes/remove_qiskit_test-777882fa1591b6e7.yaml +++ /dev/null @@ -1,4 +0,0 @@ ---- -deprecations: - - | - Removed importing qiskit.test from test and include some classes in Aer diff --git a/releasenotes/notes/0.13/renew_gpu_binaries-2cf3eba0853b8407.yaml b/releasenotes/notes/renew_gpu_binaries-2cf3eba0853b8407.yaml similarity index 100% rename from releasenotes/notes/0.13/renew_gpu_binaries-2cf3eba0853b8407.yaml rename to releasenotes/notes/renew_gpu_binaries-2cf3eba0853b8407.yaml diff --git a/releasenotes/notes/0.13/save_statevector_for_qasm3_circ-642ade99af3ff0d2.yaml b/releasenotes/notes/save_statevector_for_qasm3_circ-642ade99af3ff0d2.yaml similarity index 100% rename from releasenotes/notes/0.13/save_statevector_for_qasm3_circ-642ade99af3ff0d2.yaml rename to releasenotes/notes/save_statevector_for_qasm3_circ-642ade99af3ff0d2.yaml diff --git a/releasenotes/notes/0.13/support_int_initialize-8491979c4a003908.yaml b/releasenotes/notes/support_int_initialize-8491979c4a003908.yaml similarity index 100% rename from releasenotes/notes/0.13/support_int_initialize-8491979c4a003908.yaml rename to releasenotes/notes/support_int_initialize-8491979c4a003908.yaml diff --git a/releasenotes/notes/0.13/support_param_for_global_phase-704a97129e7bdbaa.yaml b/releasenotes/notes/support_param_for_global_phase-704a97129e7bdbaa.yaml similarity index 100% rename from releasenotes/notes/0.13/support_param_for_global_phase-704a97129e7bdbaa.yaml rename to releasenotes/notes/support_param_for_global_phase-704a97129e7bdbaa.yaml diff --git a/releasenotes/notes/0.13/support_switch-41603d87cb8358fb.yaml b/releasenotes/notes/support_switch-41603d87cb8358fb.yaml similarity index 100% rename from releasenotes/notes/0.13/support_switch-41603d87cb8358fb.yaml rename to releasenotes/notes/support_switch-41603d87cb8358fb.yaml diff --git a/releasenotes/notes/0.13/support_u3_runtime_api-42f013f111c319ff.yaml b/releasenotes/notes/support_u3_runtime_api-42f013f111c319ff.yaml similarity index 100% rename from releasenotes/notes/0.13/support_u3_runtime_api-42f013f111c319ff.yaml rename to releasenotes/notes/support_u3_runtime_api-42f013f111c319ff.yaml diff --git a/releasenotes/notes/0.13/use_omp_set_max_active_levels-7e6c1d301c4434a6.yaml b/releasenotes/notes/use_omp_set_max_active_levels-7e6c1d301c4434a6.yaml similarity index 100% rename from releasenotes/notes/0.13/use_omp_set_max_active_levels-7e6c1d301c4434a6.yaml rename to releasenotes/notes/use_omp_set_max_active_levels-7e6c1d301c4434a6.yaml diff --git a/releasenotes/notes/windows-blas-42b3dbc170c5ae94.yaml b/releasenotes/notes/windows-blas-42b3dbc170c5ae94.yaml deleted file mode 100644 index 2a17a5544f..0000000000 --- a/releasenotes/notes/windows-blas-42b3dbc170c5ae94.yaml +++ /dev/null @@ -1,6 +0,0 @@ ---- -features: - - | - Added CMake option ``USE_BUNDLED_BLAS_WIN`` which allows CMake to search - for a BLAS library against which to link instead of using the OpenBLAS - library bundled into the repo. diff --git a/requirements-dev.txt b/requirements-dev.txt index 8bde4bcb81..d1a45eda8b 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -13,7 +13,7 @@ reno>=3.4.0 ddt>=1.2.0,!=1.4.0 matplotlib>=3.3 seaborn>=0.9.0 -qiskit_sphinx_theme~=1.16.0 +qiskit_sphinx_theme~=1.12.0 sphinx-design>=0.2.0 nbsphinx qiskit_qasm3_import diff --git a/setup.py b/setup.py index 20c5268c84..5e9285c208 100644 --- a/setup.py +++ b/setup.py @@ -12,20 +12,12 @@ PACKAGE_NAME = os.getenv("QISKIT_AER_PACKAGE_NAME", "qiskit-aer") CUDA_MAJOR = os.getenv("QISKIT_AER_CUDA_MAJOR", "12") -# Allow build without the CUDA requirements. This is useful in case one intends to use a CUDA that exists in the host system. -ADD_CUDA_REQUIREMENTS = ( - False - if os.getenv("QISKIT_ADD_CUDA_REQUIREMENTS", "true").lower() in ["false", "off", "no"] - else True -) - extras_requirements = {"dask": ["dask", "distributed"]} requirements = [ - "qiskit>=0.45.0", + "qiskit-terra>=0.21.0", "numpy>=1.16.3", "scipy>=1.0", - "psutil>=5", ] classifiers = [ @@ -43,15 +35,10 @@ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", "Topic :: Scientific/Engineering", ] - -# ROCm is expected to be available in the target system to enable CDNA GPUs, so no -# requirements to be loaded. Also, no ROCm related classifiers are in place that -# could be used here. -if ADD_CUDA_REQUIREMENTS and "gpu" in PACKAGE_NAME and "rocm" not in PACKAGE_NAME: +if "gpu" in PACKAGE_NAME: if "11" in CUDA_MAJOR: requirements_cuda = [ "nvidia-cuda-runtime-cu11>=11.8.89", @@ -66,7 +53,6 @@ else: requirements_cuda = [ "nvidia-cuda-runtime-cu12>=12.1.105", - "nvidia-nvjitlink-cu12", "nvidia-cublas-cu12>=12.1.3.1", "nvidia-cusolver-cu12>=11.4.5.107", "nvidia-cusparse-cu12>=12.1.0.106", @@ -92,13 +78,12 @@ if is_win_32_bit: cmake_args.append("-DCMAKE_GENERATOR_PLATFORM=Win32") - setup( name=PACKAGE_NAME, version=VERSION, packages=setuptools.find_packages(exclude=["test*"]), cmake_source_dir=".", - description="Aer - High performance simulators for Qiskit", + description="Qiskit Aer - High performance simulators for Qiskit", long_description=README, long_description_content_type="text/markdown", url="https://github.com/Qiskit/qiskit-aer", @@ -112,11 +97,6 @@ package_data={"qiskit_aer": ["VERSION.txt"], "qiskit_aer.library": ["*.csv"]}, extras_require=extras_requirements, cmake_args=cmake_args, - keywords="qiskit, simulator, quantum computing, backend", + keywords="qiskit aer simulator quantum addon backend", zip_safe=False, - entry_points={ - "qiskit.transpiler.translation": [ - "aer_backend_plugin = qiskit_aer.backends.plugin.aer_backend_plugin:AerBackendPlugin", - ] - }, ) diff --git a/src/controllers/aer_controller.hpp b/src/controllers/aer_controller.hpp index b714ca4c33..c455f5fc20 100755 --- a/src/controllers/aer_controller.hpp +++ b/src/controllers/aer_controller.hpp @@ -74,7 +74,7 @@ namespace AER { class Controller { public: - Controller() {} + Controller() { clear_parallelization(); } //----------------------------------------------------------------------- // Execute qobj @@ -96,8 +96,8 @@ class Controller { // config settings will be passed to the State and Data classes void set_config(const Config &config); - // return available devicess - std::vector available_devices(); + // Clear the current config + void clear_config(); protected: //----------------------------------------------------------------------- @@ -131,7 +131,7 @@ class Controller { // If `throw_except` is true an exception will be thrown on the return false // case listing the invalid instructions in the circuit or noise model, or // the required memory. - bool validate_method(Method method, const Config &config, const Circuit &circ, + bool validate_method(Method method, const Circuit &circ, const Noise::NoiseModel &noise, bool throw_except = false) const; @@ -147,14 +147,13 @@ class Controller { // The noise model will be modified to enable superop or kraus sampling // methods if required by the chosen methods. std::vector - simulation_methods(const Config &config, - std::vector> &circuits, + simulation_methods(std::vector> &circuits, Noise::NoiseModel &noise_model) const; // Return the simulation method to use based on the input circuit // and noise model Method - automatic_simulation_method(const Config &config, const Circuit &circ, + automatic_simulation_method(const Circuit &circ, const Noise::NoiseModel &noise_model) const; bool has_statevector_ops(const Circuit &circuit) const; @@ -162,8 +161,13 @@ class Controller { // Parallelization Config //----------------------------------------------------------------------- + // Set OpenMP thread settings to default values + void clear_parallelization(); + // Set parallelization for experiments - void set_parallelization_experiments(const reg_t &required_memory_list); + void set_parallelization_experiments( + const std::vector> &circuits, + const Noise::NoiseModel &noise, const std::vector &methods); void save_exception_to_results(Result &result, const std::exception &e) const; @@ -172,18 +176,18 @@ class Controller { size_t get_gpu_memory_mb(); // The maximum number of threads to use for various levels of parallelization - int max_parallel_threads_ = 0; + int max_parallel_threads_; // Parameters for parallelization management in configuration - int max_parallel_experiments_ = 1; - size_t max_memory_mb_ = 0; - size_t max_gpu_memory_mb_ = 0; + int max_parallel_experiments_; + size_t max_memory_mb_; + size_t max_gpu_memory_mb_; // use explicit parallelization - bool explicit_parallelization_ = false; + bool explicit_parallelization_; // Parameters for parallelization management for experiments - int parallel_experiments_ = 1; + int parallel_experiments_; bool parallel_nested_ = false; @@ -191,11 +195,6 @@ class Controller { int myrank_ = 0; int num_processes_ = 1; int num_process_per_experiment_ = 1; - - // runtime parameter binding - bool runtime_parameter_bind_ = false; - - reg_t target_gpus_; // GPUs to be used }; //========================================================================= @@ -230,8 +229,6 @@ void Controller::set_config(const Config &config) { if (config.max_memory_mb.has_value()) max_memory_mb_ = config.max_memory_mb.value(); - else - max_memory_mb_ = get_system_memory_mb(); // for debugging if (config._parallel_experiments.has_value()) { @@ -308,21 +305,7 @@ void Controller::set_config(const Config &config) { cudaGetLastError(); throw std::runtime_error("No CUDA device available!"); } - if (config.target_gpus.has_value()) { - target_gpus_ = config.target_gpus.value(); - - if (nDev < target_gpus_.size()) { - throw std::invalid_argument( - "target_gpus has more GPUs than available."); - } - } else { - target_gpus_.resize(nDev); - for (int_t i = 0; i < nDev; i++) - target_gpus_[i] = i; - } sim_device_ = Device::GPU; - - max_gpu_memory_mb_ = get_gpu_memory_mb(); #endif } else { throw std::runtime_error(std::string("Invalid simulation device (\"") + @@ -347,19 +330,36 @@ void Controller::set_config(const Config &config) { throw std::runtime_error(std::string("Invalid simulation precision (") + precision + std::string(").")); } +} - // check if runtime binding is enable - if (config.runtime_parameter_bind_enable.has_value()) - runtime_parameter_bind_ = config.runtime_parameter_bind_enable.value(); +void Controller::clear_config() { + clear_parallelization(); + method_ = Method::automatic; + sim_device_ = Device::CPU; + sim_precision_ = Precision::Double; } -void Controller::set_parallelization_experiments( - const reg_t &required_memory_mb_list) { +void Controller::clear_parallelization() { + max_parallel_threads_ = 0; + max_parallel_experiments_ = 1; + parallel_experiments_ = 1; + parallel_nested_ = false; + + num_process_per_experiment_ = 1; + + explicit_parallelization_ = false; + max_memory_mb_ = get_system_memory_mb(); + max_gpu_memory_mb_ = get_gpu_memory_mb(); +} + +void Controller::set_parallelization_experiments( + const std::vector> &circuits, + const Noise::NoiseModel &noise, const std::vector &methods) { if (explicit_parallelization_) return; - if (required_memory_mb_list.size() == 1) { + if (circuits.size() == 1) { parallel_experiments_ = 1; return; } @@ -378,12 +378,20 @@ void Controller::set_parallelization_experiments( } // If memory allows, execute experiments in parallel - reg_t required_sorted = required_memory_mb_list; - std::sort(required_sorted.begin(), required_sorted.end(), std::greater<>()); + std::vector required_memory_mb_list(circuits.size()); + for (size_t j = 0; j < circuits.size(); j++) { + std::shared_ptr executor = + make_circuit_executor(methods[j]); + required_memory_mb_list[j] = + executor->required_memory_mb(*circuits[j], noise); + executor.reset(); + } + std::sort(required_memory_mb_list.begin(), required_memory_mb_list.end(), + std::greater<>()); size_t total_memory = 0; int parallel_experiments = 0; - for (size_t required_memory_mb : required_sorted) { + for (size_t required_memory_mb : required_memory_mb_list) { total_memory += required_memory_mb; if (total_memory > max_memory_mb_) break; @@ -393,9 +401,9 @@ void Controller::set_parallelization_experiments( if (parallel_experiments <= 0) throw std::runtime_error( "a circuit requires more memory than max_memory_mb."); - parallel_experiments_ = std::min( - {parallel_experiments, max_experiments, max_parallel_threads_, - static_cast(required_memory_mb_list.size())}); + parallel_experiments_ = + std::min({parallel_experiments, max_experiments, + max_parallel_threads_, static_cast(circuits.size())}); } size_t Controller::get_system_memory_mb() { @@ -414,9 +422,14 @@ size_t Controller::get_system_memory_mb() { size_t Controller::get_gpu_memory_mb() { size_t total_physical_memory = 0; #ifdef AER_THRUST_GPU - for (uint_t iDev = 0; iDev < target_gpus_.size(); iDev++) { + int iDev, nDev, j; + if (cudaGetDeviceCount(&nDev) != cudaSuccess) { + cudaGetLastError(); + nDev = 0; + } + for (iDev = 0; iDev < nDev; iDev++) { size_t freeMem, totalMem; - cudaSetDevice(target_gpus_[iDev]); + cudaSetDevice(iDev); cudaMemGetInfo(&freeMem, &totalMem); total_physical_memory += totalMem; } @@ -433,20 +446,6 @@ size_t Controller::get_gpu_memory_mb() { return total_physical_memory >> 20; } -std::vector Controller::available_devices() { - std::vector ret; - - ret.push_back(std::string("CPU")); -#ifdef AER_THRUST_GPU - ret.push_back(std::string("GPU")); -#else -#ifdef AER_THRUST_CPU - ret.push_back(std::string("Thrust")); -#endif -#endif - return ret; -} - //------------------------------------------------------------------------- // Qobj execution //------------------------------------------------------------------------- @@ -509,21 +508,10 @@ Result Controller::execute(std::vector> &circuits, #endif // Determine simulation method for each circuit // and enable required noise sampling methods - auto methods = simulation_methods(config, circuits, noise_model); + auto methods = simulation_methods(circuits, noise_model); // Initialize Result object for the given number of experiments - uint_t result_size; - reg_t result_offset(circuits.size()); - result_size = 0; - for (uint_t i = 0; i < circuits.size(); i++) { - result_offset[i] = result_size; - result_size += circuits[i]->num_bind_params; - } - Result result(result_size); - // Initialize circuit executors for each circuit - std::vector> executors( - circuits.size()); - reg_t required_memory_mb_list(circuits.size()); + Result result(circuits.size()); // Execute each circuit in a try block try { @@ -531,17 +519,9 @@ Result Controller::execute(std::vector> &circuits, // set parallelization for experiments try { - uint_t res_pos = 0; - for (uint_t i = 0; i < circuits.size(); i++) { - executors[i] = make_circuit_executor(methods[i]); - required_memory_mb_list[i] = - executors[i]->required_memory_mb(config, *circuits[i], noise_model); - for (uint_t j = 0; j < circuits[i]->num_bind_params; j++) { - result.results[res_pos++].metadata.add(required_memory_mb_list[i], - "required_memory_mb"); - } - } - set_parallelization_experiments(required_memory_mb_list); + // catch exception raised by required_memory_mb because of invalid + // simulation method + set_parallelization_experiments(circuits, noise_model, methods); } catch (std::exception &e) { save_exception_to_results(result, e); } @@ -561,7 +541,7 @@ Result Controller::execute(std::vector> &circuits, // nested should be set to zero if num_threads clause will be used #if _OPENMP >= 200805 - omp_set_max_active_levels(1); + omp_set_max_active_levels(2); #else omp_set_nested(1); #endif @@ -585,48 +565,46 @@ Result Controller::execute(std::vector> &circuits, // average random seed to set the same seed to each process (when // seed_simulator is not set) if (num_processes_ > 1) { - reg_t seeds(result_size); - reg_t avg_seeds(result_size); - int_t iseed = 0; - for (uint_t i = 0; i < circuits.size(); i++) { - if (circuits[i]->num_bind_params > 1) { - for (uint_t j = 0; i < circuits[i]->num_bind_params; i++) - seeds[iseed++] = circuits[i]->seed_for_params[j]; - } else - seeds[iseed++] = circuits[i]->seed; - } - MPI_Allreduce(seeds.data(), avg_seeds.data(), result_size, MPI_UINT64_T, - MPI_SUM, MPI_COMM_WORLD); - iseed = 0; - for (uint_t i = 0; i < circuits.size(); i++) { - if (circuits[i]->num_bind_params > 1) { - for (uint_t j = 0; i < circuits[i]->num_bind_params; i++) - circuits[i]->seed_for_params[j] = - avg_seeds[iseed++] / num_processes_; - } else - circuits[i]->seed = avg_seeds[iseed++] / num_processes_; - } + reg_t seeds(circuits.size()); + reg_t avg_seeds(circuits.size()); + for (int_t i = 0; i < circuits.size(); i++) + seeds[i] = circuits[i]->seed; + MPI_Allreduce(seeds.data(), avg_seeds.data(), circuits.size(), + MPI_UINT64_T, MPI_SUM, MPI_COMM_WORLD); + for (int_t i = 0; i < circuits.size(); i++) + circuits[i]->seed = avg_seeds[i] / num_processes_; } #endif - auto run_circuits = [this, &executors, &circuits, &noise_model, &config, - &methods, &result, &result_offset](int_t i) { - executors[i]->run_circuit(*circuits[i], noise_model, config, methods[i], - sim_device_, - result.results.begin() + result_offset[i]); - }; - Utils::apply_omp_parallel_for((parallel_experiments_ > 1), 0, - circuits.size(), run_circuits, - parallel_experiments_); - - executors.clear(); + const int NUM_RESULTS = result.results.size(); + // following looks very similar but we have to separate them to avoid omp + // nested loops that causes performance degradation (DO NOT use if statement + // in #pragma omp) + if (parallel_experiments_ == 1) { + for (int j = 0; j < NUM_RESULTS; ++j) { + std::shared_ptr executor = + make_circuit_executor(methods[j]); + executor->run_circuit(*circuits[j], noise_model, config, methods[j], + sim_device_, result.results[j]); + executor.reset(); + } + } else { +#pragma omp parallel for num_threads(parallel_experiments_) + for (int j = 0; j < NUM_RESULTS; ++j) { + std::shared_ptr executor = + make_circuit_executor(methods[j]); + executor->run_circuit(*circuits[j], noise_model, config, methods[j], + sim_device_, result.results[j]); + executor.reset(); + } + } // Check each experiment result for completed status. // If only some experiments completed return partial completed status. bool all_failed = true; result.status = Result::Status::completed; - for (uint_t i = 0; i < result.results.size(); ++i) { + for (int i = 0; i < NUM_RESULTS; ++i) { auto &experiment = result.results[i]; if (experiment.status == ExperimentResult::Status::completed) { all_failed = false; @@ -777,8 +755,7 @@ Controller::make_circuit_executor(const Method method) const { } std::vector -Controller::simulation_methods(const Config &config, - std::vector> &circuits, +Controller::simulation_methods(std::vector> &circuits, Noise::NoiseModel &noise_model) const { // Does noise model contain kraus noise bool kraus_noise = @@ -792,7 +769,7 @@ Controller::simulation_methods(const Config &config, bool kraus_enabled = false; for (const auto &_circ : circuits) { const auto circ = *_circ; - auto method = automatic_simulation_method(config, circ, noise_model); + auto method = automatic_simulation_method(circ, noise_model); sim_methods.push_back(method); if (!superop_enabled && (method == Method::density_matrix || method == Method::superop || @@ -834,24 +811,22 @@ Controller::simulation_methods(const Config &config, } Method Controller::automatic_simulation_method( - const Config &config, const Circuit &circ, - const Noise::NoiseModel &noise_model) const { + const Circuit &circ, const Noise::NoiseModel &noise_model) const { + // If circuit and noise model are Clifford run on Stabilizer simulator + if (validate_method(Method::stabilizer, circ, noise_model, false)) { + return Method::stabilizer; + } // For noisy simulations we enable the density matrix method if // shots > 2 ** num_qubits. This is based on a rough estimate that // a single shot of the density matrix simulator is approx 2 ** nq // times slower than a single shot of statevector due the increased // dimension - if (noise_model.has_quantum_errors() && circ.num_qubits < 30 && + if (noise_model.has_quantum_errors() && circ.num_qubits < 64 && circ.shots > (1ULL << circ.num_qubits) && - validate_method(Method::density_matrix, config, circ, noise_model, - false) && + validate_method(Method::density_matrix, circ, noise_model, false) && circ.can_sample) { return Method::density_matrix; } - // If circuit and noise model are Clifford run on Stabilizer simulator - if (validate_method(Method::stabilizer, config, circ, noise_model, false)) { - return Method::stabilizer; - } // If the special conditions for stabilizer or density matrix are // not satisfied we choose simulation method based on supported @@ -862,7 +837,7 @@ Method Controller::automatic_simulation_method( {Method::statevector, Method::density_matrix, Method::matrix_product_state, Method::unitary, Method::superop}); for (const auto &method : methods) { - if (validate_method(method, config, circ, noise_model, false)) + if (validate_method(method, circ, noise_model, false)) return method; } @@ -892,13 +867,12 @@ bool Controller::has_statevector_ops(const Circuit &circ) const { //------------------------------------------------------------------------- // Validation //------------------------------------------------------------------------- -bool Controller::validate_method(Method method, const Config &config, - const Circuit &circ, +bool Controller::validate_method(Method method, const Circuit &circ, const Noise::NoiseModel &noise_model, bool throw_except) const { std::shared_ptr executor = make_circuit_executor(method); - bool ret = executor->validate_state(config, circ, noise_model, throw_except); + bool ret = executor->validate_state(circ, noise_model, throw_except); executor.reset(); return ret; } diff --git a/src/controllers/controller_execute.hpp b/src/controllers/controller_execute.hpp index 88d9c460f1..4c2015461f 100644 --- a/src/controllers/controller_execute.hpp +++ b/src/controllers/controller_execute.hpp @@ -67,12 +67,7 @@ Result controller_execute(std::vector> &input_circs, // pars = [par0, par1, ...] is a list of different parameterizations using pos_t = std::pair; using exp_params_t = std::vector>>; - std::vector ¶m_table = config.param_table; - - // check if runtime binding is enable - bool runtime_parameter_bind = false; - if (config.runtime_parameter_bind_enable.has_value()) - runtime_parameter_bind = config.runtime_parameter_bind_enable.value(); + std::vector param_table = config.param_table; // Validate parameterizations for number of circuis if (!param_table.empty() && param_table.size() != num_circs) { @@ -83,8 +78,6 @@ Result controller_execute(std::vector> &input_circs, std::vector> circs; std::vector> template_circs; - using myclock_t = std::chrono::high_resolution_clock; - auto timer_start = myclock_t::now(); try { // Load circuits for (size_t i = 0; i < num_circs; i++) { @@ -100,41 +93,39 @@ Result controller_execute(std::vector> &input_circs, circ->set_params(false); circ->set_metadata(config, truncate); // Load different parameterizations of the initial circuit - const auto &circ_params = param_table[i]; + const auto circ_params = param_table[i]; const size_t num_params = circ_params[0].second.size(); const size_t num_instr = circ->ops.size(); - - if (runtime_parameter_bind && num_params > 1) { + for (size_t j = 0; j < num_params; j++) { // Make a copy of the initial circuit auto param_circ = std::make_shared(*circ); - param_circ->num_bind_params = num_params; - for (const auto ¶ms : circ_params) { const auto instr_pos = params.first.first; const auto param_pos = params.first.second; // Validation if (instr_pos == AER::Config::GLOBAL_PHASE_POS) { // negative position is for global phase - param_circ->global_phase_for_params.resize(num_params); - for (size_t j = 0; j < num_params; j++) - param_circ->global_phase_for_params[j] = params.second[j]; - } else if ((uint_t)instr_pos >= num_instr) { - throw std::invalid_argument( - R"(Invalid parameterized qobj: instruction position out of range)"); - } - auto &op = param_circ->ops[instr_pos]; - if (!op.has_bind_params) { - if ((uint_t)param_pos >= op.params.size()) { + param_circ->global_phase_angle = params.second[j]; + } else { + if (instr_pos >= num_instr) { + std::cout << "Invalid parameterization: instruction position " + "out of range: " + << instr_pos << std::endl; + throw std::invalid_argument( + R"(Invalid parameterization: instruction position out of range)"); + } + auto &op = param_circ->ops[instr_pos]; + if (param_pos >= op.params.size()) { + throw std::invalid_argument( + R"(Invalid parameterization: instruction param position out of range)"); + } + if (j >= params.second.size()) { throw std::invalid_argument( - R"(Invalid parameterized qobj: instruction param position out of range)"); + R"(Invalid parameterization: parameterization value out of range)"); } - // resize parameter array - op.params.resize(op.params.size() * num_params); - op.has_bind_params = true; + // Update the param + op.params[param_pos] = params.second[j]; } - uint_t stride = op.params.size() / num_params; - for (size_t j = 0; j < num_params; j++) - op.params[param_pos + stride * j] = params.second[j]; } // Run truncation. // TODO: Truncation should be performed and parameters should be @@ -146,53 +137,7 @@ Result controller_execute(std::vector> &input_circs, param_circ->set_metadata(config, true); } circs.push_back(param_circ); - for (size_t j = 0; j < num_params; j++) - template_circs.push_back(circ); - } else { - for (size_t j = 0; j < num_params; j++) { - // Make a copy of the initial circuit - auto param_circ = std::make_shared(*circ); - for (const auto ¶ms : circ_params) { - const auto instr_pos = params.first.first; - const auto param_pos = params.first.second; - // Validation - if (instr_pos == AER::Config::GLOBAL_PHASE_POS) { - // negative position is for global phase - circ->global_phase_angle = params.second[j]; - } else { - if ((uint_t)instr_pos >= num_instr) { - std::cout << "Invalid parameterization: instruction position " - "out of range: " - << instr_pos << std::endl; - throw std::invalid_argument( - R"(Invalid parameterization: instruction position out of range)"); - } - auto &op = param_circ->ops[instr_pos]; - if ((uint_t)param_pos >= op.params.size()) { - throw std::invalid_argument( - R"(Invalid parameterization: instruction param position out of range)"); - } - if (j >= params.second.size()) { - throw std::invalid_argument( - R"(Invalid parameterization: parameterization value out of range)"); - } - // Update the param - op.params[param_pos] = params.second[j]; - } - } - // Run truncation. - // TODO: Truncation should be performed and parameters should be - // resolved after it. However, parameters are associated with - // indices of instructions, which can be changed in truncation. - // Therefore, current implementation performs truncation for each - // parameter set. - if (truncate) { - param_circ->set_params(true); - param_circ->set_metadata(config, true); - } - circs.push_back(param_circ); - template_circs.push_back(circ); - } + template_circs.push_back(circ); } } } @@ -203,6 +148,7 @@ Result controller_execute(std::vector> &input_circs, result.message = std::string("Failed to load circuits: ") + e.what(); return result; } + int_t seed = -1; uint_t seed_shift = 0; @@ -211,23 +157,10 @@ Result controller_execute(std::vector> &input_circs, else seed = circs[0]->seed; - if (runtime_parameter_bind) { - for (auto &circ : circs) { - circ->seed = seed + seed_shift; - circ->seed_for_params.resize(circ->num_bind_params); - for (uint_t i = 0; i < circ->num_bind_params; i++) { - circ->seed_for_params[i] = seed + seed_shift; - seed_shift += 2113; - } - } - } else { - for (auto &circ : circs) { - circ->seed = seed + seed_shift; - seed_shift += 2113; - } + for (auto &circ : circs) { + circ->seed = seed + seed_shift; + seed_shift += 2113; } - auto time_taken = - std::chrono::duration(myclock_t::now() - timer_start).count(); // Fix for MacOS and OpenMP library double initialization crash. // Issue: https://github.com/Qiskit/qiskit-aer/issues/1 @@ -237,7 +170,6 @@ Result controller_execute(std::vector> &input_circs, for (size_t i = 0; i < ret.results.size(); ++i) ret.results[i].circ_id = template_circs[i]->circ_id; - ret.metadata.add(time_taken, "time_taken_parameter_binding"); return ret; } diff --git a/src/controllers/state_controller.hpp b/src/controllers/state_controller.hpp index 028806e822..8b3cdf30cd 100644 --- a/src/controllers/state_controller.hpp +++ b/src/controllers/state_controller.hpp @@ -310,12 +310,6 @@ class AerState { // If N=3 this implements an optimized CCRZ gate virtual void apply_mcrz(const reg_t &qubits, const double theta); - // Apply a general N-qubit multi-controlled SX-gate - // If N=1 this implements an optimized SX gate - // If N=2 this implements an optimized CSX gate - // If N=3 this implements an optimized CCSX gate - virtual void apply_mcsx(const reg_t &qubits); - //----------------------------------------------------------------------- // Apply Non-Unitary Gates //----------------------------------------------------------------------- @@ -630,7 +624,7 @@ void AerState::set_seed(int_t seed) { reg_t AerState::allocate_qubits(uint_t num_qubits) { assert_not_initialized(); reg_t ret; - for (uint_t i = 0; i < num_qubits; ++i) + for (auto i = 0; i < num_qubits; ++i) ret.push_back(num_of_qubits_++); return ret; }; @@ -816,7 +810,7 @@ reg_t AerState::initialize_statevector(uint_t num_of_qubits, complex_t *data, reg_t ret; ret.reserve(num_of_qubits); - for (uint_t i = 0; i < num_of_qubits; ++i) + for (auto i = 0; i < num_of_qubits; ++i) ret.push_back(i); return ret; }; @@ -861,7 +855,7 @@ reg_t AerState::initialize_density_matrix(uint_t num_of_qubits, complex_t *data, reg_t ret; ret.reserve(num_of_qubits); - for (uint_t i = 0; i < num_of_qubits; ++i) + for (auto i = 0; i < num_of_qubits; ++i) ret.push_back(i); return ret; }; @@ -892,7 +886,7 @@ AER::Vector AerState::move_to_vector() { throw std::runtime_error("move_to_vector() supports only statevector or " "matrix_product_state or density_matrix methods"); } - for (uint_t i = 0; i < num_of_qubits_; ++i) + for (auto i = 0; i < num_of_qubits_; ++i) op.qubits.push_back(i); op.string_params.push_back("s"); op.save_type = Operations::DataSubType::single; @@ -907,7 +901,7 @@ AER::Vector AerState::move_to_vector() { .value()["s"] .value()); clear(); - return vec; + return std::move(vec); } else if (method_ == Method::density_matrix) { auto mat = std::move(static_cast, 1>>( @@ -917,7 +911,7 @@ AER::Vector AerState::move_to_vector() { auto vec = Vector::move_from_buffer( mat.GetColumns() * mat.GetRows(), mat.move_to_buffer()); clear(); - return vec; + return std::move(vec); } else { throw std::runtime_error("move_to_vector() supports only statevector or " "matrix_product_state or density_matrix methods"); @@ -941,7 +935,7 @@ matrix AerState::move_to_matrix() { throw std::runtime_error("move_to_matrix() supports only statevector or " "matrix_product_state or density_matrix methods"); } - for (uint_t i = 0; i < num_of_qubits_; ++i) + for (auto i = 0; i < num_of_qubits_; ++i) op.qubits.push_back(i); op.string_params.push_back("s"); op.save_type = Operations::DataSubType::single; @@ -966,7 +960,7 @@ matrix AerState::move_to_matrix() { .value())["s"] .value()); clear(); - return mat; + return std::move(mat); } else { throw std::runtime_error("move_to_matrix() supports only statevector or " "matrix_product_state or density_matrix methods"); @@ -1298,17 +1292,6 @@ void AerState::apply_mcrz(const reg_t &qubits, const double theta) { buffer_op(std::move(op)); } -void AerState::apply_mcsx(const reg_t &qubits) { - assert_initialized(); - - Operations::Op op; - op.type = Operations::OpType::gate; - op.qubits = qubits; - op.name = "mcsx"; - - buffer_op(std::move(op)); -} - //----------------------------------------------------------------------- // Apply Non-Unitary Gates //----------------------------------------------------------------------- diff --git a/src/framework/circuit.hpp b/src/framework/circuit.hpp index 35e79e7b2b..bc7645d694 100644 --- a/src/framework/circuit.hpp +++ b/src/framework/circuit.hpp @@ -63,11 +63,6 @@ class Circuit { double global_phase_angle = 0; bool remapped_qubits = false; // True if qubits have been remapped - // for runtime parameter bind, number of parameters per circuit - uint_t num_bind_params = 1; - reg_t seed_for_params; // random seed for each parameter - rvector_t global_phase_for_params; // global phase angles for each param - // Constructor // The constructor automatically calculates the num_qubits, num_memory, // num_registers parameters by scanning the input list of ops. @@ -135,25 +130,20 @@ class Circuit { void gate(const std::string &name, const reg_t &qubits, const std::vector ¶ms, const std::vector &string_params, - const int_t cond_regidx = -1, - const std::shared_ptr expr = nullptr, - const std::string label = "") { + const int_t cond_regidx = -1, const std::string label = "") { ops.push_back(Operations::make_gate(name, qubits, params, string_params, - cond_regidx, expr, label)); + cond_regidx, label)); check_gate_params(ops.back()); } void diagonal(const reg_t &qubits, const cvector_t &vec, - const int_t cond_regidx = -1, const std::string label = "") { - ops.push_back(Operations::make_diagonal(qubits, vec, cond_regidx, label)); + const std::string &label) { + ops.push_back(Operations::make_diagonal(qubits, vec, label)); } void unitary(const reg_t &qubits, const cmatrix_t &mat, - const int_t cond_regidx = -1, - const std::shared_ptr expr = nullptr, - const std::string label = "") { - ops.push_back( - Operations::make_unitary(qubits, mat, cond_regidx, expr, label)); + const int_t cond_regidx = -1, const std::string label = "") { + ops.push_back(Operations::make_unitary(qubits, mat, cond_regidx, label)); } void initialize(const reg_t &qubits, @@ -167,23 +157,19 @@ class Circuit { } void multiplexer(const reg_t &qubits, const std::vector &mats, - const int_t cond_regidx = -1, - const std::shared_ptr expr = nullptr, - std::string label = "") { + const int_t cond_regidx = -1, std::string label = "") { ops.push_back( - Operations::make_multiplexer(qubits, mats, cond_regidx, expr, label)); + Operations::make_multiplexer(qubits, mats, cond_regidx, label)); } void kraus(const reg_t &qubits, const std::vector &mats, - const int_t cond_regidx = -1, - const std::shared_ptr expr = nullptr) { - ops.push_back(Operations::make_kraus(qubits, mats, cond_regidx, expr)); + const int_t cond_regidx = -1) { + ops.push_back(Operations::make_kraus(qubits, mats, cond_regidx)); } void superop(const reg_t &qubits, const cmatrix_t &mat, - const int_t cond_regidx = -1, - const std::shared_ptr expr = nullptr) { - ops.push_back(Operations::make_superop(qubits, mat, cond_regidx, expr)); + const int_t cond_regidx = -1) { + ops.push_back(Operations::make_superop(qubits, mat, cond_regidx)); } void save_state(const reg_t &qubits, const std::string &name, @@ -213,10 +199,8 @@ class Circuit { } void set_qerror_loc(const reg_t &qubits, const std::string &label, - const int_t conditional = -1, - const std::shared_ptr expr = nullptr) { - ops.push_back( - Operations::make_qerror_loc(qubits, label, conditional, expr)); + const int_t conditional = -1) { + ops.push_back(Operations::make_qerror_loc(qubits, label, conditional)); } template @@ -253,9 +237,8 @@ class Circuit { } void jump(const reg_t &qubits, const std::vector ¶ms, - const int_t cond_regidx = -1, - const std::shared_ptr expr = nullptr) { - ops.push_back(Operations::make_jump(qubits, params, cond_regidx, expr)); + const int_t cond_regidx = -1) { + ops.push_back(Operations::make_jump(qubits, params, cond_regidx)); } void mark(const reg_t &qubits, const std::vector ¶ms) { @@ -271,8 +254,8 @@ class Circuit { ops.push_back(Operations::make_measure(qubits, memory, registers)); } - void reset(const reg_t &qubits, const int_t cond_regidx = -1) { - ops.push_back(Operations::make_reset(qubits, cond_regidx)); + void reset(const reg_t &qubits) { + ops.push_back(Operations::make_reset(qubits)); } private: @@ -513,7 +496,7 @@ void Circuit::set_params(bool truncation) { } const auto &op = ops[pos]; - if (op.conditional || (op.type == OpType::jump && op.expr)) { + if (op.conditional) { can_sample = false; break; } diff --git a/src/framework/config.hpp b/src/framework/config.hpp index ae95508ef2..60a5d7c313 100644 --- a/src/framework/config.hpp +++ b/src/framework/config.hpp @@ -125,7 +125,6 @@ struct Config { double chop_threshold = 1e-8; uint_t mps_parallel_threshold = 14; uint_t mps_omp_threads = 1; - bool mps_lapack = false; // # tensor network options uint_t tensor_network_num_sampling_qubits = 10; bool use_cuTensorNet_autotuning = false; @@ -172,7 +171,6 @@ struct Config { optional memory_blocking_bits; optional extended_stabilizer_norm_estimation_default_samples; optional target_gpus; - optional runtime_parameter_bind_enable; void clear() { shots = 1024; @@ -232,7 +230,6 @@ struct Config { chop_threshold = 1e-8; mps_parallel_threshold = 14; mps_omp_threads = 1; - mps_lapack = false; // # tensor network options tensor_network_num_sampling_qubits = 10; use_cuTensorNet_autotuning = false; @@ -273,9 +270,7 @@ struct Config { unitary_parallel_threshold.clear(); memory_blocking_bits.clear(); extended_stabilizer_norm_estimation_default_samples.clear(); - target_gpus.clear(); - runtime_parameter_bind_enable.clear(); } void merge(const Config &other) { @@ -361,7 +356,6 @@ struct Config { chop_threshold = other.chop_threshold; mps_parallel_threshold = other.mps_parallel_threshold; mps_omp_threads = other.mps_omp_threads; - mps_lapack = other.mps_lapack; // # tensor network options tensor_network_num_sampling_qubits = other.tensor_network_num_sampling_qubits; @@ -418,12 +412,8 @@ struct Config { if (other.extended_stabilizer_norm_estimation_default_samples.has_value()) extended_stabilizer_norm_estimation_default_samples.value( other.extended_stabilizer_norm_estimation_default_samples.value()); - if (other.target_gpus.has_value()) target_gpus.value(other.target_gpus.value()); - if (other.runtime_parameter_bind_enable.has_value()) - runtime_parameter_bind_enable.value( - other.runtime_parameter_bind_enable.value()); } }; @@ -502,7 +492,6 @@ inline void from_json(const json_t &js, Config &config) { get_value(config.chop_threshold, "chop_threshold", js); get_value(config.mps_parallel_threshold, "mps_parallel_threshold", js); get_value(config.mps_omp_threads, "mps_omp_threads", js); - get_value(config.mps_lapack, "mps_lapack", js); // # tensor network options get_value(config.tensor_network_num_sampling_qubits, "tensor_network_num_sampling_qubits", js); @@ -540,10 +529,8 @@ inline void from_json(const json_t &js, Config &config) { get_value(config.extended_stabilizer_norm_estimation_default_samples, "extended_stabilizer_norm_estimation_default_samples", js); get_value(config.target_gpus, "target_gpus", js); - get_value(config.runtime_parameter_bind_enable, - "runtime_parameter_bind_enable", js); } } // namespace AER -#endif +#endif \ No newline at end of file diff --git a/src/framework/creg.hpp b/src/framework/creg.hpp index b9c93d3a06..1a0d012865 100644 --- a/src/framework/creg.hpp +++ b/src/framework/creg.hpp @@ -136,8 +136,6 @@ bool ClassicalRegister::check_conditional(const Operations::Op &op) const { if (op.conditional) return (creg_register_[creg_register_.size() - op.conditional_reg - 1] == '1'); - if (op.expr) - return op.expr->eval_bool(creg_memory_); // Op is not conditional return true; @@ -188,23 +186,23 @@ void ClassicalRegister::apply_bfunc(const Operations::Op &op) { } // check value of compared integer for different comparison operations bool outcome; - switch (op.binary_op) { - case Operations::BinaryOp::Equal: + switch (op.bfunc) { + case Operations::RegComparison::Equal: outcome = (compared == 0); break; - case Operations::BinaryOp::NotEqual: + case Operations::RegComparison::NotEqual: outcome = (compared != 0); break; - case Operations::BinaryOp::Less: + case Operations::RegComparison::Less: outcome = (compared < 0); break; - case Operations::BinaryOp::LessEqual: + case Operations::RegComparison::LessEqual: outcome = (compared <= 0); break; - case Operations::BinaryOp::Greater: + case Operations::RegComparison::Greater: outcome = (compared > 0); break; - case Operations::BinaryOp::GreaterEqual: + case Operations::RegComparison::GreaterEqual: outcome = (compared >= 0); break; default: diff --git a/src/framework/json.hpp b/src/framework/json.hpp index f400641c50..172f4eb1ee 100644 --- a/src/framework/json.hpp +++ b/src/framework/json.hpp @@ -263,7 +263,7 @@ void std::from_json(const json_t &js, template void std::to_json(json_t &js, const AER::Vector> &vec) { std::vector> out; - for (size_t i = 0; i < vec.size(); ++i) { + for (int64_t i = 0; i < vec.size(); ++i) { auto &z = vec[i]; out.push_back(std::vector{real(z), imag(z)}); } diff --git a/src/framework/lapack_protos.hpp b/src/framework/lapack_protos.hpp index 18967f6496..a693a65988 100644 --- a/src/framework/lapack_protos.hpp +++ b/src/framework/lapack_protos.hpp @@ -8,6 +8,48 @@ #include #include +#ifdef MKL +#define MKL_Complex16 std::complex +#define MKL_Complex8 std::complex +#define LAPACK_INT size_t +#include + +void zgesvd_(const char *jobu, const char *jobvt, const size_t *m, + const size_t *n, std::complex *a, const size_t *lda, + double *s, std::complex *u, const size_t *ldu, + std::complex *vt, const size_t *ldvt, + std::complex *work, const size_t *lwork, double *rwork, + int *info); + +void zgesvd_(const char *jobu, const char *jobvt, const size_t *m, + const size_t *n, std::complex *a, const size_t *lda, + double *s, std::complex *u, const size_t *ldu, + std::complex *vt, const size_t *ldvt, + std::complex *work, const size_t *lwork, double *rwork, + int *info) { + *info = LAPACKE_zgesvd(CblasColMajor, *jobu, *jobvt, *m, *n, a, *lda, s, u, + *ldu, vt, *ldvt, rwork); +} + +void zgesdd_(const char *jobu, const size_t *m, const size_t *n, + std::complex *a, const size_t *lda, double *s, + std::complex *u, const size_t *ldu, + std::complex *vt, const size_t *ldvt, + std::complex *work, const size_t *lwork, double *rwork, + int *iwork, int *info); + +void zgesdd_(const char *jobu, const size_t *m, const size_t *n, + std::complex *a, const size_t *lda, double *s, + std::complex *u, const size_t *ldu, + std::complex *vt, const size_t *ldvt, + std::complex *work, const size_t *lwork, double *rwork, + int *iwork, int *info) { + *info = LAPACKE_zgesdd(CblasColMajor, *jobu, *m, *n, a, *lda, s, u, *ldu, vt, + *ldvt); +} + +#else + #ifdef __cplusplus extern "C" { #endif @@ -34,4 +76,6 @@ void zgesdd_(const char *jobz, const size_t *m, const size_t *n, } #endif +#endif // MKL or not + #endif // end __lapack_protos_h_ diff --git a/src/framework/linalg/eigensystem.hpp b/src/framework/linalg/eigensystem.hpp index 3f7d463b31..431f4b01c5 100644 --- a/src/framework/linalg/eigensystem.hpp +++ b/src/framework/linalg/eigensystem.hpp @@ -15,7 +15,11 @@ #ifndef _aer_framework_linalg_eigensystem_hpp_ #define _aer_framework_linalg_eigensystem_hpp_ +#ifdef MKL +#include "framework/mklblas_protos.hpp" +#else #include "framework/blas_protos.hpp" +#endif #include "framework/matrix.hpp" #include @@ -67,15 +71,27 @@ void eigensystem_hermitian(const matrix> &hermitian_matrix, throw std::runtime_error("Input matrix in eigensystem_hermitian " "function is not a square matrix."); } - +#ifdef MKL + size_t n = static_cast(hermitian_matrix.GetLD()); + size_t ldz{n}, lda{n}, lwork{2 * n}; + size_t il{0}, iu{0}; // not referenced if range='A' + size_t m{0}; // number of eigenvalues found + size_t info{0}; + auto iwork = std::vector(5 * n, 0); + auto ifail = std::vector(n, 0); +#else int n = static_cast(hermitian_matrix.GetLD()); int ldz{n}, lda{n}, lwork{2 * n}; - int il{0}, iu{0}; // not referenced if range='A' + int il{0}, iu{0}; // not referenced if range='A' + int m{0}; // number of eigenvalues found + int info{0}; + auto iwork = std::vector(5 * n, 0); + auto ifail = std::vector(n, 0); +#endif + T vl{0.0}, vu{0.0}; // not referenced if range='A' char cmach{'S'}; T abstol{static_cast(2.0 * HeevxFuncs::lamch(&cmach))}; - int m{0}; // number of eigenvalues found - int info{0}; eigenvectors.resize(ldz, n); eigenvalues.clear(); @@ -83,8 +99,6 @@ void eigensystem_hermitian(const matrix> &hermitian_matrix, matrix> heevx_copy{hermitian_matrix}; auto work = std::vector>(lwork, {0.0, 0.0}); auto rwork = std::vector(7 * n, 0.0); - auto iwork = std::vector(5 * n, 0); - auto ifail = std::vector(n, 0); HeevxFuncs::heevx(&AerBlas::Jobz[0], &AerBlas::Range[0], &AerBlas::UpLo[0], &n, heevx_copy.data(), &lda, &vl, &vu, &il, &iu, &abstol, diff --git a/src/framework/linalg/vector.hpp b/src/framework/linalg/vector.hpp index f8ee5bde84..985b64f5b3 100644 --- a/src/framework/linalg/vector.hpp +++ b/src/framework/linalg/vector.hpp @@ -31,16 +31,7 @@ namespace AER { template T *malloc_data(size_t size) { -#if !defined(_WIN64) && !defined(_WIN32) - // Data allocated here may need to be properly aligned to be compliant with - // AVX2. - void *data = nullptr; - if (posix_memalign(&data, 64, sizeof(T) * size) != 0) - throw std::runtime_error("Cannot allocate memory by posix_memalign"); - return reinterpret_cast(data); -#else return reinterpret_cast(malloc(sizeof(T) * size)); -#endif } template diff --git a/src/framework/matrix.hpp b/src/framework/matrix.hpp index 6a0a0ffe06..d675036cbc 100644 --- a/src/framework/matrix.hpp +++ b/src/framework/matrix.hpp @@ -36,7 +36,11 @@ Multiplication is done with the C wrapper of the fortran blas library. #include #include +#ifdef MKL +#include "framework/mklblas_protos.hpp" +#else #include "framework/blas_protos.hpp" +#endif #include "framework/linalg/enable_if_numeric.hpp" /******************************************************************************* diff --git a/src/framework/mklblas_protos.hpp b/src/framework/mklblas_protos.hpp new file mode 100644 index 0000000000..13e1c8396d --- /dev/null +++ b/src/framework/mklblas_protos.hpp @@ -0,0 +1,135 @@ +// Dependencies: Intel MKL +// These are the declarations for the various high-performance matrix routines +// used by the matrix class. An Intel MKL install is required. + +#ifndef _aer_framework_blas_protos_hpp +#define _aer_framework_blas_protos_hpp + +#include +#include +#include +#include + +#define MKL_Complex16 std::complex +#define MKL_Complex8 std::complex +#define MKL_INT size_t +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************************************************** + * Function overwrite to keep the same call as in OpenBLAS * + * *********************************************************/ +void sgemv_(const CBLAS_TRANSPOSE *TransA, const size_t *M, const size_t *N, + const float *alpha, const float *A, const size_t *lda, + const float *x, const size_t *incx, const float *beta, float *y, + const size_t *lincy) { + return cblas_sgemv(CblasColMajor, *TransA, *M, *N, *alpha, A, *lda, x, *incx, + *beta, y, *lincy); +} + +void dgemv_(const CBLAS_TRANSPOSE *TransA, const size_t *M, const size_t *N, + const double *alpha, const double *A, const size_t *lda, + const double *x, const size_t *incx, const double *beta, double *y, + const size_t *lincy) { + return cblas_dgemv(CblasColMajor, *TransA, *M, *N, *alpha, A, *lda, x, *incx, + *beta, y, *lincy); +} + +void cgemv_(const CBLAS_TRANSPOSE *TransA, const size_t *M, const size_t *N, + const std::complex *alpha, const std::complex *A, + const size_t *lda, const std::complex *x, const size_t *incx, + const std::complex *beta, std::complex *y, + const size_t *lincy) { + return cblas_cgemv(CblasColMajor, *TransA, *M, *N, alpha, A, *lda, x, *incx, + beta, y, *lincy); +} + +void zgemv_(const CBLAS_TRANSPOSE *TransA, const size_t *M, const size_t *N, + const std::complex *alpha, const std::complex *A, + const size_t *lda, const std::complex *x, + const size_t *incx, const std::complex *beta, + std::complex *y, const size_t *lincy) { + return cblas_zgemv(CblasColMajor, *TransA, *M, *N, alpha, A, *lda, x, *incx, + beta, y, *lincy); +} + +void sgemm_(const CBLAS_TRANSPOSE *TransA, const CBLAS_TRANSPOSE *TransB, + const size_t *M, const size_t *N, const size_t *K, + const float *alpha, const float *A, const size_t *lda, + const float *B, const size_t *ldb, const float *beta, float *C, + size_t *ldc) { + return cblas_sgemm(CblasColMajor, *TransA, *TransB, *M, *N, *K, *alpha, A, + *lda, B, *ldb, *beta, C, *ldc); +} + +void dgemm_(const CBLAS_TRANSPOSE *TransA, const CBLAS_TRANSPOSE *TransB, + const size_t *M, const size_t *N, const size_t *K, + const double *alpha, const double *A, const size_t *lda, + const double *B, const size_t *ldb, const double *beta, double *C, + size_t *ldc) { + return cblas_dgemm(CblasColMajor, *TransA, *TransB, *M, *N, *K, *alpha, A, + *lda, B, *ldb, *beta, C, *ldc); +} + +void cgemm_(const CBLAS_TRANSPOSE *TransA, const CBLAS_TRANSPOSE *TransB, + const size_t *M, const size_t *N, const size_t *K, + const std::complex *alpha, const std::complex *A, + const size_t *lda, const std::complex *B, const size_t *ldb, + const std::complex *beta, std::complex *C, + size_t *ldc) { + return cblas_cgemm(CblasColMajor, *TransA, *TransB, *M, *N, *K, alpha, A, + *lda, B, *ldb, beta, C, *ldc); +} + +void zgemm_(const CBLAS_TRANSPOSE *TransA, const CBLAS_TRANSPOSE *TransB, + const size_t *M, const size_t *N, const size_t *K, + const std::complex *alpha, const std::complex *A, + const size_t *lda, const std::complex *B, const size_t *ldb, + const std::complex *beta, std::complex *C, + size_t *ldc) { + return cblas_zgemm(CblasColMajor, *TransA, *TransB, *M, *N, *K, alpha, A, + *lda, B, *ldb, beta, C, *ldc); +} + +#ifdef __cplusplus +} +#endif + +namespace AerBlas { + +// std::array Trans = {'N', 'T', 'C'}; +std::array Trans = {CblasNoTrans, CblasTrans, + CblasConjTrans}; + +/* Trans (input) CHARACTER*1. + On entry, TRANSA specifies the form of op( A ) to be used in the + matrix multiplication as follows: + = 'N' no transpose; + = 'T' transpose of A; + = 'C' hermitian conjugate of A. +*/ +std::array UpLo = {'U', 'L'}; +/* UpLo (input) CHARACTER*1 + = 'U': Upper triangle of A is stored; + = 'L': Lower triangle of A is stored. +*/ +std::array Jobz = {'V', 'N'}; +/* Jobz (input) CHARACTER*1 + = 'N': Compute eigenvalues only; + = 'V': Compute eigenvalues and eigenvectors. +*/ +std::array Range = {'A', 'V', 'I'}; +/* Range (input) CHARACTER*1 + = 'A': all eigenvalues will be found. + = 'V': all eigenvalues in the half-open interval + (VL,VU] will be found. + = 'I': the IL-th through IU-th eigenvalues will + be found. +*/ + +} // namespace AerBlas + +#endif // end _blas_protos_h_ diff --git a/src/framework/operations.hpp b/src/framework/operations.hpp old mode 100644 new mode 100755 index 2f6a79adf6..4ec55757ff --- a/src/framework/operations.hpp +++ b/src/framework/operations.hpp @@ -28,22 +28,12 @@ #include "simulators/stabilizer/clifford.hpp" namespace AER { - -class ClassicalRegister; - namespace Operations { -// Operator enum class used for unary classical expression. -enum class UnaryOp { BitNot, LogicNot }; - -// Operator enum class used for binary classical expression or boolean -// function operation. -enum class BinaryOp { - BitAnd, - BitOr, - BitXor, - LogicAnd, - LogicOr, +// Comparisons enum class used for Boolean function operation. +// these are used to compare two hexadecimal strings and return a bool +// for now we only have one comparison Equal, but others will be added +enum class RegComparison { Equal, NotEqual, Less, @@ -52,320 +42,6 @@ enum class BinaryOp { GreaterEqual }; -bool isBoolBinaryOp(const BinaryOp binary_op); -bool isBoolBinaryOp(const BinaryOp binary_op) { - return binary_op != BinaryOp::BitAnd && binary_op != BinaryOp::BitOr && - binary_op != BinaryOp::BitXor; -} - -uint_t truncate(const uint_t val, const size_t width); -uint_t truncate(const uint_t val, const size_t width) { - size_t shift = 64 - width; - return (val << shift) >> shift; -} - -enum class CExprType { Expr, Var, Value, Cast, Unary, Binary, Nop }; - -enum class ValueType { Bool, Uint }; - -class ScalarType { -public: - ScalarType(const ValueType _type, const size_t width_) - : type(_type), width(width_) {} - -public: - const ValueType type; - const size_t width; -}; - -template -inline std::shared_ptr get_wider_type(std::shared_ptr left, - std::shared_ptr right) { - if (left->width > right->width) - return left; - else - return right; -} - -class Uint : public ScalarType { -public: - Uint(const size_t size) : ScalarType(ValueType::Uint, size) {} -}; - -class Bool : public ScalarType { -public: - Bool() : ScalarType(ValueType::Bool, 1) {} -}; - -class CExpr { -public: - CExpr(const CExprType _expr_type, const std::shared_ptr _type) - : expr_type(_expr_type), type(_type) {} - virtual bool eval_bool(const std::string &memory) { return false; }; - virtual uint_t eval_uint(const std::string &memory) { return 0ul; }; - -public: - const CExprType expr_type; - const std::shared_ptr type; -}; - -class CastExpr : public CExpr { -public: - CastExpr(std::shared_ptr _type, - const std::shared_ptr operand_) - : CExpr(CExprType::Cast, _type), operand(operand_) {} - - virtual bool eval_bool(const std::string &memory) { - if (type->type != ValueType::Bool) - throw std::invalid_argument( - R"(eval_bool is called for non-bool expression.)"); - if (operand->type->type == ValueType::Bool) - return operand->eval_bool(memory); - else if (operand->type->type == ValueType::Uint) - return operand->eval_uint(memory) == 0ul; - else - throw std::invalid_argument(R"(invalid cast: from unknown type.)"); - } - - virtual uint_t eval_uint(const std::string &memory) { - if (type->type != ValueType::Uint) - throw std::invalid_argument( - R"(eval_uint is called for non-uint expression.)"); - if (operand->type->type == ValueType::Bool) - return operand->eval_bool(memory) ? 1ul : 0ul; - else if (operand->type->type == ValueType::Uint) - return truncate(operand->eval_uint(memory), type->width); - else - throw std::invalid_argument(R"(invalid cast: from unknown type.)"); - } - -public: - const std::shared_ptr operand; -}; - -class VarExpr : public CExpr { -public: - VarExpr(std::shared_ptr _type, - const std::vector &_cbit_idxs) - : CExpr(CExprType::Var, _type), cbit_idxs(_cbit_idxs) {} - - virtual bool eval_bool(const std::string &memory) { - if (type->type != ValueType::Bool) - throw std::invalid_argument( - R"(eval_bool is called for non-bool expression.)"); - return eval_uint_(memory) != 0ul; - } - - virtual uint_t eval_uint(const std::string &memory) { - if (type->type != ValueType::Uint) - throw std::invalid_argument( - R"(eval_uint is called for non-uint expression.)"); - return eval_uint_(memory); - } - -private: - uint_t eval_uint_(const std::string &memory) { - uint_t val = 0ul; - uint_t shift = 0; - for (const uint_t cbit_idx : cbit_idxs) { - if (memory.size() <= cbit_idx) - throw std::invalid_argument(R"(invalid cbit index.)"); - if (memory[memory.size() - cbit_idx - 1] == '1') - val |= (1 << shift); - ++shift; - } - return truncate(val, type->width); - } - -public: - const std::vector cbit_idxs; -}; - -class ValueExpr : public CExpr { -public: - ValueExpr(std::shared_ptr _type) - : CExpr(CExprType::Value, _type) {} -}; - -class UintValue : public ValueExpr { -public: - UintValue(size_t width, const uint_t value_) - : ValueExpr(std::make_shared(width)), value(value_) {} - - virtual bool eval_bool(const std::string &memory) { - throw std::invalid_argument( - R"(eval_bool is called for Uint value without cast.)"); - } - - virtual uint_t eval_uint(const std::string &memory) { return value; } - -public: - const uint_t value; -}; - -class BoolValue : public ValueExpr { -public: - BoolValue(const bool value_) - : ValueExpr(std::make_shared()), value(value_) {} - - virtual bool eval_bool(const std::string &memory) { return value != 0ul; } - - virtual uint_t eval_uint(const std::string &memory) { - throw std::invalid_argument( - R"(eval_uint is called for Bool value without cast.)"); - } - -public: - const bool value; -}; - -class UnaryExpr : public CExpr { -public: - UnaryExpr(const UnaryOp op_, const std::shared_ptr operand_) - : CExpr(CExprType::Unary, operand_->type), op(op_), operand(operand_) { - if (op == UnaryOp::LogicNot && operand_->type->type != ValueType::Bool) - throw std::invalid_argument( - R"(LogicNot unary expression must has Bool expression as its operand.)"); - - if (op == UnaryOp::BitNot && operand_->type->type != ValueType::Uint) - throw std::invalid_argument( - R"(BitNot unary expression must has Uint expression as its operand.)"); - } - - virtual bool eval_bool(const std::string &memory) { - if (op == UnaryOp::BitNot) - throw std::invalid_argument( - R"(eval_bool is called for BitNot unary expression.)"); - else // LogicNot - return !operand->eval_bool(memory); - } - - virtual uint_t eval_uint(const std::string &memory) { - if (op == UnaryOp::BitNot) - return truncate(~operand->eval_uint(memory), type->width); - else // LogicNot - throw std::invalid_argument( - R"(eval_uint is called for LogicNot unary expression.)"); - } - -public: - const UnaryOp op; - const std::shared_ptr operand; -}; - -class BinaryExpr : public CExpr { -public: - BinaryExpr(const BinaryOp op_, const std::shared_ptr left_, - const std::shared_ptr right_) - : CExpr(CExprType::Binary, - isBoolBinaryOp(op_) ? std::make_shared() - : get_wider_type(left_->type, right_->type)), - op(op_), left(left_), right(right_) { - - if (left->type->type != right->type->type) - throw std::invalid_argument( - R"(binary expression does not support different types in child expressions.)"); - - switch (op) { - case BinaryOp::BitAnd: - case BinaryOp::BitOr: - case BinaryOp::BitXor: - break; - case BinaryOp::LogicAnd: - case BinaryOp::LogicOr: - if (left->type->type != ValueType::Bool) - throw std::invalid_argument( - R"(logic operation allows only for bool expressions.)"); - break; - case BinaryOp::Equal: - case BinaryOp::NotEqual: - break; - case BinaryOp::Less: - case BinaryOp::LessEqual: - case BinaryOp::Greater: - case BinaryOp::GreaterEqual: - if (left->type->type != ValueType::Uint) - throw std::invalid_argument( - R"(comparison operation allows only for uint expressions.)"); - break; - default: - throw std::invalid_argument(R"(must not reach here.)"); - } - } - - virtual bool eval_bool(const std::string &memory) { - switch (op) { - case BinaryOp::BitAnd: - if (left->type->type == ValueType::Uint) - return eval_uint(memory) != 0; - else - return left->eval_bool(memory) && right->eval_bool(memory); - case BinaryOp::BitOr: - if (left->type->type == ValueType::Uint) - return eval_uint(memory) != 0; - else - return left->eval_bool(memory) || right->eval_bool(memory); - case BinaryOp::BitXor: - if (left->type->type == ValueType::Uint) - return eval_uint(memory) != 0; - else - return left->eval_bool(memory) ^ right->eval_bool(memory); - case BinaryOp::LogicAnd: - return left->eval_bool(memory) && right->eval_bool(memory); - case BinaryOp::LogicOr: - return left->eval_bool(memory) || right->eval_bool(memory); - case BinaryOp::Equal: - if (left->type->type == ValueType::Bool) - return left->eval_bool(memory) == right->eval_bool(memory); - else - return left->eval_uint(memory) == right->eval_uint(memory); - case BinaryOp::NotEqual: - if (left->type->type == ValueType::Bool) - return left->eval_bool(memory) != right->eval_bool(memory); - else - return left->eval_uint(memory) != right->eval_uint(memory); - case BinaryOp::Less: - return left->eval_uint(memory) < right->eval_uint(memory); - case BinaryOp::LessEqual: - return left->eval_uint(memory) <= right->eval_uint(memory); - case BinaryOp::Greater: - return left->eval_uint(memory) > right->eval_uint(memory); - case BinaryOp::GreaterEqual: - return left->eval_uint(memory) >= right->eval_uint(memory); - default: - throw std::invalid_argument(R"(must not reach here.)"); - } - } - - virtual uint_t eval_uint(const std::string &memory) { - switch (op) { - case BinaryOp::BitAnd: - return left->eval_uint(memory) & right->eval_uint(memory); - case BinaryOp::BitOr: - return left->eval_uint(memory) | right->eval_uint(memory); - case BinaryOp::BitXor: - return left->eval_uint(memory) ^ right->eval_uint(memory); - case BinaryOp::LogicAnd: - case BinaryOp::LogicOr: - case BinaryOp::Equal: - case BinaryOp::NotEqual: - case BinaryOp::Less: - case BinaryOp::LessEqual: - case BinaryOp::Greater: - case BinaryOp::GreaterEqual: - throw std::invalid_argument( - R"(eval_uint is called for binary expression that returns bool.)"); - default: - throw std::invalid_argument(R"(must not reach here.)"); - } - } - -public: - const BinaryOp op; - const std::shared_ptr left; - const std::shared_ptr right; -}; - // Enum class for operation types enum class OpType { gate, @@ -411,9 +87,7 @@ enum class OpType { set_mps, // Control Flow jump, - mark, - unary_expr, - binary_expr + mark }; enum class DataSubType { @@ -555,12 +229,6 @@ inline std::ostream &operator<<(std::ostream &stream, const OpType &type) { case OpType::jump: stream << "jump"; break; - case OpType::unary_expr: - stream << "unary_expr"; - break; - case OpType::binary_expr: - stream << "binary_expr"; - break; default: stream << "unknown"; } @@ -619,8 +287,7 @@ struct Op { bool conditional = false; // is gate conditional gate uint_t conditional_reg; // (opt) the (single) register location to look up for // conditional - BinaryOp binary_op; // (opt) boolean function relation - std::shared_ptr expr; // (opt) classical expression + RegComparison bfunc; // (opt) boolean function relation // Measurement reg_t memory; // (opt) register operation it acts on (measure) @@ -641,9 +308,6 @@ struct Op { // Save DataSubType save_type = DataSubType::single; - - // runtime parameter bind - bool has_bind_params = false; }; inline std::ostream &operator<<(std::ostream &s, const Op &op) { @@ -772,9 +436,7 @@ inline Op make_initialize(const reg_t &qubits, } inline Op make_unitary(const reg_t &qubits, const cmatrix_t &mat, - const int_t conditional = -1, - const std::shared_ptr expr = nullptr, - std::string label = "") { + const int_t conditional = -1, std::string label = "") { Op op; op.type = OpType::matrix; op.name = "unitary"; @@ -784,7 +446,6 @@ inline Op make_unitary(const reg_t &qubits, const cmatrix_t &mat, op.conditional = true; op.conditional_reg = conditional; } - op.expr = expr; if (label != "") op.string_params = {label}; return op; @@ -804,7 +465,6 @@ inline Op make_unitary(const reg_t &qubits, cmatrix_t &&mat, } inline Op make_diagonal(const reg_t &qubits, const cvector_t &vec, - const int_t conditional = -1, const std::string label = "") { Op op; op.type = OpType::diagonal_matrix; @@ -812,11 +472,6 @@ inline Op make_diagonal(const reg_t &qubits, const cvector_t &vec, op.qubits = qubits; op.params = vec; - if (conditional >= 0) { - op.conditional = true; - op.conditional_reg = conditional; - } - if (label != "") op.string_params = {label}; @@ -824,7 +479,6 @@ inline Op make_diagonal(const reg_t &qubits, const cvector_t &vec, } inline Op make_diagonal(const reg_t &qubits, cvector_t &&vec, - const int_t conditional = -1, const std::string label = "") { Op op; op.type = OpType::diagonal_matrix; @@ -832,11 +486,6 @@ inline Op make_diagonal(const reg_t &qubits, cvector_t &&vec, op.qubits = qubits; op.params = std::move(vec); - if (conditional >= 0) { - op.conditional = true; - op.conditional_reg = conditional; - } - if (label != "") op.string_params = {label}; @@ -844,8 +493,7 @@ inline Op make_diagonal(const reg_t &qubits, cvector_t &&vec, } inline Op make_superop(const reg_t &qubits, const cmatrix_t &mat, - const int_t conditional = -1, - const std::shared_ptr expr = nullptr) { + const int_t conditional = -1) { Op op; op.type = OpType::superop; op.name = "superop"; @@ -855,7 +503,6 @@ inline Op make_superop(const reg_t &qubits, const cmatrix_t &mat, op.conditional = true; op.conditional_reg = conditional; } - op.expr = expr; return op; } @@ -870,8 +517,7 @@ inline Op make_superop(const reg_t &qubits, cmatrix_t &&mat) { } inline Op make_kraus(const reg_t &qubits, const std::vector &mats, - const int_t conditional = -1, - const std::shared_ptr expr = nullptr) { + const int_t conditional = -1) { Op op; op.type = OpType::kraus; op.name = "kraus"; @@ -881,7 +527,6 @@ inline Op make_kraus(const reg_t &qubits, const std::vector &mats, op.conditional = true; op.conditional_reg = conditional; } - op.expr = expr; return op; } @@ -930,13 +575,13 @@ inline Op make_bfunc(const std::string &mask, const std::string &val, Utils::format_hex_inplace(op.string_params[0]); Utils::format_hex_inplace(op.string_params[1]); - const stringmap_t comp_table({ - {"==", BinaryOp::Equal}, - {"!=", BinaryOp::NotEqual}, - {"<", BinaryOp::Less}, - {"<=", BinaryOp::LessEqual}, - {">", BinaryOp::Greater}, - {">=", BinaryOp::GreaterEqual}, + const stringmap_t comp_table({ + {"==", RegComparison::Equal}, + {"!=", RegComparison::NotEqual}, + {"<", RegComparison::Less}, + {"<=", RegComparison::LessEqual}, + {">", RegComparison::Greater}, + {">=", RegComparison::GreaterEqual}, }); auto it = comp_table.find(relation); @@ -946,7 +591,7 @@ inline Op make_bfunc(const std::string &mask, const std::string &val, << std::endl; throw std::invalid_argument(msg.str()); } else { - op.binary_op = it->second; + op.bfunc = it->second; } return op; @@ -955,13 +600,7 @@ inline Op make_bfunc(const std::string &mask, const std::string &val, Op make_gate(const std::string &name, const reg_t &qubits, const std::vector ¶ms, const std::vector &string_params, - const int_t conditional, const std::shared_ptr expr, - const std::string &label); -Op make_gate(const std::string &name, const reg_t &qubits, - const std::vector ¶ms, - const std::vector &string_params, - const int_t conditional, const std::shared_ptr expr, - const std::string &label) { + const int_t conditional, const std::string &label) { Op op; op.type = OpType::gate; op.name = name; @@ -974,7 +613,6 @@ Op make_gate(const std::string &name, const reg_t &qubits, op.string_params = {label}; else op.string_params = {op.name}; - op.expr = expr; if (conditional >= 0) { op.conditional = true; @@ -1017,24 +655,17 @@ inline Op make_u3(uint_t qubit, T theta, T phi, T lam) { return op; } -inline Op make_reset(const reg_t &qubits, const int_t conditional) { +inline Op make_reset(const reg_t &qubits, uint_t state = 0) { Op op; op.type = OpType::reset; op.name = "reset"; op.qubits = qubits; - - if (conditional >= 0) { - op.conditional = true; - op.conditional_reg = conditional; - } - return op; } inline Op make_multiplexer(const reg_t &qubits, const std::vector &mats, const int_t conditional = -1, - const std::shared_ptr expr = nullptr, std::string label = "") { // Check matrices are N-qubit @@ -1083,7 +714,6 @@ inline Op make_multiplexer(const reg_t &qubits, op.conditional = true; op.conditional_reg = conditional; } - op.expr = expr; // Validate qubits are unique. check_empty_qubits(op); @@ -1246,8 +876,7 @@ inline Op make_set_clifford(const reg_t &qubits, const std::string &name, } inline Op make_jump(const reg_t &qubits, const std::vector ¶ms, - const int_t conditional, - const std::shared_ptr expr = nullptr) { + const int_t conditional) { Op op; op.type = OpType::jump; op.name = "jump"; @@ -1261,7 +890,6 @@ inline Op make_jump(const reg_t &qubits, const std::vector ¶ms, op.conditional = true; op.conditional_reg = conditional; } - op.expr = expr; return op; } @@ -1300,8 +928,7 @@ inline Op make_measure(const reg_t &qubits, const reg_t &memory, } inline Op make_qerror_loc(const reg_t &qubits, const std::string &label, - const int_t conditional = -1, - const std::shared_ptr expr = nullptr) { + const int_t conditional = -1) { Op op; op.type = OpType::qerror_loc; op.name = label; @@ -1310,31 +937,6 @@ inline Op make_qerror_loc(const reg_t &qubits, const std::string &label, op.conditional = true; op.conditional_reg = conditional; } - op.expr = expr; - return op; -} - -// make new op by parameter binding -inline Op bind_parameter(const Op &src, const uint_t iparam, - const uint_t num_params) { - Op op; - op.type = src.type; - op.name = src.name; - op.qubits = src.qubits; - op.conditional = src.conditional; - op.conditional_reg = src.conditional_reg; - - if (src.params.size() > 0) { - uint_t stride = src.params.size() / num_params; - op.params.resize(stride); - for (uint_t i = 0; i < stride; i++) - op.params[i] = src.params[iparam * stride + i]; - } else if (src.mats.size() > 0) { - uint_t stride = src.mats.size() / num_params; - op.mats.resize(stride); - for (uint_t i = 0; i < stride; i++) - op.mats[i] = src.mats[iparam * stride + i]; - } return op; } @@ -1542,7 +1144,6 @@ json_t op_to_json(const Op &op) { return ret; } -void to_json(json_t &js, const OpType &type); void to_json(json_t &js, const OpType &type) { std::stringstream ss; ss << type; @@ -1740,13 +1341,13 @@ Op input_to_op_bfunc(const inputdata_t &input) { Utils::format_hex_inplace(op.string_params[0]); Utils::format_hex_inplace(op.string_params[1]); - const stringmap_t comp_table({ - {"==", BinaryOp::Equal}, - {"!=", BinaryOp::NotEqual}, - {"<", BinaryOp::Less}, - {"<=", BinaryOp::LessEqual}, - {">", BinaryOp::Greater}, - {">=", BinaryOp::GreaterEqual}, + const stringmap_t comp_table({ + {"==", RegComparison::Equal}, + {"!=", RegComparison::NotEqual}, + {"<", RegComparison::Less}, + {"<=", RegComparison::LessEqual}, + {">", RegComparison::Greater}, + {">=", RegComparison::GreaterEqual}, }); auto it = comp_table.find(relation); @@ -1756,7 +1357,7 @@ Op input_to_op_bfunc(const inputdata_t &input) { << std::endl; throw std::invalid_argument(msg.str()); } else { - op.binary_op = it->second; + op.bfunc = it->second; } // Conditional @@ -1870,7 +1471,7 @@ Op input_to_op_multiplexer(const inputdata_t &input) { Parser::get_value(mats, "params", input); Parser::get_value(label, "label", input); // Construct op - auto op = make_multiplexer(qubits, mats, -1, nullptr, label); + auto op = make_multiplexer(qubits, mats, -1, label); // Conditional add_conditional(Allowed::Yes, op, input); return op; diff --git a/src/framework/pybind_json.hpp b/src/framework/pybind_json.hpp index 108e1b34ec..7ac889c3c2 100644 --- a/src/framework/pybind_json.hpp +++ b/src/framework/pybind_json.hpp @@ -32,8 +32,6 @@ #include "misc/warnings.hpp" DISABLE_WARNING_PUSH -#pragma GCC diagnostic ignored "-Wfloat-equal" - #include #include #include @@ -42,7 +40,6 @@ DISABLE_WARNING_PUSH #include DISABLE_WARNING_POP -#pragma GCC diagnostic warning "-Wfloat-equal" #include "framework/json.hpp" @@ -296,7 +293,7 @@ void std::from_json(const json_t &js, py::object &o) { o = py::str(js.get()); } else if (js.is_array()) { std::vector obj(js.size()); - for (size_t i = 0; i < js.size(); i++) { + for (auto i = 0; i < js.size(); i++) { py::object tmp; from_json(js[i], tmp); obj[i] = tmp; diff --git a/src/framework/qobj.hpp b/src/framework/qobj.hpp index 2a25f8cfe2..01084fd20e 100644 --- a/src/framework/qobj.hpp +++ b/src/framework/qobj.hpp @@ -155,12 +155,12 @@ Qobj::Qobj(const inputdata_t &input) { // negative position is for global phase param_circuit->global_phase_angle = params.second[j]; } else { - if ((uint_t)instr_pos >= num_instr) { + if (instr_pos >= num_instr) { throw std::invalid_argument( R"(Invalid parameterized qobj: instruction position out of range)"); } auto &op = param_circuit->ops[instr_pos]; - if ((uint_t)param_pos >= op.params.size()) { + if (param_pos >= op.params.size()) { throw std::invalid_argument( R"(Invalid parameterized qobj: instruction param position out of range)"); } diff --git a/src/framework/results/data/metadata.hpp b/src/framework/results/data/metadata.hpp index 789906b903..cf7cb39bb1 100644 --- a/src/framework/results/data/metadata.hpp +++ b/src/framework/results/data/metadata.hpp @@ -64,8 +64,6 @@ struct Metadata : public DataMap, // Combine stored data Metadata &combine(Metadata &&other); - - Metadata ©(Metadata &other); }; //------------------------------------------------------------------------------ @@ -79,13 +77,6 @@ Metadata &Metadata::combine(Metadata &&other) { return *this; } -Metadata &Metadata::copy(Metadata &other) { - DataMap::copy(other); - DataMap::copy(other); - DataMap::copy(other); - return *this; -} - json_t Metadata::to_json() { json_t result = json_t::object(); DataMap::add_to_json(result); diff --git a/src/framework/results/data/subtypes/data_map.hpp b/src/framework/results/data/subtypes/data_map.hpp index 2d46bd19f9..8c942ae0ac 100644 --- a/src/framework/results/data/subtypes/data_map.hpp +++ b/src/framework/results/data/subtypes/data_map.hpp @@ -43,9 +43,6 @@ class DataMap { // Combine with another data object void combine(DataMap &&other); - // copy from another data onject - void copy(DataMap &other); - // Clear all stored data void clear(); @@ -78,9 +75,6 @@ class DataMap { // Combine with another data object void combine(DataMap &&other); - // copy from another data onject - void copy(DataMap &other); - // Clear all stored data void clear(); @@ -134,22 +128,6 @@ void DataMap::combine(DataMap &&other) { } } -template