mirror of https://github.com/Qiskit/qiskit-aer.git
* Added scikit-build support for building Cython extensions
This commit is contained in:
parent
bc0028b046
commit
a76297c654
|
@ -12,8 +12,8 @@
|
|||
cmake_minimum_required(VERSION 3.6)
|
||||
project(aer_simulator_cpp LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
|
||||
set(CMAKE_PREFIX_PATH ${CMAKE_SOURCE_DIR}/cmake)
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
|
||||
list(APPEND CMAKE_PREFIX_PATH ${CMAKE_SOURCE_DIR}/cmake)
|
||||
|
||||
option(STATIC_LINKING "Specify if we want statically link the executable (for
|
||||
redistribution mainly)" FALSE)
|
||||
|
@ -161,3 +161,6 @@ target_link_libraries(aer_simulator_cpp PRIVATE ${AER_LIBRARIES})
|
|||
if(BUILD_TESTS)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
# Cyhton build
|
||||
add_subdirectory(src/bindings/python)
|
|
@ -0,0 +1,78 @@
|
|||
#.rst:
|
||||
#
|
||||
# Find ``cython`` executable.
|
||||
#
|
||||
# This module will set the following variables in your project:
|
||||
#
|
||||
# ``CYTHON_EXECUTABLE``
|
||||
# path to the ``cython`` program
|
||||
#
|
||||
# ``CYTHON_VERSION``
|
||||
# version of ``cython``
|
||||
#
|
||||
# ``CYTHON_FOUND``
|
||||
# true if the program was found
|
||||
#
|
||||
# For more information on the Cython project, see http://cython.org/.
|
||||
#
|
||||
# *Cython is a language that makes writing C extensions for the Python language
|
||||
# as easy as Python itself.*
|
||||
#
|
||||
#=============================================================================
|
||||
# Copyright 2011 Kitware, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#=============================================================================
|
||||
|
||||
# Use the Cython executable that lives next to the Python executable
|
||||
# if it is a local installation.
|
||||
find_package(PythonInterp)
|
||||
if(PYTHONINTERP_FOUND)
|
||||
get_filename_component(_python_path ${PYTHON_EXECUTABLE} PATH)
|
||||
find_program(CYTHON_EXECUTABLE
|
||||
NAMES cython cython.bat cython3
|
||||
HINTS ${_python_path}
|
||||
DOC "path to the cython executable")
|
||||
else()
|
||||
find_program(CYTHON_EXECUTABLE
|
||||
NAMES cython cython.bat cython3
|
||||
DOC "path to the cython executable")
|
||||
endif()
|
||||
|
||||
if(CYTHON_EXECUTABLE)
|
||||
set(CYTHON_version_command ${CYTHON_EXECUTABLE} --version)
|
||||
|
||||
execute_process(COMMAND ${CYTHON_version_command}
|
||||
OUTPUT_VARIABLE CYTHON_version_output
|
||||
ERROR_VARIABLE CYTHON_version_error
|
||||
RESULT_VARIABLE CYTHON_version_result
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
if(NOT ${CYTHON_version_result} EQUAL 0)
|
||||
set(_error_msg "Command \"${CYTHON_version_command}\" failed with")
|
||||
set(_error_msg "${_error_msg} output:\n${CYTHON_version_error}")
|
||||
message(SEND_ERROR "${_error_msg}")
|
||||
else()
|
||||
if("${CYTHON_version_output}" MATCHES "^[Cc]ython version ([^,]+)")
|
||||
set(CYTHON_VERSION "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Cython REQUIRED_VARS CYTHON_EXECUTABLE)
|
||||
|
||||
mark_as_advanced(CYTHON_EXECUTABLE)
|
||||
|
||||
include(UseCython)
|
||||
|
|
@ -0,0 +1,396 @@
|
|||
#.rst:
|
||||
#
|
||||
# The following functions are defined:
|
||||
#
|
||||
# .. cmake:command:: add_cython_target
|
||||
#
|
||||
# Create a custom rule to generate the source code for a Python extension module
|
||||
# using cython.
|
||||
#
|
||||
# add_cython_target(<Name> [<CythonInput>]
|
||||
# [EMBED_MAIN]
|
||||
# [C | CXX]
|
||||
# [PY2 | PY3]
|
||||
# [OUTPUT_VAR <OutputVar>])
|
||||
#
|
||||
# ``<Name>`` is the name of the new target, and ``<CythonInput>``
|
||||
# is the path to a cython source file. Note that, despite the name, no new
|
||||
# targets are created by this function. Instead, see ``OUTPUT_VAR`` for
|
||||
# retrieving the path to the generated source for subsequent targets.
|
||||
#
|
||||
# If only ``<Name>`` is provided, and it ends in the ".pyx" extension, then it
|
||||
# is assumed to be the ``<CythonInput>``. The name of the input without the
|
||||
# extension is used as the target name. If only ``<Name>`` is provided, and it
|
||||
# does not end in the ".pyx" extension, then the ``<CythonInput>`` is assumed to
|
||||
# be ``<Name>.pyx``.
|
||||
#
|
||||
# The Cython include search path is amended with any entries found in the
|
||||
# ``INCLUDE_DIRECTORIES`` property of the directory containing the
|
||||
# ``<CythonInput>`` file. Use ``include_directories`` to add to the Cython
|
||||
# include search path.
|
||||
#
|
||||
# Options:
|
||||
#
|
||||
# ``EMBED_MAIN``
|
||||
# Embed a main() function in the generated output (for stand-alone
|
||||
# applications that initialize their own Python runtime).
|
||||
#
|
||||
# ``C | CXX``
|
||||
# Force the generation of either a C or C++ file. By default, a C file is
|
||||
# generated, unless the C language is not enabled for the project; in this
|
||||
# case, a C++ file is generated by default.
|
||||
#
|
||||
# ``PY2 | PY3``
|
||||
# Force compilation using either Python-2 or Python-3 syntax and code
|
||||
# semantics. By default, Python-2 syntax and semantics are used if the major
|
||||
# version of Python found is 2. Otherwise, Python-3 syntax and sematics are
|
||||
# used.
|
||||
#
|
||||
# ``OUTPUT_VAR <OutputVar>``
|
||||
# Set the variable ``<OutputVar>`` in the parent scope to the path to the
|
||||
# generated source file. By default, ``<Name>`` is used as the output
|
||||
# variable name.
|
||||
#
|
||||
# Defined variables:
|
||||
#
|
||||
# ``<OutputVar>``
|
||||
# The path of the generated source file.
|
||||
#
|
||||
# Cache variables that effect the behavior include:
|
||||
#
|
||||
# ``CYTHON_ANNOTATE``
|
||||
# whether to create an annotated .html file when compiling
|
||||
#
|
||||
# ``CYTHON_FLAGS``
|
||||
# additional flags to pass to the Cython compiler
|
||||
#
|
||||
# Example usage
|
||||
# ^^^^^^^^^^^^^
|
||||
#
|
||||
# .. code-block:: cmake
|
||||
#
|
||||
# find_package(Cython)
|
||||
#
|
||||
# # Note: In this case, either one of these arguments may be omitted; their
|
||||
# # value would have been inferred from that of the other.
|
||||
# add_cython_target(cy_code cy_code.pyx)
|
||||
#
|
||||
# add_library(cy_code MODULE ${cy_code})
|
||||
# target_link_libraries(cy_code ...)
|
||||
#
|
||||
#=============================================================================
|
||||
# Copyright 2011 Kitware, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#=============================================================================
|
||||
|
||||
# Configuration options.
|
||||
set(CYTHON_ANNOTATE OFF
|
||||
CACHE BOOL "Create an annotated .html file when compiling *.pyx.")
|
||||
|
||||
set(CYTHON_FLAGS "" CACHE STRING
|
||||
"Extra flags to the cython compiler.")
|
||||
mark_as_advanced(CYTHON_ANNOTATE CYTHON_FLAGS)
|
||||
string(REGEX REPLACE " " ";" CYTHON_FLAGS_LIST "${CYTHON_FLAGS}")
|
||||
|
||||
find_package(PythonLibs REQUIRED)
|
||||
|
||||
set(CYTHON_CXX_EXTENSION "cxx")
|
||||
set(CYTHON_C_EXTENSION "c")
|
||||
|
||||
get_property(languages GLOBAL PROPERTY ENABLED_LANGUAGES)
|
||||
|
||||
function(add_cython_target _name)
|
||||
set(options EMBED_MAIN C CXX PY2 PY3)
|
||||
set(options1 OUTPUT_VAR)
|
||||
cmake_parse_arguments(_args "${options}" "${options1}" "" ${ARGN})
|
||||
|
||||
list(GET _args_UNPARSED_ARGUMENTS 0 _arg0)
|
||||
|
||||
# if provided, use _arg0 as the input file path
|
||||
if(_arg0)
|
||||
set(_source_file ${_arg0})
|
||||
|
||||
# otherwise, must determine source file from name, or vice versa
|
||||
else()
|
||||
get_filename_component(_name_ext "${_name}" EXT)
|
||||
|
||||
# if extension provided, _name is the source file
|
||||
if(_name_ext)
|
||||
set(_source_file ${_name})
|
||||
get_filename_component(_name "${_source_file}" NAME_WE)
|
||||
|
||||
# otherwise, assume the source file is ${_name}.pyx
|
||||
else()
|
||||
set(_source_file ${_name}.pyx)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(_embed_main FALSE)
|
||||
|
||||
if("C" IN_LIST languages)
|
||||
set(_output_syntax "C")
|
||||
elseif("CXX" IN_LIST languages)
|
||||
set(_output_syntax "CXX")
|
||||
else()
|
||||
message(FATAL_ERROR "Either C or CXX must be enabled to use Cython")
|
||||
endif()
|
||||
|
||||
if("${PYTHONLIBS_VERSION_STRING}" MATCHES "^2.")
|
||||
set(_input_syntax "PY2")
|
||||
else()
|
||||
set(_input_syntax "PY3")
|
||||
endif()
|
||||
|
||||
if(_args_EMBED_MAIN)
|
||||
set(_embed_main TRUE)
|
||||
endif()
|
||||
|
||||
if(_args_C)
|
||||
set(_output_syntax "C")
|
||||
endif()
|
||||
|
||||
if(_args_CXX)
|
||||
set(_output_syntax "CXX")
|
||||
endif()
|
||||
|
||||
if(_args_PY2)
|
||||
set(_input_syntax "PY2")
|
||||
endif()
|
||||
|
||||
if(_args_PY3)
|
||||
set(_input_syntax "PY3")
|
||||
endif()
|
||||
|
||||
set(embed_arg "")
|
||||
if(_embed_main)
|
||||
set(embed_arg "--embed")
|
||||
endif()
|
||||
|
||||
set(cxx_arg "")
|
||||
set(extension "c")
|
||||
if(_output_syntax STREQUAL "CXX")
|
||||
set(cxx_arg "--cplus")
|
||||
set(extension "cxx")
|
||||
endif()
|
||||
|
||||
set(py_version_arg "")
|
||||
if(_input_syntax STREQUAL "PY2")
|
||||
set(py_version_arg "-2")
|
||||
elseif(_input_syntax STREQUAL "PY3")
|
||||
set(py_version_arg "-3")
|
||||
endif()
|
||||
|
||||
set(generated_file "${CMAKE_CURRENT_BINARY_DIR}/${_name}.${extension}")
|
||||
set_source_files_properties(${generated_file} PROPERTIES GENERATED TRUE)
|
||||
|
||||
set(_output_var ${_name})
|
||||
if(_args_OUTPUT_VAR)
|
||||
set(_output_var ${_args_OUTPUT_VAR})
|
||||
endif()
|
||||
set(${_output_var} ${generated_file} PARENT_SCOPE)
|
||||
|
||||
file(RELATIVE_PATH generated_file_relative
|
||||
${CMAKE_BINARY_DIR} ${generated_file})
|
||||
|
||||
set(comment "Generating ${_output_syntax} source ${generated_file_relative}")
|
||||
set(cython_include_directories "")
|
||||
set(pxd_dependencies "")
|
||||
set(c_header_dependencies "")
|
||||
|
||||
# Get the include directories.
|
||||
get_source_file_property(pyx_location ${_source_file} LOCATION)
|
||||
get_filename_component(pyx_path ${pyx_location} PATH)
|
||||
get_directory_property(cmake_include_directories
|
||||
DIRECTORY ${pyx_path}
|
||||
INCLUDE_DIRECTORIES)
|
||||
list(APPEND cython_include_directories ${cmake_include_directories})
|
||||
|
||||
# Determine dependencies.
|
||||
# Add the pxd file with the same basename as the given pyx file.
|
||||
get_filename_component(pyx_file_basename ${_source_file} NAME_WE)
|
||||
unset(corresponding_pxd_file CACHE)
|
||||
find_file(corresponding_pxd_file ${pyx_file_basename}.pxd
|
||||
PATHS "${pyx_path}" ${cmake_include_directories}
|
||||
NO_DEFAULT_PATH)
|
||||
if(corresponding_pxd_file)
|
||||
list(APPEND pxd_dependencies "${corresponding_pxd_file}")
|
||||
endif()
|
||||
|
||||
# pxd files to check for additional dependencies
|
||||
set(pxds_to_check "${_source_file}" "${pxd_dependencies}")
|
||||
set(pxds_checked "")
|
||||
set(number_pxds_to_check 1)
|
||||
while(number_pxds_to_check GREATER 0)
|
||||
foreach(pxd ${pxds_to_check})
|
||||
list(APPEND pxds_checked "${pxd}")
|
||||
list(REMOVE_ITEM pxds_to_check "${pxd}")
|
||||
|
||||
# look for C headers
|
||||
file(STRINGS "${pxd}" extern_from_statements
|
||||
REGEX "cdef[ ]+extern[ ]+from.*$")
|
||||
foreach(statement ${extern_from_statements})
|
||||
# Had trouble getting the quote in the regex
|
||||
string(REGEX REPLACE
|
||||
"cdef[ ]+extern[ ]+from[ ]+[\"]([^\"]+)[\"].*" "\\1"
|
||||
header "${statement}")
|
||||
unset(header_location CACHE)
|
||||
find_file(header_location ${header} PATHS ${cmake_include_directories})
|
||||
if(header_location)
|
||||
list(FIND c_header_dependencies "${header_location}" header_idx)
|
||||
if(${header_idx} LESS 0)
|
||||
list(APPEND c_header_dependencies "${header_location}")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# check for pxd dependencies
|
||||
# Look for cimport statements.
|
||||
set(module_dependencies "")
|
||||
file(STRINGS "${pxd}" cimport_statements REGEX cimport)
|
||||
foreach(statement ${cimport_statements})
|
||||
if(${statement} MATCHES from)
|
||||
string(REGEX REPLACE
|
||||
"from[ ]+([^ ]+).*" "\\1"
|
||||
module "${statement}")
|
||||
else()
|
||||
string(REGEX REPLACE
|
||||
"cimport[ ]+([^ ]+).*" "\\1"
|
||||
module "${statement}")
|
||||
endif()
|
||||
list(APPEND module_dependencies ${module})
|
||||
endforeach()
|
||||
|
||||
# check for pxi dependencies
|
||||
# Look for include statements.
|
||||
set(include_dependencies "")
|
||||
file(STRINGS "${pxd}" include_statements REGEX include)
|
||||
foreach(statement ${include_statements})
|
||||
string(REGEX REPLACE
|
||||
"include[ ]+[\"]([^\"]+)[\"].*" "\\1"
|
||||
module "${statement}")
|
||||
list(APPEND include_dependencies ${module})
|
||||
endforeach()
|
||||
|
||||
list(REMOVE_DUPLICATES module_dependencies)
|
||||
list(REMOVE_DUPLICATES include_dependencies)
|
||||
|
||||
# Add modules to the files to check, if appropriate.
|
||||
foreach(module ${module_dependencies})
|
||||
unset(pxd_location CACHE)
|
||||
find_file(pxd_location ${module}.pxd
|
||||
PATHS "${pyx_path}" ${cmake_include_directories}
|
||||
NO_DEFAULT_PATH)
|
||||
if(pxd_location)
|
||||
list(FIND pxds_checked ${pxd_location} pxd_idx)
|
||||
if(${pxd_idx} LESS 0)
|
||||
list(FIND pxds_to_check ${pxd_location} pxd_idx)
|
||||
if(${pxd_idx} LESS 0)
|
||||
list(APPEND pxds_to_check ${pxd_location})
|
||||
list(APPEND pxd_dependencies ${pxd_location})
|
||||
endif() # if it is not already going to be checked
|
||||
endif() # if it has not already been checked
|
||||
endif() # if pxd file can be found
|
||||
endforeach() # for each module dependency discovered
|
||||
|
||||
# Add includes to the files to check, if appropriate.
|
||||
foreach(_include ${include_dependencies})
|
||||
unset(pxi_location CACHE)
|
||||
find_file(pxi_location ${_include}
|
||||
PATHS "${pyx_path}" ${cmake_include_directories}
|
||||
NO_DEFAULT_PATH)
|
||||
if(pxi_location)
|
||||
list(FIND pxds_checked ${pxi_location} pxd_idx)
|
||||
if(${pxd_idx} LESS 0)
|
||||
list(FIND pxds_to_check ${pxi_location} pxd_idx)
|
||||
if(${pxd_idx} LESS 0)
|
||||
list(APPEND pxds_to_check ${pxi_location})
|
||||
list(APPEND pxd_dependencies ${pxi_location})
|
||||
endif() # if it is not already going to be checked
|
||||
endif() # if it has not already been checked
|
||||
endif() # if include file can be found
|
||||
endforeach() # for each include dependency discovered
|
||||
endforeach() # for each include file to check
|
||||
|
||||
list(LENGTH pxds_to_check number_pxds_to_check)
|
||||
endwhile()
|
||||
|
||||
# Set additional flags.
|
||||
set(annotate_arg "")
|
||||
if(CYTHON_ANNOTATE)
|
||||
set(annotate_arg "--annotate")
|
||||
endif()
|
||||
|
||||
set(no_docstrings_arg "")
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release" OR
|
||||
CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
|
||||
set(no_docstrings_arg "--no-docstrings")
|
||||
endif()
|
||||
|
||||
set(cython_debug_arg "")
|
||||
set(embed_pos_arg "")
|
||||
set(line_directives_arg "")
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR
|
||||
CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
|
||||
set(cython_debug_arg "--gdb")
|
||||
set(embed_pos_arg "--embed-positions")
|
||||
set(line_directives_arg "--line-directives")
|
||||
endif()
|
||||
|
||||
# Include directory arguments.
|
||||
list(REMOVE_DUPLICATES cython_include_directories)
|
||||
set(include_directory_arg "")
|
||||
foreach(_include_dir ${cython_include_directories})
|
||||
set(include_directory_arg
|
||||
${include_directory_arg} "--include-dir" "${_include_dir}")
|
||||
endforeach()
|
||||
|
||||
list(REMOVE_DUPLICATES pxd_dependencies)
|
||||
list(REMOVE_DUPLICATES c_header_dependencies)
|
||||
|
||||
# Add the command to run the compiler.
|
||||
add_custom_command(OUTPUT ${generated_file}
|
||||
COMMAND ${CYTHON_EXECUTABLE}
|
||||
ARGS ${cxx_arg} ${include_directory_arg} ${py_version_arg}
|
||||
${embed_arg} ${annotate_arg} ${no_docstrings_arg}
|
||||
${cython_debug_arg} ${embed_pos_arg}
|
||||
${line_directives_arg} ${CYTHON_FLAGS_LIST} ${pyx_location}
|
||||
--output-file ${generated_file}
|
||||
DEPENDS ${_source_file}
|
||||
${pxd_dependencies}
|
||||
IMPLICIT_DEPENDS ${_output_syntax}
|
||||
${c_header_dependencies}
|
||||
COMMENT ${comment})
|
||||
|
||||
# NOTE(opadron): I thought about making a proper target, but after trying it
|
||||
# out, I decided that it would be far too convenient to use the same name as
|
||||
# the target for the extension module (e.g.: for single-file modules):
|
||||
#
|
||||
# ...
|
||||
# add_cython_target(_module.pyx)
|
||||
# add_library(_module ${_module})
|
||||
# ...
|
||||
#
|
||||
# The above example would not be possible since the "_module" target name
|
||||
# would already be taken by the cython target. Since I can't think of a
|
||||
# reason why someone would need the custom target instead of just using the
|
||||
# generated file directly, I decided to leave this commented out.
|
||||
#
|
||||
# add_custom_target(${_name} DEPENDS ${generated_file})
|
||||
|
||||
# Remove their visibility to the user.
|
||||
set(corresponding_pxd_file "" CACHE INTERNAL "")
|
||||
set(header_location "" CACHE INTERNAL "")
|
||||
set(pxd_location "" CACHE INTERNAL "")
|
||||
endfunction()
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
[build-system]
|
||||
requires = ["setuptools", "wheel", "scikit-build", "cmake", "ninja"]
|
|
@ -0,0 +1,2 @@
|
|||
scikit-build
|
||||
cython
|
37
setup.py
37
setup.py
|
@ -1,20 +1,27 @@
|
|||
from distutils.core import setup
|
||||
from Cython.Build import cythonize
|
||||
from skbuild import setup
|
||||
|
||||
import sys
|
||||
import os
|
||||
sys.path.append(os.path.abspath('./src/simulators'))
|
||||
from simulator_extension import simulator_extension
|
||||
|
||||
# Simulator extension
|
||||
package_name = 'aer.backends.aer_qv_wrapper'
|
||||
source_files = [os.path.abspath('src/simulators/qubitvector/qv_wrapper.pyx')]
|
||||
include_dirs = [os.path.abspath('./src')]
|
||||
|
||||
simulator = simulator_extension(package_name, source_files, include_dirs=include_dirs)
|
||||
|
||||
#sys.path.append(os.path.abspath('./'))
|
||||
setup(
|
||||
name=package_name,
|
||||
packages=[package_name],
|
||||
ext_modules=cythonize(simulator)
|
||||
name='aer_qv_wrapper',
|
||||
packages=['aer_qv_wrapper'],
|
||||
version="0.0.1",
|
||||
description="QV Quantum Simulator",
|
||||
author="AER Development Team",
|
||||
author_email="qiskit@us.ibm.com",
|
||||
license="Apache 2.0",
|
||||
classifiers=[
|
||||
"Environment :: Console",
|
||||
"License :: OSI Approved :: Apache Software License",
|
||||
"Intended Audience :: Developers",
|
||||
"Intended Audience :: Science/Research",
|
||||
"Operating System :: Microsoft :: Windows",
|
||||
"Operating System :: MacOS",
|
||||
"Operating System :: POSIX :: Linux",
|
||||
"Programming Language :: Python :: 3.5",
|
||||
"Programming Language :: Python :: 3.6",
|
||||
"Topic :: Scientific/Engineering",
|
||||
],
|
||||
keywords="qiskit simulator quantum"
|
||||
)
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
cmake_minimum_required(VERSION 3.6.0)
|
||||
project(aer_qv_wrapper LANGUAGES CXX)
|
||||
|
||||
find_package(Cython REQUIRED)
|
||||
find_package(PythonLibs REQUIRED)
|
||||
|
||||
add_cython_target(aer_qv_wrapper qv_wrapper.pyx)
|
||||
add_library(aer_qv_wrapper MODULE ${aer_qv_wrapper})
|
||||
set_target_properties(aer_qv_wrapper PROPERTIES
|
||||
LINKER_LANGUAGE CXX
|
||||
CXX_STANDARD 14)
|
||||
target_include_directories(aer_qv_wrapper
|
||||
PRIVATE ${AER_SIMULATOR_CPP_SRC_DIR}
|
||||
PRIVATE ${AER_SIMULATOR_CPP_EXTERNAL_LIBS}
|
||||
PRIVATE ${PYTHON_INCLUDE_DIRS})
|
||||
target_link_libraries(aer_qv_wrapper
|
||||
${PYTHON_LIBRARIES}
|
||||
${AER_LIBRARIES})
|
||||
install(TARGETS aer_qv_wrapper LIBRARY DESTINATION aer_qv_wrapper)
|
|
@ -0,0 +1,104 @@
|
|||
"""
|
||||
Cython quantum circuit simulator.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
import logging
|
||||
import warnings
|
||||
import numpy as np
|
||||
|
||||
# Import QISKit classes
|
||||
from qiskit._result import Result
|
||||
from qiskit.backends import BaseBackend
|
||||
from qiskit.backends.local.localjob import LocalJob
|
||||
|
||||
# Import Simulator tools
|
||||
from helpers import SimulatorJSONEncoder, qobj2schema
|
||||
from aer_qv_wrapper import AerSimulatorWrapper
|
||||
|
||||
# Logger
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AerSimulator(BaseBackend):
|
||||
"""Cython quantum circuit simulator"""
|
||||
|
||||
DEFAULT_CONFIGURATION = {
|
||||
'name': 'local_aer_simulator',
|
||||
'url': 'NA',
|
||||
'simulator': True,
|
||||
'local': True,
|
||||
'description': 'A C++ statevector simulator for qobj files',
|
||||
'coupling_map': 'all-to-all',
|
||||
"basis_gates": 'u0,u1,u2,u3,cx,cz,id,x,y,z,h,s,sdg,t,tdg,rzz'
|
||||
}
|
||||
|
||||
def __init__(self, configuration=None):
|
||||
super().__init__(configuration or self.DEFAULT_CONFIGURATION.copy())
|
||||
self.simulator = AerSimulatorWrapper()
|
||||
|
||||
def run(self, qobj):
|
||||
"""Run a QOBJ on the the backend."""
|
||||
return LocalJob(self._run_job, qobj)
|
||||
|
||||
def _run_job(self, qobj):
|
||||
self._validate(qobj)
|
||||
qobj_str = json.dumps(qobj2schema(qobj), cls=SimulatorJSONEncoder)
|
||||
result = json.loads(self.simulator.execute(qobj_str))
|
||||
# TODO: get schema in line with result object
|
||||
return result # Result(result)
|
||||
|
||||
def load_noise_model(self, noise_model):
|
||||
self.simulator.load_noise_model(json.dumps(noise_model, cls=SimulatorJSONEncoder))
|
||||
|
||||
def clear_noise_model(self):
|
||||
self.simulator.clear_noise_model()
|
||||
|
||||
def load_config(self, engine=None, state=None):
|
||||
if engine is not None:
|
||||
self.simulator.load_engine_config(json.dumps(engine, cls=SimulatorJSONEncoder))
|
||||
if state is not None:
|
||||
self.simulator.load_state_config(json.dumps(state, cls=SimulatorJSONEncoder))
|
||||
|
||||
def set_max_threads_shot(self, threads):
|
||||
"""
|
||||
Set the maximum threads used for parallel shot execution.
|
||||
|
||||
Args:
|
||||
threads (int): the thread limit, set to -1 to use maximum available
|
||||
|
||||
Note that using parallel shot evaluation disables parallel circuit
|
||||
evaluation.
|
||||
"""
|
||||
|
||||
self.simulator.set_max_threads_shot(int(threads))
|
||||
|
||||
def set_max_threads_circuit(self, threads):
|
||||
"""
|
||||
Set the maximum threads used for parallel circuit execution.
|
||||
|
||||
Args:
|
||||
threads (int): the thread limit, set to -1 to use maximum available
|
||||
|
||||
Note that using parallel circuit evaluation disables parallel shot
|
||||
evaluation.
|
||||
"""
|
||||
self.simulator.set_max_threads_circuit(int(threads))
|
||||
|
||||
def set_max_threads_state(self, threads):
|
||||
"""
|
||||
Set the maximum threads used for state update parallel routines.
|
||||
|
||||
Args:
|
||||
threads (int): the thread limit, set to -1 to use maximum available.
|
||||
|
||||
Note that using parallel circuit or shot execution takes precidence over
|
||||
parallel state evaluation.
|
||||
"""
|
||||
self.simulator.set_max_threads_state(int(threads))
|
||||
|
||||
def _validate(self, qobj):
|
||||
# TODO
|
||||
return
|
|
@ -0,0 +1,544 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Cython C++ QASM Simulator\n",
|
||||
"\n",
|
||||
"Author: Christopher J. Wood (cjwood@us.ibm.com)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Building the simulator\n",
|
||||
"\n",
|
||||
"The simulator backend can be compiled by running the following code cell"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Using the simulator as a QISKit engine\n",
|
||||
"\n",
|
||||
"We now import the cython simulator and use it as a qiskit backend"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Import QISKIT\n",
|
||||
"import numpy as np\n",
|
||||
"import qiskit\n",
|
||||
"from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister\n",
|
||||
"\n",
|
||||
"# Import Cython QASM Simulator Backend\n",
|
||||
"from aer_simulator import AerSimulator\n",
|
||||
"\n",
|
||||
"# Backends\n",
|
||||
"aer = AerSimulator()\n",
|
||||
"aer.set_max_threads_shot(-1)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Create a test circuit\n",
|
||||
"num_qubits = 10\n",
|
||||
"num_gates = 100\n",
|
||||
"qr = QuantumRegister(num_qubits)\n",
|
||||
"cr = ClassicalRegister(num_qubits)\n",
|
||||
"circ = QuantumCircuit(qr, cr)\n",
|
||||
"for j in range(num_gates):\n",
|
||||
" q = np.random.randint(0, num_qubits)\n",
|
||||
" r = np.random.randint(0, 4)\n",
|
||||
" if r == 0: \n",
|
||||
" circ.cx(qr[q], qr[(q + 1) % num_qubits])\n",
|
||||
" elif r == 1:\n",
|
||||
" circ.h(qr[q])\n",
|
||||
" elif r == 2:\n",
|
||||
" circ.s(qr[q])\n",
|
||||
" elif r == 3:\n",
|
||||
" circ.t(qr[q])\n",
|
||||
"for j in range(num_qubits):\n",
|
||||
" circ.measure(qr[j], cr[j])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"{'backend_name': 'qiskit_aer_simulator',\n",
|
||||
" 'backend_version': 'alpha 0.1',\n",
|
||||
" 'date': 'TODO',\n",
|
||||
" 'id': '284835d8-8617-4ba3-9192-785ad484358a',\n",
|
||||
" 'metadata': {'omp_available_threads': 4,\n",
|
||||
" 'omp_circuit_threads': 1,\n",
|
||||
" 'omp_enabled': True,\n",
|
||||
" 'time_taken': 0.17163972600000002},\n",
|
||||
" 'qobj_id': 'TODO',\n",
|
||||
" 'result': [{'data': {'counts': {'0x100': 2,\n",
|
||||
" '0x102': 8,\n",
|
||||
" '0x103': 2,\n",
|
||||
" '0x10c': 3,\n",
|
||||
" '0x10d': 3,\n",
|
||||
" '0x10f': 3,\n",
|
||||
" '0x114': 7,\n",
|
||||
" '0x115': 4,\n",
|
||||
" '0x116': 7,\n",
|
||||
" '0x117': 5,\n",
|
||||
" '0x118': 4,\n",
|
||||
" '0x119': 4,\n",
|
||||
" '0x11a': 9,\n",
|
||||
" '0x11b': 4,\n",
|
||||
" '0x120': 4,\n",
|
||||
" '0x121': 5,\n",
|
||||
" '0x122': 3,\n",
|
||||
" '0x123': 10,\n",
|
||||
" '0x12c': 4,\n",
|
||||
" '0x12d': 8,\n",
|
||||
" '0x12e': 5,\n",
|
||||
" '0x12f': 8,\n",
|
||||
" '0x134': 2,\n",
|
||||
" '0x135': 1,\n",
|
||||
" '0x136': 3,\n",
|
||||
" '0x138': 3,\n",
|
||||
" '0x139': 4,\n",
|
||||
" '0x13a': 2,\n",
|
||||
" '0x13b': 2,\n",
|
||||
" '0x14': 1,\n",
|
||||
" '0x140': 8,\n",
|
||||
" '0x141': 6,\n",
|
||||
" '0x142': 4,\n",
|
||||
" '0x143': 3,\n",
|
||||
" '0x14c': 4,\n",
|
||||
" '0x14d': 5,\n",
|
||||
" '0x14e': 8,\n",
|
||||
" '0x14f': 3,\n",
|
||||
" '0x154': 5,\n",
|
||||
" '0x155': 2,\n",
|
||||
" '0x156': 2,\n",
|
||||
" '0x157': 1,\n",
|
||||
" '0x15a': 2,\n",
|
||||
" '0x16': 1,\n",
|
||||
" '0x160': 3,\n",
|
||||
" '0x161': 3,\n",
|
||||
" '0x162': 1,\n",
|
||||
" '0x163': 1,\n",
|
||||
" '0x16d': 3,\n",
|
||||
" '0x16f': 3,\n",
|
||||
" '0x174': 4,\n",
|
||||
" '0x175': 4,\n",
|
||||
" '0x176': 7,\n",
|
||||
" '0x177': 3,\n",
|
||||
" '0x178': 8,\n",
|
||||
" '0x179': 4,\n",
|
||||
" '0x17a': 4,\n",
|
||||
" '0x17b': 7,\n",
|
||||
" '0x180': 3,\n",
|
||||
" '0x181': 2,\n",
|
||||
" '0x182': 8,\n",
|
||||
" '0x183': 7,\n",
|
||||
" '0x18c': 4,\n",
|
||||
" '0x18d': 5,\n",
|
||||
" '0x18e': 4,\n",
|
||||
" '0x18f': 5,\n",
|
||||
" '0x19': 2,\n",
|
||||
" '0x194': 1,\n",
|
||||
" '0x195': 1,\n",
|
||||
" '0x196': 2,\n",
|
||||
" '0x197': 3,\n",
|
||||
" '0x198': 2,\n",
|
||||
" '0x199': 2,\n",
|
||||
" '0x19a': 3,\n",
|
||||
" '0x19b': 2,\n",
|
||||
" '0x1a': 1,\n",
|
||||
" '0x1a0': 2,\n",
|
||||
" '0x1a1': 1,\n",
|
||||
" '0x1a2': 1,\n",
|
||||
" '0x1a3': 3,\n",
|
||||
" '0x1ac': 3,\n",
|
||||
" '0x1ad': 2,\n",
|
||||
" '0x1ae': 1,\n",
|
||||
" '0x1af': 2,\n",
|
||||
" '0x1b': 1,\n",
|
||||
" '0x1b4': 10,\n",
|
||||
" '0x1b5': 4,\n",
|
||||
" '0x1b7': 3,\n",
|
||||
" '0x1b8': 7,\n",
|
||||
" '0x1b9': 4,\n",
|
||||
" '0x1ba': 5,\n",
|
||||
" '0x1bb': 3,\n",
|
||||
" '0x1c0': 1,\n",
|
||||
" '0x1c3': 1,\n",
|
||||
" '0x1cc': 1,\n",
|
||||
" '0x1cd': 1,\n",
|
||||
" '0x1d4': 3,\n",
|
||||
" '0x1d5': 3,\n",
|
||||
" '0x1d6': 6,\n",
|
||||
" '0x1d7': 6,\n",
|
||||
" '0x1d8': 6,\n",
|
||||
" '0x1d9': 2,\n",
|
||||
" '0x1da': 2,\n",
|
||||
" '0x1db': 5,\n",
|
||||
" '0x1e0': 8,\n",
|
||||
" '0x1e1': 8,\n",
|
||||
" '0x1e2': 4,\n",
|
||||
" '0x1e3': 1,\n",
|
||||
" '0x1ec': 1,\n",
|
||||
" '0x1ed': 2,\n",
|
||||
" '0x1ee': 4,\n",
|
||||
" '0x1ef': 4,\n",
|
||||
" '0x1f4': 2,\n",
|
||||
" '0x1f5': 1,\n",
|
||||
" '0x1f6': 2,\n",
|
||||
" '0x1f7': 1,\n",
|
||||
" '0x1f8': 4,\n",
|
||||
" '0x1fa': 3,\n",
|
||||
" '0x1fb': 3,\n",
|
||||
" '0x20': 1,\n",
|
||||
" '0x20f': 1,\n",
|
||||
" '0x21': 2,\n",
|
||||
" '0x215': 1,\n",
|
||||
" '0x217': 2,\n",
|
||||
" '0x218': 1,\n",
|
||||
" '0x21b': 1,\n",
|
||||
" '0x22': 1,\n",
|
||||
" '0x220': 2,\n",
|
||||
" '0x222': 1,\n",
|
||||
" '0x22c': 4,\n",
|
||||
" '0x22d': 3,\n",
|
||||
" '0x22e': 2,\n",
|
||||
" '0x236': 1,\n",
|
||||
" '0x23b': 2,\n",
|
||||
" '0x240': 2,\n",
|
||||
" '0x241': 2,\n",
|
||||
" '0x242': 1,\n",
|
||||
" '0x243': 1,\n",
|
||||
" '0x24c': 1,\n",
|
||||
" '0x24d': 4,\n",
|
||||
" '0x24e': 1,\n",
|
||||
" '0x254': 1,\n",
|
||||
" '0x263': 1,\n",
|
||||
" '0x26d': 2,\n",
|
||||
" '0x26e': 1,\n",
|
||||
" '0x274': 2,\n",
|
||||
" '0x275': 1,\n",
|
||||
" '0x277': 1,\n",
|
||||
" '0x27b': 1,\n",
|
||||
" '0x280': 1,\n",
|
||||
" '0x281': 1,\n",
|
||||
" '0x283': 1,\n",
|
||||
" '0x28f': 1,\n",
|
||||
" '0x298': 2,\n",
|
||||
" '0x299': 1,\n",
|
||||
" '0x2b4': 1,\n",
|
||||
" '0x2b6': 1,\n",
|
||||
" '0x2b7': 1,\n",
|
||||
" '0x2b8': 1,\n",
|
||||
" '0x2ba': 1,\n",
|
||||
" '0x2bb': 1,\n",
|
||||
" '0x2cc': 1,\n",
|
||||
" '0x2ce': 1,\n",
|
||||
" '0x2d': 1,\n",
|
||||
" '0x2d5': 1,\n",
|
||||
" '0x2d9': 1,\n",
|
||||
" '0x2db': 2,\n",
|
||||
" '0x2e0': 3,\n",
|
||||
" '0x2e1': 1,\n",
|
||||
" '0x2e2': 2,\n",
|
||||
" '0x2ec': 2,\n",
|
||||
" '0x2ee': 1,\n",
|
||||
" '0x2ef': 2,\n",
|
||||
" '0x2f9': 2,\n",
|
||||
" '0x2fb': 1,\n",
|
||||
" '0x301': 2,\n",
|
||||
" '0x302': 3,\n",
|
||||
" '0x303': 1,\n",
|
||||
" '0x30c': 2,\n",
|
||||
" '0x30d': 1,\n",
|
||||
" '0x30e': 3,\n",
|
||||
" '0x30f': 4,\n",
|
||||
" '0x314': 8,\n",
|
||||
" '0x315': 3,\n",
|
||||
" '0x316': 2,\n",
|
||||
" '0x317': 4,\n",
|
||||
" '0x318': 3,\n",
|
||||
" '0x319': 7,\n",
|
||||
" '0x31a': 4,\n",
|
||||
" '0x31b': 4,\n",
|
||||
" '0x320': 7,\n",
|
||||
" '0x321': 5,\n",
|
||||
" '0x322': 2,\n",
|
||||
" '0x323': 5,\n",
|
||||
" '0x32c': 4,\n",
|
||||
" '0x32d': 4,\n",
|
||||
" '0x32e': 6,\n",
|
||||
" '0x32f': 6,\n",
|
||||
" '0x334': 1,\n",
|
||||
" '0x335': 2,\n",
|
||||
" '0x336': 3,\n",
|
||||
" '0x338': 3,\n",
|
||||
" '0x339': 1,\n",
|
||||
" '0x33a': 1,\n",
|
||||
" '0x33b': 2,\n",
|
||||
" '0x340': 4,\n",
|
||||
" '0x341': 7,\n",
|
||||
" '0x342': 2,\n",
|
||||
" '0x343': 7,\n",
|
||||
" '0x34c': 6,\n",
|
||||
" '0x34d': 2,\n",
|
||||
" '0x34e': 6,\n",
|
||||
" '0x34f': 3,\n",
|
||||
" '0x354': 3,\n",
|
||||
" '0x356': 1,\n",
|
||||
" '0x358': 4,\n",
|
||||
" '0x359': 2,\n",
|
||||
" '0x35a': 4,\n",
|
||||
" '0x35b': 1,\n",
|
||||
" '0x360': 1,\n",
|
||||
" '0x361': 2,\n",
|
||||
" '0x362': 1,\n",
|
||||
" '0x363': 1,\n",
|
||||
" '0x36c': 3,\n",
|
||||
" '0x36d': 1,\n",
|
||||
" '0x36e': 1,\n",
|
||||
" '0x374': 5,\n",
|
||||
" '0x375': 10,\n",
|
||||
" '0x376': 5,\n",
|
||||
" '0x377': 10,\n",
|
||||
" '0x378': 4,\n",
|
||||
" '0x379': 3,\n",
|
||||
" '0x37a': 3,\n",
|
||||
" '0x37b': 2,\n",
|
||||
" '0x380': 5,\n",
|
||||
" '0x381': 5,\n",
|
||||
" '0x382': 4,\n",
|
||||
" '0x383': 4,\n",
|
||||
" '0x38c': 6,\n",
|
||||
" '0x38d': 10,\n",
|
||||
" '0x38e': 7,\n",
|
||||
" '0x38f': 9,\n",
|
||||
" '0x394': 1,\n",
|
||||
" '0x395': 2,\n",
|
||||
" '0x396': 2,\n",
|
||||
" '0x397': 1,\n",
|
||||
" '0x398': 1,\n",
|
||||
" '0x399': 1,\n",
|
||||
" '0x39a': 2,\n",
|
||||
" '0x39b': 1,\n",
|
||||
" '0x3a0': 4,\n",
|
||||
" '0x3a1': 2,\n",
|
||||
" '0x3a2': 1,\n",
|
||||
" '0x3a3': 2,\n",
|
||||
" '0x3ac': 2,\n",
|
||||
" '0x3ad': 2,\n",
|
||||
" '0x3af': 1,\n",
|
||||
" '0x3b4': 5,\n",
|
||||
" '0x3b5': 8,\n",
|
||||
" '0x3b6': 4,\n",
|
||||
" '0x3b7': 4,\n",
|
||||
" '0x3b8': 6,\n",
|
||||
" '0x3b9': 5,\n",
|
||||
" '0x3ba': 7,\n",
|
||||
" '0x3bb': 6,\n",
|
||||
" '0x3c0': 2,\n",
|
||||
" '0x3c1': 2,\n",
|
||||
" '0x3cd': 1,\n",
|
||||
" '0x3ce': 1,\n",
|
||||
" '0x3cf': 1,\n",
|
||||
" '0x3d4': 8,\n",
|
||||
" '0x3d5': 7,\n",
|
||||
" '0x3d6': 1,\n",
|
||||
" '0x3d7': 6,\n",
|
||||
" '0x3d8': 4,\n",
|
||||
" '0x3d9': 3,\n",
|
||||
" '0x3da': 9,\n",
|
||||
" '0x3db': 8,\n",
|
||||
" '0x3e1': 6,\n",
|
||||
" '0x3e2': 5,\n",
|
||||
" '0x3e3': 9,\n",
|
||||
" '0x3ec': 6,\n",
|
||||
" '0x3ed': 4,\n",
|
||||
" '0x3ee': 5,\n",
|
||||
" '0x3ef': 6,\n",
|
||||
" '0x3f5': 1,\n",
|
||||
" '0x3f6': 1,\n",
|
||||
" '0x3f7': 3,\n",
|
||||
" '0x3f8': 2,\n",
|
||||
" '0x3f9': 4,\n",
|
||||
" '0x3fa': 2,\n",
|
||||
" '0x3fb': 3,\n",
|
||||
" '0x41': 1,\n",
|
||||
" '0x43': 1,\n",
|
||||
" '0x4f': 3,\n",
|
||||
" '0x56': 1,\n",
|
||||
" '0x59': 1,\n",
|
||||
" '0x76': 3,\n",
|
||||
" '0x78': 1,\n",
|
||||
" '0x80': 1,\n",
|
||||
" '0x81': 1,\n",
|
||||
" '0x82': 1,\n",
|
||||
" '0x83': 1,\n",
|
||||
" '0x8c': 1,\n",
|
||||
" '0x8e': 1,\n",
|
||||
" '0x8f': 1,\n",
|
||||
" '0x94': 1,\n",
|
||||
" '0xad': 1,\n",
|
||||
" '0xb4': 2,\n",
|
||||
" '0xb6': 1,\n",
|
||||
" '0xb7': 2,\n",
|
||||
" '0xb8': 3,\n",
|
||||
" '0xb9': 1,\n",
|
||||
" '0xba': 2,\n",
|
||||
" '0xbb': 1,\n",
|
||||
" '0xc2': 1,\n",
|
||||
" '0xc3': 1,\n",
|
||||
" '0xd5': 1,\n",
|
||||
" '0xd6': 1,\n",
|
||||
" '0xd8': 1,\n",
|
||||
" '0xd9': 2,\n",
|
||||
" '0xe1': 1,\n",
|
||||
" '0xe2': 1,\n",
|
||||
" '0xe3': 2,\n",
|
||||
" '0xed': 1,\n",
|
||||
" '0xee': 2,\n",
|
||||
" '0xef': 1,\n",
|
||||
" '0xf5': 2}},\n",
|
||||
" 'header': {'name': 'circuit1'},\n",
|
||||
" 'metadata': {'omp_shot_threads': 4,\n",
|
||||
" 'omp_state_threads': 1,\n",
|
||||
" 'seed': 1925572646,\n",
|
||||
" 'shots': 1000,\n",
|
||||
" 'time_taken': 0.17120264200000002},\n",
|
||||
" 'status': 'DONE',\n",
|
||||
" 'success': True}],\n",
|
||||
" 'status': 'COMPLETED',\n",
|
||||
" 'success': True}"
|
||||
]
|
||||
},
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"result = qiskit.execute(circ, aer, shots=1000).result()\n",
|
||||
"result"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"noise_model = {\n",
|
||||
" \"errors\": [\n",
|
||||
" {\n",
|
||||
" \"type\": \"kraus\",\n",
|
||||
" \"operations\": [\"h\"],\n",
|
||||
" \"probabilities\": [1],\n",
|
||||
" \"matrices\": [np.array([[1, 0], [0, 0.5]]),\n",
|
||||
" np.array([[0, 0.86602540378], [0, 0]])]\n",
|
||||
" }\n",
|
||||
" ]\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"aer.load_noise_model(noise_model)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"{'backend_name': 'qiskit_aer_simulator',\n",
|
||||
" 'backend_version': 'alpha 0.1',\n",
|
||||
" 'date': 'TODO',\n",
|
||||
" 'id': '2fad1b6a-7031-49b8-a486-876240caf385',\n",
|
||||
" 'metadata': {'omp_available_threads': 4,\n",
|
||||
" 'omp_circuit_threads': 1,\n",
|
||||
" 'omp_enabled': True,\n",
|
||||
" 'time_taken': 0.34858704900000004},\n",
|
||||
" 'qobj_id': 'TODO',\n",
|
||||
" 'result': [{'data': {'counts': {'0x1ff': 364,\n",
|
||||
" '0x2ff': 8,\n",
|
||||
" '0x3ff': 620,\n",
|
||||
" '0xbf': 1,\n",
|
||||
" '0xff': 31}},\n",
|
||||
" 'header': {'name': 'circuit1'},\n",
|
||||
" 'metadata': {'omp_shot_threads': 4,\n",
|
||||
" 'omp_state_threads': 1,\n",
|
||||
" 'seed': 3182171174,\n",
|
||||
" 'shots': 1024,\n",
|
||||
" 'time_taken': 0.34713111900000004},\n",
|
||||
" 'status': 'DONE',\n",
|
||||
" 'success': True}],\n",
|
||||
" 'status': 'COMPLETED',\n",
|
||||
" 'success': True}"
|
||||
]
|
||||
},
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"result = qiskit.execute(circ, aer).result()\n",
|
||||
"result"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python (qiskit)",
|
||||
"language": "python",
|
||||
"name": "qiskit"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.6.5"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
import json
|
||||
import numpy as np
|
||||
|
||||
|
||||
class SimulatorJSONEncoder(json.JSONEncoder):
|
||||
"""
|
||||
JSON encoder for NumPy arrays and complex numbers.
|
||||
|
||||
This functions as the standard JSON Encoder but adds support
|
||||
for encoding:
|
||||
complex numbers z as lists [z.real, z.imag]
|
||||
ndarrays as nested lists.
|
||||
"""
|
||||
|
||||
# pylint: disable=method-hidden,arguments-differ
|
||||
def default(self, obj):
|
||||
if isinstance(obj, np.ndarray):
|
||||
return obj.tolist()
|
||||
if isinstance(obj, complex):
|
||||
return [obj.real, obj.imag]
|
||||
return json.JSONEncoder.default(self, obj)
|
||||
|
||||
|
||||
def qobj2schema(qobj):
|
||||
"""
|
||||
Convert current Qiskit qobj in line with schema spec qobj for simulator testing.
|
||||
"""
|
||||
shots = qobj.get("config",{}).get("shots", 1)
|
||||
qobj["type"] = "QASM"
|
||||
if "circuits" in qobj:
|
||||
qobj["experiments"] = qobj.pop("circuits")
|
||||
if "experiments" in qobj:
|
||||
for i, experiment in enumerate(qobj["experiments"]):
|
||||
# adjust labels
|
||||
if "compiled_circuit" in experiment:
|
||||
experiment["compiled_circuit"].pop("header", None)
|
||||
experiment["instructions"] = experiment.pop("compiled_circuit", {}).pop("operations", [])
|
||||
for k, op in enumerate(experiment["instructions"]):
|
||||
if op.get("name") == "measure":
|
||||
op["memory"] = op.pop("clbits")
|
||||
op["register"] = op["memory"]
|
||||
experiment["instructions"][k] = op
|
||||
experiment["config"] = {"shots": shots}
|
||||
# clear compiled qasm
|
||||
experiment.pop("compiled_circuit_qasm", '')
|
||||
# clear old header
|
||||
if "name" in experiment:
|
||||
experiment["header"] = {"name": experiment.pop("name")}
|
||||
qobj["experiments"][i] = experiment
|
||||
return qobj
|
|
@ -0,0 +1,106 @@
|
|||
"""
|
||||
Cython interface to C++ quantum circuit simulator.
|
||||
"""
|
||||
|
||||
# Import C++ Classes
|
||||
from libcpp.string cimport string
|
||||
|
||||
# Import C++ simulator Interface class
|
||||
cdef extern from "framework/interface.hpp" namespace "AER":
|
||||
cdef cppclass Interface:
|
||||
Interface() except+
|
||||
string execute[STATE, STATECLASS](string &qobj) except +
|
||||
|
||||
void load_noise_model(string &qobj) except +
|
||||
void load_engine_config(string &qobj) except +
|
||||
void load_state_config(string &qobj) except +
|
||||
|
||||
void clear_noise_model()
|
||||
void clear_engine_config()
|
||||
void clear_state_config()
|
||||
|
||||
void set_max_threads(int threads)
|
||||
void set_max_threads_circuit(int threads)
|
||||
void set_max_threads_shot(int threads)
|
||||
void set_max_threads_state(int threads)
|
||||
|
||||
int get_max_threads()
|
||||
int get_max_threads_circuit()
|
||||
int get_max_threads_shot()
|
||||
int get_max_threads_state()
|
||||
|
||||
# QubitVector State class
|
||||
cdef extern from "simulators/qubitvector/qubitvector.hpp" namespace "QV":
|
||||
cdef cppclass QubitVector:
|
||||
State() except +
|
||||
|
||||
# QubitVector State class
|
||||
cdef extern from "simulators/qubitvector/qv_state.hpp" namespace "AER::QubitVector":
|
||||
cdef cppclass State:
|
||||
State() except +
|
||||
|
||||
|
||||
cdef class AerSimulatorWrapper:
|
||||
|
||||
cdef Interface *thisptr
|
||||
|
||||
def __cinit__(self):
|
||||
self.thisptr = new Interface()
|
||||
|
||||
def __dealloc__(self):
|
||||
del self.thisptr
|
||||
|
||||
def execute(self, qobj):
|
||||
# Convert input to C++ string
|
||||
cdef string qobj_enc = str(qobj).encode('UTF-8')
|
||||
# Execute
|
||||
return self.thisptr.execute[QubitVector, State](qobj_enc)
|
||||
|
||||
def load_noise_model(self, config):
|
||||
# Convert input to C++ string
|
||||
cdef string config_enc = str(config).encode('UTF-8')
|
||||
self.thisptr.load_noise_model(config_enc)
|
||||
|
||||
def load_state_config(self, config):
|
||||
# Convert input to C++ string
|
||||
cdef string config_enc = str(config).encode('UTF-8')
|
||||
self.thisptr.load_state_config(config_enc)
|
||||
|
||||
def load_engine_config(self, config):
|
||||
# Convert input to C++ string
|
||||
cdef string config_enc = str(config).encode('UTF-8')
|
||||
self.thisptr.load_engine_config(config_enc)
|
||||
|
||||
def clear_noise_model(self):
|
||||
self.thisptr.clear_noise_model()
|
||||
|
||||
def clear_state_config(self):
|
||||
|
||||
self.thisptr.clear_state_config()
|
||||
|
||||
def clear_engine_config(self):
|
||||
self.thisptr.clear_engine_config()
|
||||
|
||||
def set_max_threads(self, threads):
|
||||
self.thisptr.set_max_threads(int(threads))
|
||||
|
||||
def set_max_threads_circuit(self, threads):
|
||||
self.thisptr.set_max_threads_circuit(int(threads))
|
||||
|
||||
def set_max_threads_shot(self, threads):
|
||||
self.thisptr.set_max_threads_shot(int(threads))
|
||||
|
||||
def set_max_threads_state(self, threads):
|
||||
self.thisptr.set_max_threads_state(int(threads))
|
||||
|
||||
def get_max_threads(self):
|
||||
return self.thisptr.get_max_threads()
|
||||
|
||||
def get_max_threads_circuit(self):
|
||||
return self.thisptr.get_max_threads_circuit()
|
||||
|
||||
def get_max_threads_shot(self):
|
||||
return self.thisptr.get_max_threads_shot()
|
||||
|
||||
def get_max_threads_state(self):
|
||||
return self.thisptr.get_max_threads_state()
|
Loading…
Reference in New Issue