diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000000..cc3f2683f8 --- /dev/null +++ b/.clang-format @@ -0,0 +1,3 @@ +BasedOnStyle: LLVM +AlwaysBreakTemplateDeclarations: Yes +RemoveBracesLLVM: No diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d540b0978e..2f43de1ca8 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -34,10 +34,15 @@ jobs: pip install -U pip wheel pip install -U -c constraints.txt -r requirements-dev.txt qiskit-terra numpy scipy shell: bash + - name: Run clang-format + run: | + set -e + sh tools/clang-format.sh --Werror -n + shell: bash - name: Run Lint run: | set -e - pycodestyle --ignore=E402,W503,W504 --max-line-length=100 qiskit_aer + black --check qiskit_aer test tools setup.py pylint -j 2 -rn qiskit_aer sdist: runs-on: ${{ matrix.platform.os }} diff --git a/.pylintrc b/.pylintrc index c8443f43e8..5ae93e220b 100644 --- a/.pylintrc +++ b/.pylintrc @@ -21,7 +21,7 @@ persistent=yes # List of plugins (as comma separated values of python modules names) to load, # usually to register additional checkers. load-plugins=pylint.extensions.docparams, # enable checking of docstring args - pylint.extensions.docstyle # basic docstring stle checks + pylint.extensions.docstyle, # basic docstring style checks # Use multiple processes to speed up Pylint. jobs=1 @@ -33,8 +33,7 @@ unsafe-load-any-extension=no # A comma-separated list of package or module names from where C extensions may # be loaded. Extensions are loading into the active Python interpreter and may # run arbitrary code -extension-pkg-whitelist= - +extension-pkg-allow-list= [MESSAGES CONTROL] @@ -43,10 +42,10 @@ extension-pkg-whitelist= confidence= # Enable the message, report, category or checker with the given id(s). You can -# either give multiple identifiers separated by comma (,) or put this option +# either give multiple identifier separated by comma (,) or put this option # multiple time (only on the command line, not in the configuration file where # it should appear only once). See also the "--disable" option for examples. -#enable= +enable=use-symbolic-message-instead # Disable the message, report, category or checker with the given id(s). You # can either give multiple identifiers separated by comma (,) or put this @@ -57,7 +56,8 @@ confidence= # --enable=similarities". If you want to run only the classes checker, but have # no Warning level messages displayed, use"--disable=all --enable=classes # --disable=W" -disable=no-self-use, # disabled as it is too verbose +disable=spelling, # way too noisy + no-self-use, # disabled as it is too verbose fixme, # disabled as TODOs would show up as warnings protected-access, # disabled as we don't follow the public vs private # convention strictly @@ -70,8 +70,13 @@ disable=no-self-use, # disabled as it is too verbose unnecessary-pass, # allow for methods with just "pass", for clarity no-else-return, # relax "elif" after a clause with a return docstring-first-line-empty, # relax docstring style - unsubscriptable-object, # pylint can't determine this for numpy types - bad-continuation, bad-whitespace # differences of opinion with black + import-outside-toplevel, + bad-continuation, bad-whitespace, # differences of opinion with black + import-error, # overzealous with our optionals/dynamic packages + consider-using-f-string, # pass re-lint old commits + broad-exception-raised, # pass re-lint old commits + unsubscriptable-object # pass re-lint old commits + @@ -83,12 +88,6 @@ disable=no-self-use, # disabled as it is too verbose # mypackage.mymodule.MyReporterClass. output-format=text -# Put messages in a separate file for each module / package specified on the -# command line instead of printing them on stdout. Reports (if any) will be -# written in a file name "pylint_global.[txt|html]". This option is deprecated -# and it will be removed in Pylint 2.0. -files-output=no - # Tells whether to display a full report or only the messages reports=yes @@ -117,8 +116,8 @@ evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / stateme # pi = the PI constant # op = operation iterator # b = basis iterator -good-names=i,j,k,n,m,ex,v,w,x,y,z,Run,_,logger,q,c,r,qr,cr,qc,nd,pi,op,b,ar,br,dt, - __unittest +good-names=a,b,i,j,k,d,n,m,ex,v,w,x,y,z,Run,_,logger,q,c,r,qr,cr,qc,nd,pi,op,b,ar,br,p,cp,dt, + __unittest,iSwapGate,mu # Bad variable names which should always be refused, separated by a comma bad-names=foo,bar,toto,tutu,tata @@ -171,16 +170,16 @@ attr-rgx=[a-z_][a-z0-9_]{2,30}$ attr-name-hint=[a-z_][a-z0-9_]{2,30}$ # Regular expression matching correct argument names -argument-rgx=[a-z_][a-z0-9_]{2,30}$ +argument-rgx=[a-z_][a-z0-9_]{2,30}|ax|dt$ # Naming hint for argument names argument-name-hint=[a-z_][a-z0-9_]{2,30}$ # Regular expression matching correct variable names -variable-rgx=[a-z_][a-z0-9_]{2,30}$ +variable-rgx=[a-z_][a-z0-9_]{1,30}$ # Naming hint for variable names -variable-name-hint=[a-z_][a-z0-9_]{2,30}$ +variable-name-hint=[a-z_][a-z0-9_]{1,30}$ # Regular expression matching correct class attribute names class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ @@ -212,7 +211,7 @@ max-nested-blocks=5 [FORMAT] # Maximum number of characters on a single line. -max-line-length=100 +max-line-length=105 # Regexp for a line that is allowed to be longer than the limit. ignore-long-lines=^\s*(# )??$ @@ -279,7 +278,7 @@ spelling-dict= spelling-ignore-words= # A path to a file that contains private dictionary; one word per line. -spelling-private-dict-file= +spelling-private-dict-file=.local-spellings # Tells whether to store unknown words to indicated private dictionary in # --spelling-private-dict-file option instead of raising a message. @@ -296,7 +295,7 @@ ignore-mixin-members=yes # (useful for modules/projects where namespaces are manipulated during runtime # and thus existing member attributes cannot be deduced by static analysis. It # supports qualified module names, as well as Unix pattern matching. -ignored-modules=matplotlib.cm,numpy.random,qiskit.providers +ignored-modules=numpy # List of class names for which member attributes should not be checked (useful # for classes with dynamically set attributes). This supports the use of @@ -333,7 +332,7 @@ callbacks=cb_,_cb # List of qualified module names which can have objects that can redefine # builtins. -redefining-builtins-modules=six.moves,future.builtins,tools.compiler +redefining-builtins-modules=six.moves,future.builtins [CLASSES] diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 307136e3c5..fe22e4232d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,6 +18,11 @@ please ensure that: 1. The code follows the code style of the project and successfully passes the tests. For convenience, you can execute `tox` locally, which will run these checks and report any issues. + + If your code fails the local style checks, you can use `tox -eblack` + and `tox -eclang` to automatically fix update the code formatting + in python and C++ respectively. + 2. The documentation has been updated accordingly. In particular, if a function or class has been modified during the PR, please update the *docstring* accordingly. @@ -185,6 +190,24 @@ like for the current state of the repo, you can run: `tox -edocs` which will build all the documentation into `docs/_build/html` and the release notes in particular will be located at `docs/_build/html/release_notes.html` +## Style and lint + +Qiskit Aer uses 3 tools for verify 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 +which does a deeper analysis of the Python code to find both style issues and +potential bugs and other common issues in Python. The third tool is +[clang-format](https://clang.llvm.org/docs/ClangFormat.html) which is a +C++ code formatting tool that will automatically update codes with a consitent style. + +You can check that your local modifications conform to the style rules +by running `tox -elint` which will run `black`, `pylint` and `clang-format` +to check the local code formatting and lint. If black returns a code +formatting error you can run `tox -eblack` to automatically update the +code formatting to conform to the style. However, if `pylint` returns +any error you will have to fix these issues by manually updating your code. + ### Development Cycle The development cycle for qiskit-aer is all handled in the open using diff --git a/contrib/runtime/aer_runtime.cpp b/contrib/runtime/aer_runtime.cpp index 3686714005..037b60da7c 100644 --- a/contrib/runtime/aer_runtime.cpp +++ b/contrib/runtime/aer_runtime.cpp @@ -11,218 +11,224 @@ * copyright notice, and modified files need to carry a notice indicating * that they have been altered from the originals. */ -#include #include "controllers/state_controller.hpp" +#include // initialize and return state extern "C" { -void* aer_state() { - AER::AerState* handler = new AER::AerState(); +void *aer_state() { + AER::AerState *handler = new AER::AerState(); return handler; }; -void* aer_state_initialize(void* handler) { - AER::AerState* state = reinterpret_cast(handler); +void *aer_state_initialize(void *handler) { + AER::AerState *state = reinterpret_cast(handler); state->initialize(); return handler; }; // finalize state -void aer_state_finalize(void* handler) { - AER::AerState* state = reinterpret_cast(handler); - delete(state); +void aer_state_finalize(void *handler) { + AER::AerState *state = reinterpret_cast(handler); + delete (state); }; // configure state -void aer_state_configure(void* handler, char* key, char* value) { - AER::AerState* state = reinterpret_cast(handler); +void aer_state_configure(void *handler, char *key, char *value) { + AER::AerState *state = reinterpret_cast(handler); state->configure(key, value); }; // allocate qubits and return the first qubit index. // following qubits are indexed with incremented indices. -uint_t aer_allocate_qubits(void* handler, uint_t num_qubits) { - AER::AerState* state = reinterpret_cast(handler); +uint_t aer_allocate_qubits(void *handler, uint_t num_qubits) { + AER::AerState *state = reinterpret_cast(handler); auto qubit_ids = state->allocate_qubits(num_qubits); return qubit_ids[0]; }; // measure qubits -uint_t aer_apply_measure(void* handler, uint_t* qubits_, size_t num_qubits) { - AER::AerState* state = reinterpret_cast(handler); +uint_t aer_apply_measure(void *handler, uint_t *qubits_, size_t num_qubits) { + AER::AerState *state = reinterpret_cast(handler); std::vector qubits; qubits.insert(qubits.end(), &(qubits_[0]), &(qubits[num_qubits - 1])); return state->apply_measure(qubits); }; // return probability of a specific bitstring -double aer_probability(void* handler, uint_t outcome) { - AER::AerState* state = reinterpret_cast(handler); +double aer_probability(void *handler, uint_t outcome) { + AER::AerState *state = reinterpret_cast(handler); return state->probability(outcome); }; // return probability amplitude of a specific bitstring -complex_t aer_amplitude(void* handler, uint_t outcome) { - AER::AerState* state = reinterpret_cast(handler); +complex_t aer_amplitude(void *handler, uint_t outcome) { + AER::AerState *state = reinterpret_cast(handler); return state->amplitude(outcome); }; // return probability amplitudes // returned pointer must be freed in the caller -complex_t* aer_release_statevector(void* handler) { - AER::AerState* state = reinterpret_cast(handler); +complex_t *aer_release_statevector(void *handler) { + AER::AerState *state = reinterpret_cast(handler); AER::Vector sv = state->move_to_vector(); return sv.move_to_buffer(); }; // phase gate -void aer_apply_p(void* handler, uint_t qubit, double lambda) { - AER::AerState* state = reinterpret_cast(handler); +void aer_apply_p(void *handler, uint_t qubit, double lambda) { + AER::AerState *state = reinterpret_cast(handler); state->apply_mcphase({qubit}, lambda); }; // Pauli gate: bit-flip or NOT gate -void aer_apply_x(void* handler, uint_t qubit) { - AER::AerState* state = reinterpret_cast(handler); +void aer_apply_x(void *handler, uint_t qubit) { + AER::AerState *state = reinterpret_cast(handler); state->apply_mcx({qubit}); }; // Pauli gate: bit and phase flip -void aer_apply_y(void* handler, uint_t qubit) { - AER::AerState* state = reinterpret_cast(handler); +void aer_apply_y(void *handler, uint_t qubit) { + AER::AerState *state = reinterpret_cast(handler); state->apply_mcy({qubit}); }; // Pauli gate: phase flip -void aer_apply_z(void* handler, uint_t qubit) { - AER::AerState* state = reinterpret_cast(handler); +void aer_apply_z(void *handler, uint_t qubit) { + AER::AerState *state = reinterpret_cast(handler); state->apply_mcz({qubit}); }; // Clifford gate: Hadamard -void aer_apply_h(void* handler, uint_t qubit) { - AER::AerState* state = reinterpret_cast(handler); +void aer_apply_h(void *handler, uint_t qubit) { + AER::AerState *state = reinterpret_cast(handler); state->apply_h(qubit); }; // Clifford gate: sqrt(Z) or S gate -void aer_apply_s(void* handler, uint_t qubit) { - AER::AerState* state = reinterpret_cast(handler); +void aer_apply_s(void *handler, uint_t qubit) { + AER::AerState *state = reinterpret_cast(handler); state->apply_u(qubit, 0, 0, M_PI / 2.0); }; // Clifford gate: inverse of sqrt(Z) -void aer_apply_sdg(void* handler, uint_t qubit) { - AER::AerState* state = reinterpret_cast(handler); - state->apply_u(qubit, 0, 0, - M_PI / 2.0); +void aer_apply_sdg(void *handler, uint_t qubit) { + AER::AerState *state = reinterpret_cast(handler); + state->apply_u(qubit, 0, 0, -M_PI / 2.0); }; // // sqrt(S) or T gate -void aer_apply_t(void* handler, uint_t qubit) { - AER::AerState* state = reinterpret_cast(handler); +void aer_apply_t(void *handler, uint_t qubit) { + AER::AerState *state = reinterpret_cast(handler); state->apply_u(qubit, 0, 0, M_PI / 4.0); }; // inverse of sqrt(S) -void aer_apply_tdg(void* handler, uint_t qubit) { - AER::AerState* state = reinterpret_cast(handler); - state->apply_u({qubit}, 0, 0, - M_PI / 4.0); +void aer_apply_tdg(void *handler, uint_t qubit) { + AER::AerState *state = reinterpret_cast(handler); + state->apply_u({qubit}, 0, 0, -M_PI / 4.0); }; // sqrt(NOT) gate -void aer_apply_sx(void* handler, uint_t qubit) { - AER::AerState* state = reinterpret_cast(handler); - state->apply_mcrx({qubit}, - M_PI / 4.0); +void aer_apply_sx(void *handler, uint_t qubit) { + AER::AerState *state = reinterpret_cast(handler); + state->apply_mcrx({qubit}, -M_PI / 4.0); }; // Rotation around X-axis -void aer_apply_rx(void* handler, uint_t qubit, double theta) { - AER::AerState* state = reinterpret_cast(handler); +void aer_apply_rx(void *handler, uint_t qubit, double theta) { + AER::AerState *state = reinterpret_cast(handler); state->apply_mcrx({qubit}, theta); }; // rotation around Y-axis -void aer_apply_ry(void* handler, uint_t qubit, double theta) { - AER::AerState* state = reinterpret_cast(handler); +void aer_apply_ry(void *handler, uint_t qubit, double theta) { + AER::AerState *state = reinterpret_cast(handler); state->apply_mcry({qubit}, theta); }; // rotation around Z axis -void aer_apply_rz(void* handler, uint_t qubit, double theta) { - AER::AerState* state = reinterpret_cast(handler); +void aer_apply_rz(void *handler, uint_t qubit, double theta) { + AER::AerState *state = reinterpret_cast(handler); state->apply_mcrz({qubit}, theta); }; // controlled-NOT -void aer_apply_cx(void* handler, uint_t ctrl_qubit, uint_t tgt_qubit) { - AER::AerState* state = reinterpret_cast(handler); +void aer_apply_cx(void *handler, uint_t ctrl_qubit, uint_t tgt_qubit) { + AER::AerState *state = reinterpret_cast(handler); state->apply_mcx({ctrl_qubit, tgt_qubit}); }; // controlled-Y -void aer_apply_cy(void* handler, uint_t ctrl_qubit, uint_t tgt_qubit) { - AER::AerState* state = reinterpret_cast(handler); +void aer_apply_cy(void *handler, uint_t ctrl_qubit, uint_t tgt_qubit) { + AER::AerState *state = reinterpret_cast(handler); state->apply_mcy({ctrl_qubit, tgt_qubit}); }; // controlled-Z -void aer_apply_cz(void* handler, uint_t ctrl_qubit, uint_t tgt_qubit) { - AER::AerState* state = reinterpret_cast(handler); +void aer_apply_cz(void *handler, uint_t ctrl_qubit, uint_t tgt_qubit) { + AER::AerState *state = reinterpret_cast(handler); state->apply_mcz({ctrl_qubit, tgt_qubit}); }; // controlled-phase -void aer_apply_cp(void* handler, uint_t ctrl_qubit, uint_t tgt_qubit, double lambda) { - AER::AerState* state = reinterpret_cast(handler); +void aer_apply_cp(void *handler, uint_t ctrl_qubit, uint_t tgt_qubit, + double lambda) { + AER::AerState *state = reinterpret_cast(handler); state->apply_mcphase({ctrl_qubit, tgt_qubit}, lambda); }; // controlled-rx -void aer_apply_crx(void* handler, uint_t ctrl_qubit, uint_t tgt_qubit, double theta) { - AER::AerState* state = reinterpret_cast(handler); +void aer_apply_crx(void *handler, uint_t ctrl_qubit, uint_t tgt_qubit, + double theta) { + AER::AerState *state = reinterpret_cast(handler); state->apply_mcrx({ctrl_qubit, tgt_qubit}, theta); }; // controlled-ry -void aer_apply_cry(void* handler, uint_t ctrl_qubit, uint_t tgt_qubit, double theta) { - AER::AerState* state = reinterpret_cast(handler); +void aer_apply_cry(void *handler, uint_t ctrl_qubit, uint_t tgt_qubit, + double theta) { + AER::AerState *state = reinterpret_cast(handler); state->apply_mcry({ctrl_qubit, tgt_qubit}, theta); }; // controlled-rz -void aer_apply_crz(void* handler, uint_t ctrl_qubit, uint_t tgt_qubit, double theta) { - AER::AerState* state = reinterpret_cast(handler); +void aer_apply_crz(void *handler, uint_t ctrl_qubit, uint_t tgt_qubit, + double theta) { + AER::AerState *state = reinterpret_cast(handler); state->apply_mcrz({ctrl_qubit, tgt_qubit}, theta); }; // controlled-H -void aer_apply_ch(void* handler, uint_t ctrl_qubit, uint_t tgt_qubit) { - AER::AerState* state = reinterpret_cast(handler); +void aer_apply_ch(void *handler, uint_t ctrl_qubit, uint_t tgt_qubit) { + AER::AerState *state = reinterpret_cast(handler); state->apply_mcu({ctrl_qubit, tgt_qubit}, M_PI / 2.0, 0, M_PI, 0); }; // swap -void aer_apply_swap(void* handler, uint_t qubit0, uint_t qubit1) { - AER::AerState* state = reinterpret_cast(handler); +void aer_apply_swap(void *handler, uint_t qubit0, uint_t qubit1) { + AER::AerState *state = reinterpret_cast(handler); state->apply_mcswap({qubit0, qubit1}); }; // Toffoli -void aer_apply_ccx(void* handler, uint_t qubit0, uint_t qubit1, uint_t qubit2) { - AER::AerState* state = reinterpret_cast(handler); +void aer_apply_ccx(void *handler, uint_t qubit0, uint_t qubit1, uint_t qubit2) { + AER::AerState *state = reinterpret_cast(handler); state->apply_mcx({qubit0, qubit1, qubit2}); }; // // controlled-swap -void aer_apply_cswap(void* handler, uint_t ctrl_qubit, uint_t qubit0, uint_t qubit1) { - AER::AerState* state = reinterpret_cast(handler); +void aer_apply_cswap(void *handler, uint_t ctrl_qubit, uint_t qubit0, + uint_t qubit1) { + AER::AerState *state = reinterpret_cast(handler); state->apply_mcswap({ctrl_qubit, qubit0, qubit1}); }; // four parameter controlled-U gate with relative phase γ -void aer_apply_cu(void* handler, uint_t ctrl_qubit, uint_t tgt_qubit, double theta, double phi, double lambda, double gamma) { - AER::AerState* state = reinterpret_cast(handler); +void aer_apply_cu(void *handler, uint_t ctrl_qubit, uint_t tgt_qubit, + double theta, double phi, double lambda, double gamma) { + AER::AerState *state = reinterpret_cast(handler); state->apply_mcu({ctrl_qubit, tgt_qubit}, theta, phi, lambda, gamma); }; } diff --git a/contrib/standalone/qasm_simulator.cpp b/contrib/standalone/qasm_simulator.cpp old mode 100755 new mode 100644 index d0b8fa9c0a..708c8128ac --- a/contrib/standalone/qasm_simulator.cpp +++ b/contrib/standalone/qasm_simulator.cpp @@ -12,7 +12,7 @@ * that they have been altered from the originals. */ -//#define DEBUG // Uncomment for verbose debugging output +// #define DEBUG // Uncomment for verbose debugging output #include #include #include @@ -27,32 +27,28 @@ /******************************************************************************* * * EXIT CODES: - * + * * 0: The Qobj was succesfully executed. * Returns full result JSON. - * + * * 1: Command line invalid or Qobj JSON cannot be loaded. * Returns JSON: * {"success": false, "status": "ERROR: Invalid input (error msg)"} - * + * * 2: Qobj failed to load or execute. * Returns JSON: * {"success": false, "status": "ERROR: Failed to execute qobj (error msg)"} - * + * * 3: At least one experiment in Qobj failed to execute successfully. * Returns parial result JSON with failed experiments returning: * "{"success": false, "status": "ERROR: error msg"} * ******************************************************************************/ -enum class CmdArguments { - SHOW_VERSION, - INPUT_CONFIG, - INPUT_DATA -}; +enum class CmdArguments { SHOW_VERSION, INPUT_CONFIG, INPUT_DATA }; -inline CmdArguments parse_cmd_options(const std::string& argv){ - if(argv == "-v" || argv == "--version") +inline CmdArguments parse_cmd_options(const std::string &argv) { + if (argv == "-v" || argv == "--version") return CmdArguments::SHOW_VERSION; if (argv == "-c" || argv == "--config") @@ -61,22 +57,20 @@ inline CmdArguments parse_cmd_options(const std::string& argv){ return CmdArguments::INPUT_DATA; } -inline void show_version(){ - std::cout << "Qiskit Aer: " - << AER_MAJOR_VERSION << "." - << AER_MINOR_VERSION << "." - << AER_PATCH_VERSION << "\n"; +inline void show_version() { + std::cout << "Qiskit Aer: " << AER_MAJOR_VERSION << "." << AER_MINOR_VERSION + << "." << AER_PATCH_VERSION << "\n"; } inline void failed(const std::string &msg, std::ostream &o = std::cout, - int indent = -1){ + int indent = -1) { json_t ret; ret["success"] = false; ret["status"] = std::string("ERROR: ") + msg; o << ret.dump(indent) << std::endl; } -inline void usage(const std::string& command, std::ostream &out){ +inline void usage(const std::string &command, std::ostream &out) { failed("Invalid command line", out); // Print usage message std::cerr << "\n\n"; @@ -85,7 +79,8 @@ inline void usage(const std::string& command, std::ostream &out){ std::cerr << "Usage: \n"; std::cerr << command << " [-v] [-c ] \n"; std::cerr << " -v : Show version\n"; - std::cerr << " -c : Configuration file\n";; + std::cerr << " -c : Configuration file\n"; + ; std::cerr << " file : qobj file\n"; } @@ -95,51 +90,51 @@ int main(int argc, char **argv) { int indent = 4; json_t qobj; json_t config; - int myrank=0; + int myrank = 0; #ifdef AER_MPI int prov; - int nprocs=1; - MPI_Init_thread(&argc,&argv,MPI_THREAD_MULTIPLE,&prov); - MPI_Comm_size(MPI_COMM_WORLD,&nprocs); - MPI_Comm_rank(MPI_COMM_WORLD,&myrank); + int nprocs = 1; + MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &prov); + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); + MPI_Comm_rank(MPI_COMM_WORLD, &myrank); #endif - if(argc == 1){ // NOLINT + if (argc == 1) { // NOLINT usage(std::string(argv[0]), out); // NOLINT return 1; } // Parse command line options - for(auto pos = 1UL; pos < static_cast(argc); ++pos){ // NOLINT - auto option = parse_cmd_options(std::string(argv[pos])); // NOLINT - switch(option){ - case CmdArguments::SHOW_VERSION: - show_version(); - return 0; - case CmdArguments::INPUT_CONFIG: - if (++pos == static_cast(argc)) { - failed("Invalid config (no file is specified.)", out, indent); - return 1; - } - try { - config = JSON::load(std::string(argv[pos])); - }catch(std::exception &e){ - std::string msg = "Invalid config (" + std::string(e.what()) + ")"; - failed(msg, out, indent); - return 1; - } - break; - case CmdArguments::INPUT_DATA: - try { - qobj = JSON::load(std::string(argv[pos])); // NOLINT - pos = argc; //Exit from the loop - }catch(std::exception &e){ - std::string msg = "Invalid input (" + std::string(e.what()) + ")"; - failed(msg, out, indent); - return 1; - } - break; + for (auto pos = 1UL; pos < static_cast(argc); ++pos) { // NOLINT + auto option = parse_cmd_options(std::string(argv[pos])); // NOLINT + switch (option) { + case CmdArguments::SHOW_VERSION: + show_version(); + return 0; + case CmdArguments::INPUT_CONFIG: + if (++pos == static_cast(argc)) { + failed("Invalid config (no file is specified.)", out, indent); + return 1; + } + try { + config = JSON::load(std::string(argv[pos])); + } catch (std::exception &e) { + std::string msg = "Invalid config (" + std::string(e.what()) + ")"; + failed(msg, out, indent); + return 1; + } + break; + case CmdArguments::INPUT_DATA: + try { + qobj = JSON::load(std::string(argv[pos])); // NOLINT + pos = argc; // Exit from the loop + } catch (std::exception &e) { + std::string msg = "Invalid input (" + std::string(e.what()) + ")"; + failed(msg, out, indent); + return 1; + } + break; } } @@ -148,7 +143,7 @@ int main(int argc, char **argv) { // Check for command line config // and if present add to qobj config - json_t& config_all = qobj["config"]; + json_t &config_all = qobj["config"]; if (!config.empty()) // NOLINT config_all.update(config.begin(), config.end()); @@ -166,7 +161,7 @@ int main(int argc, char **argv) { // Initialize simulator AER::Controller sim; auto result = sim.execute(qobj).to_json(); - if(myrank == 0){ + if (myrank == 0) { out << result.dump(4) << std::endl; } @@ -179,9 +174,9 @@ int main(int argc, char **argv) { #ifdef AER_MPI MPI_Finalize(); #endif - if(status == "COMPLETED") + if (status == "COMPLETED") return 3; // The simulation was was completed unsuccesfully. - return 2; // Failed to execute the Qobj + return 2; // Failed to execute the Qobj } } catch (std::exception &e) { std::stringstream msg; diff --git a/pyproject.toml b/pyproject.toml index 27df824423..46e2c752c8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,3 +32,7 @@ environment = { CMAKE_GENERATOR = "Visual Studio 16 2019"} [[tool.cibuildwheel.overrides]] select = "cp3{7,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] +line-length = 100 +target-version = ['py37', 'py38', 'py39', 'py310', 'py311'] diff --git a/qiskit_aer/__init__.py b/qiskit_aer/__init__.py index 730eed4e52..8a76e0305f 100644 --- a/qiskit_aer/__init__.py +++ b/qiskit_aer/__init__.py @@ -62,6 +62,7 @@ # before loading our simulators, so we force it using this ugly trick if platform.system() == "Darwin": import numpy as np + np.dot(np.zeros(100), np.zeros(100)) # ... ¯\_(ツ)_/¯ diff --git a/qiskit_aer/aererror.py b/qiskit_aer/aererror.py index 4e3311c0ff..d1ffa74eab 100644 --- a/qiskit_aer/aererror.py +++ b/qiskit_aer/aererror.py @@ -23,7 +23,7 @@ class AerError(QiskitError): def __init__(self, *message): """Set the error message.""" super().__init__(*message) - self.message = ' '.join(message) + self.message = " ".join(message) def __str__(self): """Return the message.""" diff --git a/qiskit_aer/aerprovider.py b/qiskit_aer/aerprovider.py index 82bf38ca62..8fca28f521 100644 --- a/qiskit_aer/aerprovider.py +++ b/qiskit_aer/aerprovider.py @@ -37,26 +37,26 @@ def __init__(self): devices = AerSimulator().available_devices() backends = [] for method in methods: - name = 'aer_simulator' - if method not in [None, 'automatic']: - name += f'_{method}' - device_name = 'CPU' + name = "aer_simulator" + if method not in [None, "automatic"]: + name += f"_{method}" + device_name = "CPU" backends.append((name, AerSimulator, method, device_name)) # Add GPU device backends - if method in ['statevector', 'density_matrix', 'unitary']: + if method in ["statevector", "density_matrix", "unitary"]: for device in devices: - if device != 'CPU': - new_name = f'{name}_{device}'.lower() + if device != "CPU": + new_name = f"{name}_{device}".lower() device_name = device backends.append((new_name, AerSimulator, method, device_name)) # Add legacy backend names backends += [ - ('qasm_simulator', QasmSimulator, None, None), - ('statevector_simulator', StatevectorSimulator, None, None), - ('unitary_simulator', UnitarySimulator, None, None), - ('pulse_simulator', PulseSimulator, None, None) + ("qasm_simulator", QasmSimulator, None, None), + ("statevector_simulator", StatevectorSimulator, None, None), + ("unitary_simulator", UnitarySimulator, None, None), + ("pulse_simulator", PulseSimulator, None, None), ] AerProvider._BACKENDS = backends @@ -77,14 +77,14 @@ def backends(self, name=None, filters=None, **kwargs): # are set they will only last as long as that backend object exists backends = [] for backend_name, backend_cls, method, device in self._BACKENDS: - opts = {'provider': self} + opts = {"provider": self} if method is not None: - opts['method'] = method + opts["method"] = method if device is not None: - opts['device'] = device + opts["device"] = device if name is None or backend_name == name: backends.append(backend_cls(**opts)) return filter_backends(backends, filters=filters) def __str__(self): - return 'AerProvider' + return "AerProvider" diff --git a/qiskit_aer/backends/aer_compiler.py b/qiskit_aer/backends/aer_compiler.py index 9f5e714b16..fdb4fd88bd 100644 --- a/qiskit_aer/backends/aer_compiler.py +++ b/qiskit_aer/backends/aer_compiler.py @@ -21,15 +21,11 @@ from qiskit.extensions import Initialize from qiskit.providers.options import Options from qiskit.pulse import Schedule, ScheduleBlock -from qiskit.circuit.controlflow import ( - WhileLoopOp, - ForLoopOp, - IfElseOp, - BreakLoopOp, - ContinueLoopOp) +from qiskit.circuit.controlflow import WhileLoopOp, ForLoopOp, IfElseOp, BreakLoopOp, ContinueLoopOp from qiskit.compiler import transpile from qiskit.qobj import QobjExperimentHeader from qiskit_aer.aererror import AerError + # pylint: disable=import-error, no-name-in-module from qiskit_aer.backends.controller_wrappers import AerCircuit, AerConfig from .backend_utils import circuit_optypes @@ -37,7 +33,7 @@ class AerCompiler: - """ Aer Compiler to convert instructions of control-flow to mark and jump instructions""" + """Aer Compiler to convert instructions of control-flow to mark and jump instructions""" def __init__(self): self._last_flow_id = -1 @@ -67,15 +63,14 @@ def compile(self, circuits, basis_gates=None, optypes=None): # Make a shallow copy incase we modify it compiled_optypes = list(optypes) if isinstance(circuits, list): - basis_gates = basis_gates + ['mark', 'jump'] + basis_gates = basis_gates + ["mark", "jump"] compiled_circuits = [] for idx, circuit in enumerate(circuits): # Resolve initialize 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 + self._inline_circuit(circuit, None, None), basis_gates=basis_gates ) compiled_circuits.append(compiled_circ) # Recompute optype for compiled circuit @@ -118,9 +113,7 @@ def _is_dynamic(circuit, optype=None): if not isinstance(circuit, QuantumCircuit): return False - controlflow_types = ( - WhileLoopOp, ForLoopOp, IfElseOp, BreakLoopOp, ContinueLoopOp - ) + controlflow_types = (WhileLoopOp, ForLoopOp, IfElseOp, BreakLoopOp, ContinueLoopOp) # Check via optypes if isinstance(optype, set): @@ -200,12 +193,12 @@ def _inline_for_loop_op(self, instruction, parent, bit_map): self._last_flow_id += 1 loop_id = self._last_flow_id - loop_name = f'loop_{loop_id}' + loop_name = f"loop_{loop_id}" inlined_body = None - break_label = f'{loop_name}_end' + break_label = f"{loop_name}_end" for index in indexset: - continue_label = f'{loop_name}_{index}' + 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.bind_parameters({loop_parameter: index}) @@ -218,15 +211,15 @@ 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_c_if_args(instruction.operation.condition, bit_map) - body, = instruction.operation.params + (body,) = instruction.operation.params self._last_flow_id += 1 loop_id = self._last_flow_id - loop_name = f'while_{loop_id}' + loop_name = f"while_{loop_id}" - continue_label = f'{loop_name}_continue' - loop_start_label = f'{loop_name}_start' - break_label = f'{loop_name}_end' + continue_label = f"{loop_name}_continue" + loop_start_label = f"{loop_name}_start" + break_label = f"{loop_name}_end" inlined_body = self._inline_circuit( body, continue_label, @@ -243,18 +236,24 @@ def _inline_while_loop_op(self, instruction, parent, bit_map): cargs = [bit_map[c] for c in instruction.clbits] mark_cargs = cargs.copy() mark_cargs.extend( - bit_map[c] for c in ( + bit_map[c] + for c in ( ( - {condition_tuple[0]} if isinstance(condition_tuple[0], Clbit) + {condition_tuple[0]} + if isinstance(condition_tuple[0], Clbit) else set(condition_tuple[0]) - ) - set(instruction.clbits) + ) + - 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)).c_if(*c_if_args), - qargs, mark_cargs) + parent.append( + AerJump(loop_start_label, len(qargs), len(mark_cargs)).c_if(*c_if_args), + qargs, + mark_cargs, + ) parent.append(AerJump(break_label, len(qargs), len(mark_cargs)), qargs, mark_cargs) parent.append(AerMark(loop_start_label, len(qargs), len(mark_cargs)), qargs, mark_cargs) parent.append(inlined_body, qargs, cargs) @@ -268,12 +267,12 @@ def _inline_if_else_op(self, instruction, continue_label, break_label, parent, b self._last_flow_id += 1 if_id = self._last_flow_id - if_name = f'if_{if_id}' + if_name = f"if_{if_id}" - if_true_label = f'{if_name}_true' - if_end_label = f'{if_name}_end' + if_true_label = f"{if_name}_true" + if_end_label = f"{if_name}_end" if false_body: - if_else_label = f'{if_name}_else' + if_else_label = f"{if_name}_else" else: if_else_label = if_end_label @@ -283,11 +282,14 @@ def _inline_if_else_op(self, instruction, continue_label, break_label, parent, b cargs = [bit_map[c] for c in instruction.clbits] mark_cargs = cargs.copy() mark_cargs.extend( - bit_map[c] for c in ( + bit_map[c] + for c in ( ( - {condition_tuple[0]} if isinstance(condition_tuple[0], Clbit) + {condition_tuple[0]} + if isinstance(condition_tuple[0], Clbit) else set(condition_tuple[0]) - ) - set(instruction.clbits) + ) + - set(instruction.clbits) ) ) @@ -335,9 +337,7 @@ def compile_circuit(circuits, basis_gates=None, optypes=None): def generate_aer_config( - circuits: List[QuantumCircuit], - backend_options: Options, - **run_options + circuits: List[QuantumCircuit], backend_options: Options, **run_options ) -> AerConfig: """generates a configuration to run simulation. @@ -380,9 +380,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", 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, @@ -426,8 +424,7 @@ def assemble_circuit(circuit: QuantumCircuit): aer_circ.bfunc(f"0x{mask:X}", f"0x{val:X}", "==", conditional_reg) max_conditional_idx += 1 - _assemble_op(aer_circ, inst, qubit_indices, clbit_indices, - is_conditional, conditional_reg) + _assemble_op(aer_circ, inst, qubit_indices, clbit_indices, is_conditional, conditional_reg) return aer_circ @@ -442,49 +439,108 @@ def _assemble_op(aer_circ, inst, qubit_indices, clbit_indices, is_conditional, c copied = False for i, param in enumerate(params): - if (isinstance(param, ParameterExpression) and len(param.parameters) > 0): + if isinstance(param, ParameterExpression) and len(param.parameters) > 0: if not copied: params = copy(params) copied = True params[i] = 0.0 - if name in {'ccx', 'ccz', 'cp', 'cswap', 'csx', 'cx', 'cy', 'cz', 'delay', 'ecr', - 'h', 'id', 'mcp', 'mcphase', 'mcr', 'mcrx', 'mcry', 'mcrz', 'mcswap', - 'mcsx', 'mcu', 'mcu1', 'mcu2', 'mcu3', 'mcx', 'mcx_gray', 'mcy', 'mcz', - 'p', 'r', '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'}: + if name in { + "ccx", + "ccz", + "cp", + "cswap", + "csx", + "cx", + "cy", + "cz", + "delay", + "ecr", + "h", + "id", + "mcp", + "mcphase", + "mcr", + "mcrx", + "mcry", + "mcrz", + "mcswap", + "mcsx", + "mcu", + "mcu1", + "mcu2", + "mcu3", + "mcx", + "mcx_gray", + "mcy", + "mcz", + "p", + "r", + "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, label if label else name) - elif name == 'measure': + elif name == "measure": if is_conditional: aer_circ.measure(qubits, clbits, clbits) else: aer_circ.measure(qubits, clbits, []) - elif name == 'reset': + elif name == "reset": aer_circ.reset(qubits) - elif name == 'diagonal': - aer_circ.diagonal(qubits, params, label if label else 'diagonal') - elif name == 'unitary': - aer_circ.unitary(qubits, params[0], conditional_reg, label if label else 'unitary') - elif name == 'pauli': + elif name == "diagonal": + aer_circ.diagonal(qubits, params, label if label else "diagonal") + elif name == "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, label if label else name) - elif name == 'initialize': + elif name == "initialize": aer_circ.initialize(qubits, params) - elif name == 'roerror': + elif name == "roerror": aer_circ.roerror(qubits, params) - elif name == 'multiplexer': + elif name == "multiplexer": aer_circ.multiplexer(qubits, params, conditional_reg, label if label else name) - elif name == 'kraus': + elif name == "kraus": aer_circ.kraus(qubits, params, conditional_reg) - elif name in {'save_statevector', 'save_statevector_dict', 'save_clifford', - 'save_probabilities', 'save_probabilities_dict', 'save_matrix_product_state', - 'save_unitary', 'save_superop', 'save_density_matrix', 'save_state', - 'save_stabilizer'}: + elif name in { + "save_statevector", + "save_statevector_dict", + "save_clifford", + "save_probabilities", + "save_probabilities_dict", + "save_matrix_product_state", + "save_unitary", + "save_superop", + "save_density_matrix", + "save_state", + "save_stabilizer", + }: aer_circ.save_state(qubits, name, operation._subtype, label if label else name) - elif name in {'save_amplitudes', 'save_amplitudes_sq'}: - aer_circ.save_amplitudes(qubits, name, params, operation._subtype, - label if label else name) - elif name in ('save_expval', 'save_expval_var'): + elif name in {"save_amplitudes", "save_amplitudes_sq"}: + aer_circ.save_amplitudes(qubits, name, params, operation._subtype, label if label else name) + elif name in ("save_expval", "save_expval_var"): paulis = [] coeff_reals = [] coeff_imags = [] @@ -492,41 +548,47 @@ def _assemble_op(aer_circ, inst, qubit_indices, clbit_indices, is_conditional, c paulis.append(pauli) coeff_reals.append(coeff[0]) coeff_imags.append(coeff[1]) - aer_circ.save_expval(qubits, name, paulis, coeff_reals, coeff_imags, operation._subtype, - label if label else name) - elif name == 'set_statevector': + aer_circ.save_expval( + qubits, + name, + paulis, + coeff_reals, + coeff_imags, + operation._subtype, + label if label else name, + ) + elif name == "set_statevector": aer_circ.set_statevector(qubits, params) - elif name == 'set_unitary': + elif name == "set_unitary": aer_circ.set_unitary(qubits, params) - elif name == 'set_density_matrix': + elif name == "set_density_matrix": aer_circ.set_density_matrix(qubits, params) - elif name == 'set_stabilizer': + elif name == "set_stabilizer": aer_circ.set_clifford(qubits, params) - elif name == 'set_superop': + elif name == "set_superop": aer_circ.set_superop(qubits, params) - elif name == 'set_matrix_product_state': + elif name == "set_matrix_product_state": aer_circ.set_matrix_product_state(qubits, params) - elif name == 'superop': + elif name == "superop": aer_circ.superop(qubits, params[0], conditional_reg) - elif name == 'barrier': + elif name == "barrier": pass - elif name == 'jump': + elif name == "jump": aer_circ.jump(qubits, params, conditional_reg) - elif name == 'mark': + elif name == "mark": aer_circ.mark(qubits, params) - elif name == 'qerror_loc': + elif name == "qerror_loc": 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}') + elif name in ("for_loop", "while_loop", "if_else"): + raise AerError( + "control-flow instructions must be converted " f"to jump and mark instructions: {name}" + ) else: - raise AerError(f'unknown instruction: {name}') + raise AerError(f"unknown instruction: {name}") -def assemble_circuits( - circuits: List[QuantumCircuit] -) -> List[AerCircuit]: +def assemble_circuits(circuits: List[QuantumCircuit]) -> List[AerCircuit]: """converts a list of Qiskit circuits into circuits mapped AER::Circuit Args: diff --git a/qiskit_aer/backends/aer_simulator.py b/qiskit_aer/backends/aer_simulator.py index 6a4911dbd7..db601d6546 100644 --- a/qiskit_aer/backends/aer_simulator.py +++ b/qiskit_aer/backends/aer_simulator.py @@ -22,10 +22,15 @@ from ..version import __version__ from .aerbackend import AerBackend, AerError -from .backend_utils import (cpp_execute_circuits, cpp_execute_qobj, - available_methods, available_devices, - MAX_QUBITS_STATEVECTOR, - BASIS_GATES) +from .backend_utils import ( + cpp_execute_circuits, + cpp_execute_qobj, + available_methods, + available_devices, + MAX_QUBITS_STATEVECTOR, + BASIS_GATES, +) + # pylint: disable=import-error, no-name-in-module from .controller_wrappers import aer_controller_execute @@ -448,137 +453,226 @@ class AerSimulator(AerBackend): _BASIS_GATES = BASIS_GATES _CUSTOM_INSTR = { - 'statevector': sorted([ - 'quantum_channel', 'qerror_loc', 'roerror', 'kraus', - 'save_expval', 'save_expval_var', - 'save_probabilities', 'save_probabilities_dict', - 'save_amplitudes', 'save_amplitudes_sq', - 'save_density_matrix', 'save_state', 'save_statevector', - 'save_statevector_dict', 'set_statevector', - 'if_else', 'for_loop', 'while_loop', 'break_loop', 'continue_loop', - ]), - 'density_matrix': sorted([ - 'quantum_channel', 'qerror_loc', 'roerror', 'kraus', 'superop', - 'save_state', 'save_expval', 'save_expval_var', - 'save_probabilities', 'save_probabilities_dict', - 'save_density_matrix', 'save_amplitudes_sq', 'set_density_matrix', - 'if_else', 'for_loop', 'while_loop', 'break_loop', 'continue_loop', - ]), - 'matrix_product_state': sorted([ - 'quantum_channel', 'qerror_loc', 'roerror', 'kraus', - 'save_expval', 'save_expval_var', - 'save_probabilities', 'save_probabilities_dict', - 'save_state', 'save_matrix_product_state', 'save_statevector', - 'save_density_matrix', 'save_amplitudes', 'save_amplitudes_sq', - 'set_matrix_product_state', - 'if_else', 'for_loop', 'while_loop', 'break_loop', 'continue_loop', - ]), - 'stabilizer': sorted([ - 'quantum_channel', 'qerror_loc', 'roerror', - 'save_expval', 'save_expval_var', - 'save_probabilities', 'save_probabilities_dict', - 'save_amplitudes_sq', 'save_state', 'save_clifford', - 'save_stabilizer', 'set_stabilizer', - 'if_else', 'for_loop', 'while_loop', 'break_loop', 'continue_loop', - ]), - 'extended_stabilizer': sorted([ - 'quantum_channel', 'qerror_loc', 'roerror', 'save_statevector', - ]), - 'unitary': sorted([ - 'save_state', 'save_unitary', 'set_unitary', - ]), - 'superop': sorted([ - 'quantum_channel', 'qerror_loc', 'kraus', 'superop', 'save_state', - 'save_superop', 'set_superop', - ]), - 'tensor_network': sorted([ - 'quantum_channel', 'qerror_loc', 'roerror', 'kraus', 'superop', - 'save_state', 'save_expval', 'save_expval_var', - 'save_probabilities', 'save_probabilities_dict', - 'save_density_matrix', 'save_amplitudes', 'save_amplitudes_sq', - 'save_statevector', 'save_statevector_dict', - 'set_statevector', 'set_density_matrix' - ]) + "statevector": sorted( + [ + "quantum_channel", + "qerror_loc", + "roerror", + "kraus", + "save_expval", + "save_expval_var", + "save_probabilities", + "save_probabilities_dict", + "save_amplitudes", + "save_amplitudes_sq", + "save_density_matrix", + "save_state", + "save_statevector", + "save_statevector_dict", + "set_statevector", + "if_else", + "for_loop", + "while_loop", + "break_loop", + "continue_loop", + ] + ), + "density_matrix": sorted( + [ + "quantum_channel", + "qerror_loc", + "roerror", + "kraus", + "superop", + "save_state", + "save_expval", + "save_expval_var", + "save_probabilities", + "save_probabilities_dict", + "save_density_matrix", + "save_amplitudes_sq", + "set_density_matrix", + "if_else", + "for_loop", + "while_loop", + "break_loop", + "continue_loop", + ] + ), + "matrix_product_state": sorted( + [ + "quantum_channel", + "qerror_loc", + "roerror", + "kraus", + "save_expval", + "save_expval_var", + "save_probabilities", + "save_probabilities_dict", + "save_state", + "save_matrix_product_state", + "save_statevector", + "save_density_matrix", + "save_amplitudes", + "save_amplitudes_sq", + "set_matrix_product_state", + "if_else", + "for_loop", + "while_loop", + "break_loop", + "continue_loop", + ] + ), + "stabilizer": sorted( + [ + "quantum_channel", + "qerror_loc", + "roerror", + "save_expval", + "save_expval_var", + "save_probabilities", + "save_probabilities_dict", + "save_amplitudes_sq", + "save_state", + "save_clifford", + "save_stabilizer", + "set_stabilizer", + "if_else", + "for_loop", + "while_loop", + "break_loop", + "continue_loop", + ] + ), + "extended_stabilizer": sorted( + [ + "quantum_channel", + "qerror_loc", + "roerror", + "save_statevector", + ] + ), + "unitary": sorted( + [ + "save_state", + "save_unitary", + "set_unitary", + ] + ), + "superop": sorted( + [ + "quantum_channel", + "qerror_loc", + "kraus", + "superop", + "save_state", + "save_superop", + "set_superop", + ] + ), + "tensor_network": sorted( + [ + "quantum_channel", + "qerror_loc", + "roerror", + "kraus", + "superop", + "save_state", + "save_expval", + "save_expval_var", + "save_probabilities", + "save_probabilities_dict", + "save_density_matrix", + "save_amplitudes", + "save_amplitudes_sq", + "save_statevector", + "save_statevector_dict", + "set_statevector", + "set_density_matrix", + ] + ), } # Automatic method custom instructions are the union of statevector, # density matrix, and stabilizer methods - _CUSTOM_INSTR[None] = _CUSTOM_INSTR['automatic'] = sorted( - set(_CUSTOM_INSTR['statevector']).union( - _CUSTOM_INSTR['stabilizer']).union( - _CUSTOM_INSTR['density_matrix']).union( - _CUSTOM_INSTR['matrix_product_state']).union( - _CUSTOM_INSTR['unitary']).union( - _CUSTOM_INSTR['superop']).union( - _CUSTOM_INSTR['tensor_network'])) + _CUSTOM_INSTR[None] = _CUSTOM_INSTR["automatic"] = sorted( + set(_CUSTOM_INSTR["statevector"]) + .union(_CUSTOM_INSTR["stabilizer"]) + .union(_CUSTOM_INSTR["density_matrix"]) + .union(_CUSTOM_INSTR["matrix_product_state"]) + .union(_CUSTOM_INSTR["unitary"]) + .union(_CUSTOM_INSTR["superop"]) + .union(_CUSTOM_INSTR["tensor_network"]) + ) _DEFAULT_CONFIGURATION = { - 'backend_name': 'aer_simulator', - 'backend_version': __version__, - 'n_qubits': MAX_QUBITS_STATEVECTOR, - 'url': 'https://github.com/Qiskit/qiskit-aer', - 'simulator': True, - 'local': True, - 'conditional': True, - 'open_pulse': False, - 'memory': True, - 'max_shots': int(1e6), - 'description': 'A C++ QasmQobj simulator with noise', - 'coupling_map': None, - 'basis_gates': BASIS_GATES['automatic'], - 'custom_instructions': _CUSTOM_INSTR['automatic'], - 'gates': [] + "backend_name": "aer_simulator", + "backend_version": __version__, + "n_qubits": MAX_QUBITS_STATEVECTOR, + "url": "https://github.com/Qiskit/qiskit-aer", + "simulator": True, + "local": True, + "conditional": True, + "open_pulse": False, + "memory": True, + "max_shots": int(1e6), + "description": "A C++ QasmQobj simulator with noise", + "coupling_map": None, + "basis_gates": BASIS_GATES["automatic"], + "custom_instructions": _CUSTOM_INSTR["automatic"], + "gates": [], } _SIMULATION_METHODS = [ - 'automatic', 'statevector', 'density_matrix', - 'stabilizer', 'matrix_product_state', 'extended_stabilizer', - 'unitary', 'superop', 'tensor_network' + "automatic", + "statevector", + "density_matrix", + "stabilizer", + "matrix_product_state", + "extended_stabilizer", + "unitary", + "superop", + "tensor_network", ] _AVAILABLE_METHODS = None - _SIMULATION_DEVICES = ('CPU', 'GPU', 'Thrust') + _SIMULATION_DEVICES = ("CPU", "GPU", "Thrust") _AVAILABLE_DEVICES = None - def __init__(self, - configuration=None, - properties=None, - provider=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._SIMULATION_DEVICES) + self._controller, AerSimulator._SIMULATION_DEVICES + ) if AerSimulator._AVAILABLE_METHODS is None: AerSimulator._AVAILABLE_METHODS = available_methods( - self._controller, AerSimulator._SIMULATION_METHODS, AerSimulator._AVAILABLE_DEVICES) + self._controller, AerSimulator._SIMULATION_METHODS, AerSimulator._AVAILABLE_DEVICES + ) # Default configuration if configuration is None: - configuration = QasmBackendConfiguration.from_dict( - AerSimulator._DEFAULT_CONFIGURATION) + configuration = QasmBackendConfiguration.from_dict(AerSimulator._DEFAULT_CONFIGURATION) # Cache basis gates since computing the intersection # of noise model, method, and config gates is expensive. - self._cached_basis_gates = self._BASIS_GATES['automatic'] + self._cached_basis_gates = self._BASIS_GATES["automatic"] - super().__init__(configuration, - properties=properties, - provider=provider, - backend_options=backend_options) + super().__init__( + configuration, properties=properties, provider=provider, backend_options=backend_options + ) @classmethod def _default_options(cls): return Options( # Global options shots=1024, - method='automatic', - device='CPU', + method="automatic", + device="CPU", precision="double", executor=None, max_job_size=None, @@ -614,7 +708,7 @@ def _default_options(cls): # stabilizer options stabilizer_max_snapshot_probabilities=32, # extended stabilizer options - extended_stabilizer_sampling_method='resampled_metropolis', + extended_stabilizer_sampling_method="resampled_metropolis", extended_stabilizer_metropolis_mixing_time=5000, extended_stabilizer_approximation_error=0.05, extended_stabilizer_norm_estimation_samples=100, @@ -624,35 +718,35 @@ def _default_options(cls): # MPS options matrix_product_state_truncation_threshold=1e-16, matrix_product_state_max_bond_dimension=None, - mps_sample_measure_algorithm='mps_heuristic', + mps_sample_measure_algorithm="mps_heuristic", mps_log_data=False, - mps_swap_direction='mps_swap_left', + mps_swap_direction="mps_swap_left", chop_threshold=1e-8, mps_parallel_threshold=14, mps_omp_threads=1, # tensor network options tensor_network_num_sampling_qubits=10, - use_cuTensorNet_autotuning=False + use_cuTensorNet_autotuning=False, ) def __repr__(self): """String representation of an AerSimulator.""" display = super().__repr__() - noise_model = getattr(self.options, 'noise_model', None) + noise_model = getattr(self.options, "noise_model", None) if noise_model is None or noise_model.is_ideal(): return display - pad = ' ' * (len(self.__class__.__name__) + 1) - return f'{display[:-1]}\n{pad}noise_model={repr(noise_model)})' + pad = " " * (len(self.__class__.__name__) + 1) + return f"{display[:-1]}\n{pad}noise_model={repr(noise_model)})" def name(self): """Format backend name string for simulator""" name = self._configuration.backend_name - method = getattr(self.options, 'method', None) - if method not in [None, 'automatic']: - name += f'_{method}' - device = getattr(self.options, 'device', None) - if device not in [None, 'CPU']: - name += f'_{device}'.lower() + method = getattr(self.options, "method", None) + if method not in [None, "automatic"]: + name += f"_{method}" + device = getattr(self.options, "device", None) + if device not in [None, "CPU"]: + name += f"_{device}".lower() return name @classmethod @@ -682,26 +776,24 @@ def from_backend(cls, backend, **options): # Customize configuration name name = configuration.backend_name - configuration.backend_name = f'aer_simulator({name})' + configuration.backend_name = f"aer_simulator({name})" else: raise TypeError( "The backend argument requires a BackendV2 or BackendV1 object, " f"not a {type(backend)} object" ) # Use automatic noise model if none is provided - if 'noise_model' not in options: + if "noise_model" not in options: # pylint: disable=import-outside-toplevel # Avoid cyclic import from ..noise.noise_model import NoiseModel noise_model = NoiseModel.from_backend(backend) if not noise_model.is_ideal(): - options['noise_model'] = noise_model + options["noise_model"] = noise_model # Initialize simulator - sim = cls(configuration=configuration, - properties=properties, - **options) + sim = cls(configuration=configuration, properties=properties, **options) return sim def available_methods(self): @@ -724,15 +816,15 @@ def configuration(self): # Update basis gates based on custom options, config, method, # and noise model config.custom_instructions = self._CUSTOM_INSTR[ - getattr(self.options, 'method', 'automatic')] + getattr(self.options, "method", "automatic") + ] config.basis_gates = self._cached_basis_gates + config.custom_instructions # Update simulator name config.backend_name = self.name() return config def _execute_circuits(self, aer_circuits, noise_model, config): - """Execute circuits on the backend. - """ + """Execute circuits on the backend.""" ret = cpp_execute_circuits(self._controller, aer_circuits, noise_model, config) return ret @@ -752,10 +844,11 @@ def set_option(self, key, value): self._set_configuration_option(key, value) return if key == "method": - if (value is not None and value not in self.available_methods()): + if value is not None and value not in self.available_methods(): raise AerError( f"Invalid simulation method {value}. Available methods" - f" are: {self.available_methods()}") + f" are: {self.available_methods()}" + ) self._set_method_config(value) super().set_option(key, value) if key in ["method", "noise_model", "basis_gates"]: @@ -776,9 +869,9 @@ def _validate(self, qobj): break if no_data: logger.warning( - 'No measure or save instruction in circuit "%s": ' - 'results will be empty.', - experiment.header.name) + 'No measure or save instruction in circuit "%s": ' "results will be empty.", + experiment.header.name, + ) def _basis_gates(self): """Return simualtor basis gates. @@ -788,21 +881,20 @@ def _basis_gates(self): and method supported basis gates. """ # Use option value for basis gates if set - if 'basis_gates' in self._options_configuration: - return self._options_configuration['basis_gates'] + if "basis_gates" in self._options_configuration: + return self._options_configuration["basis_gates"] # Compute intersection with method basis gates - method = getattr(self._options, 'method', 'automatic') + method = getattr(self._options, "method", "automatic") method_gates = self._BASIS_GATES[method] config_gates = self._configuration.basis_gates if config_gates: - basis_gates = set(config_gates).intersection( - method_gates) + basis_gates = set(config_gates).intersection(method_gates) else: basis_gates = method_gates # Compute intersection with noise model basis gates - noise_model = getattr(self.options, 'noise_model', None) + noise_model = getattr(self.options, "noise_model", None) if noise_model: noise_gates = noise_model.basis_gates basis_gates = basis_gates.intersection(noise_gates) @@ -814,36 +906,39 @@ def _basis_gates(self): "The intersection of configuration basis gates (%s), " "simulation method basis gates (%s), and " "noise model basis gates (%s) is empty", - config_gates, method_gates, noise_gates) + config_gates, + method_gates, + noise_gates, + ) return sorted(basis_gates) def _set_method_config(self, method=None): """Set non-basis gate options when setting method""" # Update configuration description and number of qubits - if method == 'statevector': - description = 'A C++ statevector simulator with noise' + if method == "statevector": + description = "A C++ statevector simulator with noise" n_qubits = MAX_QUBITS_STATEVECTOR - elif method == 'density_matrix': - description = 'A C++ density matrix simulator with noise' + elif method == "density_matrix": + description = "A C++ density matrix simulator with noise" n_qubits = MAX_QUBITS_STATEVECTOR // 2 - elif method == 'unitary': - description = 'A C++ unitary matrix simulator' + elif method == "unitary": + description = "A C++ unitary matrix simulator" n_qubits = MAX_QUBITS_STATEVECTOR // 2 - elif method == 'superop': - description = 'A C++ superop matrix simulator with noise' + elif method == "superop": + description = "A C++ superop matrix simulator with noise" n_qubits = MAX_QUBITS_STATEVECTOR // 4 - elif method == 'matrix_product_state': - description = 'A C++ matrix product state simulator with noise' + elif method == "matrix_product_state": + description = "A C++ matrix product state simulator with noise" n_qubits = 63 # TODO: not sure what to put here? - elif method == 'stabilizer': - description = 'A C++ Clifford stabilizer simulator with noise' + elif method == "stabilizer": + description = "A C++ Clifford stabilizer simulator with noise" n_qubits = 10000 # TODO: estimate from memory - elif method == 'extended_stabilizer': - description = 'A C++ Clifford+T extended stabilizer simulator with noise' + elif method == "extended_stabilizer": + description = "A C++ Clifford+T extended stabilizer simulator with noise" n_qubits = 63 # TODO: estimate from memory else: # Clear options to default description = None n_qubits = None - self._set_configuration_option('description', description) - self._set_configuration_option('n_qubits', n_qubits) + self._set_configuration_option("description", description) + self._set_configuration_option("n_qubits", n_qubits) diff --git a/qiskit_aer/backends/aerbackend.py b/qiskit_aer/backends/aerbackend.py index 501ff50756..4ff9a3d6ed 100644 --- a/qiskit_aer/backends/aerbackend.py +++ b/qiskit_aer/backends/aerbackend.py @@ -42,12 +42,9 @@ class AerBackend(Backend, ABC): """Qiskit Aer Backend class.""" - def __init__(self, - configuration, - properties=None, - defaults=None, - backend_options=None, - provider=None): + def __init__( + self, configuration, properties=None, defaults=None, backend_options=None, provider=None + ): """Aer class for backends. This method should initialize the module and its configuration, and @@ -120,17 +117,13 @@ def _convert_binds(self, circuits, parameter_binds): "parameter bind dictionaries" ) parameterizations = [ - self._convert_circuit_binds( - circuit, parameter_binds[idx]) for idx, circuit in enumerate(circuits) + self._convert_circuit_binds(circuit, parameter_binds[idx]) + for idx, circuit in enumerate(circuits) ] return parameterizations # pylint: disable=arguments-differ - def run(self, - circuits, - validate=False, - parameter_binds=None, - **run_options): + def run(self, circuits, validate=False, parameter_binds=None, **run_options): """Run a qobj on the backend. Args: @@ -172,11 +165,13 @@ def run(self, if isinstance(circuits, (QasmQobj, PulseQobj)): warnings.warn( - 'Using a qobj for run() is deprecated as of qiskit-aer 0.9.0' - ' and will be removed no sooner than 3 months from that release' - ' date. Transpiled circuits should now be passed directly using' - ' `backend.run(circuits, **run_options).', - DeprecationWarning, stacklevel=2) + "Using a qobj for run() is deprecated as of qiskit-aer 0.9.0" + " and will be removed no sooner than 3 months from that release" + " date. Transpiled circuits should now be passed directly using" + " `backend.run(circuits, **run_options).", + DeprecationWarning, + stacklevel=2, + ) if parameter_binds: raise TypeError("Parameter binds can't be used with an input qobj") # A work around to support both qobj options and run options until @@ -191,8 +186,8 @@ def run(self, for key, value in circuits.config.__dict__.items(): if key not in run_options and value is not None: run_options[key] = value - if 'parameter_binds' in run_options: - parameter_binds = run_options.pop('parameter_binds') + if "parameter_binds" in run_options: + parameter_binds = run_options.pop("parameter_binds") return self._run_qobj(circuits, validate, parameter_binds, **run_options) only_circuits = True @@ -203,12 +198,14 @@ def run(self, if only_circuits and not only_pulse: if validate: - raise TypeError("bad input to run() function;" - "`validation` argument is only effective for input qobj") - - executor = run_options.get('executor', None) - if executor is None and 'executor' in self.options.__dict__: - executor = self.options.__dict__.get('executor', None) + raise TypeError( + "bad input to run() function;" + "`validation` argument is only effective for input qobj" + ) + + executor = run_options.get("executor", None) + if executor is None and "executor" in self.options.__dict__: + executor = self.options.__dict__.get("executor", None) if executor: # This path remains for DASK execution to split a qobj insttance # into sub-qobj instances. This will be replaced with _run_circuits path @@ -219,39 +216,39 @@ def run(self, elif not only_circuits and only_pulse: return self._run_qobj(circuits, validate, parameter_binds, **run_options) elif not only_circuits and not only_pulse: - raise TypeError("bad input to run() function;" - "circuits and schedules cannot be mixed in a single run") + raise TypeError( + "bad input to run() function;" + "circuits and schedules cannot be mixed in a single run" + ) else: - raise TypeError("bad input to run() function;" - "circuits must be either circuits or schedules") - - def _run_circuits(self, - circuits, - parameter_binds, - **run_options): - """Run circuits by generating native circuits. - """ + raise TypeError( + "bad input to run() function;" "circuits must be either circuits or schedules" + ) + + def _run_circuits(self, circuits, parameter_binds, **run_options): + """Run circuits by generating native circuits.""" circuits, noise_model = self._compile(circuits, **run_options) if parameter_binds: - run_options['parameterizations'] = self._convert_binds(circuits, parameter_binds) + run_options["parameterizations"] = self._convert_binds(circuits, parameter_binds) config = generate_aer_config(circuits, self.options, **run_options) # Submit job job_id = str(uuid.uuid4()) - aer_job = AerJob(self, job_id, self._execute_circuits_job, - circuits=circuits, noise_model=noise_model, config=config) + aer_job = AerJob( + self, + job_id, + self._execute_circuits_job, + circuits=circuits, + noise_model=noise_model, + config=config, + ) aer_job.submit() return aer_job # pylint: disable=arguments-differ - def _run_qobj(self, - circuits, - validate=False, - parameter_binds=None, - **run_options): - """Run circuits by assembling qobj. - """ + def _run_qobj(self, circuits, validate=False, parameter_binds=None, **run_options): + """Run circuits by assembling qobj.""" qobj = self._assemble(circuits, parameter_binds=parameter_binds, **run_options) # Optional validation @@ -259,19 +256,21 @@ def _run_qobj(self, self._validate(qobj) # Get executor from qobj config and delete attribute so qobj can still be serialized - executor = getattr(qobj.config, 'executor', None) - if hasattr(qobj.config, 'executor'): - delattr(qobj.config, 'executor') + executor = getattr(qobj.config, "executor", None) + if hasattr(qobj.config, "executor"): + delattr(qobj.config, "executor") # Optionally split the job experiments = split_qobj( - qobj, max_size=getattr(qobj.config, 'max_job_size', None), - max_shot_size=getattr(qobj.config, 'max_shot_size', None)) + qobj, + max_size=getattr(qobj.config, "max_job_size", None), + max_shot_size=getattr(qobj.config, "max_shot_size", None), + ) # Temporarily remove any executor from options so that job submission # can work with Dask client executors which can't be pickled - opts_executor = getattr(self._options, 'executor', None) - if hasattr(self._options, 'executor'): + opts_executor = getattr(self._options, "executor", None) + if hasattr(self._options, "executor"): self._options.executor = None # Submit job @@ -279,12 +278,13 @@ def _run_qobj(self, if isinstance(experiments, list): aer_job = AerJobSet(self, job_id, self._execute_qobj_job, experiments, executor) else: - aer_job = AerJob(self, job_id, self._execute_qobj_job, qobj=experiments, - executor=executor) + aer_job = AerJob( + self, job_id, self._execute_qobj_job, qobj=experiments, executor=executor + ) aer_job.submit() # Restore removed executor after submission - if hasattr(self._options, 'executor'): + if hasattr(self._options, "executor"): self._options.executor = opts_executor return aer_job @@ -300,7 +300,7 @@ def configuration(self): setattr(config, key, val) # If config has custom instructions add them to # basis gates to include them for the terra transpiler - if hasattr(config, 'custom_instructions'): + if hasattr(config, "custom_instructions"): config.basis_gates = config.basis_gates + config.custom_instructions return config @@ -350,9 +350,10 @@ def status(self): backend_version=self.configuration().backend_version, operational=True, pending_jobs=0, - status_msg='') + status_msg="", + ) - def _execute_qobj_job(self, qobj, job_id='', format_result=True): + def _execute_qobj_job(self, qobj, job_id="", format_result=True): """Run a qobj job""" # Start timer start = time.time() @@ -385,9 +386,8 @@ def _execute_qobj_job(self, qobj, job_id='', format_result=True): if not isinstance(output, dict): logger.error("%s: simulation failed.", self.name()) if output: - logger.error('Output: %s', output) - raise AerError( - "simulation terminated without returning valid output.") + logger.error("Output: %s", output) + raise AerError("simulation terminated without returning valid output.") # Format results output["job_id"] = job_id @@ -397,9 +397,11 @@ def _execute_qobj_job(self, qobj, job_id='', format_result=True): # Push metadata to experiment headers for result in output["results"]: - if ("header" in result and - "metadata" in result["header"] and - "metadata_index" in result["header"]["metadata"]): + if ( + "header" in result + and "metadata" in result["header"] + and "metadata_index" in result["header"]["metadata"] + ): metadata_index = result["header"]["metadata"]["metadata_index"] result["header"]["metadata"] = metadata_list[metadata_index] @@ -416,8 +418,7 @@ def _execute_qobj_job(self, qobj, job_id='', format_result=True): return self._format_results(output) return output - def _execute_circuits_job(self, circuits, noise_model, config, job_id='', - format_result=True): + def _execute_circuits_job(self, circuits, noise_model, config, job_id="", format_result=True): """Run a job""" # Start timer start = time.time() @@ -441,9 +442,8 @@ def _execute_circuits_job(self, circuits, noise_model, config, job_id='', if not isinstance(output, dict): logger.error("%s: simulation failed.", self.name()) if output: - logger.error('Output: %s', output) - raise AerError( - "simulation terminated without returning valid output.") + logger.error("Output: %s", output) + raise AerError("simulation terminated without returning valid output.") # Format results output["job_id"] = job_id @@ -453,9 +453,12 @@ def _execute_circuits_job(self, circuits, noise_model, config, job_id='', # Push metadata to experiment headers for result in output["results"]: - if ("header" in result and - "metadata" in result["header"] and result["header"]["metadata"] and - "metadata_index" in result["header"]["metadata"]): + if ( + "header" in result + and "metadata" in result["header"] + and result["header"]["metadata"] + and "metadata_index" in result["header"]["metadata"] + ): metadata_index = result["header"]["metadata"]["metadata_index"] result["header"]["metadata"] = metadata_list[metadata_index] @@ -496,13 +499,13 @@ def _compile(self, circuits, **run_options): # Compile Qasm3 instructions circuits, optypes = compile_circuit( - circuits, - basis_gates=self.configuration().basis_gates, - optypes=optypes) + circuits, basis_gates=self.configuration().basis_gates, optypes=optypes + ) # run option noise model circuits, noise_model, run_options = self._assemble_noise_model( - circuits, optypes, **run_options) + circuits, optypes, **run_options + ) return circuits, noise_model @@ -517,7 +520,7 @@ def _assemble(self, circuits, parameter_binds=None, **run_options): # If noise model exists, add it to the run options if noise_model: - run_options['noise_model'] = noise_model + run_options["noise_model"] = noise_model if parameter_binds: # Handle parameter binding @@ -529,7 +532,8 @@ def _assemble(self, circuits, parameter_binds=None, **run_options): [circuit], backend=self, parameter_binds=[assemble_bind], - parameterizations=parameterizations) + parameterizations=parameterizations, + ) if qobj: qobj.experiments.append(qobj_tmp.experiments[0]) else: @@ -557,8 +561,7 @@ def _assemble_noise_model(self, circuits, optypes, **run_options): # This avoids unnecessarily copying the noise model for circuits # that do not contain a quantum error updated_noise = False - noise_model = run_options.get( - 'noise_model', getattr(self.options, 'noise_model', None)) + noise_model = run_options.get("noise_model", getattr(self.options, "noise_model", None)) # Add custom pass noise only to QuantumCircuit objects that contain delay # instructions since this is the only instruction handled by the noise pass @@ -567,9 +570,7 @@ def _assemble_noise_model(self, circuits, optypes, **run_options): npm = noise_model._pass_manager() if npm is not None: # Get indicies of circuits that need noise transpiling - transpile_idxs = [ - idx for idx, optype in enumerate(optypes) if Delay in optype - ] + transpile_idxs = [idx for idx, optype in enumerate(optypes) if Delay in optype] # Transpile only the required circuits transpiled_circuits = npm.run([run_circuits[i] for i in transpile_idxs]) @@ -584,7 +585,8 @@ def _assemble_noise_model(self, circuits, optypes, **run_options): # Check if circuits contain quantum error instructions for idx, circ in enumerate(run_circuits): if QuantumChannelInstruction in optypes[idx] and not isinstance( - circ, (Schedule, ScheduleBlock)): + circ, (Schedule, ScheduleBlock) + ): updated_circ = False new_data = [] for inst, qargs, cargs in circ.data: @@ -618,10 +620,10 @@ def _assemble_noise_model(self, circuits, optypes, **run_options): def _get_executor(self, **run_options): """Get the executor""" - if 'executor' in run_options: - return run_options['executor'] + if "executor" in run_options: + return run_options["executor"] else: - return getattr(self._options, 'executor', None) + return getattr(self._options, "executor", None) @abstractmethod def _execute_qobj(self, qobj): @@ -718,4 +720,4 @@ def __repr__(self): """String representation of an AerBackend.""" name = self.__class__.__name__ display = f"'{self.name()}'" - return f'{name}({display})' + return f"{name}({display})" diff --git a/qiskit_aer/backends/backend_utils.py b/qiskit_aer/backends/backend_utils.py index c85049e6f2..446406c796 100644 --- a/qiskit_aer/backends/backend_utils.py +++ b/qiskit_aer/backends/backend_utils.py @@ -22,11 +22,10 @@ from qiskit.qobj import QasmQobjInstruction from qiskit.result import ProbDistribution from qiskit.quantum_info import Clifford -from .compatibility import ( - Statevector, DensityMatrix, StabilizerState, Operator, SuperOp) +from .compatibility import Statevector, DensityMatrix, StabilizerState, Operator, SuperOp # Available system memory -SYSTEM_MEMORY_GB = local_hardware_info()['memory'] +SYSTEM_MEMORY_GB = local_hardware_info()["memory"] # Max number of qubits for complex double statevector # given available system memory @@ -49,71 +48,370 @@ } BASIS_GATES = { - 'statevector': sorted([ - 'u1', 'u2', 'u3', 'u', 'p', 'r', 'rx', 'ry', 'rz', 'id', 'x', - 'y', 'z', 'h', 's', 'sdg', 'sx', 'sxdg', 't', 'tdg', 'swap', 'cx', - 'cy', 'cz', 'csx', 'cp', 'cu', 'cu1', 'cu2', 'cu3', 'rxx', 'ryy', - 'rzz', 'rzx', 'ccx', 'cswap', 'mcx', 'mcy', 'mcz', 'mcsx', - 'mcp', 'mcphase', 'mcu', 'mcu1', 'mcu2', 'mcu3', 'mcrx', 'mcry', 'mcrz', - 'mcr', 'mcswap', 'unitary', 'diagonal', 'multiplexer', - 'initialize', 'delay', 'pauli', 'mcx_gray', 'ecr' - ]), - 'density_matrix': sorted([ - 'u1', 'u2', 'u3', 'u', 'p', 'r', 'rx', 'ry', 'rz', 'id', 'x', - 'y', 'z', 'h', 's', 'sdg', 'sx', 'sxdg', 't', 'tdg', 'swap', 'cx', - 'cy', 'cz', 'cp', 'cu1', 'rxx', 'ryy', 'rzz', 'rzx', 'ccx', - 'unitary', 'diagonal', 'delay', 'pauli', 'ecr', - ]), - 'matrix_product_state': sorted([ - 'u1', 'u2', 'u3', 'u', 'p', 'cp', 'cx', 'cy', 'cz', 'id', 'x', 'y', 'z', 'h', 's', - 'sdg', 'sx', 'sxdg', 't', 'tdg', 'swap', 'ccx', 'unitary', 'roerror', 'delay', 'pauli', - 'r', 'rx', 'ry', 'rz', 'rxx', 'ryy', 'rzz', 'rzx', 'csx', 'cswap', 'diagonal', - 'initialize' - ]), - 'stabilizer': sorted([ - 'id', 'x', 'y', 'z', 'h', 's', 'sdg', 'sx', 'sxdg', 'cx', 'cy', 'cz', - 'swap', 'delay', 'pauli' - ]), - 'extended_stabilizer': sorted([ - 'cx', 'cz', 'id', 'x', 'y', 'z', 'h', 's', 'sdg', 'sx', 'sxdg', - 'swap', 'u0', 't', 'tdg', 'u1', 'p', 'ccx', 'ccz', 'delay', 'pauli' - ]), - 'unitary': sorted([ - 'u1', 'u2', 'u3', 'u', 'p', 'r', 'rx', 'ry', 'rz', 'id', 'x', - 'y', 'z', 'h', 's', 'sdg', 'sx', 'sxdg', 't', 'tdg', 'swap', 'cx', - 'cy', 'cz', 'csx', 'cp', 'cu', 'cu1', 'cu2', 'cu3', 'rxx', 'ryy', - 'rzz', 'rzx', 'ccx', 'cswap', 'mcx', 'mcy', 'mcz', 'mcsx', - 'mcp', 'mcphase', 'mcu', 'mcu1', 'mcu2', 'mcu3', 'mcrx', 'mcry', 'mcrz', - 'mcr', 'mcswap', 'unitary', 'diagonal', 'multiplexer', 'delay', 'pauli', - 'ecr', - ]), - 'superop': sorted([ - 'u1', 'u2', 'u3', 'u', 'p', 'r', 'rx', 'ry', 'rz', 'id', 'x', - 'y', 'z', 'h', 's', 'sdg', 'sx', 'sxdg', 't', 'tdg', 'swap', 'cx', - 'cy', 'cz', 'cp', 'cu1', 'rxx', 'ryy', - 'rzz', 'rzx', 'ccx', 'unitary', 'diagonal', 'delay', 'pauli' - ]), - 'tensor_network': sorted([ - 'u1', 'u2', 'u3', 'u', 'p', 'r', 'rx', 'ry', 'rz', 'id', 'x', - 'y', 'z', 'h', 's', 'sdg', 'sx', 'sxdg', 't', 'tdg', 'swap', 'cx', - 'cy', 'cz', 'csx', 'cp', 'cu', 'cu1', 'cu2', 'cu3', 'rxx', 'ryy', - 'rzz', 'rzx', 'ccx', 'cswap', 'mcx', 'mcy', 'mcz', 'mcsx', - 'mcp', 'mcphase', 'mcu', 'mcu1', 'mcu2', 'mcu3', 'mcrx', 'mcry', 'mcrz', - 'mcr', 'mcswap', 'unitary', 'diagonal', 'multiplexer', - 'initialize', 'delay', 'pauli', 'mcx_gray' - ]) + "statevector": sorted( + [ + "u1", + "u2", + "u3", + "u", + "p", + "r", + "rx", + "ry", + "rz", + "id", + "x", + "y", + "z", + "h", + "s", + "sdg", + "sx", + "sxdg", + "t", + "tdg", + "swap", + "cx", + "cy", + "cz", + "csx", + "cp", + "cu", + "cu1", + "cu2", + "cu3", + "rxx", + "ryy", + "rzz", + "rzx", + "ccx", + "cswap", + "mcx", + "mcy", + "mcz", + "mcsx", + "mcp", + "mcphase", + "mcu", + "mcu1", + "mcu2", + "mcu3", + "mcrx", + "mcry", + "mcrz", + "mcr", + "mcswap", + "unitary", + "diagonal", + "multiplexer", + "initialize", + "delay", + "pauli", + "mcx_gray", + "ecr", + ] + ), + "density_matrix": sorted( + [ + "u1", + "u2", + "u3", + "u", + "p", + "r", + "rx", + "ry", + "rz", + "id", + "x", + "y", + "z", + "h", + "s", + "sdg", + "sx", + "sxdg", + "t", + "tdg", + "swap", + "cx", + "cy", + "cz", + "cp", + "cu1", + "rxx", + "ryy", + "rzz", + "rzx", + "ccx", + "unitary", + "diagonal", + "delay", + "pauli", + "ecr", + ] + ), + "matrix_product_state": sorted( + [ + "u1", + "u2", + "u3", + "u", + "p", + "cp", + "cx", + "cy", + "cz", + "id", + "x", + "y", + "z", + "h", + "s", + "sdg", + "sx", + "sxdg", + "t", + "tdg", + "swap", + "ccx", + "unitary", + "roerror", + "delay", + "pauli", + "r", + "rx", + "ry", + "rz", + "rxx", + "ryy", + "rzz", + "rzx", + "csx", + "cswap", + "diagonal", + "initialize", + ] + ), + "stabilizer": sorted( + [ + "id", + "x", + "y", + "z", + "h", + "s", + "sdg", + "sx", + "sxdg", + "cx", + "cy", + "cz", + "swap", + "delay", + "pauli", + ] + ), + "extended_stabilizer": sorted( + [ + "cx", + "cz", + "id", + "x", + "y", + "z", + "h", + "s", + "sdg", + "sx", + "sxdg", + "swap", + "u0", + "t", + "tdg", + "u1", + "p", + "ccx", + "ccz", + "delay", + "pauli", + ] + ), + "unitary": sorted( + [ + "u1", + "u2", + "u3", + "u", + "p", + "r", + "rx", + "ry", + "rz", + "id", + "x", + "y", + "z", + "h", + "s", + "sdg", + "sx", + "sxdg", + "t", + "tdg", + "swap", + "cx", + "cy", + "cz", + "csx", + "cp", + "cu", + "cu1", + "cu2", + "cu3", + "rxx", + "ryy", + "rzz", + "rzx", + "ccx", + "cswap", + "mcx", + "mcy", + "mcz", + "mcsx", + "mcp", + "mcphase", + "mcu", + "mcu1", + "mcu2", + "mcu3", + "mcrx", + "mcry", + "mcrz", + "mcr", + "mcswap", + "unitary", + "diagonal", + "multiplexer", + "delay", + "pauli", + "ecr", + ] + ), + "superop": sorted( + [ + "u1", + "u2", + "u3", + "u", + "p", + "r", + "rx", + "ry", + "rz", + "id", + "x", + "y", + "z", + "h", + "s", + "sdg", + "sx", + "sxdg", + "t", + "tdg", + "swap", + "cx", + "cy", + "cz", + "cp", + "cu1", + "rxx", + "ryy", + "rzz", + "rzx", + "ccx", + "unitary", + "diagonal", + "delay", + "pauli", + ] + ), + "tensor_network": sorted( + [ + "u1", + "u2", + "u3", + "u", + "p", + "r", + "rx", + "ry", + "rz", + "id", + "x", + "y", + "z", + "h", + "s", + "sdg", + "sx", + "sxdg", + "t", + "tdg", + "swap", + "cx", + "cy", + "cz", + "csx", + "cp", + "cu", + "cu1", + "cu2", + "cu3", + "rxx", + "ryy", + "rzz", + "rzx", + "ccx", + "cswap", + "mcx", + "mcy", + "mcz", + "mcsx", + "mcp", + "mcphase", + "mcu", + "mcu1", + "mcu2", + "mcu3", + "mcrx", + "mcry", + "mcrz", + "mcr", + "mcswap", + "unitary", + "diagonal", + "multiplexer", + "initialize", + "delay", + "pauli", + "mcx_gray", + ] + ), } # Automatic method basis gates are the union of statevector, # density matrix, and stabilizer methods -BASIS_GATES[None] = BASIS_GATES['automatic'] = sorted( - set(BASIS_GATES['statevector']).union( - BASIS_GATES['stabilizer']).union( - BASIS_GATES['density_matrix']).union( - BASIS_GATES['matrix_product_state']).union( - BASIS_GATES['unitary']).union( - BASIS_GATES['superop']).union( - BASIS_GATES['tensor_network'])) +BASIS_GATES[None] = BASIS_GATES["automatic"] = sorted( + set(BASIS_GATES["statevector"]) + .union(BASIS_GATES["stabilizer"]) + .union(BASIS_GATES["density_matrix"]) + .union(BASIS_GATES["matrix_product_state"]) + .union(BASIS_GATES["unitary"]) + .union(BASIS_GATES["superop"]) + .union(BASIS_GATES["tensor_network"]) +) def cpp_execute_qobj(controller, qobj): @@ -147,13 +445,11 @@ def available_methods(controller, methods, devices): 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) + qobj = assemble( + dummy_circ, optimization_level=0, shots=1, method=method, device=device + ) result = cpp_execute_qobj(controller, qobj) - if result.get('success', False): + if result.get("success", False): valid_methods.append(method) return tuple(valid_methods) @@ -166,13 +462,11 @@ def available_devices(controller, devices): valid_devices = [] for device in devices: - qobj = assemble(dummy_circ, - optimization_level=0, - shots=1, - method="statevector", - device=device) + qobj = assemble( + dummy_circ, optimization_level=0, shots=1, method="statevector", device=device + ) result = cpp_execute_qobj(controller, qobj) - if result.get('success', False): + if result.get("success", False): valid_devices.append(device) return tuple(valid_devices) @@ -186,7 +480,8 @@ def save_inst(num_qubits): name=f"save_{state}", qubits=list(range(num_qubits)), label=f"{state}", - snapshot_type="single") + snapshot_type="single", + ) for exp in qobj.experiments: num_qubits = exp.config.n_qubits @@ -200,10 +495,7 @@ def add_final_save_op(aer_circuits, state): for aer_circuit in aer_circuits: num_qubits = aer_circuit.num_qubits - aer_circuit.save_state(list(range(num_qubits)), - f"save_{state}", - "single", - state) + aer_circuit.save_state(list(range(num_qubits)), f"save_{state}", "single", state) return aer_circuits @@ -241,9 +533,11 @@ def format_save_type(data, save_type, save_subtype): return data if save_subtype in ["list", "c_list"]: + def func(data): init_fn = init_fns[save_type] return [init_fn(i) for i in data] + else: func = init_fns[save_type] diff --git a/qiskit_aer/backends/compatibility.py b/qiskit_aer/backends/compatibility.py index faaccda273..068edda4be 100644 --- a/qiskit_aer/backends/compatibility.py +++ b/qiskit_aer/backends/compatibility.py @@ -30,7 +30,7 @@ def _forward_attr(attr): # Pass Iterable magic methods on to the Numpy array. We can't pass # `__getitem__` (and consequently `__setitem__`, `__delitem__`) on because # `Statevector` implements them itself. - if attr[:2] == '__' or attr in ['_data', '_op_shape']: + if attr[:2] == "__" or attr in ["_data", "_op_shape"]: return False return True @@ -60,9 +60,9 @@ def __getattr__(self, attr): def __eq__(self, other): return ( - isinstance(self, type(other)) and - self._op_shape == other._op_shape and - np.allclose(self.data, other.data, rtol=self.rtol, atol=self.atol) + isinstance(self, type(other)) + and self._op_shape == other._op_shape + and np.allclose(self.data, other.data, rtol=self.rtol, atol=self.atol) ) def __bool__(self): @@ -103,9 +103,9 @@ def __getattr__(self, attr): def __eq__(self, other): return ( - isinstance(self, type(other)) and - self._op_shape == other._op_shape and - np.allclose(self.data, other.data, rtol=self.rtol, atol=self.atol) + isinstance(self, type(other)) + and self._op_shape == other._op_shape + and np.allclose(self.data, other.data, rtol=self.rtol, atol=self.atol) ) def __len__(self): @@ -144,9 +144,9 @@ def __getattr__(self, attr): def __eq__(self, other): return ( - isinstance(self, type(other)) and - self._op_shape == other._op_shape and - np.allclose(self.data, other.data, rtol=self.rtol, atol=self.atol) + isinstance(self, type(other)) + and self._op_shape == other._op_shape + and np.allclose(self.data, other.data, rtol=self.rtol, atol=self.atol) ) def __bool__(self): @@ -190,9 +190,9 @@ def __getattr__(self, attr): def __eq__(self, other): return ( - isinstance(self, type(other)) and - self._op_shape == other._op_shape and - np.allclose(self.data, other.data, rtol=self.rtol, atol=self.atol) + isinstance(self, type(other)) + and self._op_shape == other._op_shape + and np.allclose(self.data, other.data, rtol=self.rtol, atol=self.atol) ) def __bool__(self): @@ -253,7 +253,9 @@ def __getitem__(self, item): " Accessing dict items is deprecated and will result in an" " error in a future release. Use the `.clifford.to_dict()` methods to access " " the stored Clifford operator and convert to a dictionary.", - DeprecationWarning, stacklevel=2) + DeprecationWarning, + stacklevel=2, + ) return self._data.to_dict()[item] raise TypeError("'StabilizerState object is not subscriptable'") diff --git a/qiskit_aer/backends/pulse_simulator.py b/qiskit_aer/backends/pulse_simulator.py index b3be282793..4fea7f0974 100644 --- a/qiskit_aer/backends/pulse_simulator.py +++ b/qiskit_aer/backends/pulse_simulator.py @@ -34,22 +34,22 @@ logger = logging.getLogger(__name__) DEFAULT_CONFIGURATION = { - 'backend_name': 'pulse_simulator', - 'backend_version': __version__, - 'n_qubits': 20, - 'coupling_map': None, - 'url': 'https://github.com/Qiskit/qiskit-aer', - 'simulator': True, - 'meas_levels': [1, 2], - 'local': True, - 'conditional': True, - 'open_pulse': True, - 'memory': False, - 'max_shots': int(1e6), - 'description': 'A Pulse-based Hamiltonian simulator for Pulse Qobj files', - 'gates': [], - 'basis_gates': [], - 'parametric_pulses': [] + "backend_name": "pulse_simulator", + "backend_version": __version__, + "n_qubits": 20, + "coupling_map": None, + "url": "https://github.com/Qiskit/qiskit-aer", + "simulator": True, + "meas_levels": [1, 2], + "local": True, + "conditional": True, + "open_pulse": True, + "memory": False, + "max_shots": int(1e6), + "description": "A Pulse-based Hamiltonian simulator for Pulse Qobj files", + "gates": [], + "basis_gates": [], + "parametric_pulses": [], } @@ -155,12 +155,10 @@ class PulseSimulator(AerBackend): are ``'atol'``, ``'rtol'``, ``'nsteps'``, ``'max_step'``, ``'num_cpus'``, ``'norm_tol'``, and ``'norm_steps'``. """ - def __init__(self, - configuration=None, - properties=None, - defaults=None, - provider=None, - **backend_options): + + def __init__( + self, configuration=None, properties=None, defaults=None, provider=None, **backend_options + ): warn( "The Pulse simulator backend in Qiskit Aer is deprecated and will " "be removed in a future release. Instead the qiskit-dynamics " @@ -170,8 +168,7 @@ def __init__(self, ) if configuration is None: - configuration = BackendConfiguration.from_dict( - DEFAULT_CONFIGURATION) + configuration = BackendConfiguration.from_dict(DEFAULT_CONFIGURATION) else: configuration = copy.copy(configuration) configuration.meas_levels = self._meas_levels(configuration.meas_levels) @@ -179,24 +176,23 @@ def __init__(self, configuration.parametric_pulses = [] if defaults is None: - defaults = PulseDefaults(qubit_freq_est=[inf], - meas_freq_est=[inf], - buffer=0, - cmd_def=[], - pulse_library=[]) - - super().__init__(configuration, - properties=properties, - defaults=defaults, - provider=provider, - backend_options=backend_options) + defaults = PulseDefaults( + qubit_freq_est=[inf], meas_freq_est=[inf], buffer=0, cmd_def=[], pulse_library=[] + ) + + super().__init__( + configuration, + properties=properties, + defaults=defaults, + provider=provider, + backend_options=backend_options, + ) # Set up default system model - subsystem_list = backend_options.get('subsystem_list', None) - if backend_options.get('system_model') is None: - if hasattr(configuration, 'hamiltonian'): - system_model = PulseSystemModel.from_config( - configuration, subsystem_list) + subsystem_list = backend_options.get("subsystem_list", None) + if backend_options.get("system_model") is None: + if hasattr(configuration, "hamiltonian"): + system_model = PulseSystemModel.from_config(configuration, subsystem_list) self._set_system_model(system_model) @classmethod @@ -218,13 +214,11 @@ def _default_options(cls): executor=None, memory_slots=1, max_job_size=None, - max_shot_size=None) + max_shot_size=None, + ) # pylint: disable=arguments-differ, missing-param-doc - def run(self, - schedules, - validate=True, - **run_options): + def run(self, schedules, validate=True, **run_options): """Run a qobj on the backend. Args: @@ -255,29 +249,29 @@ def run(self, @property def _system_model(self): - return getattr(self._options, 'system_model') + return getattr(self._options, "system_model") @classmethod def from_backend(cls, backend, **options): """Initialize simulator from backend.""" if isinstance(backend, BackendV2): - raise AerError( - "PulseSimulator.from_backend does not currently support V2 Backends." - ) + raise AerError("PulseSimulator.from_backend does not currently support V2 Backends.") configuration = copy.copy(backend.configuration()) defaults = copy.copy(backend.defaults()) properties = copy.copy(backend.properties()) - backend_name = 'pulse_simulator({})'.format(configuration.backend_name) - description = 'A Pulse-based simulator configured from the backend: ' + backend_name = "pulse_simulator({})".format(configuration.backend_name) + description = "A Pulse-based simulator configured from the backend: " description += configuration.backend_name - sim = cls(configuration=configuration, - properties=properties, - defaults=defaults, - backend_name=backend_name, - description=description, - **options) + sim = cls( + configuration=configuration, + properties=properties, + defaults=defaults, + backend_name=backend_name, + description=description, + **options, + ) return sim def _execute_qobj(self, qobj): @@ -293,42 +287,42 @@ def _execute_qobj(self, qobj): return pulse_controller(qobj) def _execute_circuits(self, aer_circuits, noise_model, config): - """Execute circuits on the backend. - """ + """Execute circuits on the backend.""" raise TypeError("pulse simulator does not support circuit execution") def set_option(self, key, value): """Set pulse simulation options and update backend.""" - if key == 'meas_levels': + if key == "meas_levels": self._set_configuration_option(key, self._meas_levels(value)) return # Handle cases that require updating two places - if key in ['dt', 'u_channel_lo']: + if key in ["dt", "u_channel_lo"]: self._set_configuration_option(key, value) if self._system_model is not None: setattr(self._system_model, key, value) return - if key == 'hamiltonian': + if key == "hamiltonian": # if option is hamiltonian, set in configuration and reconstruct pulse system model - subsystem_list = getattr(self._options.get, 'subsystem_list', None) - system_model = PulseSystemModel.from_config(self.configuration(), - subsystem_list) - super().set_option('system_model', system_model) + subsystem_list = getattr(self._options.get, "subsystem_list", None) + system_model = PulseSystemModel.from_config(self.configuration(), subsystem_list) + super().set_option("system_model", system_model) self._set_configuration_option(key, value) return # if system model is specified directly - if key == 'system_model': - if hasattr(self.configuration(), 'hamiltonian'): - warn('Specifying both a configuration with a Hamiltonian and a ' - 'system model may result in inconsistencies.') + if key == "system_model": + if hasattr(self.configuration(), "hamiltonian"): + warn( + "Specifying both a configuration with a Hamiltonian and a " + "system model may result in inconsistencies." + ) # Set config dt and u_channel_lo to system model values self._set_system_model(value) return - if key == 'qubit_lo_freq': + if key == "qubit_lo_freq": value = [freq * 1e-9 for freq in value] # Set all other options from AerBackend @@ -336,11 +330,9 @@ def set_option(self, key, value): def _set_system_model(self, system_model): """Set system model option""" - self._set_configuration_option( - 'dt', getattr(system_model, 'dt', [])) - self._set_configuration_option( - 'u_channel_lo', getattr(system_model, 'u_channel_lo', [])) - super().set_option('system_model', system_model) + self._set_configuration_option("dt", getattr(system_model, "dt", [])) + self._set_configuration_option("u_channel_lo", getattr(system_model, "u_channel_lo", [])) + super().set_option("system_model", system_model) def _validate(self, qobj): """Validation of qobj. @@ -348,28 +340,31 @@ def _validate(self, qobj): Ensures that exactly one Acquire instruction is present in each schedule. Checks SystemModel is in qobj config """ - if getattr(qobj.config, 'system_model', None) is None: + if getattr(qobj.config, "system_model", None) is None: raise AerError("PulseSimulator requires a system model to run.") for exp in qobj.experiments: num_acquires = 0 for instruction in exp.instructions: - if instruction.name == 'acquire': + if instruction.name == "acquire": num_acquires += 1 if num_acquires > 1: - raise AerError("PulseSimulator does not support multiple Acquire " - "instructions in a single schedule.") + raise AerError( + "PulseSimulator does not support multiple Acquire " + "instructions in a single schedule." + ) if num_acquires == 0: - raise AerError("PulseSimulator requires at least one Acquire " - "instruction per schedule.") + raise AerError( + "PulseSimulator requires at least one Acquire " "instruction per schedule." + ) @staticmethod def _meas_levels(meas_levels): """Function for setting meas_levels in a pulse simulator configuration.""" if 0 in meas_levels: - warn('Measurement level 0 not supported in pulse simulator.') + warn("Measurement level 0 not supported in pulse simulator.") tmp = copy.copy(meas_levels) tmp.remove(0) return tmp diff --git a/qiskit_aer/backends/qasm_simulator.py b/qiskit_aer/backends/qasm_simulator.py index 4a17dd8f37..a7978da705 100644 --- a/qiskit_aer/backends/qasm_simulator.py +++ b/qiskit_aer/backends/qasm_simulator.py @@ -23,13 +23,16 @@ from ..version import __version__ from ..aererror import AerError from .aerbackend import AerBackend -from .backend_utils import (cpp_execute_qobj, - cpp_execute_circuits, - available_methods, - MAX_QUBITS_STATEVECTOR, - LEGACY_METHOD_MAP, - map_legacy_method_options, - map_legacy_method_config) +from .backend_utils import ( + cpp_execute_qobj, + cpp_execute_circuits, + available_methods, + MAX_QUBITS_STATEVECTOR, + LEGACY_METHOD_MAP, + map_legacy_method_options, + map_legacy_method_config, +) + # pylint: disable=import-error, no-name-in-module from .controller_wrappers import aer_controller_execute @@ -303,79 +306,153 @@ class QasmSimulator(AerBackend): than or equal to enable fusion optimization [Default: 14] """ - _DEFAULT_BASIS_GATES = sorted([ - 'u1', 'u2', 'u3', 'u', 'p', 'r', 'rx', 'ry', 'rz', 'id', 'x', - 'y', 'z', 'h', 's', 'sdg', 'sx', 'sxdg', 't', 'tdg', 'swap', 'cx', - 'cy', 'cz', 'csx', 'cp', 'cu', 'cu1', 'cu2', 'cu3', 'rxx', 'ryy', - 'rzz', 'rzx', 'ccx', 'cswap', 'mcx', 'mcy', 'mcz', 'mcsx', - 'mcp', 'mcphase', 'mcu', 'mcu1', 'mcu2', 'mcu3', 'mcrx', 'mcry', 'mcrz', - 'mcr', 'mcswap', 'unitary', 'diagonal', 'multiplexer', - 'initialize', 'delay', 'pauli', 'mcx_gray', 'ecr' - ]) - - _DEFAULT_CUSTOM_INSTR = sorted([ - 'quantum_channel', 'qerror_loc', 'roerror', 'kraus', - 'save_expval', 'save_expval_var', - 'save_probabilities', 'save_probabilities_dict', - 'save_amplitudes', 'save_amplitudes_sq', 'save_state', - 'save_density_matrix', 'save_statevector', 'save_statevector_dict', - 'save_stabilizer', 'set_statevector', 'set_density_matrix', - 'set_stabilizer', - ]) + _DEFAULT_BASIS_GATES = sorted( + [ + "u1", + "u2", + "u3", + "u", + "p", + "r", + "rx", + "ry", + "rz", + "id", + "x", + "y", + "z", + "h", + "s", + "sdg", + "sx", + "sxdg", + "t", + "tdg", + "swap", + "cx", + "cy", + "cz", + "csx", + "cp", + "cu", + "cu1", + "cu2", + "cu3", + "rxx", + "ryy", + "rzz", + "rzx", + "ccx", + "cswap", + "mcx", + "mcy", + "mcz", + "mcsx", + "mcp", + "mcphase", + "mcu", + "mcu1", + "mcu2", + "mcu3", + "mcrx", + "mcry", + "mcrz", + "mcr", + "mcswap", + "unitary", + "diagonal", + "multiplexer", + "initialize", + "delay", + "pauli", + "mcx_gray", + "ecr", + ] + ) + + _DEFAULT_CUSTOM_INSTR = sorted( + [ + "quantum_channel", + "qerror_loc", + "roerror", + "kraus", + "save_expval", + "save_expval_var", + "save_probabilities", + "save_probabilities_dict", + "save_amplitudes", + "save_amplitudes_sq", + "save_state", + "save_density_matrix", + "save_statevector", + "save_statevector_dict", + "save_stabilizer", + "set_statevector", + "set_density_matrix", + "set_stabilizer", + ] + ) _DEFAULT_CONFIGURATION = { - 'backend_name': 'qasm_simulator', - 'backend_version': __version__, - 'n_qubits': MAX_QUBITS_STATEVECTOR, - 'url': 'https://github.com/Qiskit/qiskit-aer', - 'simulator': True, - 'local': True, - 'conditional': True, - 'open_pulse': False, - 'memory': True, - 'max_shots': int(1e6), - 'description': 'A C++ QasmQobj simulator with noise', - 'coupling_map': None, - 'basis_gates': _DEFAULT_BASIS_GATES, - 'custom_instructions': _DEFAULT_CUSTOM_INSTR, - 'gates': [] + "backend_name": "qasm_simulator", + "backend_version": __version__, + "n_qubits": MAX_QUBITS_STATEVECTOR, + "url": "https://github.com/Qiskit/qiskit-aer", + "simulator": True, + "local": True, + "conditional": True, + "open_pulse": False, + "memory": True, + "max_shots": int(1e6), + "description": "A C++ QasmQobj simulator with noise", + "coupling_map": None, + "basis_gates": _DEFAULT_BASIS_GATES, + "custom_instructions": _DEFAULT_CUSTOM_INSTR, + "gates": [], } _SIMULATION_METHODS = [ - 'automatic', 'statevector', 'statevector_gpu', 'statevector_custatevec', - 'statevector_thrust', 'density_matrix', - 'density_matrix_gpu', 'density_matrix_custatevec', 'density_matrix_thrust', - 'stabilizer', 'matrix_product_state', 'extended_stabilizer' + "automatic", + "statevector", + "statevector_gpu", + "statevector_custatevec", + "statevector_thrust", + "density_matrix", + "density_matrix_gpu", + "density_matrix_custatevec", + "density_matrix_thrust", + "stabilizer", + "matrix_product_state", + "extended_stabilizer", ] _AVAILABLE_METHODS = None - _SIMULATION_DEVICES = ('CPU', 'GPU', 'Thrust') + _SIMULATION_DEVICES = ("CPU", "GPU", "Thrust") _AVAILABLE_DEVICES = None - def __init__(self, - configuration=None, - properties=None, - provider=None, - **backend_options): - - warn('The `QasmSimulator` backend will be deprecated in the' - ' future. It has been superseded by the `AerSimulator`' - ' backend.', PendingDeprecationWarning) + def __init__(self, configuration=None, properties=None, provider=None, **backend_options): + warn( + "The `QasmSimulator` backend will be deprecated in the" + " future. It has been superseded by the `AerSimulator`" + " backend.", + PendingDeprecationWarning, + ) self._controller = aer_controller_execute() # Update available methods for class if QasmSimulator._AVAILABLE_METHODS is None: QasmSimulator._AVAILABLE_METHODS = available_methods( - self._controller, QasmSimulator._SIMULATION_METHODS, - QasmSimulator._SIMULATION_DEVICES) + self._controller, + QasmSimulator._SIMULATION_METHODS, + QasmSimulator._SIMULATION_DEVICES, + ) # Default configuration if configuration is None: - configuration = QasmBackendConfiguration.from_dict( - QasmSimulator._DEFAULT_CONFIGURATION) + configuration = QasmBackendConfiguration.from_dict(QasmSimulator._DEFAULT_CONFIGURATION) else: configuration.open_pulse = False @@ -383,23 +460,22 @@ def __init__(self, # of noise model, method, and config gates is expensive. self._cached_basis_gates = self._DEFAULT_BASIS_GATES - super().__init__(configuration, - properties=properties, - provider=provider, - backend_options=backend_options) + super().__init__( + configuration, properties=properties, provider=provider, backend_options=backend_options + ) def __repr__(self): """String representation of an AerBackend.""" display = super().__repr__()[:-1] - pad = ' ' * (len(self.__class__.__name__) + 1) + pad = " " * (len(self.__class__.__name__) + 1) - method = getattr(self.options, 'method', None) - if method not in [None, 'automatic']: + method = getattr(self.options, "method", None) + if method not in [None, "automatic"]: display += f",\n{pad}method='{method}'" - noise_model = getattr(self.options, 'noise_model', None) + noise_model = getattr(self.options, "noise_model", None) if noise_model is not None and not noise_model.is_ideal(): - display += f',\n{pad}noise_model={repr(noise_model)})' + display += f",\n{pad}noise_model={repr(noise_model)})" display += ")" return display @@ -438,7 +514,7 @@ def _default_options(cls): # stabilizer options stabilizer_max_snapshot_probabilities=32, # extended stabilizer options - extended_stabilizer_sampling_method='resampled_metropolis', + extended_stabilizer_sampling_method="resampled_metropolis", extended_stabilizer_metropolis_mixing_time=5000, extended_stabilizer_approximation_error=0.05, extended_stabilizer_norm_estimation_samples=100, @@ -448,19 +524,18 @@ def _default_options(cls): # MPS options matrix_product_state_truncation_threshold=1e-16, matrix_product_state_max_bond_dimension=None, - mps_sample_measure_algorithm='mps_heuristic', + mps_sample_measure_algorithm="mps_heuristic", mps_log_data=False, chop_threshold=1e-8, mps_parallel_threshold=14, - mps_omp_threads=1) + mps_omp_threads=1, + ) @classmethod def from_backend(cls, backend, **options): """Initialize simulator from backend.""" if isinstance(backend, BackendV2): - raise AerError( - "QasmSimulator.from_backend does not currently support V2 Backends." - ) + raise AerError("QasmSimulator.from_backend does not currently support V2 Backends.") # pylint: disable=import-outside-toplevel # Avoid cyclic import from ..noise.noise_model import NoiseModel @@ -471,18 +546,16 @@ def from_backend(cls, backend, **options): # Customize configuration name name = configuration.backend_name - configuration.backend_name = f'qasm_simulator({name})' + configuration.backend_name = f"qasm_simulator({name})" # Use automatic noise model if none is provided - if 'noise_model' not in options: + if "noise_model" not in options: noise_model = NoiseModel.from_backend(backend) if not noise_model.is_ideal(): - options['noise_model'] = noise_model + options["noise_model"] = noise_model # Initialize simulator - sim = cls(configuration=configuration, - properties=properties, - **options) + sim = cls(configuration=configuration, properties=properties, **options) return sim def configuration(self): @@ -521,8 +594,7 @@ def _execute_qobj(self, qobj): return cpp_execute_qobj(self._controller, qobj) def _execute_circuits(self, aer_circuits, noise_model, config): - """Execute circuits on the backend. - """ + """Execute circuits on the backend.""" config = map_legacy_method_config(config) return cpp_execute_circuits(self._controller, aer_circuits, noise_model, config) @@ -534,10 +606,11 @@ def set_option(self, key, value): if value in LEGACY_METHOD_MAP: value, device = LEGACY_METHOD_MAP[value] self.set_option("device", device) - if (value is not None and value not in self.available_methods()): + if value is not None and value not in self.available_methods(): raise AerError( f"Invalid simulation method {value}. Available methods" - f" are: {self.available_methods()}") + f" are: {self.available_methods()}" + ) self._set_method_config(value) super().set_option(key, value) if key in ["method", "noise_model", "basis_gates"]: @@ -562,9 +635,9 @@ def _validate(self, qobj): # Print warning if clbits but no measure if no_measure: logger.warning( - 'No measurements in circuit "%s": ' - 'count data will return all zeros.', - experiment.header.name) + 'No measurements in circuit "%s": ' "count data will return all zeros.", + experiment.header.name, + ) def _basis_gates(self): """Return simualtor basis gates. @@ -574,20 +647,19 @@ def _basis_gates(self): and method supported basis gates. """ # Use option value for basis gates if set - if 'basis_gates' in self._options_configuration: - return self._options_configuration['basis_gates'] + if "basis_gates" in self._options_configuration: + return self._options_configuration["basis_gates"] # Compute intersection with method basis gates method_gates = self._method_basis_gates() config_gates = self._configuration.basis_gates if config_gates: - basis_gates = set(config_gates).intersection( - method_gates) + basis_gates = set(config_gates).intersection(method_gates) else: basis_gates = method_gates # Compute intersection with noise model basis gates - noise_model = getattr(self.options, 'noise_model', None) + noise_model = getattr(self.options, "noise_model", None) if noise_model: noise_gates = noise_model.basis_gates basis_gates = basis_gates.intersection(noise_gates) @@ -599,106 +671,279 @@ def _basis_gates(self): "The intersection of configuration basis gates (%s), " "simulation method basis gates (%s), and " "noise model basis gates (%s) is empty", - config_gates, method_gates, noise_gates) + config_gates, + method_gates, + noise_gates, + ) return sorted(basis_gates) def _method_basis_gates(self): """Return method basis gates and custom instructions""" - method = self._options.get('method', None) - if method in ['density_matrix', 'density_matrix_gpu', - 'density_matrix_custatevec', 'density_matrix_thrust']: - return sorted([ - 'u1', 'u2', 'u3', 'u', 'p', 'r', 'rx', 'ry', 'rz', 'id', 'x', - 'y', 'z', 'h', 's', 'sdg', 'sx', 'sxdg', 't', 'tdg', 'swap', 'cx', - 'cy', 'cz', 'cp', 'cu1', 'rxx', 'ryy', 'rzz', 'rzx', 'ccx', - 'unitary', 'diagonal', 'delay', 'pauli', 'ecr' - ]) - if method == 'matrix_product_state': - return sorted([ - 'u1', 'u2', 'u3', 'u', 'p', 'cp', 'cx', 'cy', 'cz', 'id', 'x', - 'y', 'z', 'h', 's', 'sdg', 'sx', 'sxdg', 't', 'tdg', 'swap', 'ccx', - 'unitary', 'roerror', 'delay', 'pauli', 'r', 'rx', 'ry', 'rz', 'rxx', - 'ryy', 'rzz', 'rzx', 'csx', 'cswap', 'diagonal', 'initialize' - ]) - if method == 'stabilizer': - return sorted([ - 'id', 'x', 'y', 'z', 'h', 's', 'sdg', 'sx', 'sxdg', 'cx', 'cy', 'cz', - 'swap', 'delay', 'pauli' - ]) - if method == 'extended_stabilizer': - return sorted([ - 'cx', 'cz', 'id', 'x', 'y', 'z', 'h', 's', 'sdg', 'sx', 'sxdg', - 'swap', 'u0', 't', 'tdg', 'u1', 'p', 'ccx', 'ccz', 'delay', 'pauli' - ]) + method = self._options.get("method", None) + if method in [ + "density_matrix", + "density_matrix_gpu", + "density_matrix_custatevec", + "density_matrix_thrust", + ]: + return sorted( + [ + "u1", + "u2", + "u3", + "u", + "p", + "r", + "rx", + "ry", + "rz", + "id", + "x", + "y", + "z", + "h", + "s", + "sdg", + "sx", + "sxdg", + "t", + "tdg", + "swap", + "cx", + "cy", + "cz", + "cp", + "cu1", + "rxx", + "ryy", + "rzz", + "rzx", + "ccx", + "unitary", + "diagonal", + "delay", + "pauli", + "ecr", + ] + ) + if method == "matrix_product_state": + return sorted( + [ + "u1", + "u2", + "u3", + "u", + "p", + "cp", + "cx", + "cy", + "cz", + "id", + "x", + "y", + "z", + "h", + "s", + "sdg", + "sx", + "sxdg", + "t", + "tdg", + "swap", + "ccx", + "unitary", + "roerror", + "delay", + "pauli", + "r", + "rx", + "ry", + "rz", + "rxx", + "ryy", + "rzz", + "rzx", + "csx", + "cswap", + "diagonal", + "initialize", + ] + ) + if method == "stabilizer": + return sorted( + [ + "id", + "x", + "y", + "z", + "h", + "s", + "sdg", + "sx", + "sxdg", + "cx", + "cy", + "cz", + "swap", + "delay", + "pauli", + ] + ) + if method == "extended_stabilizer": + return sorted( + [ + "cx", + "cz", + "id", + "x", + "y", + "z", + "h", + "s", + "sdg", + "sx", + "sxdg", + "swap", + "u0", + "t", + "tdg", + "u1", + "p", + "ccx", + "ccz", + "delay", + "pauli", + ] + ) return QasmSimulator._DEFAULT_BASIS_GATES def _custom_instructions(self): """Return method basis gates and custom instructions""" # pylint: disable = too-many-return-statements - if 'custom_instructions' in self._options_configuration: - return self._options_configuration['custom_instructions'] - - method = self._options.get('method', None) - if method in ['statevector', 'statevector_gpu', - 'statevector_custatevec', 'statevector_thrust']: - return sorted([ - 'quantum_channel', 'qerror_loc', 'roerror', 'kraus', 'save_expval', - 'save_expval_var', 'save_probabilities', 'save_probabilities_dict', - 'save_amplitudes', 'save_amplitudes_sq', 'save_state', - 'save_density_matrix', 'save_statevector', 'save_statevector_dict', - 'set_statevector' - ]) - if method in ['density_matrix', 'density_matrix_gpu', - 'density_matrix_custatevec', 'density_matrix_thrust']: - return sorted([ - 'quantum_channel', 'qerror_loc', 'roerror', 'kraus', 'superop', - 'save_expval', 'save_expval_var', 'save_probabilities', 'save_probabilities_dict', - 'save_state', 'save_density_matrix', 'save_amplitudes_sq', - 'set_statevector', 'set_density_matrix' - ]) - if method == 'matrix_product_state': - return sorted([ - 'quantum_channel', 'qerror_loc', 'roerror', 'kraus', 'save_expval', - 'save_expval_var', 'save_probabilities', 'save_probabilities_dict', - 'save_density_matrix', 'save_state', 'save_statevector', - 'save_amplitudes', 'save_amplitudes_sq', 'save_matrix_product_state', - 'set_matrix_product_state']) - if method == 'stabilizer': - return sorted([ - 'quantum_channel', 'qerror_loc', 'roerror', 'save_expval', - 'save_expval_var', 'save_probabilities', 'save_probabilities_dict', - 'save_amplitudes_sq', 'save_state', 'save_stabilizer', - 'set_stabilizer' - ]) - if method == 'extended_stabilizer': - return sorted([ - 'quantum_channel', 'qerror_loc', 'roerror', - 'save_statevector']) + if "custom_instructions" in self._options_configuration: + return self._options_configuration["custom_instructions"] + + method = self._options.get("method", None) + if method in [ + "statevector", + "statevector_gpu", + "statevector_custatevec", + "statevector_thrust", + ]: + return sorted( + [ + "quantum_channel", + "qerror_loc", + "roerror", + "kraus", + "save_expval", + "save_expval_var", + "save_probabilities", + "save_probabilities_dict", + "save_amplitudes", + "save_amplitudes_sq", + "save_state", + "save_density_matrix", + "save_statevector", + "save_statevector_dict", + "set_statevector", + ] + ) + if method in [ + "density_matrix", + "density_matrix_gpu", + "density_matrix_custatevec", + "density_matrix_thrust", + ]: + return sorted( + [ + "quantum_channel", + "qerror_loc", + "roerror", + "kraus", + "superop", + "save_expval", + "save_expval_var", + "save_probabilities", + "save_probabilities_dict", + "save_state", + "save_density_matrix", + "save_amplitudes_sq", + "set_statevector", + "set_density_matrix", + ] + ) + if method == "matrix_product_state": + return sorted( + [ + "quantum_channel", + "qerror_loc", + "roerror", + "kraus", + "save_expval", + "save_expval_var", + "save_probabilities", + "save_probabilities_dict", + "save_density_matrix", + "save_state", + "save_statevector", + "save_amplitudes", + "save_amplitudes_sq", + "save_matrix_product_state", + "set_matrix_product_state", + ] + ) + if method == "stabilizer": + return sorted( + [ + "quantum_channel", + "qerror_loc", + "roerror", + "save_expval", + "save_expval_var", + "save_probabilities", + "save_probabilities_dict", + "save_amplitudes_sq", + "save_state", + "save_stabilizer", + "set_stabilizer", + ] + ) + if method == "extended_stabilizer": + return sorted(["quantum_channel", "qerror_loc", "roerror", "save_statevector"]) return QasmSimulator._DEFAULT_CUSTOM_INSTR def _set_method_config(self, method=None): """Set non-basis gate options when setting method""" # Update configuration description and number of qubits - if method in ['statevector', 'statevector_gpu', - 'statevector_custatevec', 'statevector_thrust']: - description = 'A C++ statevector simulator with noise' + if method in [ + "statevector", + "statevector_gpu", + "statevector_custatevec", + "statevector_thrust", + ]: + description = "A C++ statevector simulator with noise" n_qubits = MAX_QUBITS_STATEVECTOR - elif method in ['density_matrix', 'density_matrix_gpu', - 'density_matrix_custatevec', 'density_matrix_thrust']: - description = 'A C++ density matrix simulator with noise' + elif method in [ + "density_matrix", + "density_matrix_gpu", + "density_matrix_custatevec", + "density_matrix_thrust", + ]: + description = "A C++ density matrix simulator with noise" n_qubits = MAX_QUBITS_STATEVECTOR // 2 - elif method == 'matrix_product_state': - description = 'A C++ matrix product state simulator with noise' + elif method == "matrix_product_state": + description = "A C++ matrix product state simulator with noise" n_qubits = 63 # TODO: not sure what to put here? - elif method == 'stabilizer': - description = 'A C++ Clifford stabilizer simulator with noise' + elif method == "stabilizer": + description = "A C++ Clifford stabilizer simulator with noise" n_qubits = 10000 # TODO: estimate from memory - elif method == 'extended_stabilizer': - description = 'A C++ Clifford+T extended stabilizer simulator with noise' + elif method == "extended_stabilizer": + description = "A C++ Clifford+T extended stabilizer simulator with noise" n_qubits = 63 # TODO: estimate from memory else: # Clear options to default description = None n_qubits = None - self._set_configuration_option('description', description) - self._set_configuration_option('n_qubits', n_qubits) + self._set_configuration_option("description", description) + self._set_configuration_option("n_qubits", n_qubits) diff --git a/qiskit_aer/backends/statevector_simulator.py b/qiskit_aer/backends/statevector_simulator.py index 93564bb723..e7affcf1c7 100644 --- a/qiskit_aer/backends/statevector_simulator.py +++ b/qiskit_aer/backends/statevector_simulator.py @@ -23,15 +23,18 @@ from ..aererror import AerError from ..version import __version__ from .aerbackend import AerBackend -from .backend_utils import (cpp_execute_qobj, available_devices, - MAX_QUBITS_STATEVECTOR, - LEGACY_METHOD_MAP, - add_final_save_instruction, - cpp_execute_circuits, - map_legacy_method_options, - map_legacy_method_config, - add_final_save_op, - ) +from .backend_utils import ( + cpp_execute_qobj, + available_devices, + MAX_QUBITS_STATEVECTOR, + LEGACY_METHOD_MAP, + add_final_save_instruction, + cpp_execute_circuits, + map_legacy_method_options, + map_legacy_method_config, + add_final_save_op, +) + # pylint: disable=import-error, no-name-in-module from .controller_wrappers import aer_controller_execute @@ -135,73 +138,134 @@ class StatevectorSimulator(AerBackend): """ _DEFAULT_CONFIGURATION = { - 'backend_name': 'statevector_simulator', - 'backend_version': __version__, - 'n_qubits': MAX_QUBITS_STATEVECTOR, - 'url': 'https://github.com/Qiskit/qiskit-aer', - 'simulator': True, - 'local': True, - 'conditional': True, - 'open_pulse': False, - 'memory': True, - 'max_shots': int(1e6), # Note that this backend will only ever + "backend_name": "statevector_simulator", + "backend_version": __version__, + "n_qubits": MAX_QUBITS_STATEVECTOR, + "url": "https://github.com/Qiskit/qiskit-aer", + "simulator": True, + "local": True, + "conditional": True, + "open_pulse": False, + "memory": True, + "max_shots": int(1e6), # Note that this backend will only ever # perform a single shot. This value is just # so that the default shot value for execute # will not raise an error when trying to run # a simulation - 'description': 'A C++ statevector circuit simulator', - 'coupling_map': None, - 'basis_gates': sorted([ - 'u1', 'u2', 'u3', 'u', 'p', 'r', 'rx', 'ry', 'rz', 'id', 'x', - 'y', 'z', 'h', 's', 'sdg', 'sx', 'sxdg', 't', 'tdg', 'swap', 'cx', - 'cy', 'cz', 'csx', 'cu', 'cp', 'cu1', 'cu2', 'cu3', 'rxx', 'ryy', - 'rzz', 'rzx', 'ccx', 'cswap', 'mcx', 'mcy', 'mcz', 'mcsx', - 'mcu', 'mcp', 'mcphase', 'mcu1', 'mcu2', 'mcu3', 'mcrx', 'mcry', 'mcrz', - 'mcr', 'mcswap', 'unitary', 'diagonal', 'multiplexer', - 'initialize', 'delay', 'pauli' - ]), - 'custom_instructions': sorted([ - 'kraus', 'roerror', 'quantum_channel', 'qerror_loc', - 'save_expval', 'save_density_matrix', 'save_statevector', - 'save_probs', 'save_probs_ket', 'save_amplitudes', - 'save_amplitudes_sq', 'save_state', 'set_statevector' - ]), - 'gates': [] + "description": "A C++ statevector circuit simulator", + "coupling_map": None, + "basis_gates": sorted( + [ + "u1", + "u2", + "u3", + "u", + "p", + "r", + "rx", + "ry", + "rz", + "id", + "x", + "y", + "z", + "h", + "s", + "sdg", + "sx", + "sxdg", + "t", + "tdg", + "swap", + "cx", + "cy", + "cz", + "csx", + "cu", + "cp", + "cu1", + "cu2", + "cu3", + "rxx", + "ryy", + "rzz", + "rzx", + "ccx", + "cswap", + "mcx", + "mcy", + "mcz", + "mcsx", + "mcu", + "mcp", + "mcphase", + "mcu1", + "mcu2", + "mcu3", + "mcrx", + "mcry", + "mcrz", + "mcr", + "mcswap", + "unitary", + "diagonal", + "multiplexer", + "initialize", + "delay", + "pauli", + ] + ), + "custom_instructions": sorted( + [ + "kraus", + "roerror", + "quantum_channel", + "qerror_loc", + "save_expval", + "save_density_matrix", + "save_statevector", + "save_probs", + "save_probs_ket", + "save_amplitudes", + "save_amplitudes_sq", + "save_state", + "set_statevector", + ] + ), + "gates": [], } - _SIMULATION_DEVICES = ('CPU', 'GPU', 'Thrust') + _SIMULATION_DEVICES = ("CPU", "GPU", "Thrust") _AVAILABLE_DEVICES = None - def __init__(self, - configuration=None, - properties=None, - provider=None, - **backend_options): - - warn('The `StatevectorSimulator` backend will be deprecated in the' - ' future. It has been superseded by the `AerSimulator`' - ' backend. To obtain legacy functionality initialize with' - ' `AerSimulator(method="statevector")` and append run circuits' - ' with the `save_state` instruction.', PendingDeprecationWarning) + def __init__(self, configuration=None, properties=None, provider=None, **backend_options): + warn( + "The `StatevectorSimulator` backend will be deprecated in the" + " future. It has been superseded by the `AerSimulator`" + " backend. To obtain legacy functionality initialize with" + ' `AerSimulator(method="statevector")` and append run circuits' + " with the `save_state` instruction.", + PendingDeprecationWarning, + ) self._controller = aer_controller_execute() if StatevectorSimulator._AVAILABLE_DEVICES is None: StatevectorSimulator._AVAILABLE_DEVICES = available_devices( - self._controller, StatevectorSimulator._SIMULATION_DEVICES) + self._controller, StatevectorSimulator._SIMULATION_DEVICES + ) if configuration is None: configuration = QasmBackendConfiguration.from_dict( - StatevectorSimulator._DEFAULT_CONFIGURATION) + StatevectorSimulator._DEFAULT_CONFIGURATION + ) else: configuration.open_pulse = False super().__init__( - configuration, - properties=properties, - provider=provider, - backend_options=backend_options) + configuration, properties=properties, provider=provider, backend_options=backend_options + ) @classmethod def _default_options(cls): @@ -225,31 +289,37 @@ def _default_options(cls): fusion_max_qubit=5, fusion_threshold=14, # statevector options - statevector_parallel_threshold=14) + statevector_parallel_threshold=14, + ) def set_option(self, key, value): if key == "method": # Handle deprecation of method option for device option - warn("The method option of the `StatevectorSimulator` has been" - " deprecated as of qiskit-aer 0.9.0. To run a GPU statevector" - " simulation use the option `device='GPU'` instead", - DeprecationWarning) + warn( + "The method option of the `StatevectorSimulator` has been" + " deprecated as of qiskit-aer 0.9.0. To run a GPU statevector" + " simulation use the option `device='GPU'` instead", + DeprecationWarning, + ) if value in LEGACY_METHOD_MAP: value, device = LEGACY_METHOD_MAP[value] self.set_option("device", device) if value != "statevector": raise AerError( - "only the 'statevector' method is supported for the StatevectorSimulator") + "only the 'statevector' method is supported for the StatevectorSimulator" + ) return super().set_option(key, value) def available_methods(self): """Return the available simulation methods.""" - warn("The `available_methods` method of the StatevectorSimulator" - " is deprecated as of qiskit-aer 0.9.0 as this simulator only" - " supports a single method. To check if GPU simulation is available" - " use the `available_devices` method instead.", - DeprecationWarning) + warn( + "The `available_methods` method of the StatevectorSimulator" + " is deprecated as of qiskit-aer 0.9.0 as this simulator only" + " supports a single method. To check if GPU simulation is available" + " use the `available_devices` method instead.", + DeprecationWarning, + ) return ("statevector",) def available_devices(self): @@ -272,8 +342,7 @@ def _execute_qobj(self, qobj): return cpp_execute_qobj(self._controller, qobj) def _execute_circuits(self, aer_circuits, noise_model, config): - """Execute circuits on the backend. - """ + """Execute circuits on the backend.""" config = map_legacy_method_config(config) aer_circuits = add_final_save_op(aer_circuits, "statevector") return cpp_execute_circuits(self._controller, aer_circuits, noise_model, config) @@ -286,15 +355,16 @@ def _validate(self, qobj): 2. Check number of qubits will fit in local memory. """ name = self.name() - if getattr(qobj.config, 'noise_model', None) is not None: + if getattr(qobj.config, "noise_model", None) is not None: raise AerError(f"{name} does not support noise.") n_qubits = qobj.config.n_qubits max_qubits = self.configuration().n_qubits if n_qubits > max_qubits: raise AerError( - f'Number of qubits ({n_qubits}) is greater than max ({max_qubits}) ' - f'for "{name}" with {int(local_hardware_info()["memory"])} GB system memory.') + f"Number of qubits ({n_qubits}) is greater than max ({max_qubits}) " + f'for "{name}" with {int(local_hardware_info()["memory"])} GB system memory.' + ) if qobj.config.shots != 1: logger.info('"%s" only supports 1 shot. Setting shots=1.', name) @@ -302,8 +372,10 @@ def _validate(self, qobj): for experiment in qobj.experiments: exp_name = experiment.header.name - if getattr(experiment.config, 'shots', 1) != 1: + if getattr(experiment.config, "shots", 1) != 1: logger.info( - '"%s" only supports 1 shot. ' - 'Setting shots=1 for circuit "%s".', name, exp_name) + '"%s" only supports 1 shot. ' 'Setting shots=1 for circuit "%s".', + name, + exp_name, + ) experiment.config.shots = 1 diff --git a/qiskit_aer/backends/unitary_simulator.py b/qiskit_aer/backends/unitary_simulator.py index 7971391f3d..190a3eb508 100644 --- a/qiskit_aer/backends/unitary_simulator.py +++ b/qiskit_aer/backends/unitary_simulator.py @@ -24,15 +24,18 @@ from ..aererror import AerError from ..version import __version__ from .aerbackend import AerBackend -from .backend_utils import (cpp_execute_qobj, - cpp_execute_circuits, - available_devices, - MAX_QUBITS_STATEVECTOR, - LEGACY_METHOD_MAP, - add_final_save_instruction, - map_legacy_method_options, - add_final_save_op, - map_legacy_method_config) +from .backend_utils import ( + cpp_execute_qobj, + cpp_execute_circuits, + available_devices, + MAX_QUBITS_STATEVECTOR, + LEGACY_METHOD_MAP, + add_final_save_instruction, + map_legacy_method_options, + add_final_save_op, + map_legacy_method_config, +) + # pylint: disable=import-error, no-name-in-module from .controller_wrappers import aer_controller_execute @@ -139,66 +142,117 @@ class UnitarySimulator(AerBackend): """ _DEFAULT_CONFIGURATION = { - 'backend_name': 'unitary_simulator', - 'backend_version': __version__, - 'n_qubits': MAX_QUBITS_STATEVECTOR // 2, - 'url': 'https://github.com/Qiskit/qiskit-aer', - 'simulator': True, - 'local': True, - 'conditional': False, - 'open_pulse': False, - 'memory': False, - 'max_shots': int(1e6), # Note that this backend will only ever - # perform a single shot. This value is just - # so that the default shot value for execute - # will not raise an error when trying to run - # a simulation - 'description': 'A C++ unitary circuit simulator', - 'coupling_map': None, - 'basis_gates': sorted([ - 'u1', 'u2', 'u3', 'u', 'p', 'r', 'rx', 'ry', 'rz', 'id', 'x', - 'y', 'z', 'h', 's', 'sdg', 'sx', 'sxdg', 't', 'tdg', 'swap', 'cx', - 'cy', 'cz', 'csx', 'cu', 'cp', 'cu1', 'cu2', 'cu3', 'rxx', 'ryy', - 'rzz', 'rzx', 'ccx', 'cswap', 'mcx', 'mcy', 'mcz', 'mcsx', - 'mcu', 'mcp', 'mcphase', 'mcu1', 'mcu2', 'mcu3', 'mcrx', 'mcry', 'mcrz', - 'mcr', 'mcswap', 'unitary', 'diagonal', 'multiplexer', 'delay', 'pauli', - ]), - 'custom_instructions': sorted(['save_unitary', 'save_state', 'set_unitary']), - 'gates': [] + "backend_name": "unitary_simulator", + "backend_version": __version__, + "n_qubits": MAX_QUBITS_STATEVECTOR // 2, + "url": "https://github.com/Qiskit/qiskit-aer", + "simulator": True, + "local": True, + "conditional": False, + "open_pulse": False, + "memory": False, + "max_shots": int(1e6), # Note that this backend will only ever + # perform a single shot. This value is just + # so that the default shot value for execute + # will not raise an error when trying to run + # a simulation + "description": "A C++ unitary circuit simulator", + "coupling_map": None, + "basis_gates": sorted( + [ + "u1", + "u2", + "u3", + "u", + "p", + "r", + "rx", + "ry", + "rz", + "id", + "x", + "y", + "z", + "h", + "s", + "sdg", + "sx", + "sxdg", + "t", + "tdg", + "swap", + "cx", + "cy", + "cz", + "csx", + "cu", + "cp", + "cu1", + "cu2", + "cu3", + "rxx", + "ryy", + "rzz", + "rzx", + "ccx", + "cswap", + "mcx", + "mcy", + "mcz", + "mcsx", + "mcu", + "mcp", + "mcphase", + "mcu1", + "mcu2", + "mcu3", + "mcrx", + "mcry", + "mcrz", + "mcr", + "mcswap", + "unitary", + "diagonal", + "multiplexer", + "delay", + "pauli", + ] + ), + "custom_instructions": sorted(["save_unitary", "save_state", "set_unitary"]), + "gates": [], } - _SIMULATION_DEVICES = ('CPU', 'GPU', 'Thrust') + _SIMULATION_DEVICES = ("CPU", "GPU", "Thrust") _AVAILABLE_DEVICES = None - def __init__(self, - configuration=None, - properties=None, - provider=None, - **backend_options): - - warn('The `UnitarySimulator` backend will be deprecated in the' - ' future. It has been superseded by the `AerSimulator`' - ' backend. To obtain legacy functionality initialize with' - ' `AerSimulator(method="unitary")` and append run circuits' - ' with the `save_state` instruction.', PendingDeprecationWarning) + def __init__(self, configuration=None, properties=None, provider=None, **backend_options): + warn( + "The `UnitarySimulator` backend will be deprecated in the" + " future. It has been superseded by the `AerSimulator`" + " backend. To obtain legacy functionality initialize with" + ' `AerSimulator(method="unitary")` and append run circuits' + " with the `save_state` instruction.", + PendingDeprecationWarning, + ) self._controller = aer_controller_execute() if UnitarySimulator._AVAILABLE_DEVICES is None: UnitarySimulator._AVAILABLE_DEVICES = available_devices( - self._controller, UnitarySimulator._SIMULATION_DEVICES) + self._controller, UnitarySimulator._SIMULATION_DEVICES + ) if configuration is None: configuration = QasmBackendConfiguration.from_dict( - UnitarySimulator._DEFAULT_CONFIGURATION) + UnitarySimulator._DEFAULT_CONFIGURATION + ) else: configuration.open_pulse = False - super().__init__(configuration, - properties=properties, - provider=provider, - backend_options=backend_options) + super().__init__( + configuration, properties=properties, provider=provider, backend_options=backend_options + ) @classmethod def _default_options(cls): @@ -224,31 +278,35 @@ def _default_options(cls): blocking_qubits=None, blocking_enable=False, # statevector options - statevector_parallel_threshold=14) + statevector_parallel_threshold=14, + ) def set_option(self, key, value): if key == "method": # Handle deprecation of method option for device option - warn("The method option of the `UnitarySimulator` has been" - " deprecated as of qiskit-aer 0.9.0. To run a GPU statevector" - " simulation use the option `device='GPU'` instead", - DeprecationWarning) + warn( + "The method option of the `UnitarySimulator` has been" + " deprecated as of qiskit-aer 0.9.0. To run a GPU statevector" + " simulation use the option `device='GPU'` instead", + DeprecationWarning, + ) if value in LEGACY_METHOD_MAP: value, device = LEGACY_METHOD_MAP[value] self.set_option("device", device) if value != "unitary": - raise AerError( - "only the 'unitary' method is supported for the UnitarySimulator") + raise AerError("only the 'unitary' method is supported for the UnitarySimulator") return super().set_option(key, value) def available_methods(self): """Return the available simulation methods.""" - warn("The `available_methods` method of the UnitarySimulator" - " is deprecated as of qiskit-aer 0.9.0 as this simulator only" - " supports a single method. To check if GPU simulation is available" - " use the `available_devices` method instead.", - DeprecationWarning) + warn( + "The `available_methods` method of the UnitarySimulator" + " is deprecated as of qiskit-aer 0.9.0 as this simulator only" + " supports a single method. To check if GPU simulation is available" + " use the `available_devices` method instead.", + DeprecationWarning, + ) return ("unitary",) def available_devices(self): @@ -271,8 +329,7 @@ def _execute_qobj(self, qobj): return cpp_execute_qobj(self._controller, qobj) def _execute_circuits(self, aer_circuits, noise_model, config): - """Execute circuits on the backend. - """ + """Execute circuits on the backend.""" config = map_legacy_method_config(config) aer_circuits = add_final_save_op(aer_circuits, "unitary") return cpp_execute_circuits(self._controller, aer_circuits, noise_model, config) @@ -285,27 +342,31 @@ def _validate(self, qobj): 3. Check number of qubits will fit in local memory. """ name = self.name() - if getattr(qobj.config, 'noise_model', None) is not None: + if getattr(qobj.config, "noise_model", None) is not None: raise AerError(f"{name} does not support noise.") n_qubits = qobj.config.n_qubits max_qubits = self.configuration().n_qubits if n_qubits > max_qubits: raise AerError( - f'Number of qubits ({n_qubits}) is greater than ' + f"Number of qubits ({n_qubits}) is greater than " f'max ({max_qubits}) for "{name}" with ' - f"{int(local_hardware_info()['memory'])} 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) qobj.config.shots = 1 for experiment in qobj.experiments: exp_name = experiment.header.name - if getattr(experiment.config, 'shots', 1) != 1: + if getattr(experiment.config, "shots", 1) != 1: logger.info( - '"%s" only supports 1 shot. ' - 'Setting shots=1 for circuit "%s".', name, exp_name) + '"%s" only supports 1 shot. ' 'Setting shots=1 for circuit "%s".', + name, + exp_name, + ) experiment.config.shots = 1 for operation in experiment.instructions: - if operation.name in ['measure', 'reset']: + if operation.name in ["measure", "reset"]: raise AerError( - f'Unsupported {name} instruction {operation.name} in circuit {exp_name}') + f"Unsupported {name} instruction {operation.name} in circuit {exp_name}" + ) diff --git a/qiskit_aer/backends/wrappers/aer_circuit_binding.hpp b/qiskit_aer/backends/wrappers/aer_circuit_binding.hpp index ffd7fe37a9..6aaf9a8cba 100644 --- a/qiskit_aer/backends/wrappers/aer_circuit_binding.hpp +++ b/qiskit_aer/backends/wrappers/aer_circuit_binding.hpp @@ -20,34 +20,33 @@ DISABLE_WARNING_PUSH #include DISABLE_WARNING_POP #if defined(_MSC_VER) - #undef snprintf +#undef snprintf #endif #include #include "framework/matrix.hpp" -#include "framework/python_parser.hpp" -#include "framework/pybind_json.hpp" #include "framework/pybind_casts.hpp" +#include "framework/pybind_json.hpp" +#include "framework/python_parser.hpp" -#include "framework/types.hpp" #include "framework/results/pybind_result.hpp" +#include "framework/types.hpp" #include "framework/circuit.hpp" namespace py = pybind11; using namespace AER; -template +template void bind_aer_circuit(MODULE m) { py::class_ aer_circuit(m, "AerCircuit"); aer_circuit.def(py::init()); aer_circuit.def("__repr__", [](const Circuit &circ) { std::stringstream ss; ss << "Circuit(" - << "qubit=" << circ.num_qubits - << ", num_memory=" << circ.num_memory - << ", num_registers=" << circ.num_registers; + << "qubit=" << circ.num_qubits << ", num_memory=" << circ.num_memory + << ", num_registers=" << circ.num_registers; ss << ", ops={"; for (auto i = 0; i < circ.ops.size(); ++i) @@ -57,10 +56,8 @@ void bind_aer_circuit(MODULE m) { ss << "," << circ.ops[i]; ss << "}" - << ", shots=" << circ.shots - << ", seed=" << circ.seed - << ", global_phase_angle=" << circ.global_phase_angle - ; + << ", shots=" << circ.shots << ", seed=" << circ.seed + << ", global_phase_angle=" << circ.global_phase_angle; ss << ")"; return ss.str(); }); @@ -71,10 +68,10 @@ void bind_aer_circuit(MODULE m) { aer_circuit.def_readwrite("seed", &Circuit::seed); aer_circuit.def_readwrite("ops", &Circuit::ops); aer_circuit.def_readwrite("global_phase_angle", &Circuit::global_phase_angle); - aer_circuit.def("set_header", [aer_circuit](Circuit &circ, - const py::handle& header) { - circ.header = header; - }); + aer_circuit.def("set_header", + [aer_circuit](Circuit &circ, const py::handle &header) { + circ.header = header; + }); aer_circuit.def("bfunc", &Circuit::bfunc); aer_circuit.def("gate", &Circuit::gate); aer_circuit.def("diagonal", &Circuit::diagonal); @@ -88,17 +85,18 @@ void bind_aer_circuit(MODULE m) { aer_circuit.def("save_expval", &Circuit::save_expval); aer_circuit.def("initialize", &Circuit::initialize); aer_circuit.def("set_statevector", &Circuit::set_statevector); - aer_circuit.def("set_density_matrix", &Circuit::set_density_matrix); + aer_circuit.def("set_density_matrix", + &Circuit::set_density_matrix); aer_circuit.def("set_unitary", &Circuit::set_unitary); aer_circuit.def("set_superop", &Circuit::set_superop); - aer_circuit.def("set_matrix_product_state", &Circuit::set_matrix_product_state); + aer_circuit.def("set_matrix_product_state", + &Circuit::set_matrix_product_state); aer_circuit.def("set_clifford", &Circuit::set_clifford); aer_circuit.def("jump", &Circuit::jump); aer_circuit.def("mark", &Circuit::mark); aer_circuit.def("measure", &Circuit::measure); aer_circuit.def("reset", &Circuit::reset); aer_circuit.def("set_qerror_loc", &Circuit::set_qerror_loc); - } #endif \ No newline at end of file diff --git a/qiskit_aer/backends/wrappers/aer_controller_binding.hpp b/qiskit_aer/backends/wrappers/aer_controller_binding.hpp index a04a6a8430..d862c8690f 100644 --- a/qiskit_aer/backends/wrappers/aer_controller_binding.hpp +++ b/qiskit_aer/backends/wrappers/aer_controller_binding.hpp @@ -20,16 +20,16 @@ DISABLE_WARNING_PUSH #include DISABLE_WARNING_POP #if defined(_MSC_VER) - #undef snprintf +#undef snprintf #endif #include #include "framework/matrix.hpp" -#include "framework/python_parser.hpp" #include "framework/pybind_casts.hpp" -#include "framework/types.hpp" +#include "framework/python_parser.hpp" #include "framework/results/pybind_result.hpp" +#include "framework/types.hpp" #include "controllers/aer_controller.hpp" @@ -38,421 +38,546 @@ DISABLE_WARNING_POP namespace py = pybind11; using namespace AER; -template +template class ControllerExecutor { public: - ControllerExecutor() = default; - py::object operator()(const py::handle &qobj) { + ControllerExecutor() = default; + py::object operator()(const py::handle &qobj) { #ifdef TEST_JSON // Convert input qobj to json to test standalone data reading - return AerToPy::to_python(controller_execute(json_t(qobj))); + return AerToPy::to_python(controller_execute(json_t(qobj))); #else - return AerToPy::to_python(controller_execute(qobj)); + return AerToPy::to_python(controller_execute(qobj)); #endif - } + } - py::object execute(std::vector &circuits, Noise::NoiseModel &noise_model, AER::Config& config) const { - return AerToPy::to_python(controller_execute(circuits, noise_model, config)); - } + py::object execute(std::vector &circuits, + Noise::NoiseModel &noise_model, + AER::Config &config) const { + return AerToPy::to_python( + controller_execute(circuits, noise_model, config)); + } }; -template +template py::tuple write_value(size_t index, const optional &v) { - return py::make_tuple(v.has_value(), v.value()); + return py::make_tuple(v.has_value(), v.value()); } -template +template T write_value(size_t index, const T &v) { - return v; + return v; } -template +template void read_value(const py::tuple &t, size_t index, optional &v) { - if (t[index].cast()[0].cast()) - v.value(t[index].cast()[1].cast()); + if (t[index].cast()[0].cast()) + v.value(t[index].cast()[1].cast()); } -template +template void read_value(const py::tuple &t, size_t index, T &v) { - v = t[index].cast(); + v = t[index].cast(); } -template +template void bind_aer_controller(MODULE m) { - py::class_ > aer_ctrl (m, "aer_controller_execute"); - aer_ctrl.def(py::init<>()); - aer_ctrl.def("__call__", &ControllerExecutor::operator()); - aer_ctrl.def("__reduce__", [aer_ctrl](const ControllerExecutor &self) { - return py::make_tuple(aer_ctrl, py::tuple()); - }); - aer_ctrl.def("execute", [aer_ctrl](ControllerExecutor &self, - std::vector &circuits, - py::object noise_model, - AER::Config &config) { - - Noise::NoiseModel noise_model_native; - if (noise_model) - noise_model_native.load_from_json(noise_model); + py::class_> aer_ctrl(m, + "aer_controller_execute"); + aer_ctrl.def(py::init<>()); + aer_ctrl.def("__call__", &ControllerExecutor::operator()); + aer_ctrl.def("__reduce__", + [aer_ctrl](const ControllerExecutor &self) { + return py::make_tuple(aer_ctrl, py::tuple()); + }); + aer_ctrl.def("execute", + [aer_ctrl](ControllerExecutor &self, + std::vector &circuits, + py::object noise_model, AER::Config &config) { + Noise::NoiseModel noise_model_native; + if (noise_model) + noise_model_native.load_from_json(noise_model); - return self.execute(circuits, noise_model_native, config); - }); + return self.execute(circuits, noise_model_native, config); + }); - py::class_ aer_config(m, "AerConfig"); - aer_config.def(py::init()); - aer_config.def_readwrite("shots", &Config::shots); - aer_config.def_readwrite("method", &Config::method); - aer_config.def_readwrite("device", &Config::device); - aer_config.def_readwrite("precision", &Config::precision); - aer_config.def_readwrite("enable_truncation", &Config::enable_truncation); - aer_config.def_readwrite("zero_threshold", &Config::zero_threshold); - aer_config.def_readwrite("validation_threshold", &Config::validation_threshold); - aer_config.def_property("max_parallel_threads", - [](const Config &config) { return config.max_parallel_threads.val;}, - [](Config &config, uint_t val) { config.max_parallel_threads.value(val);}); - aer_config.def_property("max_parallel_experiments", - [](const Config &config) { return config.max_parallel_experiments.val;}, - [](Config &config, uint_t val) { config.max_parallel_experiments.value(val);}); - aer_config.def_property("max_parallel_shots", - [](const Config &config) { return config.max_parallel_shots.val;}, - [](Config &config, uint_t val) { config.max_parallel_shots.value(val);}); - aer_config.def_property("max_memory_mb", - [](const Config &config) { return config.max_memory_mb.val;}, - [](Config &config, uint_t val) { config.max_memory_mb.value(val);}); - aer_config.def_readwrite("fusion_enable", &Config::fusion_enable); - aer_config.def_readwrite("fusion_verbose", &Config::fusion_verbose); - aer_config.def_property("fusion_max_qubit", - [](const Config &config) { return config.fusion_max_qubit.val;}, - [](Config &config, uint_t val) { config.fusion_max_qubit.value(val);}); - aer_config.def_property("fusion_threshold", - [](const Config &config) { return config.fusion_threshold.val;}, - [](Config &config, uint_t val) { config.fusion_threshold.value(val);}); - aer_config.def_property("accept_distributed_results", - [](const Config &config) { return config.accept_distributed_results.val;}, - [](Config &config, bool val) { config.accept_distributed_results.value(val);}); - aer_config.def_property("memory", - [](const Config &config) { return config.memory.val;}, - [](Config &config, bool val) { config.memory.value(val);}); - aer_config.def_property("seed_simulator", - [](const Config &config) { return config.seed_simulator.val;}, - [](Config &config, int_t val) { config.seed_simulator.value(val);}); - // # cuStateVec (cuQuantum) option - aer_config.def_property("cuStateVec_enable", - [](const Config &config) { return config.cuStateVec_enable.val;}, - [](Config &config, bool val) { config.cuStateVec_enable.value(val);}); - // # cache blocking for multi-GPUs/MPI options - aer_config.def_property("blocking_qubits", - [](const Config &config) { return config.blocking_qubits.val;}, - [](Config &config, uint_t val) { config.blocking_qubits.value(val);}); - aer_config.def_readwrite("blocking_enable", &Config::blocking_enable); - aer_config.def_property("chunk_swap_buffer_qubits", - [](const Config &config) { return config.chunk_swap_buffer_qubits.val;}, - [](Config &config, uint_t val) { config.chunk_swap_buffer_qubits.value(val);}); - // # multi-shots optimization options (GPU only) - aer_config.def_readwrite("batched_shots_gpu", &Config::batched_shots_gpu); - aer_config.def_readwrite("batched_shots_gpu_max_qubits", &Config::batched_shots_gpu_max_qubits); - aer_config.def_property("num_threads_per_device", - [](const Config &config) { return config.num_threads_per_device.val;}, - [](Config &config, uint_t val) { config.num_threads_per_device.value(val);}); - // # statevector options - aer_config.def_readwrite("statevector_parallel_threshold", &Config::statevector_parallel_threshold); - aer_config.def_readwrite("statevector_sample_measure_opt", &Config::statevector_sample_measure_opt); - // # stabilizer options - aer_config.def_readwrite("stabilizer_max_snapshot_probabilities", &Config::stabilizer_max_snapshot_probabilities); - // # extended stabilizer options - aer_config.def_readwrite("extended_stabilizer_sampling_method", &Config::extended_stabilizer_sampling_method); - aer_config.def_readwrite("extended_stabilizer_metropolis_mixing_time", &Config::extended_stabilizer_metropolis_mixing_time); - aer_config.def_readwrite("extended_stabilizer_approximation_error", &Config::extended_stabilizer_approximation_error); - aer_config.def_readwrite("extended_stabilizer_norm_estimation_samples", &Config::extended_stabilizer_norm_estimation_samples); - aer_config.def_readwrite("extended_stabilizer_norm_estimation_repetitions", &Config::extended_stabilizer_norm_estimation_repetitions); - aer_config.def_readwrite("extended_stabilizer_parallel_threshold", &Config::extended_stabilizer_parallel_threshold); - aer_config.def_readwrite("extended_stabilizer_probabilities_snapshot_samples", &Config::extended_stabilizer_probabilities_snapshot_samples); - // # MPS options - aer_config.def_readwrite("matrix_product_state_truncation_threshold", &Config::matrix_product_state_truncation_threshold); - aer_config.def_property("matrix_product_state_max_bond_dimension", - [](const Config &config) { return config.matrix_product_state_max_bond_dimension.val;}, - [](Config &config, uint_t val) { config.matrix_product_state_max_bond_dimension.value(val);}); - aer_config.def_readwrite("mps_sample_measure_algorithm", &Config::mps_sample_measure_algorithm); - aer_config.def_readwrite("mps_log_data", &Config::mps_log_data); - aer_config.def_readwrite("mps_swap_direction", &Config::mps_swap_direction); - aer_config.def_readwrite("chop_threshold", &Config::chop_threshold); - aer_config.def_readwrite("mps_parallel_threshold", &Config::mps_parallel_threshold); - aer_config.def_readwrite("mps_omp_threads", &Config::mps_omp_threads); - // # tensor network options - aer_config.def_readwrite("tensor_network_num_sampling_qubits", &Config::tensor_network_num_sampling_qubits); - aer_config.def_readwrite("use_cuTensorNet_autotuning", &Config::use_cuTensorNet_autotuning); + py::class_ aer_config(m, "AerConfig"); + aer_config.def(py::init()); + aer_config.def_readwrite("shots", &Config::shots); + aer_config.def_readwrite("method", &Config::method); + aer_config.def_readwrite("device", &Config::device); + aer_config.def_readwrite("precision", &Config::precision); + aer_config.def_readwrite("enable_truncation", &Config::enable_truncation); + aer_config.def_readwrite("zero_threshold", &Config::zero_threshold); + aer_config.def_readwrite("validation_threshold", + &Config::validation_threshold); + aer_config.def_property( + "max_parallel_threads", + [](const Config &config) { return config.max_parallel_threads.val; }, + [](Config &config, uint_t val) { + config.max_parallel_threads.value(val); + }); + aer_config.def_property( + "max_parallel_experiments", + [](const Config &config) { return config.max_parallel_experiments.val; }, + [](Config &config, uint_t val) { + config.max_parallel_experiments.value(val); + }); + aer_config.def_property( + "max_parallel_shots", + [](const Config &config) { return config.max_parallel_shots.val; }, + [](Config &config, uint_t val) { config.max_parallel_shots.value(val); }); + aer_config.def_property( + "max_memory_mb", + [](const Config &config) { return config.max_memory_mb.val; }, + [](Config &config, uint_t val) { config.max_memory_mb.value(val); }); + aer_config.def_readwrite("fusion_enable", &Config::fusion_enable); + aer_config.def_readwrite("fusion_verbose", &Config::fusion_verbose); + aer_config.def_property( + "fusion_max_qubit", + [](const Config &config) { return config.fusion_max_qubit.val; }, + [](Config &config, uint_t val) { config.fusion_max_qubit.value(val); }); + aer_config.def_property( + "fusion_threshold", + [](const Config &config) { return config.fusion_threshold.val; }, + [](Config &config, uint_t val) { config.fusion_threshold.value(val); }); + aer_config.def_property( + "accept_distributed_results", + [](const Config &config) { + return config.accept_distributed_results.val; + }, + [](Config &config, bool val) { + config.accept_distributed_results.value(val); + }); + aer_config.def_property( + "memory", [](const Config &config) { return config.memory.val; }, + [](Config &config, bool val) { config.memory.value(val); }); + aer_config.def_property( + "seed_simulator", + [](const Config &config) { return config.seed_simulator.val; }, + [](Config &config, int_t val) { config.seed_simulator.value(val); }); + // # cuStateVec (cuQuantum) option + aer_config.def_property( + "cuStateVec_enable", + [](const Config &config) { return config.cuStateVec_enable.val; }, + [](Config &config, bool val) { config.cuStateVec_enable.value(val); }); + // # cache blocking for multi-GPUs/MPI options + aer_config.def_property( + "blocking_qubits", + [](const Config &config) { return config.blocking_qubits.val; }, + [](Config &config, uint_t val) { config.blocking_qubits.value(val); }); + aer_config.def_readwrite("blocking_enable", &Config::blocking_enable); + aer_config.def_property( + "chunk_swap_buffer_qubits", + [](const Config &config) { return config.chunk_swap_buffer_qubits.val; }, + [](Config &config, uint_t val) { + config.chunk_swap_buffer_qubits.value(val); + }); + // # multi-shots optimization options (GPU only) + aer_config.def_readwrite("batched_shots_gpu", &Config::batched_shots_gpu); + aer_config.def_readwrite("batched_shots_gpu_max_qubits", + &Config::batched_shots_gpu_max_qubits); + aer_config.def_property( + "num_threads_per_device", + [](const Config &config) { return config.num_threads_per_device.val; }, + [](Config &config, uint_t val) { + config.num_threads_per_device.value(val); + }); + // # statevector options + aer_config.def_readwrite("statevector_parallel_threshold", + &Config::statevector_parallel_threshold); + aer_config.def_readwrite("statevector_sample_measure_opt", + &Config::statevector_sample_measure_opt); + // # stabilizer options + aer_config.def_readwrite("stabilizer_max_snapshot_probabilities", + &Config::stabilizer_max_snapshot_probabilities); + // # extended stabilizer options + aer_config.def_readwrite("extended_stabilizer_sampling_method", + &Config::extended_stabilizer_sampling_method); + aer_config.def_readwrite("extended_stabilizer_metropolis_mixing_time", + &Config::extended_stabilizer_metropolis_mixing_time); + aer_config.def_readwrite("extended_stabilizer_approximation_error", + &Config::extended_stabilizer_approximation_error); + aer_config.def_readwrite( + "extended_stabilizer_norm_estimation_samples", + &Config::extended_stabilizer_norm_estimation_samples); + aer_config.def_readwrite( + "extended_stabilizer_norm_estimation_repetitions", + &Config::extended_stabilizer_norm_estimation_repetitions); + aer_config.def_readwrite("extended_stabilizer_parallel_threshold", + &Config::extended_stabilizer_parallel_threshold); + aer_config.def_readwrite( + "extended_stabilizer_probabilities_snapshot_samples", + &Config::extended_stabilizer_probabilities_snapshot_samples); + // # MPS options + aer_config.def_readwrite("matrix_product_state_truncation_threshold", + &Config::matrix_product_state_truncation_threshold); + aer_config.def_property( + "matrix_product_state_max_bond_dimension", + [](const Config &config) { + return config.matrix_product_state_max_bond_dimension.val; + }, + [](Config &config, uint_t val) { + config.matrix_product_state_max_bond_dimension.value(val); + }); + aer_config.def_readwrite("mps_sample_measure_algorithm", + &Config::mps_sample_measure_algorithm); + aer_config.def_readwrite("mps_log_data", &Config::mps_log_data); + aer_config.def_readwrite("mps_swap_direction", &Config::mps_swap_direction); + aer_config.def_readwrite("chop_threshold", &Config::chop_threshold); + aer_config.def_readwrite("mps_parallel_threshold", + &Config::mps_parallel_threshold); + aer_config.def_readwrite("mps_omp_threads", &Config::mps_omp_threads); + // # tensor network options + aer_config.def_readwrite("tensor_network_num_sampling_qubits", + &Config::tensor_network_num_sampling_qubits); + aer_config.def_readwrite("use_cuTensorNet_autotuning", + &Config::use_cuTensorNet_autotuning); - // system configurations - aer_config.def_readwrite("library_dir", &Config::library_dir); - aer_config.def_readwrite("parameterizations", &Config::param_table); - aer_config.def_property("n_qubits", - [](const Config &config) { return config.n_qubits.val;}, - [](Config &config, uint_t val) { config.n_qubits.value(val);}); - aer_config.def_readwrite("global_phase", &Config::global_phase); - aer_config.def_readwrite("memory_slots", &Config::memory_slots); - aer_config.def_property("_parallel_experiments", - [](const Config &config) { return config._parallel_experiments.val;}, - [](Config &config, uint_t val) { config._parallel_experiments.value(val);}); - aer_config.def_property("_parallel_shots", - [](const Config &config) { return config._parallel_shots.val;}, - [](Config &config, uint_t val) { config._parallel_shots.value(val);}); - aer_config.def_property("_parallel_state_update", - [](const Config &config) { return config._parallel_state_update.val;}, - [](Config &config, uint_t val) { config._parallel_state_update.value(val);}); - aer_config.def_property("fusion_allow_kraus", - [](const Config &config) { return config.fusion_allow_kraus.val;}, - [](Config &config, bool val) { config.fusion_allow_kraus.value(val);}); - aer_config.def_property("fusion_allow_superop", - [](const Config &config) { return config.fusion_allow_superop.val;}, - [](Config &config, bool val) { config.fusion_allow_superop.value(val);}); - aer_config.def_property("fusion_parallelization_threshold", - [](const Config &config) { return config.fusion_parallelization_threshold.val;}, - [](Config &config, uint_t val) { config.fusion_parallelization_threshold.value(val);}); - aer_config.def_property("_fusion_enable_n_qubits", - [](const Config &config) { return config._fusion_enable_n_qubits.val;}, - [](Config &config, bool val) { config._fusion_enable_n_qubits.value(val);}); - aer_config.def_property("_fusion_enable_n_qubits_1", - [](const Config &config) { return config._fusion_enable_n_qubits_1.val;}, - [](Config &config, uint_t val) { config._fusion_enable_n_qubits_1.value(val);}); - aer_config.def_property("_fusion_enable_n_qubits_2", - [](const Config &config) { return config._fusion_enable_n_qubits_2.val;}, - [](Config &config, uint_t val) { config._fusion_enable_n_qubits_2.value(val);}); - aer_config.def_property("_fusion_enable_n_qubits_3", - [](const Config &config) { return config._fusion_enable_n_qubits_3.val;}, - [](Config &config, uint_t val) { config._fusion_enable_n_qubits_3.value(val);}); - aer_config.def_property("_fusion_enable_n_qubits_4", - [](const Config &config) { return config._fusion_enable_n_qubits_4.val;}, - [](Config &config, uint_t val) { config._fusion_enable_n_qubits_4.value(val);}); - aer_config.def_property("_fusion_enable_n_qubits_5", - [](const Config &config) { return config._fusion_enable_n_qubits_5.val;}, - [](Config &config, uint_t val) { config._fusion_enable_n_qubits_5.value(val);}); - aer_config.def_property("_fusion_enable_diagonal", - [](const Config &config) { return config._fusion_enable_diagonal.val;}, - [](Config &config, uint_t val) { config._fusion_enable_diagonal.value(val);}); - aer_config.def_property("_fusion_min_qubit", - [](const Config &config) { return config._fusion_min_qubit.val;}, - [](Config &config, uint_t val) { config._fusion_min_qubit.value(val);}); - aer_config.def_property("fusion_cost_factor", - [](const Config &config) { return config.fusion_cost_factor.val;}, - [](Config &config, double val) { config.fusion_cost_factor.value(val);}); - aer_config.def_property("_fusion_enable_cost_based", - [](const Config &config) { return config._fusion_enable_cost_based.val;}, - [](Config &config, bool val) { config._fusion_enable_cost_based.value(val);}); - aer_config.def_property("_fusion_cost_1", - [](const Config &config) { return config._fusion_cost_1.val;}, - [](Config &config, uint_t val) { config._fusion_cost_1.value(val);}); - aer_config.def_property("_fusion_cost_2", - [](const Config &config) { return config._fusion_cost_2.val;}, - [](Config &config, uint_t val) { config._fusion_cost_2.value(val);}); - aer_config.def_property("_fusion_cost_3", - [](const Config &config) { return config._fusion_cost_3.val;}, - [](Config &config, uint_t val) { config._fusion_cost_3.value(val);}); - aer_config.def_property("_fusion_cost_4", - [](const Config &config) { return config._fusion_cost_4.val;}, - [](Config &config, uint_t val) { config._fusion_cost_4.value(val);}); - aer_config.def_property("_fusion_cost_5", - [](const Config &config) { return config._fusion_cost_5.val;}, - [](Config &config, uint_t val) { config._fusion_cost_5.value(val);}); - aer_config.def_property("_fusion_cost_6", - [](const Config &config) { return config._fusion_cost_6.val;}, - [](Config &config, uint_t val) { config._fusion_cost_6.value(val);}); - aer_config.def_property("_fusion_cost_7", - [](const Config &config) { return config._fusion_cost_7.val;}, - [](Config &config, uint_t val) { config._fusion_cost_7.value(val);}); - aer_config.def_property("_fusion_cost_8", - [](const Config &config) { return config._fusion_cost_8.val;}, - [](Config &config, uint_t val) { config._fusion_cost_8.value(val);}); - aer_config.def_property("_fusion_cost_9", - [](const Config &config) { return config._fusion_cost_9.val;}, - [](Config &config, uint_t val) { config._fusion_cost_9.value(val);}); - aer_config.def_property("_fusion_cost_10", - [](const Config &config) { return config._fusion_cost_10.val;}, - [](Config &config, uint_t val) { config._fusion_cost_10.value(val);}); + // system configurations + aer_config.def_readwrite("library_dir", &Config::library_dir); + aer_config.def_readwrite("parameterizations", &Config::param_table); + aer_config.def_property( + "n_qubits", [](const Config &config) { return config.n_qubits.val; }, + [](Config &config, uint_t val) { config.n_qubits.value(val); }); + aer_config.def_readwrite("global_phase", &Config::global_phase); + aer_config.def_readwrite("memory_slots", &Config::memory_slots); + aer_config.def_property( + "_parallel_experiments", + [](const Config &config) { return config._parallel_experiments.val; }, + [](Config &config, uint_t val) { + config._parallel_experiments.value(val); + }); + aer_config.def_property( + "_parallel_shots", + [](const Config &config) { return config._parallel_shots.val; }, + [](Config &config, uint_t val) { config._parallel_shots.value(val); }); + aer_config.def_property( + "_parallel_state_update", + [](const Config &config) { return config._parallel_state_update.val; }, + [](Config &config, uint_t val) { + config._parallel_state_update.value(val); + }); + aer_config.def_property( + "fusion_allow_kraus", + [](const Config &config) { return config.fusion_allow_kraus.val; }, + [](Config &config, bool val) { config.fusion_allow_kraus.value(val); }); + aer_config.def_property( + "fusion_allow_superop", + [](const Config &config) { return config.fusion_allow_superop.val; }, + [](Config &config, bool val) { config.fusion_allow_superop.value(val); }); + aer_config.def_property( + "fusion_parallelization_threshold", + [](const Config &config) { + return config.fusion_parallelization_threshold.val; + }, + [](Config &config, uint_t val) { + config.fusion_parallelization_threshold.value(val); + }); + aer_config.def_property( + "_fusion_enable_n_qubits", + [](const Config &config) { return config._fusion_enable_n_qubits.val; }, + [](Config &config, bool val) { + config._fusion_enable_n_qubits.value(val); + }); + aer_config.def_property( + "_fusion_enable_n_qubits_1", + [](const Config &config) { return config._fusion_enable_n_qubits_1.val; }, + [](Config &config, uint_t val) { + config._fusion_enable_n_qubits_1.value(val); + }); + aer_config.def_property( + "_fusion_enable_n_qubits_2", + [](const Config &config) { return config._fusion_enable_n_qubits_2.val; }, + [](Config &config, uint_t val) { + config._fusion_enable_n_qubits_2.value(val); + }); + aer_config.def_property( + "_fusion_enable_n_qubits_3", + [](const Config &config) { return config._fusion_enable_n_qubits_3.val; }, + [](Config &config, uint_t val) { + config._fusion_enable_n_qubits_3.value(val); + }); + aer_config.def_property( + "_fusion_enable_n_qubits_4", + [](const Config &config) { return config._fusion_enable_n_qubits_4.val; }, + [](Config &config, uint_t val) { + config._fusion_enable_n_qubits_4.value(val); + }); + aer_config.def_property( + "_fusion_enable_n_qubits_5", + [](const Config &config) { return config._fusion_enable_n_qubits_5.val; }, + [](Config &config, uint_t val) { + config._fusion_enable_n_qubits_5.value(val); + }); + aer_config.def_property( + "_fusion_enable_diagonal", + [](const Config &config) { return config._fusion_enable_diagonal.val; }, + [](Config &config, uint_t val) { + config._fusion_enable_diagonal.value(val); + }); + aer_config.def_property( + "_fusion_min_qubit", + [](const Config &config) { return config._fusion_min_qubit.val; }, + [](Config &config, uint_t val) { config._fusion_min_qubit.value(val); }); + aer_config.def_property( + "fusion_cost_factor", + [](const Config &config) { return config.fusion_cost_factor.val; }, + [](Config &config, double val) { config.fusion_cost_factor.value(val); }); + aer_config.def_property( + "_fusion_enable_cost_based", + [](const Config &config) { return config._fusion_enable_cost_based.val; }, + [](Config &config, bool val) { + config._fusion_enable_cost_based.value(val); + }); + aer_config.def_property( + "_fusion_cost_1", + [](const Config &config) { return config._fusion_cost_1.val; }, + [](Config &config, uint_t val) { config._fusion_cost_1.value(val); }); + aer_config.def_property( + "_fusion_cost_2", + [](const Config &config) { return config._fusion_cost_2.val; }, + [](Config &config, uint_t val) { config._fusion_cost_2.value(val); }); + aer_config.def_property( + "_fusion_cost_3", + [](const Config &config) { return config._fusion_cost_3.val; }, + [](Config &config, uint_t val) { config._fusion_cost_3.value(val); }); + aer_config.def_property( + "_fusion_cost_4", + [](const Config &config) { return config._fusion_cost_4.val; }, + [](Config &config, uint_t val) { config._fusion_cost_4.value(val); }); + aer_config.def_property( + "_fusion_cost_5", + [](const Config &config) { return config._fusion_cost_5.val; }, + [](Config &config, uint_t val) { config._fusion_cost_5.value(val); }); + aer_config.def_property( + "_fusion_cost_6", + [](const Config &config) { return config._fusion_cost_6.val; }, + [](Config &config, uint_t val) { config._fusion_cost_6.value(val); }); + aer_config.def_property( + "_fusion_cost_7", + [](const Config &config) { return config._fusion_cost_7.val; }, + [](Config &config, uint_t val) { config._fusion_cost_7.value(val); }); + aer_config.def_property( + "_fusion_cost_8", + [](const Config &config) { return config._fusion_cost_8.val; }, + [](Config &config, uint_t val) { config._fusion_cost_8.value(val); }); + aer_config.def_property( + "_fusion_cost_9", + [](const Config &config) { return config._fusion_cost_9.val; }, + [](Config &config, uint_t val) { config._fusion_cost_9.value(val); }); + aer_config.def_property( + "_fusion_cost_10", + [](const Config &config) { return config._fusion_cost_10.val; }, + [](Config &config, uint_t val) { config._fusion_cost_10.value(val); }); - aer_config.def_property("superoperator_parallel_threshold", - [](const Config &config) { return config.superoperator_parallel_threshold.val;}, - [](Config &config, uint_t val) { config.superoperator_parallel_threshold.value(val);}); - aer_config.def_property("unitary_parallel_threshold", - [](const Config &config) { return config.unitary_parallel_threshold.val;}, - [](Config &config, uint_t val) { config.unitary_parallel_threshold.value(val);}); - aer_config.def_property("memory_blocking_bits", - [](const Config &config) { return config.memory_blocking_bits.val;}, - [](Config &config, uint_t val) { config.memory_blocking_bits.value(val);}); - aer_config.def_property("extended_stabilizer_norm_estimation_default_samples", - [](const Config &config) { return config.extended_stabilizer_norm_estimation_default_samples.val;}, - [](Config &config, uint_t val) { config.extended_stabilizer_norm_estimation_default_samples.value(val);}); + aer_config.def_property( + "superoperator_parallel_threshold", + [](const Config &config) { + return config.superoperator_parallel_threshold.val; + }, + [](Config &config, uint_t val) { + config.superoperator_parallel_threshold.value(val); + }); + aer_config.def_property( + "unitary_parallel_threshold", + [](const Config &config) { + return config.unitary_parallel_threshold.val; + }, + [](Config &config, uint_t val) { + config.unitary_parallel_threshold.value(val); + }); + aer_config.def_property( + "memory_blocking_bits", + [](const Config &config) { return config.memory_blocking_bits.val; }, + [](Config &config, uint_t val) { + config.memory_blocking_bits.value(val); + }); + aer_config.def_property( + "extended_stabilizer_norm_estimation_default_samples", + [](const Config &config) { + return config.extended_stabilizer_norm_estimation_default_samples.val; + }, + [](Config &config, uint_t val) { + config.extended_stabilizer_norm_estimation_default_samples.value(val); + }); - aer_config.def(py::pickle( - [](const AER::Config &config) { - return py::make_tuple( - write_value(0, config.shots), - write_value(1, config.method), - write_value(2, config.device), - write_value(3, config.precision), - write_value(4, config.enable_truncation), - write_value(5, config.zero_threshold), - write_value(6, config.validation_threshold), - write_value(7, config.max_parallel_threads), - write_value(8, config.max_parallel_experiments), - write_value(9, config.max_parallel_shots), - write_value(10, config.max_memory_mb), - write_value(11, config.fusion_enable), - write_value(12, config.fusion_verbose), - write_value(13, config.fusion_max_qubit), - write_value(14, config.fusion_threshold), - write_value(15, config.accept_distributed_results), - write_value(16, config.memory), - write_value(17, config.seed_simulator), - write_value(18, config.cuStateVec_enable), - write_value(19, config.blocking_qubits), - write_value(20, config.blocking_enable), - write_value(21, config.chunk_swap_buffer_qubits), - write_value(22, config.batched_shots_gpu), - write_value(23, config.batched_shots_gpu_max_qubits), - write_value(24, config.num_threads_per_device), - write_value(25, config.statevector_parallel_threshold), - write_value(26, config.statevector_sample_measure_opt), - write_value(27, config.stabilizer_max_snapshot_probabilities), - write_value(28, config.extended_stabilizer_sampling_method), - write_value(29, config.extended_stabilizer_metropolis_mixing_time), - write_value(20, config.extended_stabilizer_approximation_error), - write_value(31, config.extended_stabilizer_norm_estimation_samples), - write_value(32, config.extended_stabilizer_norm_estimation_repetitions), - write_value(33, config.extended_stabilizer_parallel_threshold), - write_value(34, config.extended_stabilizer_probabilities_snapshot_samples), - write_value(35, config.matrix_product_state_truncation_threshold), - write_value(36, config.matrix_product_state_max_bond_dimension), - write_value(37, config.mps_sample_measure_algorithm), - write_value(38, config.mps_log_data), - write_value(39, config.mps_swap_direction), - write_value(30, config.chop_threshold), - write_value(41, config.mps_parallel_threshold), - write_value(42, config.mps_omp_threads), - write_value(43, config.tensor_network_num_sampling_qubits), - write_value(44, config.use_cuTensorNet_autotuning), - write_value(45, config.library_dir), - write_value(46, config.param_table), - write_value(47, config.n_qubits), - write_value(48, config.global_phase), - write_value(49, config.memory_slots), - write_value(50, config._parallel_experiments), - write_value(51, config._parallel_shots), - write_value(52, config._parallel_state_update), - write_value(53, config.fusion_allow_kraus), - write_value(54, config.fusion_allow_superop), - write_value(55, config.fusion_parallelization_threshold), - write_value(56, config._fusion_enable_n_qubits), - write_value(57, config._fusion_enable_n_qubits_1), - write_value(58, config._fusion_enable_n_qubits_2), - write_value(59, config._fusion_enable_n_qubits_3), - write_value(60, config._fusion_enable_n_qubits_4), - write_value(61, config._fusion_enable_n_qubits_5), - write_value(62, config._fusion_enable_diagonal), - write_value(63, config._fusion_min_qubit), - write_value(64, config.fusion_cost_factor), - write_value(65, config._fusion_enable_cost_based), - write_value(66, config._fusion_cost_1), - write_value(67, config._fusion_cost_2), - write_value(68, config._fusion_cost_3), - write_value(69, config._fusion_cost_4), - write_value(70, config._fusion_cost_5), - write_value(71, config._fusion_cost_6), - write_value(72, config._fusion_cost_7), - write_value(73, config._fusion_cost_8), - write_value(74, config._fusion_cost_9), - write_value(75, config._fusion_cost_10), + aer_config.def(py::pickle( + [](const AER::Config &config) { + return py::make_tuple( + write_value(0, config.shots), write_value(1, config.method), + write_value(2, config.device), write_value(3, config.precision), + write_value(4, config.enable_truncation), + write_value(5, config.zero_threshold), + write_value(6, config.validation_threshold), + write_value(7, config.max_parallel_threads), + write_value(8, config.max_parallel_experiments), + write_value(9, config.max_parallel_shots), + write_value(10, config.max_memory_mb), + write_value(11, config.fusion_enable), + write_value(12, config.fusion_verbose), + write_value(13, config.fusion_max_qubit), + write_value(14, config.fusion_threshold), + write_value(15, config.accept_distributed_results), + write_value(16, config.memory), + write_value(17, config.seed_simulator), + write_value(18, config.cuStateVec_enable), + write_value(19, config.blocking_qubits), + write_value(20, config.blocking_enable), + write_value(21, config.chunk_swap_buffer_qubits), + write_value(22, config.batched_shots_gpu), + write_value(23, config.batched_shots_gpu_max_qubits), + write_value(24, config.num_threads_per_device), + write_value(25, config.statevector_parallel_threshold), + write_value(26, config.statevector_sample_measure_opt), + write_value(27, config.stabilizer_max_snapshot_probabilities), + write_value(28, config.extended_stabilizer_sampling_method), + write_value(29, config.extended_stabilizer_metropolis_mixing_time), + write_value(20, config.extended_stabilizer_approximation_error), + write_value(31, config.extended_stabilizer_norm_estimation_samples), + write_value(32, + config.extended_stabilizer_norm_estimation_repetitions), + write_value(33, config.extended_stabilizer_parallel_threshold), + write_value( + 34, config.extended_stabilizer_probabilities_snapshot_samples), + write_value(35, config.matrix_product_state_truncation_threshold), + write_value(36, config.matrix_product_state_max_bond_dimension), + write_value(37, config.mps_sample_measure_algorithm), + write_value(38, config.mps_log_data), + write_value(39, config.mps_swap_direction), + write_value(30, config.chop_threshold), + write_value(41, config.mps_parallel_threshold), + write_value(42, config.mps_omp_threads), + write_value(43, config.tensor_network_num_sampling_qubits), + write_value(44, config.use_cuTensorNet_autotuning), + write_value(45, config.library_dir), + write_value(46, config.param_table), + write_value(47, config.n_qubits), + write_value(48, config.global_phase), + write_value(49, config.memory_slots), + write_value(50, config._parallel_experiments), + write_value(51, config._parallel_shots), + write_value(52, config._parallel_state_update), + write_value(53, config.fusion_allow_kraus), + write_value(54, config.fusion_allow_superop), + write_value(55, config.fusion_parallelization_threshold), + write_value(56, config._fusion_enable_n_qubits), + write_value(57, config._fusion_enable_n_qubits_1), + write_value(58, config._fusion_enable_n_qubits_2), + write_value(59, config._fusion_enable_n_qubits_3), + write_value(60, config._fusion_enable_n_qubits_4), + write_value(61, config._fusion_enable_n_qubits_5), + write_value(62, config._fusion_enable_diagonal), + write_value(63, config._fusion_min_qubit), + write_value(64, config.fusion_cost_factor), + write_value(65, config._fusion_enable_cost_based), + write_value(66, config._fusion_cost_1), + write_value(67, config._fusion_cost_2), + write_value(68, config._fusion_cost_3), + write_value(69, config._fusion_cost_4), + write_value(70, config._fusion_cost_5), + write_value(71, config._fusion_cost_6), + write_value(72, config._fusion_cost_7), + write_value(73, config._fusion_cost_8), + write_value(74, config._fusion_cost_9), + write_value(75, config._fusion_cost_10), - write_value(76, config.superoperator_parallel_threshold), - write_value(77, config.unitary_parallel_threshold), - write_value(78, config.memory_blocking_bits), - write_value(79, config.extended_stabilizer_norm_estimation_default_samples) - ); - }, - [](py::tuple t) { - AER::Config config; - if (t.size() != 79) - throw std::runtime_error("Invalid serialization format."); + write_value(76, config.superoperator_parallel_threshold), + write_value(77, config.unitary_parallel_threshold), + write_value(78, config.memory_blocking_bits), + write_value( + 79, + config.extended_stabilizer_norm_estimation_default_samples)); + }, + [](py::tuple t) { + AER::Config config; + if (t.size() != 79) + throw std::runtime_error("Invalid serialization format."); - read_value(t, 0, config.shots); - read_value(t, 1, config.method); - read_value(t, 2, config.device); - read_value(t, 3, config.precision); - read_value(t, 4, config.enable_truncation); - read_value(t, 5, config.zero_threshold); - read_value(t, 6, config.validation_threshold); - read_value(t, 7, config.max_parallel_threads); - read_value(t, 8, config.max_parallel_experiments); - read_value(t, 9, config.max_parallel_shots); - read_value(t, 10, config.max_memory_mb); - read_value(t, 11, config.fusion_enable); - read_value(t, 12, config.fusion_verbose); - read_value(t, 13, config.fusion_max_qubit); - read_value(t, 14, config.fusion_threshold); - read_value(t, 15, config.accept_distributed_results); - read_value(t, 16, config.memory); - read_value(t, 17, config.seed_simulator); - read_value(t, 18, config.cuStateVec_enable); - read_value(t, 19, config.blocking_qubits); - read_value(t, 20, config.blocking_enable); - read_value(t, 21, config.chunk_swap_buffer_qubits); - read_value(t, 22, config.batched_shots_gpu); - read_value(t, 23, config.batched_shots_gpu_max_qubits); - read_value(t, 24, config.num_threads_per_device); - read_value(t, 25, config.statevector_parallel_threshold); - read_value(t, 26, config.statevector_sample_measure_opt); - read_value(t, 27, config.stabilizer_max_snapshot_probabilities); - read_value(t, 28, config.extended_stabilizer_sampling_method); - read_value(t, 29, config.extended_stabilizer_metropolis_mixing_time); - read_value(t, 20, config.extended_stabilizer_approximation_error); - read_value(t, 31, config.extended_stabilizer_norm_estimation_samples); - read_value(t, 32, config.extended_stabilizer_norm_estimation_repetitions); - read_value(t, 33, config.extended_stabilizer_parallel_threshold); - read_value(t, 34, config.extended_stabilizer_probabilities_snapshot_samples); - read_value(t, 35, config.matrix_product_state_truncation_threshold); - read_value(t, 36, config.matrix_product_state_max_bond_dimension); - read_value(t, 37, config.mps_sample_measure_algorithm); - read_value(t, 38, config.mps_log_data); - read_value(t, 39, config.mps_swap_direction); - 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, 43, config.tensor_network_num_sampling_qubits); - read_value(t, 44, config.use_cuTensorNet_autotuning); - read_value(t, 45, config.library_dir); - read_value(t, 46, config.param_table); - read_value(t, 47, config.n_qubits); - read_value(t, 48, config.global_phase); - read_value(t, 49, config.memory_slots); - read_value(t, 50, config._parallel_experiments); - read_value(t, 51, config._parallel_shots); - read_value(t, 52, config._parallel_state_update); - read_value(t, 53, config.fusion_allow_kraus); - read_value(t, 54, config.fusion_allow_superop); - read_value(t, 55, config.fusion_parallelization_threshold); - read_value(t, 56, config._fusion_enable_n_qubits); - read_value(t, 57, config._fusion_enable_n_qubits_1); - read_value(t, 58, config._fusion_enable_n_qubits_2); - read_value(t, 59, config._fusion_enable_n_qubits_3); - read_value(t, 60, config._fusion_enable_n_qubits_4); - read_value(t, 61, config._fusion_enable_n_qubits_5); - read_value(t, 62, config._fusion_enable_diagonal); - read_value(t, 63, config._fusion_min_qubit); - read_value(t, 64, config.fusion_cost_factor); - read_value(t, 65, config._fusion_enable_cost_based); - read_value(t, 66, config._fusion_cost_1); - read_value(t, 67, config._fusion_cost_2); - read_value(t, 68, config._fusion_cost_3); - read_value(t, 69, config._fusion_cost_4); - read_value(t, 70, config._fusion_cost_5); - read_value(t, 71, config._fusion_cost_6); - read_value(t, 72, config._fusion_cost_7); - read_value(t, 73, config._fusion_cost_8); - read_value(t, 74, config._fusion_cost_9); - read_value(t, 75, config._fusion_cost_10); + read_value(t, 0, config.shots); + read_value(t, 1, config.method); + read_value(t, 2, config.device); + read_value(t, 3, config.precision); + read_value(t, 4, config.enable_truncation); + read_value(t, 5, config.zero_threshold); + read_value(t, 6, config.validation_threshold); + read_value(t, 7, config.max_parallel_threads); + read_value(t, 8, config.max_parallel_experiments); + read_value(t, 9, config.max_parallel_shots); + read_value(t, 10, config.max_memory_mb); + read_value(t, 11, config.fusion_enable); + read_value(t, 12, config.fusion_verbose); + read_value(t, 13, config.fusion_max_qubit); + read_value(t, 14, config.fusion_threshold); + read_value(t, 15, config.accept_distributed_results); + read_value(t, 16, config.memory); + read_value(t, 17, config.seed_simulator); + read_value(t, 18, config.cuStateVec_enable); + read_value(t, 19, config.blocking_qubits); + read_value(t, 20, config.blocking_enable); + read_value(t, 21, config.chunk_swap_buffer_qubits); + read_value(t, 22, config.batched_shots_gpu); + read_value(t, 23, config.batched_shots_gpu_max_qubits); + read_value(t, 24, config.num_threads_per_device); + read_value(t, 25, config.statevector_parallel_threshold); + read_value(t, 26, config.statevector_sample_measure_opt); + read_value(t, 27, config.stabilizer_max_snapshot_probabilities); + read_value(t, 28, config.extended_stabilizer_sampling_method); + read_value(t, 29, config.extended_stabilizer_metropolis_mixing_time); + read_value(t, 20, config.extended_stabilizer_approximation_error); + read_value(t, 31, config.extended_stabilizer_norm_estimation_samples); + read_value(t, 32, + config.extended_stabilizer_norm_estimation_repetitions); + read_value(t, 33, config.extended_stabilizer_parallel_threshold); + read_value(t, 34, + config.extended_stabilizer_probabilities_snapshot_samples); + read_value(t, 35, config.matrix_product_state_truncation_threshold); + read_value(t, 36, config.matrix_product_state_max_bond_dimension); + read_value(t, 37, config.mps_sample_measure_algorithm); + read_value(t, 38, config.mps_log_data); + read_value(t, 39, config.mps_swap_direction); + 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, 43, config.tensor_network_num_sampling_qubits); + read_value(t, 44, config.use_cuTensorNet_autotuning); + read_value(t, 45, config.library_dir); + read_value(t, 46, config.param_table); + read_value(t, 47, config.n_qubits); + read_value(t, 48, config.global_phase); + read_value(t, 49, config.memory_slots); + read_value(t, 50, config._parallel_experiments); + read_value(t, 51, config._parallel_shots); + read_value(t, 52, config._parallel_state_update); + read_value(t, 53, config.fusion_allow_kraus); + read_value(t, 54, config.fusion_allow_superop); + read_value(t, 55, config.fusion_parallelization_threshold); + read_value(t, 56, config._fusion_enable_n_qubits); + read_value(t, 57, config._fusion_enable_n_qubits_1); + read_value(t, 58, config._fusion_enable_n_qubits_2); + read_value(t, 59, config._fusion_enable_n_qubits_3); + read_value(t, 60, config._fusion_enable_n_qubits_4); + read_value(t, 61, config._fusion_enable_n_qubits_5); + read_value(t, 62, config._fusion_enable_diagonal); + read_value(t, 63, config._fusion_min_qubit); + read_value(t, 64, config.fusion_cost_factor); + read_value(t, 65, config._fusion_enable_cost_based); + read_value(t, 66, config._fusion_cost_1); + read_value(t, 67, config._fusion_cost_2); + read_value(t, 68, config._fusion_cost_3); + read_value(t, 69, config._fusion_cost_4); + read_value(t, 70, config._fusion_cost_5); + read_value(t, 71, config._fusion_cost_6); + read_value(t, 72, config._fusion_cost_7); + read_value(t, 73, config._fusion_cost_8); + read_value(t, 74, config._fusion_cost_9); + read_value(t, 75, config._fusion_cost_10); - read_value(t, 76, config.superoperator_parallel_threshold); - read_value(t, 77, config.unitary_parallel_threshold); - read_value(t, 78, config.memory_blocking_bits); - read_value(t, 79, config.extended_stabilizer_norm_estimation_default_samples); - return config; - })); + read_value(t, 76, config.superoperator_parallel_threshold); + read_value(t, 77, config.unitary_parallel_threshold); + read_value(t, 78, config.memory_blocking_bits); + read_value(t, 79, + config.extended_stabilizer_norm_estimation_default_samples); + return config; + })); } #endif diff --git a/qiskit_aer/backends/wrappers/aer_state_binding.hpp b/qiskit_aer/backends/wrappers/aer_state_binding.hpp index 36fd4da9a4..45dd55bcbf 100644 --- a/qiskit_aer/backends/wrappers/aer_state_binding.hpp +++ b/qiskit_aer/backends/wrappers/aer_state_binding.hpp @@ -20,17 +20,17 @@ DISABLE_WARNING_PUSH #include DISABLE_WARNING_POP #if defined(_MSC_VER) - #undef snprintf +#undef snprintf #endif -#include #include +#include #include "framework/matrix.hpp" -#include "framework/python_parser.hpp" #include "framework/pybind_casts.hpp" -#include "framework/types.hpp" +#include "framework/python_parser.hpp" #include "framework/results/pybind_result.hpp" +#include "framework/types.hpp" #include "controllers/state_controller.hpp" @@ -46,50 +46,57 @@ void bind_aer_state(MODULE m) { aer_state.def("__repr__", [](const AerState &state) { std::stringstream ss; ss << "AerStateWrapper(" - << "initialized=" << state.is_initialized() - << ", num_of_qubits=" << state.num_of_qubits(); + << "initialized=" << state.is_initialized() + << ", num_of_qubits=" << state.num_of_qubits(); ss << ")"; return ss.str(); }); - aer_state.def("configure", &AerState::configure); - aer_state.def("allocate_qubits", &AerState::allocate_qubits); - aer_state.def("reallocate_qubits", &AerState::reallocate_qubits); - aer_state.def("set_random_seed", &AerState::set_random_seed); - aer_state.def("set_seed", &AerState::set_seed); - aer_state.def("clear", &AerState::clear); - aer_state.def("num_of_qubits", &AerState::num_of_qubits); - - aer_state.def("initialize", &AerState::initialize); - aer_state.def("initialize_statevector", [aer_state](AerState &state, - int num_of_qubits, - py::array_t> &values, - bool copy) { - auto c_contiguous = values.attr("flags").attr("c_contiguous").template cast(); - auto f_contiguous = values.attr("flags").attr("f_contiguous").template cast(); - if (!c_contiguous && !f_contiguous) - return false; - std::complex* data_ptr = reinterpret_cast*>(values.mutable_data(0)); - state.configure("method", "statevector"); - state.initialize_statevector(num_of_qubits, data_ptr, copy); - return true; - }); - - aer_state.def("initialize_density_matrix", [aer_state](AER::AerState &state, - int num_of_qubits, - py::array_t> &values, - bool copy) { - auto c_contiguous = values.attr("flags").attr("c_contiguous").template cast(); - auto f_contiguous = values.attr("flags").attr("f_contiguous").template cast(); - if (!c_contiguous && !f_contiguous) - return false; - std::complex* data_ptr = reinterpret_cast*>(values.mutable_data(0)); - state.configure("method", "density_matrix"); - state.initialize_density_matrix(num_of_qubits, data_ptr, f_contiguous, copy); - return true; - }); - - aer_state.def("move_to_buffer", [aer_state](AER::AerState &state) { + aer_state.def("configure", &AerState::configure); + aer_state.def("allocate_qubits", &AerState::allocate_qubits); + aer_state.def("reallocate_qubits", &AerState::reallocate_qubits); + aer_state.def("set_random_seed", &AerState::set_random_seed); + aer_state.def("set_seed", &AerState::set_seed); + aer_state.def("clear", &AerState::clear); + aer_state.def("num_of_qubits", &AerState::num_of_qubits); + + aer_state.def("initialize", &AerState::initialize); + aer_state.def( + "initialize_statevector", + [aer_state](AerState &state, int num_of_qubits, + py::array_t> &values, bool copy) { + auto c_contiguous = + values.attr("flags").attr("c_contiguous").template cast(); + auto f_contiguous = + values.attr("flags").attr("f_contiguous").template cast(); + if (!c_contiguous && !f_contiguous) + return false; + std::complex *data_ptr = + reinterpret_cast *>(values.mutable_data(0)); + state.configure("method", "statevector"); + state.initialize_statevector(num_of_qubits, data_ptr, copy); + return true; + }); + + aer_state.def( + "initialize_density_matrix", + [aer_state](AER::AerState &state, int num_of_qubits, + py::array_t> &values, bool copy) { + auto c_contiguous = + values.attr("flags").attr("c_contiguous").template cast(); + auto f_contiguous = + values.attr("flags").attr("f_contiguous").template cast(); + if (!c_contiguous && !f_contiguous) + return false; + std::complex *data_ptr = + reinterpret_cast *>(values.mutable_data(0)); + state.configure("method", "density_matrix"); + state.initialize_density_matrix(num_of_qubits, data_ptr, f_contiguous, + copy); + return true; + }); + + aer_state.def("move_to_buffer", [aer_state](AER::AerState &state) { return state.move_to_vector().move_to_buffer(); }); @@ -99,85 +106,85 @@ void bind_aer_state(MODULE m) { auto ret = AerToPy::to_numpy(std::move(vec)); return ret; }); - + aer_state.def("move_to_matrix", [aer_state](AER::AerState &state) { auto mat = state.move_to_matrix(); auto ret = AerToPy::to_numpy(std::move(mat)); return ret; }); - aer_state.def("flush", &AerState::flush_ops); + aer_state.def("flush", &AerState::flush_ops); - aer_state.def("last_result", [aer_state](AerState &state) { + aer_state.def("last_result", [aer_state](AerState &state) { return AerToPy::to_python(state.last_result().to_json()); }); - - aer_state.def("apply_initialize", &AerState::apply_initialize); - aer_state.def("set_statevector", &AER::AerState::set_statevector); - aer_state.def("set_density_matrix", &AER::AerState::set_density_matrix); - - aer_state.def("apply_global_phase", &AerState::apply_global_phase); - aer_state.def("apply_unitary", [aer_state](AerState &state, - const reg_t &qubits, - const py::array_t> &values) { - size_t mat_len = (1UL << qubits.size()); - auto ptr = values.unchecked<2>(); - cmatrix_t mat(mat_len, mat_len); - 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); - }); - - aer_state.def("apply_multiplexer", [aer_state](AerState &state, - const reg_t &control_qubits, - const reg_t &target_qubits, - const py::array_t> &values) { - size_t mat_len = (1UL << target_qubits.size()); - size_t mat_size = (1UL << control_qubits.size()); - auto ptr = values.unchecked<3>(); - std::vector mats; - for (auto i = 0; i < mat_size; ++i) { - cmatrix_t mat(mat_len, mat_len); - 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); - } - state.apply_multiplexer(control_qubits, target_qubits, mats); - }); - - aer_state.def("apply_diagonal", &AerState::apply_diagonal_matrix); - aer_state.def("apply_x", &AerState::apply_x); - aer_state.def("apply_cx", &AerState::apply_cx); - aer_state.def("apply_mcx", &AerState::apply_mcx); - aer_state.def("apply_y", &AerState::apply_y); - aer_state.def("apply_cy", &AerState::apply_cy); - aer_state.def("apply_mcy", &AerState::apply_mcy); - aer_state.def("apply_z", &AerState::apply_z); - aer_state.def("apply_cz", &AerState::apply_cz); - aer_state.def("apply_mcz", &AerState::apply_mcz); - aer_state.def("apply_mcphase", &AerState::apply_mcphase); - aer_state.def("apply_h", &AerState::apply_h); - aer_state.def("apply_u", &AerState::apply_u); - aer_state.def("apply_cu", &AerState::apply_cu); - aer_state.def("apply_mcu", &AerState::apply_mcu); - aer_state.def("apply_mcswap", &AerState::apply_mcswap); - aer_state.def("apply_measure", &AerState::apply_measure); - aer_state.def("apply_reset", &AerState::apply_reset); - aer_state.def("apply_kraus", &AER::AerState::apply_kraus); - aer_state.def("probability", &AerState::probability); - aer_state.def("probabilities", [aer_state](AerState &state, - const reg_t qubits) { - if (qubits.empty()) - return state.probabilities(); - else - return state.probabilities(qubits); - }, py::arg("qubits") = reg_t()); - aer_state.def("sample_memory", &AerState::sample_memory); - aer_state.def("sample_counts", &AerState::sample_counts); - + aer_state.def("apply_initialize", &AerState::apply_initialize); + aer_state.def("set_statevector", &AER::AerState::set_statevector); + aer_state.def("set_density_matrix", &AER::AerState::set_density_matrix); + + aer_state.def("apply_global_phase", &AerState::apply_global_phase); + aer_state.def("apply_unitary", + [aer_state](AerState &state, const reg_t &qubits, + const py::array_t> &values) { + size_t mat_len = (1UL << qubits.size()); + auto ptr = values.unchecked<2>(); + cmatrix_t mat(mat_len, mat_len); + 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); + }); + + aer_state.def("apply_multiplexer", + [aer_state](AerState &state, const reg_t &control_qubits, + const reg_t &target_qubits, + const py::array_t> &values) { + size_t mat_len = (1UL << target_qubits.size()); + size_t mat_size = (1UL << control_qubits.size()); + auto ptr = values.unchecked<3>(); + std::vector mats; + for (auto i = 0; i < mat_size; ++i) { + cmatrix_t mat(mat_len, mat_len); + 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); + } + state.apply_multiplexer(control_qubits, target_qubits, mats); + }); + + aer_state.def("apply_diagonal", &AerState::apply_diagonal_matrix); + aer_state.def("apply_x", &AerState::apply_x); + aer_state.def("apply_cx", &AerState::apply_cx); + aer_state.def("apply_mcx", &AerState::apply_mcx); + aer_state.def("apply_y", &AerState::apply_y); + aer_state.def("apply_cy", &AerState::apply_cy); + aer_state.def("apply_mcy", &AerState::apply_mcy); + aer_state.def("apply_z", &AerState::apply_z); + aer_state.def("apply_cz", &AerState::apply_cz); + aer_state.def("apply_mcz", &AerState::apply_mcz); + aer_state.def("apply_mcphase", &AerState::apply_mcphase); + aer_state.def("apply_h", &AerState::apply_h); + aer_state.def("apply_u", &AerState::apply_u); + aer_state.def("apply_cu", &AerState::apply_cu); + aer_state.def("apply_mcu", &AerState::apply_mcu); + aer_state.def("apply_mcswap", &AerState::apply_mcswap); + aer_state.def("apply_measure", &AerState::apply_measure); + aer_state.def("apply_reset", &AerState::apply_reset); + aer_state.def("apply_kraus", &AER::AerState::apply_kraus); + aer_state.def("probability", &AerState::probability); + aer_state.def( + "probabilities", + [aer_state](AerState &state, const reg_t qubits) { + if (qubits.empty()) + return state.probabilities(); + else + return state.probabilities(qubits); + }, + py::arg("qubits") = reg_t()); + aer_state.def("sample_memory", &AerState::sample_memory); + aer_state.def("sample_counts", &AerState::sample_counts); } #endif \ No newline at end of file diff --git a/qiskit_aer/jobs/aerjob.py b/qiskit_aer/jobs/aerjob.py index 0bd0124264..545fbe773e 100644 --- a/qiskit_aer/jobs/aerjob.py +++ b/qiskit_aer/jobs/aerjob.py @@ -27,11 +27,18 @@ class AerJob(Job): """AerJob class for Qiskit Aer Simulators.""" - def __init__(self, backend, job_id, fn, - qobj=None, - circuits=None, noise_model=None, config=None, - executor=None): - """ Initializes the asynchronous job. + def __init__( + self, + backend, + job_id, + fn, + qobj=None, + circuits=None, + noise_model=None, + config=None, + executor=None, + ): + """Initializes the asynchronous job. Args: backend(AerBackend): the backend used to run the job. @@ -65,7 +72,7 @@ def __init__(self, backend, job_id, fn, self._noise_model = noise_model self._config = config else: - raise JobError('AerJob needs a qobj or circuits') + raise JobError("AerJob needs a qobj or circuits") self._executor = executor or DEFAULT_EXECUTOR self._future = None @@ -82,8 +89,9 @@ def submit(self): if self._qobj: self._future = self._executor.submit(self._fn, self._qobj, self._job_id) else: - self._future = self._executor.submit(self._fn, self._circuits, self._noise_model, - self._config, self._job_id) + self._future = self._executor.submit( + self._fn, self._circuits, self._noise_model, self._config, self._job_id + ) @requires_submit def result(self, timeout=None): @@ -147,11 +155,13 @@ def qobj(self): Qobj: the Qobj submitted for this job. """ warnings.warn( - '`AerJob.qobj() is deprecated as of qiskit-aer 0.12.0`. ' - 'Using a qobj for `backend.run()` is deprecated as of qiskit-aer 0.9.0' - ' and will be removed no sooner than 3 months from that release' - ' date. Once it is removed, this `qobj()` returns always `None`.', - DeprecationWarning, stacklevel=2) + "`AerJob.qobj() is deprecated as of qiskit-aer 0.12.0`. " + "Using a qobj for `backend.run()` is deprecated as of qiskit-aer 0.9.0" + " and will be removed no sooner than 3 months from that release" + " date. Once it is removed, this `qobj()` returns always `None`.", + DeprecationWarning, + stacklevel=2, + ) return self._qobj def circuits(self): diff --git a/qiskit_aer/jobs/aerjobset.py b/qiskit_aer/jobs/aerjobset.py index 5b32625371..ce3d3d6229 100644 --- a/qiskit_aer/jobs/aerjobset.py +++ b/qiskit_aer/jobs/aerjobset.py @@ -79,8 +79,7 @@ def submit(self): RuntimeError: If the jobs were already submitted. """ if self._futures: - raise RuntimeError( - 'The jobs for this managed job set have already been submitted.') + raise RuntimeError("The jobs for this managed job set have already been submitted.") self._future = True worker_id = 0 @@ -99,8 +98,7 @@ def submit(self): self._combined_result.append(_worker_id_list) @requires_submit - def status(self, worker: Union[None, int, Iterable[int]] - ) -> Union[JobStatus, List[JobStatus]]: + def status(self, worker: Union[None, int, Iterable[int]]) -> Union[JobStatus, List[JobStatus]]: """Return the status of each job in this set. Args @@ -122,9 +120,10 @@ def status(self, worker: Union[None, int, Iterable[int]] return [aer.status() for aer in self._futures] @requires_submit - def result(self, - timeout: Optional[float] = None, - ) -> Result: + def result( + self, + timeout: Optional[float] = None, + ) -> Result: """Return the results of the jobs as a single Result object. This call will block until all job results become available or @@ -145,10 +144,11 @@ def result(self, return res @requires_submit - def worker_results(self, - worker: Union[None, int, Iterable[int]], - timeout: Optional[float] = None, - ) -> Union[Result, List[Result]]: + def worker_results( + self, + worker: Union[None, int, Iterable[int]], + timeout: Optional[float] = None, + ) -> Union[Result, List[Result]]: """Return the result of the jobs specified with worker_id. When the worker is None, this call return all worker's result. @@ -216,19 +216,18 @@ def _get_worker_result(self, worker: int, timeout: Optional[float] = None): result = aer_job.result(timeout=timeout) if result is None or not result.success: if result: - logger.warning('AerJobSet %s Error: %s', aer_job.name(), result.header) + logger.warning("AerJobSet %s Error: %s", aer_job.name(), result.header) else: - logger.warning('AerJobSet %s did not return a result', aer_job.name()) + logger.warning("AerJobSet %s did not return a result", aer_job.name()) except JobError: raise JobError( - 'Timeout while waiting for the results of experiment {}'.format( - aer_job.name())) + "Timeout while waiting for the results of experiment {}".format(aer_job.name()) + ) if timeout: timeout = original_timeout - (time.time() - start_time) if timeout <= 0: - raise JobError( - "Timeout while waiting for JobSet results") + raise JobError("Timeout while waiting for JobSet results") return result def _combine_job_results(self, result_list: List[Result]): @@ -239,7 +238,7 @@ def _combine_job_results(self, result_list: List[Result]): _merge_result_list = [] for _result in result_list[1:]: - for (_master_result, _sub_result) in zip(master_result.results, _result.results): + for _master_result, _sub_result in zip(master_result.results, _result.results): _merge_result_list.append(self._merge_exp(_master_result, _sub_result)) master_result.results = _merge_result_list return master_result @@ -268,8 +267,7 @@ def _accumulate_experiment_results(self, results: List[Result]): for _result in each_result.results: if not hasattr(_result.data, "counts") and not hasattr(_result.data, "memory"): - raise JobError( - "Results do not include counts or memory data") + raise JobError("Results do not include counts or memory data") meta_data = getattr(_result.header, "metadata", None) if meta_data and "id" in meta_data: _id = meta_data["id"] @@ -295,9 +293,7 @@ def _merge_exp(self, master: Result, sub: Result): return master - def _combine_results(self, - results: List[Union[Result, None]] = None - ) -> Result: + def _combine_results(self, results: List[Union[Result, None]] = None) -> Result: """Combine results from all jobs into a single `Result`. Note: @@ -313,8 +309,7 @@ def _combine_results(self, JobError: If results cannot be combined because some jobs failed. """ if not results: - raise JobError( - "Results cannot be combined - no results.") + raise JobError("Results cannot be combined - no results.") # find first non-null result and copy it's config _result = next((r for r in results if r is not None), None) @@ -334,8 +329,7 @@ def _combine_results(self, combined_result["header"] = _result.header.to_dict() combined_result.update(_result._metadata) else: - raise JobError( - "Results cannot be combined - no results.") + raise JobError("Results cannot be combined - no results.") for each_result in results: if each_result is not None: @@ -381,9 +375,7 @@ def job(self, experiment: Union[str, QuantumCircuit, Schedule]) -> Tuple[AerJob, return self.worker_job(worker_index) @requires_submit - def worker(self, - experiment: Union[str, QuantumCircuit, Schedule] - ) -> Union[int, List[int]]: + def worker(self, experiment: Union[str, QuantumCircuit, Schedule]) -> Union[int, List[int]]: """Retrieve the index of job. Args: @@ -406,7 +398,7 @@ def worker(self, job_list = [] for job in self._futures: for i, exp in enumerate(job.qobj().experiments): - if hasattr(exp.header, 'name') and exp.header.name == experiment: + if hasattr(exp.header, "name") and exp.header.name == experiment: job_list.append(i) if len(job_list) == 1: @@ -414,13 +406,10 @@ def worker(self, elif len(job_list) > 1: return job_list - raise JobError( - 'Unable to find the job for experiment {}.'.format(experiment)) + raise JobError("Unable to find the job for experiment {}.".format(experiment)) @requires_submit - def worker_job(self, - worker: Union[None, int, Iterable[int]] - ) -> Union[AerJob, List[AerJob]]: + def worker_job(self, worker: Union[None, int, Iterable[int]]) -> Union[AerJob, List[AerJob]]: """Retrieve the job specified with job's id Args: diff --git a/qiskit_aer/jobs/utils.py b/qiskit_aer/jobs/utils.py index b778496a54..ad016d1f0c 100644 --- a/qiskit_aer/jobs/utils.py +++ b/qiskit_aer/jobs/utils.py @@ -34,11 +34,13 @@ def requires_submit(func): Returns: callable: the decorated function. """ + @wraps(func) def _wrapper(self, *args, **kwargs): if self._future is None: raise JobError("Job not submitted yet!. You have to .submit() first!") return func(self, *args, **kwargs) + return _wrapper @@ -51,13 +53,13 @@ def methdispatch(func): def wrapper(*args, **kw): return dispatcher.dispatch(args[2].__class__)(*args, **kw) + wrapper.register = dispatcher.register update_wrapper(wrapper, func) return wrapper def _copy_qobj_for_noise(qobj, max_shot_size, qobj_id): - num_shot_jobs, shot_mod = divmod(qobj.config.shots, max_shot_size) qobj_list = [] @@ -99,7 +101,7 @@ def _split_qobj(qobj, max_size, qobj_id, seed): qobjs = [] # Check for parameterizations - params = getattr(qobj.config, 'parameterizations', None) + params = getattr(qobj.config, "parameterizations", None) for i in range(num_jobs): sub_id = qobj_id or str(uuid.uuid4()) @@ -125,20 +127,13 @@ def _check_custom_instruction(experiments, optypes=None): # Check via optype list if available if optypes is not None: # Optypes store class names as strings - return any( - {"SaveData"}.intersection(optype) - for optype in optypes - ) + return any({"SaveData"}.intersection(optype) for optype in optypes) # Otherwise iterate over instruction names - return any( - "save_" in inst.name - for exp in experiments for inst in exp.instructions - ) + return any("save_" in inst.name for exp in experiments for inst in exp.instructions) def _set_seed(qobj_list, seed): - # set seed number to each qobj seed_shift = 256 @@ -169,19 +164,22 @@ def split_qobj(qobj, max_size=None, max_shot_size=None, qobj_id=None): Returns: List: A list of qobjs. """ - optypes = getattr(qobj.config, 'optypes', None) + optypes = getattr(qobj.config, "optypes", None) split_qobj_list = [] - if (max_shot_size is not None and max_shot_size > 0): + if max_shot_size is not None and max_shot_size > 0: if _check_custom_instruction(qobj.experiments, optypes): raise JobError( "`max_shot_size` option cannot be used with circuits" - " containing save instructions.") + " containing save instructions." + ) _seed = getattr(qobj.config, "seed_simulator", 0) if hasattr(qobj.config, "noise_model"): if _seed and max_size is not None and max_size > 1: - raise JobError("cannot support max_job_size > 1 for noise simulation, " - "when seed_simulator is set.") + raise JobError( + "cannot support max_job_size > 1 for noise simulation, " + "when seed_simulator is set." + ) if max_shot_size is not None and max_shot_size > 0: _qobj = _copy_qobj_for_noise(qobj, max_shot_size, qobj_id) diff --git a/qiskit_aer/library/__init__.py b/qiskit_aer/library/__init__.py index da05a836aa..965099e41c 100644 --- a/qiskit_aer/library/__init__.py +++ b/qiskit_aer/library/__init__.py @@ -177,27 +177,27 @@ """ __all__ = [ - 'SaveAmplitudes', - 'SaveAmplitudesSquared', - 'SaveClifford', - 'SaveDensityMatrix', - 'SaveExpectationValue', - 'SaveExpectationValueVariance', - 'SaveMatrixProductState', - 'SaveProbabilities', - 'SaveProbabilitiesDict', - 'SaveStabilizer', - 'SaveState', - 'SaveStatevector', - 'SaveStatevectorDict', - 'SaveSuperOp', - 'SaveUnitary', - 'SetDensityMatrix', - 'SetStabilizer', - 'SetStatevector', - 'SetSuperOp', - 'SetUnitary', - 'SetMatrixProductState' + "SaveAmplitudes", + "SaveAmplitudesSquared", + "SaveClifford", + "SaveDensityMatrix", + "SaveExpectationValue", + "SaveExpectationValueVariance", + "SaveMatrixProductState", + "SaveProbabilities", + "SaveProbabilitiesDict", + "SaveStabilizer", + "SaveState", + "SaveStatevector", + "SaveStatevectorDict", + "SaveSuperOp", + "SaveUnitary", + "SetDensityMatrix", + "SetStabilizer", + "SetStatevector", + "SetSuperOp", + "SetUnitary", + "SetMatrixProductState", ] from .save_instructions import * diff --git a/qiskit_aer/library/default_qubits.py b/qiskit_aer/library/default_qubits.py index 2e81fdc5a3..df251d158d 100644 --- a/qiskit_aer/library/default_qubits.py +++ b/qiskit_aer/library/default_qubits.py @@ -43,7 +43,7 @@ def default_qubits(circuit, qubits=None): for register in circuit.qregs: tuples.append(register) if not tuples: - raise ExtensionError('no qubits for snapshot') + raise ExtensionError("no qubits for snapshot") qubits = [] for tuple_element in tuples: if isinstance(tuple_element, QuantumRegister): diff --git a/qiskit_aer/library/save_instructions/__init__.py b/qiskit_aer/library/save_instructions/__init__.py index 1c5b990676..cb18acd870 100644 --- a/qiskit_aer/library/save_instructions/__init__.py +++ b/qiskit_aer/library/save_instructions/__init__.py @@ -11,22 +11,34 @@ # that they have been altered from the originals. """Save directive instructions for the Aer simulator""" -from .save_state import (SaveState, save_state) -from .save_expectation_value import (SaveExpectationValue, - save_expectation_value, - SaveExpectationValueVariance, - save_expectation_value_variance) -from .save_probabilities import (SaveProbabilities, save_probabilities, - SaveProbabilitiesDict, - save_probabilities_dict) -from .save_statevector import (SaveStatevector, save_statevector, - SaveStatevectorDict, save_statevector_dict) +from .save_state import SaveState, save_state +from .save_expectation_value import ( + SaveExpectationValue, + save_expectation_value, + SaveExpectationValueVariance, + save_expectation_value_variance, +) +from .save_probabilities import ( + SaveProbabilities, + save_probabilities, + SaveProbabilitiesDict, + save_probabilities_dict, +) +from .save_statevector import ( + SaveStatevector, + save_statevector, + SaveStatevectorDict, + save_statevector_dict, +) from .save_density_matrix import SaveDensityMatrix, save_density_matrix -from .save_amplitudes import (SaveAmplitudes, save_amplitudes, - SaveAmplitudesSquared, save_amplitudes_squared) -from .save_stabilizer import (SaveStabilizer, save_stabilizer) -from .save_clifford import (SaveClifford, save_clifford) -from .save_unitary import (SaveUnitary, save_unitary) -from .save_matrix_product_state import ( - SaveMatrixProductState, save_matrix_product_state) -from .save_superop import (SaveSuperOp, save_superop) +from .save_amplitudes import ( + SaveAmplitudes, + save_amplitudes, + SaveAmplitudesSquared, + save_amplitudes_squared, +) +from .save_stabilizer import SaveStabilizer, save_stabilizer +from .save_clifford import SaveClifford, save_clifford +from .save_unitary import SaveUnitary, save_unitary +from .save_matrix_product_state import SaveMatrixProductState, save_matrix_product_state +from .save_superop import SaveSuperOp, save_superop diff --git a/qiskit_aer/library/save_instructions/save_amplitudes.py b/qiskit_aer/library/save_instructions/save_amplitudes.py index 4daa0d3488..bcc12383d1 100644 --- a/qiskit_aer/library/save_instructions/save_amplitudes.py +++ b/qiskit_aer/library/save_instructions/save_amplitudes.py @@ -21,12 +21,8 @@ class SaveAmplitudes(SaveSingleData): """Save complex statevector amplitudes.""" - def __init__(self, - num_qubits, - params, - label="amplitudes", - pershot=False, - conditional=False): + + def __init__(self, num_qubits, params, label="amplitudes", pershot=False, conditional=False): """Instruction to save complex statevector amplitudes. Args: @@ -44,21 +40,28 @@ def __init__(self, ExtensionError: if params is invalid for the specified number of qubits. """ params = _format_amplitude_params(params, num_qubits) - super().__init__("save_amplitudes", num_qubits, label, - pershot=pershot, - conditional=conditional, - params=params) + super().__init__( + "save_amplitudes", + num_qubits, + label, + pershot=pershot, + conditional=conditional, + params=params, + ) class SaveAmplitudesSquared(SaveAverageData): """Save squared statevector amplitudes (probabilities).""" - def __init__(self, - num_qubits, - params, - label="amplitudes_squared", - unnormalized=False, - pershot=False, - conditional=False): + + def __init__( + self, + num_qubits, + params, + label="amplitudes_squared", + unnormalized=False, + pershot=False, + conditional=False, + ): """Instruction to save squared statevector amplitudes (probabilities). Args: @@ -78,13 +81,15 @@ def __init__(self, ExtensionError: if params is invalid for the specified number of qubits. """ params = _format_amplitude_params(params, num_qubits) - super().__init__("save_amplitudes_sq", - num_qubits, - label, - unnormalized=unnormalized, - pershot=pershot, - conditional=conditional, - params=params) + super().__init__( + "save_amplitudes_sq", + num_qubits, + label, + unnormalized=unnormalized, + pershot=pershot, + conditional=conditional, + params=params, + ) def save_amplitudes(self, params, label="amplitudes", pershot=False, conditional=False): @@ -107,15 +112,15 @@ def save_amplitudes(self, params, label="amplitudes", pershot=False, conditional ExtensionError: if params is invalid for the specified number of qubits. """ qubits = default_qubits(self) - instr = SaveAmplitudes(len(qubits), params, label=label, - pershot=pershot, conditional=conditional) + instr = SaveAmplitudes( + len(qubits), params, label=label, pershot=pershot, conditional=conditional + ) return self.append(instr, qubits) -def save_amplitudes_squared(self, params, label="amplitudes_squared", - unnormalized=False, - pershot=False, - conditional=False): +def save_amplitudes_squared( + self, params, label="amplitudes_squared", unnormalized=False, pershot=False, conditional=False +): """Save squared statevector amplitudes (probabilities). Args: @@ -137,23 +142,26 @@ def save_amplitudes_squared(self, params, label="amplitudes_squared", ExtensionError: if params is invalid for the specified number of qubits. """ qubits = default_qubits(self) - instr = SaveAmplitudesSquared(len(qubits), params, label=label, - unnormalized=unnormalized, - pershot=pershot, - conditional=conditional) + instr = SaveAmplitudesSquared( + len(qubits), + params, + label=label, + unnormalized=unnormalized, + pershot=pershot, + conditional=conditional, + ) return self.append(instr, qubits) def _format_amplitude_params(params, num_qubits=None): """Format amplitude params as a interger list.""" if isinstance(params[0], str): - if params[0].find('0x') == 0: + if params[0].find("0x") == 0: params = [int(i, 16) for i in params] else: params = [int(i, 2) for i in params] - if num_qubits and max(params) >= 2 ** num_qubits: - raise ExtensionError( - "Param values contain a state larger than the number of qubits") + if num_qubits and max(params) >= 2**num_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_clifford.py b/qiskit_aer/library/save_instructions/save_clifford.py index 866d1954d5..9088d1e9c2 100644 --- a/qiskit_aer/library/save_instructions/save_clifford.py +++ b/qiskit_aer/library/save_instructions/save_clifford.py @@ -20,6 +20,7 @@ class SaveClifford(SaveSingleData): """Save Clifford instruction""" + def __init__(self, num_qubits, label="clifford", pershot=False): """Create new instruction to save the stabilizer simulator state as a Clifford. @@ -36,7 +37,7 @@ def __init__(self, num_qubits, label="clifford", pershot=False): qubits in a circuit, otherwise an exception will be raised during simulation. """ - super().__init__('save_clifford', num_qubits, label, pershot=pershot) + super().__init__("save_clifford", num_qubits, label, pershot=pershot) def save_clifford(self, label="clifford", pershot=False): diff --git a/qiskit_aer/library/save_instructions/save_data.py b/qiskit_aer/library/save_instructions/save_data.py index c3803ff152..cb86edd94e 100644 --- a/qiskit_aer/library/save_instructions/save_data.py +++ b/qiskit_aer/library/save_instructions/save_data.py @@ -23,12 +23,11 @@ class SaveData(Instruction): """Pragma Instruction to save simulator data.""" _directive = True - _allowed_subtypes = set([ - 'single', 'c_single', 'list', 'c_list', - 'average', 'c_average', 'accum', 'c_accum' - ]) + _allowed_subtypes = set( + ["single", "c_single", "list", "c_list", "average", "c_average", "accum", "c_accum"] + ) - def __init__(self, name, num_qubits, label, subtype='single', params=None): + def __init__(self, name, num_qubits, label, subtype="single", params=None): """Create new save data instruction. Args: @@ -47,12 +46,12 @@ def __init__(self, name, num_qubits, label, subtype='single', params=None): 'c_average', 'accum', 'c_accum'. """ if subtype not in self._allowed_subtypes: - raise ExtensionError( - "Invalid data subtype for SaveData instruction.") + raise ExtensionError("Invalid data subtype for SaveData instruction.") if not isinstance(label, str): raise ExtensionError( - f"Invalid label for save data instruction, {label} must be a string.") + f"Invalid label for save data instruction, {label} must be a string." + ) if params is None: params = {} @@ -78,14 +77,17 @@ def inverse(self): class SaveAverageData(SaveData): """Save averageble data""" - def __init__(self, - name, - num_qubits, - label, - unnormalized=False, - pershot=False, - conditional=False, - params=None): + + def __init__( + self, + name, + num_qubits, + label, + unnormalized=False, + pershot=False, + conditional=False, + params=None, + ): """Create new save data instruction. Args: @@ -105,26 +107,20 @@ def __init__(self, [Default: None]. """ if pershot: - subtype = 'list' + subtype = "list" elif unnormalized: - subtype = 'accum' + subtype = "accum" else: - subtype = 'average' + subtype = "average" if conditional: - subtype = 'c_' + subtype + subtype = "c_" + subtype super().__init__(name, num_qubits, label, subtype=subtype, params=params) class SaveSingleData(SaveData): """Save non-averagable single data type.""" - def __init__(self, - name, - num_qubits, - label, - pershot=False, - conditional=False, - params=None): + def __init__(self, name, num_qubits, label, pershot=False, conditional=False, params=None): """Create new save data instruction. Args: @@ -139,7 +135,7 @@ def __init__(self, params (list or None): Optional, the parameters for instruction [Default: None]. """ - subtype = 'list' if pershot else 'single' + subtype = "list" if pershot else "single" if conditional: - subtype = 'c_' + subtype + subtype = "c_" + subtype super().__init__(name, num_qubits, label, subtype=subtype, params=params) diff --git a/qiskit_aer/library/save_instructions/save_density_matrix.py b/qiskit_aer/library/save_instructions/save_density_matrix.py index 289c050788..4532fef2f3 100644 --- a/qiskit_aer/library/save_instructions/save_density_matrix.py +++ b/qiskit_aer/library/save_instructions/save_density_matrix.py @@ -20,12 +20,15 @@ class SaveDensityMatrix(SaveAverageData): """Save a reduced density matrix.""" - def __init__(self, - num_qubits, - label="density_matrix", - unnormalized=False, - pershot=False, - conditional=False): + + def __init__( + self, + num_qubits, + label="density_matrix", + unnormalized=False, + pershot=False, + conditional=False, + ): """Create new instruction to save the simulator reduced density matrix. Args: @@ -41,18 +44,19 @@ def __init__(self, conditional on the current classical register values [Default: False]. """ - super().__init__("save_density_matrix", num_qubits, label, - unnormalized=unnormalized, - pershot=pershot, - conditional=conditional) + super().__init__( + "save_density_matrix", + num_qubits, + label, + unnormalized=unnormalized, + pershot=pershot, + conditional=conditional, + ) -def save_density_matrix(self, - qubits=None, - label="density_matrix", - unnormalized=False, - pershot=False, - conditional=False): +def save_density_matrix( + self, qubits=None, label="density_matrix", unnormalized=False, pershot=False, conditional=False +): """Save the current simulator quantum state as a density matrix. Args: @@ -74,11 +78,13 @@ def save_density_matrix(self, QuantumCircuit: with attached instruction. """ qubits = default_qubits(self, qubits=qubits) - instr = SaveDensityMatrix(len(qubits), - label=label, - unnormalized=unnormalized, - pershot=pershot, - conditional=conditional) + instr = SaveDensityMatrix( + len(qubits), + label=label, + unnormalized=unnormalized, + pershot=pershot, + conditional=conditional, + ) return self.append(instr, qubits) diff --git a/qiskit_aer/library/save_instructions/save_expectation_value.py b/qiskit_aer/library/save_instructions/save_expectation_value.py index 71fd85bd8a..27bcad9da0 100644 --- a/qiskit_aer/library/save_instructions/save_expectation_value.py +++ b/qiskit_aer/library/save_instructions/save_expectation_value.py @@ -22,12 +22,15 @@ class SaveExpectationValue(SaveAverageData): """Save expectation value of an operator.""" - def __init__(self, - operator, - label="expectation_value", - unnormalized=False, - pershot=False, - conditional=False): + + def __init__( + self, + operator, + label="expectation_value", + unnormalized=False, + pershot=False, + conditional=False, + ): r"""Instruction to save the expectation value of a Hermitian operator. The expectation value of a Hermitian operator :math:`H` for a simulator @@ -63,21 +66,28 @@ def __init__(self, if not allclose(operator.coeffs.imag, 0): raise ExtensionError("Input operator is not Hermitian.") params = _expval_params(operator, variance=False) - super().__init__('save_expval', operator.num_qubits, label, - unnormalized=unnormalized, - pershot=pershot, - conditional=conditional, - params=params) + super().__init__( + "save_expval", + operator.num_qubits, + label, + unnormalized=unnormalized, + pershot=pershot, + conditional=conditional, + params=params, + ) class SaveExpectationValueVariance(SaveAverageData): """Save expectation value and variance of an operator.""" - def __init__(self, - operator, - label="expectation_value_variance", - unnormalized=False, - pershot=False, - conditional=False): + + def __init__( + self, + operator, + label="expectation_value_variance", + unnormalized=False, + pershot=False, + conditional=False, + ): r"""Instruction to save the expectation value and variance of a Hermitian operator. The expectation value of a Hermitian operator :math:`H` for a @@ -114,15 +124,18 @@ def __init__(self, if not allclose(operator.coeffs.imag, 0): raise ExtensionError("Input operator is not Hermitian.") params = _expval_params(operator, variance=True) - super().__init__('save_expval_var', operator.num_qubits, label, - unnormalized=unnormalized, - pershot=pershot, - conditional=conditional, - params=params) + super().__init__( + "save_expval_var", + operator.num_qubits, + label, + unnormalized=unnormalized, + pershot=pershot, + conditional=conditional, + params=params, + ) def _expval_params(operator, variance=False): - # Convert O to SparsePauliOp representation if isinstance(operator, Pauli): operator = SparsePauliOp(operator) @@ -154,13 +167,15 @@ def _expval_params(operator, variance=False): return list(params.items()) -def save_expectation_value(self, - operator, - qubits, - label="expectation_value", - unnormalized=False, - pershot=False, - conditional=False): +def save_expectation_value( + self, + operator, + qubits, + label="expectation_value", + unnormalized=False, + pershot=False, + conditional=False, +): r"""Save the expectation value of a Hermitian operator. Args: @@ -188,21 +203,21 @@ def save_expectation_value(self, This method appends a :class:`SaveExpectationValue` instruction to the quantum circuit. """ - instr = SaveExpectationValue(operator, - label=label, - unnormalized=unnormalized, - pershot=pershot, - conditional=conditional) + instr = SaveExpectationValue( + operator, label=label, unnormalized=unnormalized, pershot=pershot, conditional=conditional + ) return self.append(instr, qubits) -def save_expectation_value_variance(self, - operator, - qubits, - label="expectation_value_variance", - unnormalized=False, - pershot=False, - conditional=False): +def save_expectation_value_variance( + self, + operator, + qubits, + label="expectation_value_variance", + unnormalized=False, + pershot=False, + conditional=False, +): r"""Save the expectation value of a Hermitian operator. Args: @@ -229,11 +244,9 @@ def save_expectation_value_variance(self, This method appends a :class:`SaveExpectationValueVariance` instruction to the quantum circuit. """ - instr = SaveExpectationValueVariance(operator, - label=label, - unnormalized=unnormalized, - pershot=pershot, - conditional=conditional) + instr = SaveExpectationValueVariance( + operator, label=label, unnormalized=unnormalized, pershot=pershot, conditional=conditional + ) return self.append(instr, qubits) diff --git a/qiskit_aer/library/save_instructions/save_matrix_product_state.py b/qiskit_aer/library/save_instructions/save_matrix_product_state.py index 12f6ed51ee..31163beeb3 100644 --- a/qiskit_aer/library/save_instructions/save_matrix_product_state.py +++ b/qiskit_aer/library/save_instructions/save_matrix_product_state.py @@ -20,10 +20,8 @@ class SaveMatrixProductState(SaveSingleData): """Save matrix product state instruction""" - def __init__(self, num_qubits, - label="matrix_product_state", - pershot=False, - conditional=False): + + def __init__(self, num_qubits, label="matrix_product_state", pershot=False, conditional=False): """Create new instruction to save the matrix product state. Args: @@ -40,11 +38,9 @@ def __init__(self, num_qubits, qubits in a circuit, otherwise an exception will be raised during simulation. """ - super().__init__('save_matrix_product_state', - num_qubits, - label, - pershot=pershot, - conditional=conditional) + super().__init__( + "save_matrix_product_state", num_qubits, label, pershot=pershot, conditional=conditional + ) def save_matrix_product_state(self, label="matrix_product_state", pershot=False, conditional=False): @@ -66,10 +62,9 @@ def save_matrix_product_state(self, label="matrix_product_state", pershot=False, This instruction is always defined across all qubits in a circuit. """ qubits = default_qubits(self) - instr = SaveMatrixProductState(len(qubits), - label=label, - pershot=pershot, - conditional=conditional) + instr = SaveMatrixProductState( + len(qubits), label=label, pershot=pershot, conditional=conditional + ) return self.append(instr, qubits) diff --git a/qiskit_aer/library/save_instructions/save_probabilities.py b/qiskit_aer/library/save_instructions/save_probabilities.py index caabbe53c6..cb3fcec678 100644 --- a/qiskit_aer/library/save_instructions/save_probabilities.py +++ b/qiskit_aer/library/save_instructions/save_probabilities.py @@ -20,12 +20,15 @@ class SaveProbabilities(SaveAverageData): """Save measurement outcome probabilities vector.""" - def __init__(self, - num_qubits, - label="probabilities", - unnormalized=False, - pershot=False, - conditional=False): + + def __init__( + self, + num_qubits, + label="probabilities", + unnormalized=False, + pershot=False, + conditional=False, + ): """Instruction to save measurement probabilities vector. Args: @@ -40,20 +43,27 @@ def __init__(self, on the current classical register values [Default: False]. """ - super().__init__("save_probabilities", num_qubits, label, - conditional=conditional, - pershot=pershot, - unnormalized=unnormalized) + super().__init__( + "save_probabilities", + num_qubits, + label, + conditional=conditional, + pershot=pershot, + unnormalized=unnormalized, + ) class SaveProbabilitiesDict(SaveAverageData): """Save measurement outcome probabilities dict.""" - def __init__(self, - num_qubits, - label="probabilities_dict", - unnormalized=False, - pershot=False, - conditional=False): + + def __init__( + self, + num_qubits, + label="probabilities_dict", + unnormalized=False, + pershot=False, + conditional=False, + ): """Instruction to save measurement probabilities dict. Args: @@ -68,18 +78,19 @@ def __init__(self, on the current classical register values [Default: False]. """ - super().__init__("save_probabilities_dict", num_qubits, label, - unnormalized=unnormalized, - pershot=pershot, - conditional=conditional) - - -def save_probabilities(self, - qubits=None, - label="probabilities", - unnormalized=False, - pershot=False, - conditional=False): + super().__init__( + "save_probabilities_dict", + num_qubits, + label, + unnormalized=unnormalized, + pershot=pershot, + conditional=conditional, + ) + + +def save_probabilities( + self, qubits=None, label="probabilities", unnormalized=False, pershot=False, conditional=False +): """Save measurement outcome probabilities vector. Args: @@ -99,20 +110,19 @@ def save_probabilities(self, QuantumCircuit: with attached instruction. """ qubits = default_qubits(self, qubits=qubits) - instr = SaveProbabilities(len(qubits), - label=label, - unnormalized=unnormalized, - pershot=pershot, - conditional=conditional) + instr = SaveProbabilities( + len(qubits), + label=label, + unnormalized=unnormalized, + pershot=pershot, + conditional=conditional, + ) return self.append(instr, qubits) -def save_probabilities_dict(self, - qubits=None, - label="probabilities", - unnormalized=False, - pershot=False, - conditional=False): +def save_probabilities_dict( + self, qubits=None, label="probabilities", unnormalized=False, pershot=False, conditional=False +): """Save measurement outcome probabilities vector. Args: @@ -132,11 +142,13 @@ def save_probabilities_dict(self, QuantumCircuit: with attached instruction. """ qubits = default_qubits(self, qubits=qubits) - instr = SaveProbabilitiesDict(len(qubits), - label=label, - unnormalized=unnormalized, - pershot=pershot, - conditional=conditional) + instr = SaveProbabilitiesDict( + len(qubits), + label=label, + unnormalized=unnormalized, + pershot=pershot, + conditional=conditional, + ) return self.append(instr, qubits) diff --git a/qiskit_aer/library/save_instructions/save_stabilizer.py b/qiskit_aer/library/save_instructions/save_stabilizer.py index 4a1ca163f1..9ad04e3724 100644 --- a/qiskit_aer/library/save_instructions/save_stabilizer.py +++ b/qiskit_aer/library/save_instructions/save_stabilizer.py @@ -20,8 +20,8 @@ class SaveStabilizer(SaveSingleData): """Save Stabilizer instruction""" - def __init__(self, num_qubits, label="stabilizer", - pershot=False, conditional=False): + + def __init__(self, num_qubits, label="stabilizer", pershot=False, conditional=False): """Create new instruction to save the stabilizer simulator state as a StabilizerState. Args: @@ -39,9 +39,9 @@ def __init__(self, num_qubits, label="stabilizer", qubits in a circuit, otherwise an exception will be raised during simulation. """ - super().__init__('save_stabilizer', num_qubits, label, - pershot=pershot, - conditional=conditional) + super().__init__( + "save_stabilizer", num_qubits, label, pershot=pershot, conditional=conditional + ) def save_stabilizer(self, label="stabilizer", pershot=False, conditional=False): @@ -63,10 +63,7 @@ def save_stabilizer(self, label="stabilizer", pershot=False, conditional=False): This instruction is always defined across all qubits in a circuit. """ qubits = default_qubits(self) - instr = SaveStabilizer(len(qubits), - label=label, - pershot=pershot, - conditional=conditional) + instr = SaveStabilizer(len(qubits), label=label, pershot=pershot, conditional=conditional) return self.append(instr, qubits) diff --git a/qiskit_aer/library/save_instructions/save_state.py b/qiskit_aer/library/save_instructions/save_state.py index 3e320d86ea..ab0d43ef4b 100644 --- a/qiskit_aer/library/save_instructions/save_state.py +++ b/qiskit_aer/library/save_instructions/save_state.py @@ -23,10 +23,8 @@ class SaveState(SaveSingleData): The format of the saved state depends on the simulation method used. """ - def __init__(self, num_qubits, - label=None, - pershot=False, - conditional=False): + + def __init__(self, num_qubits, label=None, pershot=False, conditional=False): """Create new instruction to save the simualtor state. The format of the saved state depends on the simulation method used. @@ -49,10 +47,8 @@ def __init__(self, num_qubits, simulation. """ if label is None: - label = '_method_' - super().__init__('save_state', num_qubits, label, - pershot=pershot, - conditional=conditional) + label = "_method_" + super().__init__("save_state", num_qubits, label, pershot=pershot, conditional=conditional) def save_state(self, label=None, pershot=False, conditional=False): @@ -76,10 +72,7 @@ def save_state(self, label=None, pershot=False, conditional=False): This instruction is always defined across all qubits in a circuit. """ qubits = default_qubits(self) - instr = SaveState(len(qubits), - label=label, - pershot=pershot, - conditional=conditional) + instr = SaveState(len(qubits), label=label, pershot=pershot, conditional=conditional) return self.append(instr, qubits) diff --git a/qiskit_aer/library/save_instructions/save_statevector.py b/qiskit_aer/library/save_instructions/save_statevector.py index 2358f86642..5bb112c32d 100644 --- a/qiskit_aer/library/save_instructions/save_statevector.py +++ b/qiskit_aer/library/save_instructions/save_statevector.py @@ -20,10 +20,8 @@ class SaveStatevector(SaveSingleData): """Save statevector""" - def __init__(self, num_qubits, - label="statevector", - pershot=False, - conditional=False): + + def __init__(self, num_qubits, label="statevector", pershot=False, conditional=False): """Create new instruction to save the simulator statevector. Args: @@ -41,17 +39,15 @@ def __init__(self, num_qubits, qubits in a circuit, otherwise an exception will be raised during simulation. """ - super().__init__('save_statevector', num_qubits, label, - pershot=pershot, - conditional=conditional) + super().__init__( + "save_statevector", num_qubits, label, pershot=pershot, conditional=conditional + ) class SaveStatevectorDict(SaveSingleData): """Save statevector as ket-form dictionary.""" - def __init__(self, num_qubits, - label="statevector_dict", - pershot=False, - conditional=False): + + def __init__(self, num_qubits, label="statevector_dict", pershot=False, conditional=False): """Create new instruction to save the simulator statevector as a dict. Args: @@ -69,9 +65,9 @@ def __init__(self, num_qubits, qubits in a circuit, otherwise an exception will be raised during simulation. """ - super().__init__('save_statevector_dict', num_qubits, label, - pershot=pershot, - conditional=conditional) + super().__init__( + "save_statevector_dict", num_qubits, label, pershot=pershot, conditional=conditional + ) def save_statevector(self, label="statevector", pershot=False, conditional=False): @@ -93,10 +89,7 @@ def save_statevector(self, label="statevector", pershot=False, conditional=False This instruction is always defined across all qubits in a circuit. """ qubits = default_qubits(self) - instr = SaveStatevector(len(qubits), - label=label, - pershot=pershot, - conditional=conditional) + instr = SaveStatevector(len(qubits), label=label, pershot=pershot, conditional=conditional) return self.append(instr, qubits) @@ -119,10 +112,7 @@ def save_statevector_dict(self, label="statevector", pershot=False, conditional= This instruction is always defined across all qubits in a circuit. """ qubits = default_qubits(self) - instr = SaveStatevectorDict(len(qubits), - label=label, - pershot=pershot, - conditional=conditional) + instr = SaveStatevectorDict(len(qubits), label=label, pershot=pershot, conditional=conditional) return self.append(instr, qubits) diff --git a/qiskit_aer/library/save_instructions/save_superop.py b/qiskit_aer/library/save_instructions/save_superop.py index d8ebca6103..d2ea183481 100644 --- a/qiskit_aer/library/save_instructions/save_superop.py +++ b/qiskit_aer/library/save_instructions/save_superop.py @@ -20,6 +20,7 @@ class SaveSuperOp(SaveSingleData): """Save a SuperOp matrix.""" + def __init__(self, num_qubits, label="superop", pershot=False): """Create new instruction to save the superop simulator state. diff --git a/qiskit_aer/library/save_instructions/save_unitary.py b/qiskit_aer/library/save_instructions/save_unitary.py index 8766852cbc..542992ca57 100644 --- a/qiskit_aer/library/save_instructions/save_unitary.py +++ b/qiskit_aer/library/save_instructions/save_unitary.py @@ -20,6 +20,7 @@ class SaveUnitary(SaveSingleData): """Save Unitary""" + def __init__(self, num_qubits, label="unitary", pershot=False): """Create new instruction to save the unitary simulator state. @@ -36,7 +37,7 @@ def __init__(self, num_qubits, label="unitary", pershot=False): qubits in a circuit, otherwise an exception will be raised during simulation. """ - super().__init__('save_unitary', num_qubits, label, pershot=pershot) + super().__init__("save_unitary", num_qubits, label, pershot=pershot) def save_unitary(self, label="unitary", pershot=False): diff --git a/qiskit_aer/library/set_instructions/set_density_matrix.py b/qiskit_aer/library/set_instructions/set_density_matrix.py index e228288440..08b013e1aa 100644 --- a/qiskit_aer/library/set_instructions/set_density_matrix.py +++ b/qiskit_aer/library/set_instructions/set_density_matrix.py @@ -43,9 +43,7 @@ def __init__(self, state): state = DensityMatrix(state) if not state.num_qubits or not state.is_valid(): raise ExtensionError("The input state is not valid") - super().__init__('set_density_matrix', - state.num_qubits, 0, - [state.data]) + super().__init__("set_density_matrix", state.num_qubits, 0, [state.data]) def set_density_matrix(self, state): @@ -73,7 +71,8 @@ def set_density_matrix(self, state): "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})" - f" != QuantumCircuit.num_qubits ({self.num_qubits})).") + f" != QuantumCircuit.num_qubits ({self.num_qubits}))." + ) return self.append(SetDensityMatrix(state), 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 302057bc70..1546c842f1 100644 --- a/qiskit_aer/library/set_instructions/set_matrix_product_state.py +++ b/qiskit_aer/library/set_instructions/set_matrix_product_state.py @@ -38,7 +38,7 @@ def __init__(self, state): vector of pairs of matrices of complex numbers. The second is a vector of vectors of double. """ - super().__init__('set_matrix_product_state', len(state[0]), 0, [state]) + super().__init__("set_matrix_product_state", len(state[0]), 0, [state]) def set_matrix_product_state(self, state): @@ -61,19 +61,23 @@ def set_matrix_product_state(self, state): qubits = default_qubits(self) if not isinstance(state, tuple) or len(state) != 2: raise ExtensionError( - "The input matrix product state is not valid. Should be a list of 2 elements") + "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 ExtensionError( - "The first element of the input matrix product state is not valid. Should be a list.") + "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 ExtensionError( "The input matrix product state is not valid. " - "Length of q_reg vector should be 1 more than length of lambda_reg") + "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 ExtensionError( "The input matrix product state is not valid." - "The first element should be a list of length 2") + "The first element should be a list of length 2" + ) return self.append(SetMatrixProductState(state), qubits) diff --git a/qiskit_aer/library/set_instructions/set_stabilizer.py b/qiskit_aer/library/set_instructions/set_stabilizer.py index bbafbc8703..7767560f41 100644 --- a/qiskit_aer/library/set_instructions/set_stabilizer.py +++ b/qiskit_aer/library/set_instructions/set_stabilizer.py @@ -40,7 +40,7 @@ def __init__(self, state): state = state.clifford elif not isinstance(state, Clifford): state = Clifford(state) - super().__init__('set_stabilizer', state.num_qubits, 0, [state.to_dict()]) + super().__init__("set_stabilizer", state.num_qubits, 0, [state.to_dict()]) def set_stabilizer(self, state): @@ -70,7 +70,8 @@ def set_stabilizer(self, state): "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})" - f" != QuantumCircuit.num_qubits ({self.num_qubits})).") + f" != QuantumCircuit.num_qubits ({self.num_qubits}))." + ) return self.append(SetStabilizer(state), qubits) diff --git a/qiskit_aer/library/set_instructions/set_statevector.py b/qiskit_aer/library/set_instructions/set_statevector.py index a2fb6ab8d9..25603cecc5 100644 --- a/qiskit_aer/library/set_instructions/set_statevector.py +++ b/qiskit_aer/library/set_instructions/set_statevector.py @@ -43,7 +43,7 @@ def __init__(self, state): state = Statevector(state) if not state.num_qubits or not state.is_valid(): raise ExtensionError("The input statevector is not valid") - super().__init__('set_statevector', state.num_qubits, 0, [state.data]) + super().__init__("set_statevector", state.num_qubits, 0, [state.data]) def set_statevector(self, state): @@ -71,7 +71,8 @@ def set_statevector(self, state): "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})" - f" != QuantumCircuit.num_qubits ({self.num_qubits})).") + f" != QuantumCircuit.num_qubits ({self.num_qubits}))." + ) return self.append(SetStatevector(state), qubits) diff --git a/qiskit_aer/library/set_instructions/set_superop.py b/qiskit_aer/library/set_instructions/set_superop.py index e176834c99..0538e5f2dd 100644 --- a/qiskit_aer/library/set_instructions/set_superop.py +++ b/qiskit_aer/library/set_instructions/set_superop.py @@ -43,8 +43,7 @@ def __init__(self, state): state = SuperOp(state) if not state.num_qubits or not state.is_cptp(): raise ExtensionError("The input quantum channel is not CPTP") - super().__init__('set_superop', state.num_qubits, 0, - [state.data]) + super().__init__("set_superop", state.num_qubits, 0, [state.data]) def set_superop(self, state): @@ -73,7 +72,8 @@ def set_superop(self, state): "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})" - f" != QuantumCircuit.num_qubits ({self.num_qubits})).") + f" != QuantumCircuit.num_qubits ({self.num_qubits}))." + ) return self.append(SetSuperOp(state), qubits) diff --git a/qiskit_aer/library/set_instructions/set_unitary.py b/qiskit_aer/library/set_instructions/set_unitary.py index 744923d5ac..ab8e261cdc 100644 --- a/qiskit_aer/library/set_instructions/set_unitary.py +++ b/qiskit_aer/library/set_instructions/set_unitary.py @@ -43,8 +43,7 @@ def __init__(self, state): state = Operator(state) if not state.num_qubits or not state.is_unitary(): raise ExtensionError("The input matrix is not unitary") - super().__init__('set_unitary', state.num_qubits, 0, - [state.data]) + super().__init__("set_unitary", state.num_qubits, 0, [state.data]) def set_unitary(self, state): @@ -73,7 +72,8 @@ def set_unitary(self, state): "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})" - f" != QuantumCircuit.num_qubits ({self.num_qubits})).") + f" != QuantumCircuit.num_qubits ({self.num_qubits}))." + ) return self.append(SetUnitary(state), qubits) diff --git a/qiskit_aer/noise/device/models.py b/qiskit_aer/noise/device/models.py index 657e74c8ec..480c571a2e 100644 --- a/qiskit_aer/noise/device/models.py +++ b/qiskit_aer/noise/device/models.py @@ -79,14 +79,16 @@ def basic_device_readout_errors(properties=None, target=None): return errors -def basic_device_gate_errors(properties=None, - gate_error=True, - thermal_relaxation=True, - gate_lengths=None, - gate_length_units='ns', - temperature=0, - warnings=None, - target=None): +def basic_device_gate_errors( + properties=None, + gate_error=True, + thermal_relaxation=True, + gate_lengths=None, + gate_length_units="ns", + temperature=0, + warnings=None, + target=None, +): """ Return QuantumErrors derived from either of a devices BackendProperties or Target. @@ -134,26 +136,33 @@ def basic_device_gate_errors(properties=None, if warnings is not None: warn( '"warnings" argument has been deprecated as of qiskit-aer 0.12.0 ' - 'and will be removed no earlier than 3 months from that release date. ' - 'Use the warnings filter in Python standard library instead.', - DeprecationWarning, stacklevel=2) + "and will be removed no earlier than 3 months from that release date. " + "Use the warnings filter in Python standard library instead.", + DeprecationWarning, + stacklevel=2, + ) else: warnings = True if target is not None: if not warnings: - warn("When `target` is supplied, `warnings` are ignored," - " and they are always set to true.", UserWarning) + warn( + "When `target` is supplied, `warnings` are ignored," + " and they are always set to true.", + UserWarning, + ) if gate_lengths: - raise NoiseError("When `target` is supplied, `gate_lengths` option is not allowed." - "Use `duration` property in target's InstructionProperties instead.") + raise NoiseError( + "When `target` is supplied, `gate_lengths` option is not allowed." + "Use `duration` property in target's InstructionProperties instead." + ) return _basic_device_target_gate_errors( target=target, gate_error=gate_error, thermal_relaxation=thermal_relaxation, - temperature=temperature + temperature=temperature, ) # Generate custom gate time dict @@ -186,23 +195,19 @@ def basic_device_gate_errors(properties=None, relax_time = gate_length # Override with custom value if name in custom_times: - filtered = [ - val for q, val in custom_times[name] - if q is None or q == qubits - ] + filtered = [val for q, val in custom_times[name] if q is None or q == qubits] if filtered: # get first value relax_time = filtered[0] # Get relaxation error if thermal_relaxation: relax_error = _device_thermal_relaxation_error( - qubits, relax_time, relax_params, temperature, - thermal_relaxation) + qubits, relax_time, relax_params, temperature, thermal_relaxation + ) # Get depolarizing error channel if gate_error: - depol_error = _device_depolarizing_error( - qubits, error_param, relax_error) + depol_error = _device_depolarizing_error(qubits, error_param, relax_error) # Combine errors combined_error = _combine_depol_and_relax_error(depol_error, relax_error) @@ -222,10 +227,9 @@ def _combine_depol_and_relax_error(depol_error, relax_error): return None -def _basic_device_target_gate_errors(target, - gate_error=True, - thermal_relaxation=True, - temperature=0): +def _basic_device_target_gate_errors( + target, gate_error=True, thermal_relaxation=True, temperature=0 +): """Return QuantumErrors derived from a devices Target. 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, @@ -245,10 +249,14 @@ def _basic_device_target_gate_errors(target, relax_error = None # Get relaxation error if thermal_relaxation and inst_prop.duration: - relax_params = {q: (target.qubit_properties[q].t1, - target.qubit_properties[q].t2, - target.qubit_properties[q].frequency) - for q in qubits} + relax_params = { + q: ( + target.qubit_properties[q].t1, + target.qubit_properties[q].t2, + target.qubit_properties[q].frequency, + ) + for q in qubits + } relax_error = _device_thermal_relaxation_error( qubits=qubits, gate_time=inst_prop.duration, @@ -270,9 +278,7 @@ def _basic_device_target_gate_errors(target, return errors -def _device_depolarizing_error(qubits, - error_param, - relax_error=None): +def _device_depolarizing_error(qubits, error_param, relax_error=None): """Construct a depolarizing_error for device. If un-physical parameters are supplied, they are truncated to the theoretical bound values.""" @@ -301,7 +307,7 @@ def _device_depolarizing_error(qubits, relax_infid = 0 if error_param is not None and error_param > relax_infid: num_qubits = len(qubits) - dim = 2 ** num_qubits + dim = 2**num_qubits error_max = dim / (dim + 1) # Check if reported error param is un-physical # The minimum average gate fidelity is F_min = 1 / (dim + 1) @@ -309,7 +315,7 @@ def _device_depolarizing_error(qubits, error_param = min(error_param, error_max) # Model gate error entirely as depolarizing error num_qubits = len(qubits) - dim = 2 ** num_qubits + dim = 2**num_qubits depol_param = dim * (error_param - relax_infid) / (dim * relax_fid - 1) max_param = 4**num_qubits / (4**num_qubits - 1) if depol_param > max_param: @@ -318,11 +324,9 @@ def _device_depolarizing_error(qubits, return None -def _device_thermal_relaxation_error(qubits, - gate_time, - relax_params, - temperature, - thermal_relaxation=True): +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 not thermal_relaxation or gate_time is None or gate_time == 0: diff --git a/qiskit_aer/noise/device/parameters.py b/qiskit_aer/noise/device/parameters.py index 88e8fcb473..04cf0df41a 100644 --- a/qiskit_aer/noise/device/parameters.py +++ b/qiskit_aer/noise/device/parameters.py @@ -17,8 +17,8 @@ from numpy import inf # Time and frequency unit conversions -_NANOSECOND_UNITS = {'s': 1e9, 'ms': 1e6, 'µs': 1e3, 'us': 1e3, 'ns': 1} -_GHZ_UNITS = {'Hz': 1e-9, 'KHz': 1e-6, 'MHz': 1e-3, 'GHz': 1, 'THz': 1e3} +_NANOSECOND_UNITS = {"s": 1e9, "ms": 1e6, "µs": 1e3, "us": 1e3, "ns": 1} +_GHZ_UNITS = {"Hz": 1e-9, "KHz": 1e-6, "MHz": 1e-3, "GHz": 1, "THz": 1e3} def gate_param_values(properties): @@ -39,16 +39,16 @@ def gate_param_values(properties): qubits = gate.qubits # Check for gate time information gate_length = None # default value - time_param = _check_for_item(gate.parameters, 'gate_length') - if hasattr(time_param, 'value'): + time_param = _check_for_item(gate.parameters, "gate_length") + if hasattr(time_param, "value"): gate_length = time_param.value - if hasattr(time_param, 'unit'): + if hasattr(time_param, "unit"): # Convert gate time to ns gate_length *= _NANOSECOND_UNITS.get(time_param.unit, 1) # Check for gate error information gate_error = None # default value - error_param = _check_for_item(gate.parameters, 'gate_error') - if hasattr(error_param, 'value'): + error_param = _check_for_item(gate.parameters, "gate_error") + if hasattr(error_param, "value"): gate_error = error_param.value values.append((name, qubits, gate_length, gate_error)) @@ -72,8 +72,8 @@ def gate_error_values(properties): name = gate.gate qubits = gate.qubits value = None # default value - params = _check_for_item(gate.parameters, 'gate_error') - if hasattr(params, 'value'): + params = _check_for_item(gate.parameters, "gate_error") + if hasattr(params, "value"): value = params.value values.append((name, qubits, value)) return values @@ -98,10 +98,10 @@ def gate_length_values(properties): name = gate.gate qubits = gate.qubits value = None # default value - params = _check_for_item(gate.parameters, 'gate_length') - if hasattr(params, 'value'): + params = _check_for_item(gate.parameters, "gate_length") + if hasattr(params, "value"): value = params.value - if hasattr(params, 'unit'): + if hasattr(params, "unit"): # Convert gate time to ns value *= _NANOSECOND_UNITS.get(params.unit, 1) values.append((name, qubits, value)) @@ -124,13 +124,13 @@ def readout_error_values(properties): for qubit_props in properties.qubits: value = None # default value - params_roerror = _check_for_item(qubit_props, 'readout_error') - params_m1p0 = _check_for_item(qubit_props, 'prob_meas1_prep0') - params_m0p1 = _check_for_item(qubit_props, 'prob_meas0_prep1') + params_roerror = _check_for_item(qubit_props, "readout_error") + params_m1p0 = _check_for_item(qubit_props, "prob_meas1_prep0") + params_m0p1 = _check_for_item(qubit_props, "prob_meas0_prep1") - if hasattr(params_m1p0, 'value') and hasattr(params_m0p1, 'value'): + if hasattr(params_m1p0, "value") and hasattr(params_m0p1, "value"): value = [params_m1p0.value, params_m0p1.value] - elif hasattr(params_roerror, 'value'): + elif hasattr(params_roerror, "value"): value = [params_roerror.value, params_roerror.value] values.append(value) return values @@ -161,24 +161,24 @@ def thermal_relaxation_values(properties): t1, t2, freq = inf, inf, inf # Get the readout error value - t1_params = _check_for_item(qubit_props, 'T1') - t2_params = _check_for_item(qubit_props, 'T2') - freq_params = _check_for_item(qubit_props, 'frequency') + t1_params = _check_for_item(qubit_props, "T1") + t2_params = _check_for_item(qubit_props, "T2") + freq_params = _check_for_item(qubit_props, "frequency") # Load values from parameters - if hasattr(t1_params, 'value'): + if hasattr(t1_params, "value"): t1 = t1_params.value - if hasattr(t1_params, 'unit'): + if hasattr(t1_params, "unit"): # Convert to nanoseconds t1 *= _NANOSECOND_UNITS.get(t1_params.unit, 1) - if hasattr(t2_params, 'value'): + if hasattr(t2_params, "value"): t2 = t2_params.value - if hasattr(t2_params, 'unit'): + if hasattr(t2_params, "unit"): # Convert to nanoseconds t2 *= _NANOSECOND_UNITS.get(t2_params.unit, 1) - if hasattr(freq_params, 'value'): + if hasattr(freq_params, "value"): freq = freq_params.value - if hasattr(freq_params, 'unit'): + if hasattr(freq_params, "unit"): # Convert to Gigahertz freq *= _GHZ_UNITS.get(freq_params.unit, 1) diff --git a/qiskit_aer/noise/errors/quantum_error.py b/qiskit_aer/noise/errors/quantum_error.py index 5d8efd335c..59d65c469f 100644 --- a/qiskit_aer/noise/errors/quantum_error.py +++ b/qiskit_aer/noise/errors/quantum_error.py @@ -44,8 +44,7 @@ class QuantumError(BaseOperator, TolerancesMixin): module. """ - def __init__(self, - noise_ops): + def __init__(self, noise_ops): """ Create a quantum error for a noise model. @@ -102,8 +101,9 @@ def __init__(self, return # Single circuit case - if not isinstance(noise_ops, Iterable) or \ - (isinstance(noise_ops, tuple) and isinstance(noise_ops[0], Instruction)): + if not isinstance(noise_ops, Iterable) or ( + isinstance(noise_ops, tuple) and isinstance(noise_ops[0], Instruction) + ): noise_ops = [(noise_ops, 1.0)] # Convert zipped object to list (to enable multiple iteration over it) @@ -180,7 +180,7 @@ def _to_circuit(cls, op): f"Fail to convert {op.__class__.__name__} to Instruction." ) from err if isinstance(op, BaseOperator): - if hasattr(op, 'to_instruction'): + if hasattr(op, "to_instruction"): try: return cls._to_circuit(op.to_instruction()) except QiskitError as err: @@ -231,7 +231,7 @@ def __hash__(self): return hash(self._id) @property - def id(self): # pylint: disable=invalid-name + def id(self): # pylint: disable=invalid-name """Return unique ID string for error""" return self._id @@ -273,15 +273,16 @@ def ideal(self): if isinstance(op, IGate): continue if isinstance(op, PauliGate): - if op.params[0].replace('I', ''): + if op.params[0].replace("I", ""): return False else: # Convert to Kraus and check if identity kmats = Kraus(op).data if len(kmats) > 1: return False - if not is_identity_matrix(kmats[0], ignore_phase=True, - atol=self.atol, rtol=self.rtol): + if not is_identity_matrix( + kmats[0], ignore_phase=True, atol=self.atol, rtol=self.rtol + ): return False return True @@ -289,7 +290,7 @@ def to_quantumchannel(self): """Convert the QuantumError to a SuperOp quantum channel. Required to enable SuperOp(QuantumError).""" # Initialize as an empty superoperator of the correct size - dim = 2 ** self.num_qubits + dim = 2**self.num_qubits ret = SuperOp(np.zeros([dim * dim, dim * dim])) for circ, prob in zip(self.circuits, self.probabilities): component = prob * SuperOp(circ) @@ -340,7 +341,7 @@ def to_dict(self): "id": self.id, "operations": [], "instructions": instructions, - "probabilities": list(self.probabilities) + "probabilities": list(self.probabilities), } return error @@ -349,22 +350,26 @@ def compose(self, other, qargs=None, front=False): other = QuantumError(other) if qargs is not None: if self.num_qubits < other.num_qubits: - raise QiskitError("Number of qubits of this error must be less than" - " that of the error to be composed if using 'qargs' argument.") + raise QiskitError( + "Number of qubits of this error must be less than" + " that of the error to be composed if using 'qargs' argument." + ) if len(qargs) != other.num_qubits: - raise QiskitError("Number of items in 'qargs' argument must be the same as" - " number of qubits of the error to be composed.") + raise QiskitError( + "Number of items in 'qargs' argument must be the same as" + " number of qubits of the error to be composed." + ) if front: raise QiskitError( "QuantumError.compose does not support 'qargs' when 'front=True'." ) - circs = [self._compose_circ(lqc, rqc, qubits=qargs, front=front) - for lqc in self.circuits - for rqc in other.circuits] - probs = [lpr * rpr - for lpr in self.probabilities - for rpr in other.probabilities] + circs = [ + self._compose_circ(lqc, rqc, qubits=qargs, front=front) + for lqc in self.circuits + for rqc in other.circuits + ] + probs = [lpr * rpr for lpr in self.probabilities for rpr in other.probabilities] return QuantumError(zip(circs, probs)) @staticmethod @@ -389,12 +394,8 @@ def tensor(self, other): if not isinstance(other, QuantumError): other = QuantumError(other) - circs = [lqc.tensor(rqc) - for lqc in self.circuits - for rqc in other.circuits] - probs = [lpr * rpr - for lpr in self.probabilities - for rpr in other.probabilities] + circs = [lqc.tensor(rqc) for lqc in self.circuits for rqc in other.circuits] + probs = [lpr * rpr for lpr in self.probabilities for rpr in other.probabilities] return QuantumError(zip(circs, probs)) def expand(self, other): diff --git a/qiskit_aer/noise/errors/readout_error.py b/qiskit_aer/noise/errors/readout_error.py index f84661d494..8374e6736c 100644 --- a/qiskit_aer/noise/errors/readout_error.py +++ b/qiskit_aer/noise/errors/readout_error.py @@ -27,6 +27,7 @@ class ReadoutError: """ Readout error class for Qiskit Aer noise model. """ + # pylint: disable=invalid-name _ATOL_DEFAULT = ATOL_DEFAULT _RTOL_DEFAULT = RTOL_DEFAULT @@ -82,8 +83,10 @@ def __repr__(self): def __str__(self): """Print error information.""" - output = "ReadoutError on {} qubits.".format(self._number_of_qubits) + \ - " Assignment probabilities:" + output = ( + "ReadoutError on {} qubits.".format(self._number_of_qubits) + + " Assignment probabilities:" + ) for j, vec in enumerate(self._probabilities): output += "\n P(j|{0}) = {1}".format(j, vec) return output @@ -94,8 +97,9 @@ def __eq__(self, other): return False if self.number_of_qubits != other.number_of_qubits: return False - return np.allclose(self._probabilities, other._probabilities, - atol=self.atol, rtol=self.rtol) + return np.allclose( + self._probabilities, other._probabilities, atol=self.atol, rtol=self.rtol + ) def copy(self): """Make a copy of current ReadoutError.""" @@ -127,24 +131,18 @@ def rtol(self): def set_atol(cls, value): """Set the class default absolute tolerance parameter for float comparisons.""" if value < 0: - raise NoiseError( - "Invalid atol ({}) must be non-negative.".format(value)) + raise NoiseError("Invalid atol ({}) must be non-negative.".format(value)) if value > cls._MAX_TOL: - raise NoiseError( - "Invalid atol ({}) must be less than {}.".format( - value, cls._MAX_TOL)) + raise NoiseError("Invalid atol ({}) must be less than {}.".format(value, cls._MAX_TOL)) cls._ATOL_DEFAULT = value @classmethod def set_rtol(cls, value): """Set the class default relative tolerance parameter for float comparisons.""" if value < 0: - raise NoiseError( - "Invalid rtol ({}) must be non-negative.".format(value)) + raise NoiseError("Invalid rtol ({}) must be non-negative.".format(value)) if value > cls._MAX_TOL: - raise NoiseError( - "Invalid rtol ({}) must be less than {}.".format( - value, cls._MAX_TOL)) + raise NoiseError("Invalid rtol ({}) must be less than {}.".format(value, cls._MAX_TOL)) cls._RTOL_DEFAULT = value def ideal(self): @@ -164,7 +162,7 @@ def to_dict(self): error = { "type": "roerror", "operations": ["measure"], - "probabilities": self._probabilities.tolist() + "probabilities": self._probabilities.tolist(), } return error @@ -256,28 +254,30 @@ def expand(self, other): def _check_probabilities(probabilities, threshold): """Check probabilities are valid.""" # probabilities parameter can be a list or a numpy.ndarray - if (isinstance(probabilities, list) and not probabilities) or \ - (isinstance(probabilities, np.ndarray) and probabilities.size == 0): + if (isinstance(probabilities, list) and not probabilities) or ( + isinstance(probabilities, np.ndarray) and probabilities.size == 0 + ): raise NoiseError("Input probabilities: empty.") num_outcomes = len(probabilities[0]) num_qubits = int(np.log2(num_outcomes)) if 2**num_qubits != num_outcomes: - raise NoiseError("Invalid probabilities: length " - "{} != 2**{}".format(num_outcomes, num_qubits)) + raise NoiseError( + "Invalid probabilities: length " "{} != 2**{}".format(num_outcomes, num_qubits) + ) if len(probabilities) != num_outcomes: raise NoiseError("Invalid probabilities.") for vec in probabilities: arr = np.array(vec) if len(arr) != num_outcomes: - raise NoiseError( - "Invalid probabilities: vectors are different lengths.") + raise NoiseError("Invalid probabilities: vectors are different lengths.") if abs(sum(arr) - 1) > threshold: - raise NoiseError("Invalid probabilities: sum({})= {} " - "is not 1.".format(vec, sum(arr))) + raise NoiseError( + "Invalid probabilities: sum({})= {} " "is not 1.".format(vec, sum(arr)) + ) if arr[arr < 0].size > 0: raise NoiseError( - "Invalid probabilities: {} " - "contains a negative probability.".format(vec)) + "Invalid probabilities: {} " "contains a negative probability.".format(vec) + ) def _matmul(self, other, left_multiply=False): """Return the composition readout error. @@ -335,8 +335,7 @@ def __xor__(self, other): return self.tensor(other) def __rmul__(self, other): - raise NotImplementedError( - "'ReadoutError' does not support scalar multiplication.") + raise NotImplementedError("'ReadoutError' does not support scalar multiplication.") def __truediv__(self, other): raise NotImplementedError("'ReadoutError' does not support division.") @@ -345,8 +344,7 @@ def __add__(self, other): raise NotImplementedError("'ReadoutError' does not support addition.") def __sub__(self, other): - raise NotImplementedError( - "'ReadoutError' does not support subtraction.") + raise NotImplementedError("'ReadoutError' does not support subtraction.") def __neg__(self): raise NotImplementedError("'ReadoutError' does not support negation.") diff --git a/qiskit_aer/noise/errors/standard_errors.py b/qiskit_aer/noise/errors/standard_errors.py index cbb01e8667..a02a8652fd 100644 --- a/qiskit_aer/noise/errors/standard_errors.py +++ b/qiskit_aer/noise/errors/standard_errors.py @@ -83,7 +83,7 @@ def mixed_unitary_error(noise_ops): raise NoiseError("Input noise list is empty.") # Check for identity unitaries - prob_identity = 0. + prob_identity = 0.0 instructions = [] instructions_probs = [] num_qubits = int(np.log2(noise_ops[0][0].shape[0])) @@ -202,11 +202,10 @@ def depolarizing_error(param, num_qubits): if not isinstance(num_qubits, int) or num_qubits < 1: raise NoiseError("num_qubits must be a positive integer.") # Check that the depolarizing parameter gives a valid CPTP - num_terms = 4 ** num_qubits + num_terms = 4**num_qubits max_param = num_terms / (num_terms - 1) if param < 0 or param > max_param: - raise NoiseError("Depolarizing parameter must be in between 0 " - "and {}.".format(max_param)) + raise NoiseError("Depolarizing parameter must be in between 0 " "and {}.".format(max_param)) # Rescale completely depolarizing channel error probs # with the identity component removed @@ -216,7 +215,7 @@ def depolarizing_error(param, num_qubits): # Generate pauli strings. The order doesn't matter as long # as the all identity string is first. - paulis = [Pauli("".join(tup)) for tup in it.product(['I', 'X', 'Y', 'Z'], repeat=num_qubits)] + paulis = [Pauli("".join(tup)) for tup in it.product(["I", "X", "Y", "Z"], repeat=num_qubits)] return QuantumError(zip(paulis, probs)) @@ -249,7 +248,7 @@ def reset_error(prob0, prob1=0): noise_ops = [ ([(IGate(), [0])], 1 - prob0 - prob1), ([(Reset(), [0])], prob0), - ([(Reset(), [0]), (XGate(), [0])], prob1) + ([(Reset(), [0]), (XGate(), [0])], prob1), ] return QuantumError(noise_ops) @@ -283,11 +282,13 @@ def thermal_relaxation_error(t1, t2, time, excited_state_population=0): general non-unitary Kraus error channel. """ if excited_state_population < 0: - raise NoiseError("Invalid excited state population " - "({} < 0).".format(excited_state_population)) + raise NoiseError( + "Invalid excited state population " "({} < 0).".format(excited_state_population) + ) if excited_state_population > 1: - raise NoiseError("Invalid excited state population " - "({} > 1).".format(excited_state_population)) + raise NoiseError( + "Invalid excited state population " "({} > 1).".format(excited_state_population) + ) if time < 0: raise NoiseError("Invalid gate_time ({} < 0)".format(time)) if t1 <= 0: @@ -295,8 +296,7 @@ def thermal_relaxation_error(t1, t2, time, excited_state_population=0): if t2 <= 0: raise NoiseError("Invalid T_2 relaxation time parameter: T_2 <= 0.") if t2 - 2 * t1 > 0: - raise NoiseError( - "Invalid T_2 relaxation time parameter: T_2 greater than 2 * T_1.") + raise NoiseError("Invalid T_2 relaxation time parameter: T_2 greater than 2 * T_1.") # T1 relaxation rate if t1 == np.inf: @@ -320,9 +320,15 @@ def thermal_relaxation_error(t1, t2, time, excited_state_population=0): # If T_2 > T_1 we must express this as a Kraus channel # We start with the Choi-matrix representation: chan = Choi( - np.array([[1 - p1 * p_reset, 0, 0, exp_t2], - [0, p1 * p_reset, 0, 0], [0, 0, p0 * p_reset, 0], - [exp_t2, 0, 0, 1 - p0 * p_reset]])) + np.array( + [ + [1 - p1 * p_reset, 0, 0, exp_t2], + [0, p1 * p_reset, 0, 0], + [0, 0, p0 * p_reset, 0], + [exp_t2, 0, 0, 1 - p0 * p_reset], + ] + ) + ) return QuantumError(Kraus(chan)) else: # If T_2 < T_1 we can express this channel as a probabilistic @@ -331,7 +337,7 @@ def thermal_relaxation_error(t1, t2, time, excited_state_population=0): [(IGate(), [0])], [(ZGate(), [0])], [(Reset(), [0])], - [(Reset(), [0]), (XGate(), [0])] + [(Reset(), [0]), (XGate(), [0])], ] # Probability p_reset0 = p_reset * p0 @@ -342,10 +348,9 @@ def thermal_relaxation_error(t1, t2, time, excited_state_population=0): return QuantumError(zip(circuits, probabilities)) -def phase_amplitude_damping_error(param_amp, - param_phase, - excited_state_population=0, - canonical_kraus=True): +def phase_amplitude_damping_error( + param_amp, param_phase, excited_state_population=0, canonical_kraus=True +): r""" Return a single-qubit combined phase and amplitude damping quantum error channel. @@ -385,20 +390,22 @@ def phase_amplitude_damping_error(param_amp, """ if param_amp < 0: - raise NoiseError("Invalid amplitude damping to |0> parameter " - "({} < 0)".format(param_amp)) + raise NoiseError("Invalid amplitude damping to |0> parameter " "({} < 0)".format(param_amp)) if param_phase < 0: - raise NoiseError("Invalid phase damping parameter " - "({} < 0)".format(param_phase)) + raise NoiseError("Invalid phase damping parameter " "({} < 0)".format(param_phase)) if param_phase + param_amp > 1: - raise NoiseError("Invalid amplitude and phase damping parameters " - "({} + {} > 1)".format(param_phase, param_amp)) + raise NoiseError( + "Invalid amplitude and phase damping parameters " + "({} + {} > 1)".format(param_phase, param_amp) + ) if excited_state_population < 0: - raise NoiseError("Invalid excited state population " - "({} < 0).".format(excited_state_population)) + raise NoiseError( + "Invalid excited state population " "({} < 0).".format(excited_state_population) + ) if excited_state_population > 1: - raise NoiseError("Invalid excited state population " - "({} > 1).".format(excited_state_population)) + raise NoiseError( + "Invalid excited state population " "({} > 1).".format(excited_state_population) + ) c0 = np.sqrt(1 - excited_state_population) c1 = np.sqrt(excited_state_population) param = 1 - param_amp - param_phase @@ -411,15 +418,11 @@ def phase_amplitude_damping_error(param_amp, B1 = c1 * np.array([[0, 0], [np.sqrt(param_amp), 0]], dtype=complex) B2 = c1 * np.array([[np.sqrt(param_phase), 0], [0, 0]], dtype=complex) # Select non-zero ops - noise_ops = [ - a for a in [A0, A1, A2, B0, B1, B2] if np.linalg.norm(a) > 1e-10 - ] + noise_ops = [a for a in [A0, A1, A2, B0, B1, B2] if np.linalg.norm(a) > 1e-10] return kraus_error(noise_ops, canonical_kraus=canonical_kraus) -def amplitude_damping_error(param_amp, - excited_state_population=0, - canonical_kraus=True): +def amplitude_damping_error(param_amp, excited_state_population=0, canonical_kraus=True): r""" Return a single-qubit generalized amplitude damping quantum error channel. @@ -455,7 +458,8 @@ def amplitude_damping_error(param_amp, param_amp, 0, excited_state_population=excited_state_population, - canonical_kraus=canonical_kraus) + canonical_kraus=canonical_kraus, + ) def phase_damping_error(param_phase, canonical_kraus=True): @@ -490,7 +494,5 @@ def phase_damping_error(param_phase, canonical_kraus=True): """ return phase_amplitude_damping_error( - 0, - param_phase, - excited_state_population=0, - canonical_kraus=canonical_kraus) + 0, param_phase, excited_state_population=0, canonical_kraus=canonical_kraus + ) diff --git a/qiskit_aer/noise/noise_model.py b/qiskit_aer/noise/noise_model.py index fa2aa6f11d..29d852dbb6 100644 --- a/qiskit_aer/noise/noise_model.py +++ b/qiskit_aer/noise/noise_model.py @@ -129,14 +129,52 @@ class NoiseModel: print(noise_model) """ + # Checks for standard 1-3 qubit instructions - _1qubit_instructions = set([ - 'u1', 'u2', 'u3', 'u', 'p', 'r', 'rx', 'ry', 'rz', 'id', 'x', - 'y', 'z', 'h', 's', 'sdg', 'sx', 'sxdg', 't', 'tdg']) - _2qubit_instructions = set([ - 'swap', 'cx', 'cy', 'cz', 'csx', 'cp', 'cu', 'cu1', 'cu2', 'cu3', 'rxx', - 'ryy', 'rzz', 'rzx', 'ecr']) - _3qubit_instructions = set(['ccx', 'cswap']) + _1qubit_instructions = set( + [ + "u1", + "u2", + "u3", + "u", + "p", + "r", + "rx", + "ry", + "rz", + "id", + "x", + "y", + "z", + "h", + "s", + "sdg", + "sx", + "sxdg", + "t", + "tdg", + ] + ) + _2qubit_instructions = set( + [ + "swap", + "cx", + "cy", + "cz", + "csx", + "cp", + "cu", + "cu1", + "cu2", + "cu3", + "rxx", + "ryy", + "rzz", + "rzx", + "ecr", + ] + ) + _3qubit_instructions = set(["ccx", "cswap"]) def __init__(self, basis_gates=None): """Initialize an empty noise model. @@ -160,10 +198,9 @@ def __init__(self, basis_gates=None): # Default basis gates is id, rz, sx, cx so that all standard # non-identity instructions can be unrolled to rz, sx, cx, # and identities won't be unrolled - self._basis_gates = set(['id', 'rz', 'sx', 'cx']) + self._basis_gates = set(["id", "rz", "sx", "cx"]) else: - self._basis_gates = set( - name for name, _ in self._instruction_names_labels(basis_gates)) + self._basis_gates = set(name for name, _ in self._instruction_names_labels(basis_gates)) # Store gates with a noise model defined self._noise_instructions = set() # Store qubits referenced in noise model. @@ -205,14 +242,17 @@ def noise_qubits(self): return sorted(self._noise_qubits) @classmethod - def from_backend(cls, backend, - gate_error=True, - readout_error=True, - thermal_relaxation=True, - temperature=0, - gate_lengths=None, - gate_length_units='ns', - warnings=None): + def from_backend( + cls, + backend, + gate_error=True, + readout_error=True, + thermal_relaxation=True, + temperature=0, + gate_lengths=None, + gate_length_units="ns", + warnings=None, + ): """Return a noise model derived from a devices backend properties. This function generates a noise model based on: @@ -305,9 +345,11 @@ def from_backend(cls, backend, if warnings is not None: warn( '"warnings" argument has been deprecated as of qiskit-aer 0.12.0 ' - 'and will be removed no earlier than 3 months from that release date. ' - 'Use the warnings filter in Python standard library instead.', - DeprecationWarning, stacklevel=2) + "and will be removed no earlier than 3 months from that release date. " + "Use the warnings filter in Python standard library instead.", + DeprecationWarning, + stacklevel=2, + ) else: warnings = True @@ -318,8 +360,11 @@ def from_backend(cls, backend, target = None if backend_interface_version == 2: if not warnings: - warn("When a BackendV2 is supplied, `warnings`" - " are ignored, and their default values are used.", UserWarning) + warn( + "When a BackendV2 is supplied, `warnings`" + " are ignored, and their default values are used.", + UserWarning, + ) properties = None basis_gates = backend.operation_names target = backend.target @@ -332,22 +377,27 @@ def from_backend(cls, backend, target.update_instruction_properties(op_name, qubits, prop) all_qubit_properties = backend.target.qubit_properties if not all_qubit_properties: - warn(f"Qiskit backend {backend} has no QubitProperties, so the resulting" - " noise model will not include any thermal relaxation errors.", UserWarning) + warn( + f"Qiskit backend {backend} has no QubitProperties, so the resulting" + " noise model will not include any thermal relaxation errors.", + UserWarning, + ) dt = backend.dt elif backend_interface_version <= 1: properties = backend.properties() configuration = backend.configuration() basis_gates = configuration.basis_gates - all_qubit_properties = [QubitProperties(t1=properties.t1(q), - t2=properties.t2(q), - frequency=properties.frequency(q)) - for q in range(configuration.num_qubits)] + all_qubit_properties = [ + QubitProperties( + t1=properties.t1(q), t2=properties.t2(q), frequency=properties.frequency(q) + ) + for q in range(configuration.num_qubits) + ] dt = getattr(configuration, "dt", 0) if not properties: - raise NoiseError(f'Qiskit backend {backend} does not have a BackendProperties') + raise NoiseError(f"Qiskit backend {backend} does not have a BackendProperties") else: - raise NoiseError(f'{backend} is not a Qiskit backend') + raise NoiseError(f"{backend} is not a Qiskit backend") noise_model = NoiseModel(basis_gates=basis_gates) @@ -358,11 +408,7 @@ def from_backend(cls, backend, # Add gate errors with catch_warnings(): - filterwarnings( - "ignore", - category=DeprecationWarning, - module="qiskit_aer.noise" - ) + filterwarnings("ignore", category=DeprecationWarning, module="qiskit_aer.noise") gate_errors = basic_device_gate_errors( properties, gate_error=gate_error, @@ -380,9 +426,9 @@ def from_backend(cls, backend, # Add delay errors via RelaxationNiose pass try: excited_state_populations = [ - _excited_population( - freq=q.frequency, temperature=temperature - ) for q in all_qubit_properties] + _excited_population(freq=q.frequency, temperature=temperature) + for q in all_qubit_properties + ] except BackendPropertyError: excited_state_populations = None try: @@ -393,7 +439,7 @@ def from_backend(cls, backend, t2s=t2s, dt=dt, op_types=Delay, - excited_state_populations=excited_state_populations + excited_state_populations=excited_state_populations, ) noise_model._custom_noise_passes.append(delay_pass) except BackendPropertyError: @@ -452,8 +498,7 @@ def from_backend_properties( """ if not isinstance(backend_properties, BackendProperties): raise NoiseError( - "{} is not a Qiskit backend or" - " BackendProperties".format(backend_properties) + "{} is not a Qiskit backend or" " BackendProperties".format(backend_properties) ) basis_gates = set() for prop in backend_properties.gates: @@ -492,8 +537,10 @@ def from_backend_properties( try: delay_pass = RelaxationNoisePass( t1s=[backend_properties.t1(q) for q in range(num_qubits)], - t2s=[_truncate_t2_value(backend_properties.t1( - q), backend_properties.t2(q)) for q in range(num_qubits)], + t2s=[ + _truncate_t2_value(backend_properties.t1(q), backend_properties.t2(q)) + for q in range(num_qubits) + ], dt=dt, op_types=Delay, excited_state_populations=excited_state_populations, @@ -535,10 +582,10 @@ def __str__(self): # Get default errors default_error_ops = [] for inst in self._default_quantum_errors: - default_error_ops.append('{}'.format(inst)) + default_error_ops.append("{}".format(inst)) if self._default_readout_error is not None: - if 'measure' not in default_error_ops: - default_error_ops.append('measure') + if "measure" not in default_error_ops: + default_error_ops.append("measure") # Get local errors local_error_ops = [] @@ -546,23 +593,20 @@ def __str__(self): for qubits in dic.keys(): local_error_ops.append((inst, qubits)) for qubits in self._local_readout_errors: - tmp = ('measure', qubits) + tmp = ("measure", qubits) if tmp not in local_error_ops: local_error_ops.append(tmp) output = "NoiseModel:" output += "\n Basis gates: {}".format(self.basis_gates) if self._noise_instructions: - output += "\n Instructions with noise: {}".format( - list(self._noise_instructions)) + output += "\n Instructions with noise: {}".format(list(self._noise_instructions)) if self._noise_qubits: - output += "\n Qubits with noise: {}".format( - list(self._noise_qubits)) + output += "\n Qubits with noise: {}".format(list(self._noise_qubits)) if default_error_ops: output += "\n All-qubits errors: {}".format(default_error_ops) if local_error_ops: - output += "\n Specific qubit errors: {}".format( - local_error_ops) + output += "\n Specific qubit errors: {}".format(local_error_ops) return output def __eq__(self, other): @@ -571,10 +615,12 @@ def __eq__(self, other): # the same basis_gates # the same noise_qubits # the same noise_instructions - if (not isinstance(other, NoiseModel) or - self.basis_gates != other.basis_gates or - self.noise_qubits != other.noise_qubits or - self.noise_instructions != other.noise_instructions): + if ( + not isinstance(other, NoiseModel) + or self.basis_gates != other.basis_gates + or self.noise_qubits != other.noise_qubits + or self.noise_instructions != other.noise_instructions + ): return False # Check default readout errors is equal if not self._readout_errors_equal(other): @@ -604,9 +650,8 @@ def add_basis_gates(self, instructions): for name, _ in self._instruction_names_labels(instructions): # If the instruction is in the default basis gates for the # AerSimulator we add it to the basis gates. - if name in BASIS_GATES['automatic']: - if name not in ['measure', 'reset', 'initialize', - 'kraus', 'superop', 'roerror']: + if name in BASIS_GATES["automatic"]: + if name not in ["measure", "reset", "initialize", "kraus", "superop", "roerror"]: self._basis_gates.add(name) def add_all_qubit_quantum_error(self, error, instructions, warnings=True): @@ -646,20 +691,23 @@ def add_all_qubit_quantum_error(self, error, instructions, warnings=True): if warnings: logger.warning( "WARNING: all-qubit error already exists for " - "instruction \"%s\", " - "composing with additional error.", label) + 'instruction "%s", ' + "composing with additional error.", + label, + ) else: self._default_quantum_errors[label] = error # Check if a specific qubit error has been applied for this instruction if label in self._local_quantum_errors: - local_qubits = self._keys2str( - self._local_quantum_errors[label].keys()) + local_qubits = self._keys2str(self._local_quantum_errors[label].keys()) if warnings: logger.warning( "WARNING: all-qubit error for instruction " - "\"%s\" will not apply to qubits: " - "%s as specific error already exists.", label, - local_qubits) + '"%s" will not apply to qubits: ' + "%s as specific error already exists.", + label, + local_qubits, + ) self._noise_instructions.add(label) self.add_basis_gates(name) @@ -712,17 +760,21 @@ def add_quantum_error(self, error, instructions, qubits, warnings=True): # Convert qubits list to hashable string if error.num_qubits != len(qubits): - raise NoiseError("Number of qubits ({}) does not match " - " the error size ({})".format( - len(qubits), error.num_qubits)) + raise NoiseError( + "Number of qubits ({}) does not match " + " the error size ({})".format(len(qubits), error.num_qubits) + ) if qubits in qubit_dict: new_error = qubit_dict[qubits].compose(error) qubit_dict[qubits] = new_error if warnings: logger.warning( "WARNING: quantum error already exists for " - "instruction \"%s\" on qubits %s " - ", appending additional error.", label, qubits) + 'instruction "%s" on qubits %s ' + ", appending additional error.", + label, + qubits, + ) else: qubit_dict[qubits] = error # Add updated dictionary @@ -732,9 +784,12 @@ def add_quantum_error(self, error, instructions, qubits, warnings=True): if label in self._default_quantum_errors: if warnings: logger.warning( - "WARNING: Specific error for instruction \"%s\" " + 'WARNING: Specific error for instruction "%s" ' "on qubits %s overrides previously defined " - "all-qubit error for these qubits.", label, qubits) + "all-qubit error for these qubits.", + label, + qubits, + ) self._noise_instructions.add(label) self.add_basis_gates(name) @@ -767,14 +822,13 @@ def add_all_qubit_readout_error(self, error, warnings=True): # Check number of qubits is correct for standard instructions if error.number_of_qubits != 1: - raise NoiseError( - "All-qubit readout errors must defined as single-qubit errors." - ) + raise NoiseError("All-qubit readout errors must defined as single-qubit errors.") if self._default_readout_error is not None: if warnings: logger.warning( "WARNING: all-qubit readout error already exists, " - "overriding with new readout error.") + "overriding with new readout error." + ) self._default_readout_error = error # Check if a specific qubit error has been applied for this instruction @@ -784,7 +838,9 @@ def add_all_qubit_readout_error(self, error, warnings=True): logger.warning( "WARNING: The all-qubit readout error will not " "apply to measure of qubits qubits: %s " - "as specific readout errors already exist.", local_qubits) + "as specific readout errors already exist.", + local_qubits, + ) self._noise_instructions.add("measure") def add_readout_error(self, error, qubits, warnings=True): @@ -827,13 +883,16 @@ def add_readout_error(self, error, qubits, warnings=True): if error.number_of_qubits != len(qubits): raise NoiseError( "Number of qubits ({}) does not match the readout " - "error size ({})".format(len(qubits), error.number_of_qubits)) + "error size ({})".format(len(qubits), error.number_of_qubits) + ) # Check if we are overriding a previous error if qubits in self._local_readout_errors: if warnings: logger.warning( "WARNING: readout error already exists for qubits " - "%s, overriding with new readout error.", qubits) + "%s, overriding with new readout error.", + qubits, + ) self._local_readout_errors[qubits] = error # Check if all-qubit readout error is already defined @@ -842,7 +901,9 @@ def add_readout_error(self, error, qubits, warnings=True): logger.warning( "WARNING: Specific readout error on qubits " "%s overrides previously defined " - "all-qubit readout error for these qubits.", qubits) + "all-qubit readout error for these qubits.", + qubits, + ) self._noise_instructions.add("measure") def to_dict(self, serializable=False): @@ -903,84 +964,89 @@ def from_dict(noise_dict): Raises: NoiseError: if dict cannot be converted to NoiseModel. """ - warn('from_dict has been deprecated as of qiskit-aer 0.10.0' - ' and will be removed no earlier than 3 months from that release date.', - DeprecationWarning, stacklevel=2) + warn( + "from_dict has been deprecated as of qiskit-aer 0.10.0" + " and will be removed no earlier than 3 months from that release date.", + DeprecationWarning, + stacklevel=2, + ) def inst_dic_list_to_circuit(dic_list): - num_qubits = max([max(dic['qubits']) for dic in dic_list]) + 1 + num_qubits = max([max(dic["qubits"]) for dic in dic_list]) + 1 circ = QuantumCircuit(num_qubits) for dic in dic_list: - if dic['name'] == 'reset': - circ.append(Reset(), qargs=dic['qubits']) - elif dic['name'] == 'kraus': - circ.append(Instruction(name='kraus', - num_qubits=len(dic['qubits']), - num_clbits=0, - params=dic['params']), - qargs=dic['qubits']) - elif dic['name'] == 'unitary': - circ.append(UnitaryGate(data=dic['params'][0]), - qargs=dic['qubits']) - elif dic['name'] == 'pauli': - circ.append(PauliGate(dic['params'][0]), - qargs=dic['qubits']) + if dic["name"] == "reset": + circ.append(Reset(), qargs=dic["qubits"]) + elif dic["name"] == "kraus": + circ.append( + Instruction( + name="kraus", + num_qubits=len(dic["qubits"]), + num_clbits=0, + params=dic["params"], + ), + qargs=dic["qubits"], + ) + elif dic["name"] == "unitary": + circ.append(UnitaryGate(data=dic["params"][0]), qargs=dic["qubits"]) + elif dic["name"] == "pauli": + circ.append(PauliGate(dic["params"][0]), qargs=dic["qubits"]) else: with catch_warnings(): filterwarnings( "ignore", category=DeprecationWarning, - module="qiskit_aer.noise.errors.errorutils" + module="qiskit_aer.noise.errors.errorutils", + ) + circ.append( + UnitaryGate( + label=dic["name"], data=_standard_gate_unitary(dic["name"]) + ), + qargs=dic["qubits"], ) - circ.append(UnitaryGate(label=dic['name'], - data=_standard_gate_unitary(dic['name'])), - qargs=dic['qubits']) return circ # Return noise model noise_model = NoiseModel() # Get error terms - errors = noise_dict.get('errors', []) + errors = noise_dict.get("errors", []) for error in errors: - error_type = error['type'] + error_type = error["type"] # Add QuantumError - if error_type == 'qerror': - circuits = [inst_dic_list_to_circuit(dics) for dics in error['instructions']] - noise_ops = tuple(zip(circuits, error['probabilities'])) + if error_type == "qerror": + circuits = [inst_dic_list_to_circuit(dics) for dics in error["instructions"]] + noise_ops = tuple(zip(circuits, error["probabilities"])) qerror = QuantumError(noise_ops) - qerror._id = error.get('id', None) or qerror.id - instruction_names = error['operations'] - all_gate_qubits = error.get('gate_qubits', None) + qerror._id = error.get("id", None) or qerror.id + instruction_names = error["operations"] + all_gate_qubits = error.get("gate_qubits", None) if all_gate_qubits is not None: for gate_qubits in all_gate_qubits: # Add local quantum error noise_model.add_quantum_error( - qerror, - instruction_names, - gate_qubits, - warnings=False) + qerror, instruction_names, gate_qubits, warnings=False + ) else: # Add all-qubit quantum error noise_model.add_all_qubit_quantum_error( - qerror, instruction_names, warnings=False) + qerror, instruction_names, warnings=False + ) # Add ReadoutError - elif error_type == 'roerror': - probabilities = error['probabilities'] - all_gate_qubits = error.get('gate_qubits', None) + elif error_type == "roerror": + probabilities = error["probabilities"] + all_gate_qubits = error.get("gate_qubits", None) roerror = ReadoutError(probabilities) # Add local readout error if all_gate_qubits is not None: for gate_qubits in all_gate_qubits: - noise_model.add_readout_error( - roerror, gate_qubits, warnings=False) + noise_model.add_readout_error(roerror, gate_qubits, warnings=False) # Add all-qubit readout error else: - noise_model.add_all_qubit_readout_error( - roerror, warnings=False) + noise_model.add_all_qubit_readout_error(roerror, warnings=False) # Invalid error type else: raise NoiseError("Invalid error type: {}".format(error_type)) @@ -996,12 +1062,12 @@ def _instruction_names_labels(self, instructions): # as the label if isinstance(inst, Instruction): name = inst.name - label = getattr(inst, 'label', inst.name) + label = getattr(inst, "label", inst.name) names_labels.append((name, label)) elif isinstance(inst, str): names_labels.append((inst, inst)) else: - raise NoiseError('Invalid instruction type {}'.format(inst)) + raise NoiseError("Invalid instruction type {}".format(inst)) return names_labels def _check_number_of_qubits(self, error, name): @@ -1017,9 +1083,11 @@ def _check_number_of_qubits(self, error, name): """ def error_message(gate_qubits): - msg = "{} qubit QuantumError".format(error.num_qubits) + \ - " cannot be applied to {} qubit".format(gate_qubits) + \ - " instruction \"{}\".".format(name) + msg = ( + "{} qubit QuantumError".format(error.num_qubits) + + " cannot be applied to {} qubit".format(gate_qubits) + + ' instruction "{}".'.format(name) + ) return msg if name in self._1qubit_instructions and error.num_qubits != 1: @@ -1040,30 +1108,27 @@ def _readout_errors_equal(self, other): if self._default_readout_error != other._default_readout_error: return False # Check local readout errors are equal - if sorted(self._local_readout_errors.keys()) != sorted( - other._local_readout_errors.keys()): + if sorted(self._local_readout_errors.keys()) != sorted(other._local_readout_errors.keys()): return False for key in self._local_readout_errors: - if self._local_readout_errors[key] != other._local_readout_errors[ - key]: + if self._local_readout_errors[key] != other._local_readout_errors[key]: return False return True def _all_qubit_quantum_errors_equal(self, other): """Check two noise models have equal local quantum errors""" if sorted(self._default_quantum_errors.keys()) != sorted( - other._default_quantum_errors.keys()): + other._default_quantum_errors.keys() + ): return False for key in self._default_quantum_errors: - if self._default_quantum_errors[ - key] != other._default_quantum_errors[key]: + if self._default_quantum_errors[key] != other._default_quantum_errors[key]: return False return True def _local_quantum_errors_equal(self, other): """Check two noise models have equal local quantum errors""" - if sorted(self._local_quantum_errors.keys()) != sorted( - other._local_quantum_errors.keys()): + if sorted(self._local_quantum_errors.keys()) != sorted(other._local_quantum_errors.keys()): return False for key in self._local_quantum_errors: inner_dict1 = self._local_quantum_errors[key] @@ -1073,8 +1138,7 @@ def _local_quantum_errors_equal(self, other): for inner_key in inner_dict1: if inner_dict1[inner_key] != inner_dict2[inner_key]: return False - if self._local_quantum_errors[key] != other._local_quantum_errors[ - key]: + if self._local_quantum_errors[key] != other._local_quantum_errors[key]: return False return True @@ -1094,50 +1158,66 @@ def _pass_manager(self) -> Optional[PassManager]: def _standard_gate_unitary(name): # To be removed with from_dict unitary_matrices = { - ("id", "I"): - np.eye(2, dtype=complex), - ("x", "X"): - np.array([[0, 1], [1, 0]], dtype=complex), - ("y", "Y"): - np.array([[0, -1j], [1j, 0]], dtype=complex), - ("z", "Z"): - np.array([[1, 0], [0, -1]], dtype=complex), - ("h", "H"): - np.array([[1, 1], [1, -1]], dtype=complex) / np.sqrt(2), - ("s", "S"): - np.array([[1, 0], [0, 1j]], dtype=complex), - ("sdg", "Sdg"): - np.array([[1, 0], [0, -1j]], dtype=complex), - ("t", "T"): - np.array([[1, 0], [0, np.exp(1j * np.pi / 4)]], dtype=complex), - ("tdg", "Tdg"): - np.array([[1, 0], [0, np.exp(-1j * np.pi / 4)]], dtype=complex), - ("cx", "CX", "cx_01"): - np.array([[1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0]], dtype=complex), - ("cx_10",): - np.array([[1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0]], dtype=complex), - ("cz", "CZ"): - np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, -1]], dtype=complex), - ("swap", "SWAP"): - np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]], dtype=complex), - ("ccx", "CCX", "ccx_012", "ccx_102"): - np.array([[1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], - [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1], - [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0], - [0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 1, 0, 0, 0, 0]], - dtype=complex), - ("ccx_021", "ccx_201"): - np.array([[1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], - [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], - [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1], - [0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 1, 0, 0]], - dtype=complex), - ("ccx_120", "ccx_210"): - np.array([[1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], - [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], - [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 1, 0]], - dtype=complex) + ("id", "I"): np.eye(2, dtype=complex), + ("x", "X"): np.array([[0, 1], [1, 0]], dtype=complex), + ("y", "Y"): np.array([[0, -1j], [1j, 0]], dtype=complex), + ("z", "Z"): np.array([[1, 0], [0, -1]], dtype=complex), + ("h", "H"): np.array([[1, 1], [1, -1]], dtype=complex) / np.sqrt(2), + ("s", "S"): np.array([[1, 0], [0, 1j]], dtype=complex), + ("sdg", "Sdg"): np.array([[1, 0], [0, -1j]], dtype=complex), + ("t", "T"): np.array([[1, 0], [0, np.exp(1j * np.pi / 4)]], dtype=complex), + ("tdg", "Tdg"): np.array([[1, 0], [0, np.exp(-1j * np.pi / 4)]], dtype=complex), + ("cx", "CX", "cx_01"): np.array( + [[1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0]], dtype=complex + ), + ("cx_10",): np.array( + [[1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0]], dtype=complex + ), + ("cz", "CZ"): np.array( + [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, -1]], dtype=complex + ), + ("swap", "SWAP"): np.array( + [[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]], dtype=complex + ), + ("ccx", "CCX", "ccx_012", "ccx_102"): np.array( + [ + [1, 0, 0, 0, 0, 0, 0, 0], + [0, 1, 0, 0, 0, 0, 0, 0], + [0, 0, 1, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 1], + [0, 0, 0, 0, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 0, 0, 0, 0, 1, 0], + [0, 0, 0, 1, 0, 0, 0, 0], + ], + dtype=complex, + ), + ("ccx_021", "ccx_201"): np.array( + [ + [1, 0, 0, 0, 0, 0, 0, 0], + [0, 1, 0, 0, 0, 0, 0, 0], + [0, 0, 1, 0, 0, 0, 0, 0], + [0, 0, 0, 1, 0, 0, 0, 0], + [0, 0, 0, 0, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 1], + [0, 0, 0, 0, 0, 0, 1, 0], + [0, 0, 0, 0, 0, 1, 0, 0], + ], + dtype=complex, + ), + ("ccx_120", "ccx_210"): np.array( + [ + [1, 0, 0, 0, 0, 0, 0, 0], + [0, 1, 0, 0, 0, 0, 0, 0], + [0, 0, 1, 0, 0, 0, 0, 0], + [0, 0, 0, 1, 0, 0, 0, 0], + [0, 0, 0, 0, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 1], + [0, 0, 0, 0, 0, 0, 1, 0], + ], + dtype=complex, + ), } return next((value for key, value in unitary_matrices.items() if name in key), None) diff --git a/qiskit_aer/noise/noiseerror.py b/qiskit_aer/noise/noiseerror.py index 32edb0febf..cc3e5244c6 100644 --- a/qiskit_aer/noise/noiseerror.py +++ b/qiskit_aer/noise/noiseerror.py @@ -23,7 +23,7 @@ class NoiseError(QiskitError): def __init__(self, *message): """Set the error message.""" super().__init__(*message) - self.message = ' '.join(message) + self.message = " ".join(message) def __str__(self): """Return the message.""" diff --git a/qiskit_aer/noise/passes/local_noise_pass.py b/qiskit_aer/noise/passes/local_noise_pass.py index e141d6f685..8713ed494d 100644 --- a/qiskit_aer/noise/passes/local_noise_pass.py +++ b/qiskit_aer/noise/passes/local_noise_pass.py @@ -53,10 +53,10 @@ def func( """ def __init__( - self, - func: Callable[[Instruction, Sequence[int]], Optional[InstructionLike]], - op_types: Optional[Union[type, Iterable[type]]] = None, - method: str = 'append' + self, + func: Callable[[Instruction, Sequence[int]], Optional[InstructionLike]], + op_types: Optional[Union[type, Iterable[type]]] = None, + method: str = "append", ): """Initialize noise pass. diff --git a/qiskit_aer/noise/passes/relaxation_noise_pass.py b/qiskit_aer/noise/passes/relaxation_noise_pass.py index b441ce6a3b..d2bf6159bc 100644 --- a/qiskit_aer/noise/passes/relaxation_noise_pass.py +++ b/qiskit_aer/noise/passes/relaxation_noise_pass.py @@ -28,12 +28,12 @@ class RelaxationNoisePass(LocalNoisePass): """Add duration dependent thermal relaxation noise after instructions.""" def __init__( - self, - t1s: List[float], - t2s: List[float], - dt: Optional[float] = None, - op_types: Optional[Union[type, Sequence[type]]] = None, - excited_state_populations: Optional[List[float]] = None, + self, + t1s: List[float], + t2s: List[float], + dt: Optional[float] = None, + op_types: Optional[Union[type, Sequence[type]]] = None, + excited_state_populations: Optional[List[float]] = None, ): """Initialize RelaxationNoisePass. @@ -57,24 +57,24 @@ def __init__( self._dt = dt super().__init__(self._thermal_relaxation_error, op_types=op_types, method="append") - def _thermal_relaxation_error( - self, - op: Instruction, - qubits: Sequence[int] - ): + def _thermal_relaxation_error(self, op: Instruction, qubits: Sequence[int]): """Return thermal relaxation error on each operand qubit""" if not op.duration: if op.duration is None: - warnings.warn("RelaxationNoisePass ignores instructions without duration," - " you may need to schedule circuit in advance.", UserWarning) + warnings.warn( + "RelaxationNoisePass ignores instructions without duration," + " you may need to schedule circuit in advance.", + UserWarning, + ) return None # Convert op duration to seconds - if op.unit == 'dt': + if op.unit == "dt": if self._dt is None: raise NoiseError( "RelaxationNoisePass cannot apply noise to a 'dt' unit duration" - " without a dt time set.") + " without a dt time set." + ) duration = op.duration * self._dt else: duration = apply_prefix(op.duration, op.unit) diff --git a/qiskit_aer/primitives/estimator.py b/qiskit_aer/primitives/estimator.py index 1917d145e9..157f83b6b5 100644 --- a/qiskit_aer/primitives/estimator.py +++ b/qiskit_aer/primitives/estimator.py @@ -106,7 +106,6 @@ def _call( parameter_values: Sequence[Sequence[float]], **run_options, ) -> EstimatorResult: - seed = run_options.pop("seed", None) if seed is not None: run_options.setdefault("seed_simulator", seed) @@ -125,7 +124,6 @@ def _run( parameter_values: Sequence[Sequence[float]], **run_options, ) -> PrimitiveJob: - circuit_indices: list = [] for circuit in circuits: index = self._circuit_ids.get(_circuit_key(circuit)) diff --git a/qiskit_aer/pulse/controllers/digest_pulse_qobj.py b/qiskit_aer/pulse/controllers/digest_pulse_qobj.py index a64d032423..ea278a2b84 100644 --- a/qiskit_aer/pulse/controllers/digest_pulse_qobj.py +++ b/qiskit_aer/pulse/controllers/digest_pulse_qobj.py @@ -21,6 +21,7 @@ from qiskit.pulse import DriveChannel from ...aererror import AerError + # pylint: disable=no-name-in-module from .pulse_utils import oplist_to_array @@ -29,7 +30,6 @@ class DigestedPulseQobj: """Container class for information extracted from PulseQobj.""" def __init__(self): - # #################################### # Some "Simulation description" # #################################### @@ -66,7 +66,7 @@ def __init__(self): def digest_pulse_qobj(qobj, channels, dt, qubit_list): - """ Given a PulseQobj (and other parameters), returns a DigestedPulseQobj + """Given a PulseQobj (and other parameters), returns a DigestedPulseQobj containing relevant extracted information Parameters: @@ -86,47 +86,50 @@ def digest_pulse_qobj(qobj, channels, dt, qubit_list): digested_qobj = DigestedPulseQobj() qobj_dict = qobj.to_dict() - qobj_config = qobj_dict['config'] + qobj_config = qobj_dict["config"] # extract schedule_los - if qobj_config.get('schedule_los') is not None: - for exp, schedule_lo in zip(qobj_dict['experiments'], qobj_config['schedule_los']): - if exp.get('config') is None: - exp['config'] = {} + if qobj_config.get("schedule_los") is not None: + for exp, schedule_lo in zip(qobj_dict["experiments"], qobj_config["schedule_los"]): + if exp.get("config") is None: + exp["config"] = {} schedule_lo_list = [] for idx in qubit_list: freq = schedule_lo.get(DriveChannel(idx), None) if freq is None: - raise ValueError('''A qubit in the simulation is missing an entry in - schedule_los.''') + raise ValueError( + """A qubit in the simulation is missing an entry in + schedule_los.""" + ) schedule_lo_list.append(freq * 1e-9) - exp['config']['qubit_lo_freq'] = schedule_lo_list + exp["config"]["qubit_lo_freq"] = schedule_lo_list # raises errors for unsupported features _unsupported_errors(qobj_dict) - if 'memory_slots' not in qobj_config: - raise ValueError('Number of memory_slots must be specific in Qobj config') + if "memory_slots" not in qobj_config: + raise ValueError("Number of memory_slots must be specific in Qobj config") # set memory and measurement details - digested_qobj.shots = int(qobj_config.get('shots', 1024)) - digested_qobj.meas_level = int(qobj_config.get('meas_level', 2)) - digested_qobj.meas_return = qobj_config.get('meas_return', 'avg') - digested_qobj.memory_slots = qobj_config.get('memory_slots', 0) - digested_qobj.memory = qobj_config.get('memory', False) - digested_qobj.n_registers = qobj_config.get('n_registers', 0) + digested_qobj.shots = int(qobj_config.get("shots", 1024)) + digested_qobj.meas_level = int(qobj_config.get("meas_level", 2)) + digested_qobj.meas_return = qobj_config.get("meas_return", "avg") + digested_qobj.memory_slots = qobj_config.get("memory_slots", 0) + digested_qobj.memory = qobj_config.get("memory", False) + digested_qobj.n_registers = qobj_config.get("n_registers", 0) # set qubit_lo_freq as given in qobj - if 'qubit_lo_freq' in qobj_config and qobj_config['qubit_lo_freq'] != [np.inf]: + if "qubit_lo_freq" in qobj_config and qobj_config["qubit_lo_freq"] != [np.inf]: # qobj frequencies are divided by 1e9, so multiply back - digested_qobj.qubit_lo_freq = [freq * 1e9 for freq in qobj_config['qubit_lo_freq']] + digested_qobj.qubit_lo_freq = [freq * 1e9 for freq in qobj_config["qubit_lo_freq"]] # build pulse arrays from qobj - pulses, pulses_idx, pulse_dict = build_pulse_arrays(qobj_dict['experiments'], - qobj_config['pulse_library']) + pulses, pulses_idx, pulse_dict = build_pulse_arrays( + qobj_dict["experiments"], qobj_config["pulse_library"] + ) digested_qobj.pulse_array = pulses digested_qobj.pulse_indices = pulses_idx @@ -134,13 +137,8 @@ def digest_pulse_qobj(qobj, channels, dt, qubit_list): experiments = [] - for exp in qobj_dict['experiments']: - exp_struct = experiment_to_structs(exp, - channels, - pulses_idx, - pulse_dict, - dt, - qubit_list) + for exp in qobj_dict["experiments"]: + exp_struct = experiment_to_structs(exp, channels, pulses_idx, pulse_dict, dt, qubit_list) experiments.append(exp_struct) digested_qobj.experiments = experiments @@ -149,7 +147,7 @@ def digest_pulse_qobj(qobj, channels, dt, qubit_list): def _unsupported_errors(qobj_dict): - """ Raises errors for untested/unsupported features. + """Raises errors for untested/unsupported features. Parameters: qobj_dict (dict): qobj in dictionary form @@ -159,26 +157,26 @@ def _unsupported_errors(qobj_dict): """ # Warnings that don't stop execution - warning_str = '{} are an untested feature, and therefore may not behave as expected.' - if _contains_pv_instruction(qobj_dict['experiments']): - raise AerError(warning_str.format('PersistentValue instructions')) + warning_str = "{} are an untested feature, and therefore may not behave as expected." + if _contains_pv_instruction(qobj_dict["experiments"]): + raise AerError(warning_str.format("PersistentValue instructions")) - error_str = '''{} are not directly supported by PulseSimulator. Convert to - explicit WaveForms to simulate.''' - if _contains_parametric_pulse(qobj_dict['experiments']): - raise AerError(error_str.format('Parametric Pulses')) + error_str = """{} are not directly supported by PulseSimulator. Convert to + explicit WaveForms to simulate.""" + if _contains_parametric_pulse(qobj_dict["experiments"]): + raise AerError(error_str.format("Parametric Pulses")) - error_str = '''Schedules contain {}, are not supported by PulseSimulator.''' - if _contains_frequency_instruction(qobj_dict['experiments']): - raise AerError(error_str.format('shift frequency and/or set frequency instructions')) + error_str = """Schedules contain {}, are not supported by PulseSimulator.""" + if _contains_frequency_instruction(qobj_dict["experiments"]): + raise AerError(error_str.format("shift frequency and/or set frequency instructions")) - required_str = '{} are required for simulation, and none were specified.' - if not _contains_acquire_instruction(qobj_dict['experiments']): - raise AerError(required_str.format('Acquire instructions')) + required_str = "{} are required for simulation, and none were specified." + if not _contains_acquire_instruction(qobj_dict["experiments"]): + raise AerError(required_str.format("Acquire instructions")) def _contains_acquire_instruction(experiments): - """ Return True if the list of experiments contains an Acquire instruction + """Return True if the list of experiments contains an Acquire instruction Parameters: experiments (list): list of schedules Returns: @@ -187,14 +185,14 @@ def _contains_acquire_instruction(experiments): """ for exp in experiments: - for inst in exp['instructions']: - if inst['name'] == 'acquire': + for inst in exp["instructions"]: + if inst["name"] == "acquire": return True return False def _contains_pv_instruction(experiments): - """ Return True if the list of experiments contains a PersistentValue instruction. + """Return True if the list of experiments contains a PersistentValue instruction. Parameters: experiments (list): list of schedules @@ -203,14 +201,14 @@ def _contains_pv_instruction(experiments): Raises: """ for exp in experiments: - for inst in exp['instructions']: - if inst['name'] == 'pv': + for inst in exp["instructions"]: + if inst["name"] == "pv": return True return False def _contains_frequency_instruction(experiments): - """ Return True if the list of experiments contains either a set fruquency or shift + """Return True if the list of experiments contains either a set fruquency or shift frequency instruction. Parameters: @@ -220,8 +218,8 @@ def _contains_frequency_instruction(experiments): Raises: """ for exp in experiments: - for inst in exp['instructions']: - if inst['name'] == 'setf' or inst['name'] == 'shiftf': + for inst in exp["instructions"]: + if inst["name"] == "setf" or inst["name"] == "shiftf": return True return False @@ -236,14 +234,14 @@ def _contains_parametric_pulse(experiments): Raises: """ for exp in experiments: - for inst in exp['instructions']: - if inst['name'] == 'parametric_pulse': + for inst in exp["instructions"]: + if inst["name"] == "parametric_pulse": return True return False def build_pulse_arrays(experiments, pulse_library): - """ Build pulses and pulse_idx arrays, and a pulse_dict + """Build pulses and pulse_idx arrays, and a pulse_dict used in simulations and mapping of experimental pulse sequencies to pulse_idx sequencies and timings. @@ -261,22 +259,22 @@ def build_pulse_arrays(experiments, pulse_library): num_pulse = 0 for pulse in pulse_library: - pulse_dict[pulse['name']] = num_pulse - total_pulse_length += len(pulse['samples']) + pulse_dict[pulse["name"]] = num_pulse + total_pulse_length += len(pulse["samples"]) num_pulse += 1 idx = num_pulse + 1 # now go through experiments looking for PV gates pv_pulses = [] for exp in experiments: - for pulse in exp['instructions']: - if pulse['name'] == 'pv': - if pulse['val'] not in [pval[1] for pval in pv_pulses] and pulse['val'] != 0: - pv_pulses.append((pulse['val'], idx)) + for pulse in exp["instructions"]: + if pulse["name"] == "pv": + if pulse["val"] not in [pval[1] for pval in pv_pulses] and pulse["val"] != 0: + pv_pulses.append((pulse["val"], idx)) idx += 1 total_pulse_length += 1 - pulse_dict['pv'] = pv_pulses + pulse_dict["pv"] = pv_pulses pulses = np.empty(total_pulse_length, dtype=complex) pulses_idx = np.zeros(idx + 1, dtype=np.uint32) @@ -284,9 +282,9 @@ def build_pulse_arrays(experiments, pulse_library): stop = 0 ind = 1 for _, pulse in enumerate(pulse_library): - stop = pulses_idx[ind - 1] + len(pulse['samples']) + stop = pulses_idx[ind - 1] + len(pulse["samples"]) pulses_idx[ind] = stop - oplist_to_array(format_pulse_samples(pulse['samples']), pulses, pulses_idx[ind - 1]) + oplist_to_array(format_pulse_samples(pulse["samples"]), pulses, pulses_idx[ind - 1]) ind += 1 for pv in pv_pulses: @@ -341,171 +339,173 @@ def experiment_to_structs(experiment, ham_chans, pulse_inds, pulse_to_int, dt, q # TO DO: Error check that operations are restricted to qubit list max_time = 0 structs = {} - structs['header'] = experiment['header'] - structs['channels'] = OrderedDict() + structs["header"] = experiment["header"] + structs["channels"] = OrderedDict() for chan_name in ham_chans: - structs['channels'][chan_name] = [[], []] - structs['acquire'] = [] - structs['cond'] = [] - structs['snapshot'] = [] - structs['tlist'] = [] - structs['can_sample'] = True + structs["channels"][chan_name] = [[], []] + structs["acquire"] = [] + structs["cond"] = [] + structs["snapshot"] = [] + structs["tlist"] = [] + structs["can_sample"] = True # set an experiment qubit_lo_freq if present in experiment - structs['qubit_lo_freq'] = None - if 'config' in experiment: - if ('qubit_lo_freq' in experiment['config'] and - experiment['config']['qubit_lo_freq'] is not None): - freq_list = experiment['config']['qubit_lo_freq'] + structs["qubit_lo_freq"] = None + if "config" in experiment: + if ( + "qubit_lo_freq" in experiment["config"] + and experiment["config"]["qubit_lo_freq"] is not None + ): + freq_list = experiment["config"]["qubit_lo_freq"] freq_list = [freq * 1e9 for freq in freq_list] - structs['qubit_lo_freq'] = freq_list + structs["qubit_lo_freq"] = freq_list # This is a list that tells us whether # the last PV pulse on a channel needs to # be assigned a final time based on the next pulse on that channel pv_needs_tf = [0] * len(ham_chans) # The instructions are time-ordered so just loop through them. - for inst in experiment['instructions']: + for inst in experiment["instructions"]: # Do D and U channels - if 'ch' in inst.keys() and inst['ch'][0] in ['d', 'u']: - chan_name = inst['ch'].upper() + if "ch" in inst.keys() and inst["ch"][0] in ["d", "u"]: + chan_name = inst["ch"].upper() if chan_name not in ham_chans.keys(): - raise ValueError('Channel {} is not in Hamiltonian model'.format(inst['ch'])) + raise ValueError("Channel {} is not in Hamiltonian model".format(inst["ch"])) # If last pulse on channel was a PV then need to set # its final time to be start time of current pulse if pv_needs_tf[ham_chans[chan_name]]: - structs['channels'][chan_name][0][-3] = inst['t0'] * dt + structs["channels"][chan_name][0][-3] = inst["t0"] * dt pv_needs_tf[ham_chans[chan_name]] = 0 # Get condtional info - if 'conditional' in inst.keys(): - cond = inst['conditional'] + if "conditional" in inst.keys(): + cond = inst["conditional"] else: cond = -1 # PV's - if inst['name'] == 'pv': + if inst["name"] == "pv": # Get PV index - for pv in pulse_to_int['pv']: - if pv[0] == inst['val']: + for pv in pulse_to_int["pv"]: + if pv[0] == inst["val"]: index = pv[1] break - structs['channels'][chan_name][0].extend([inst['t0'] * dt, None, index, cond]) + structs["channels"][chan_name][0].extend([inst["t0"] * dt, None, index, cond]) pv_needs_tf[ham_chans[chan_name]] = 1 # ShiftPhase instructions - elif inst['name'] == 'fc': + elif inst["name"] == "fc": # get current phase value current_phase = 0 - if len(structs['channels'][chan_name][1]) > 0: - current_phase = structs['channels'][chan_name][1][-2] + if len(structs["channels"][chan_name][1]) > 0: + current_phase = structs["channels"][chan_name][1][-2] - structs['channels'][chan_name][1].extend([inst['t0'] * dt, - current_phase + inst['phase'], - cond]) + structs["channels"][chan_name][1].extend( + [inst["t0"] * dt, current_phase + inst["phase"], cond] + ) # SetPhase instruction - elif inst['name'] == 'setp': - structs['channels'][chan_name][1].extend([inst['t0'] * dt, - inst['phase'], - cond]) + elif inst["name"] == "setp": + structs["channels"][chan_name][1].extend([inst["t0"] * dt, inst["phase"], cond]) # Delay instruction - elif inst['name'] == 'delay': + elif inst["name"] == "delay": pass # nothing to be done in this case # A standard pulse else: - start = inst['t0'] * dt - pulse_int = pulse_to_int[inst['name']] + start = inst["t0"] * dt + pulse_int = pulse_to_int[inst["name"]] pulse_width = (pulse_inds[pulse_int + 1] - pulse_inds[pulse_int]) * dt stop = start + pulse_width - structs['channels'][chan_name][0].extend([start, stop, pulse_int, cond]) + structs["channels"][chan_name][0].extend([start, stop, pulse_int, cond]) max_time = max(max_time, stop) # Take care of acquires and snapshots (bfuncs added ) else: # measurements - if inst['name'] == 'acquire': - + if inst["name"] == "acquire": # Better way?? qlist2 = [] mlist2 = [] if qubit_list is None: - qlist2 = inst['qubits'] - mlist2 = inst['memory_slot'] + qlist2 = inst["qubits"] + mlist2 = inst["memory_slot"] else: - for qind, qb in enumerate(inst['qubits']): + for qind, qb in enumerate(inst["qubits"]): if qb in qubit_list: qlist2.append(qb) - mlist2.append(inst['memory_slot'][qind]) - - acq_vals = [inst['t0'] * dt, - np.asarray(qlist2, dtype=np.uint32), - np.asarray(mlist2, dtype=np.uint32) - ] - if 'register_slot' in inst.keys(): - acq_vals.append(np.asarray(inst['register_slot'], - dtype=np.uint32)) + mlist2.append(inst["memory_slot"][qind]) + + acq_vals = [ + inst["t0"] * dt, + np.asarray(qlist2, dtype=np.uint32), + np.asarray(mlist2, dtype=np.uint32), + ] + if "register_slot" in inst.keys(): + acq_vals.append(np.asarray(inst["register_slot"], dtype=np.uint32)) else: acq_vals.append(None) - structs['acquire'].append(acq_vals) + structs["acquire"].append(acq_vals) # update max_time - max_time = max(max_time, (inst['t0'] + inst['duration']) * dt) + max_time = max(max_time, (inst["t0"] + inst["duration"]) * dt) # Add time to tlist - if inst['t0'] * dt not in structs['tlist']: - structs['tlist'].append(inst['t0'] * dt) + if inst["t0"] * dt not in structs["tlist"]: + structs["tlist"].append(inst["t0"] * dt) # conditionals - elif inst['name'] == 'bfunc': - bfun_vals = [inst['t0'] * dt, inst['mask'], inst['relation'], - inst['val'], inst['register']] - if 'memory' in inst.keys(): - bfun_vals.append(inst['memory']) + elif inst["name"] == "bfunc": + bfun_vals = [ + inst["t0"] * dt, + inst["mask"], + inst["relation"], + inst["val"], + inst["register"], + ] + if "memory" in inst.keys(): + bfun_vals.append(inst["memory"]) else: bfun_vals.append(None) - structs['cond'].append(acq_vals) + structs["cond"].append(acq_vals) # update max_time - max_time = max(max_time, inst['t0'] * dt) + max_time = max(max_time, inst["t0"] * dt) # Add time to tlist - if inst['t0'] * dt not in structs['tlist']: - structs['tlist'].append(inst['t0'] * dt) + if inst["t0"] * dt not in structs["tlist"]: + structs["tlist"].append(inst["t0"] * dt) # snapshots - elif inst['name'] == 'snapshot': - if inst['type'] != 'state': + elif inst["name"] == "snapshot": + if inst["type"] != "state": raise TypeError("Snapshots must be of type 'state'") - structs['snapshot'].append([inst['t0'] * dt, inst['label']]) + structs["snapshot"].append([inst["t0"] * dt, inst["label"]]) # Add time to tlist - if inst['t0'] * dt not in structs['tlist']: - structs['tlist'].append(inst['t0'] * dt) + if inst["t0"] * dt not in structs["tlist"]: + structs["tlist"].append(inst["t0"] * dt) # update max_time - max_time = max(max_time, inst['t0'] * dt) + max_time = max(max_time, inst["t0"] * dt) # If any PVs still need time then they are at the end # and should just go til final time ham_keys = list(ham_chans.keys()) for idx, pp in enumerate(pv_needs_tf): if pp: - structs['channels'][ham_keys[idx]][0][-3] = max_time + structs["channels"][ham_keys[idx]][0][-3] = max_time pv_needs_tf[idx] = 0 # Convert lists to numpy arrays - for key in structs['channels'].keys(): - structs['channels'][key][0] = np.asarray(structs['channels'][key][0], - dtype=float) - structs['channels'][key][1] = np.asarray(structs['channels'][key][1], - dtype=float) + for key in structs["channels"].keys(): + structs["channels"][key][0] = np.asarray(structs["channels"][key][0], dtype=float) + structs["channels"][key][1] = np.asarray(structs["channels"][key][1], dtype=float) - structs['tlist'] = np.asarray([0] + structs['tlist'], dtype=float) + structs["tlist"] = np.asarray([0] + structs["tlist"], dtype=float) - if structs['tlist'][-1] > structs['acquire'][-1][0]: - structs['can_sample'] = False + if structs["tlist"][-1] > structs["acquire"][-1][0]: + structs["can_sample"] = False return structs diff --git a/qiskit_aer/pulse/controllers/mc_controller.py b/qiskit_aer/pulse/controllers/mc_controller.py index 03e93faf1d..00e14d7f84 100644 --- a/qiskit_aer/pulse/controllers/mc_controller.py +++ b/qiskit_aer/pulse/controllers/mc_controller.py @@ -29,13 +29,13 @@ from qiskit.tools.parallel import parallel_map, CPU_COUNT from .pulse_sim_options import PulseSimOptions from .pulse_de_solver import setup_de_solver -from .pulse_utils import (occ_probabilities, write_shots_memory, spmv, cy_expect_psi) +from .pulse_utils import occ_probabilities, write_shots_memory, spmv, cy_expect_psi dznrm2 = get_blas_funcs("znrm2", dtype=np.float64) def run_monte_carlo_experiments(pulse_sim_desc, pulse_de_model, solver_options=None): - """ Runs monte carlo experiments for a given op_system + """Runs monte carlo experiments for a given op_system Parameters: pulse_sim_desc (PulseSimDescription): description of pulse simulation @@ -64,9 +64,9 @@ def run_monte_carlo_experiments(pulse_sim_desc, pulse_de_model, solver_options=N seed = pulse_sim_desc.seed or np.random.randint(np.iinfo(np.int32).max - 1) prng = np.random.RandomState(seed) for exp in pulse_sim_desc.experiments: - exp['seed'] = prng.randint(np.iinfo(np.int32).max - 1) + exp["seed"] = prng.randint(np.iinfo(np.int32).max - 1) - map_kwargs = {'num_processes': solver_options.num_cpus} + map_kwargs = {"num_processes": solver_options.num_cpus} exp_results = [] exp_times = [] @@ -76,16 +76,20 @@ def run_monte_carlo_experiments(pulse_sim_desc, pulse_de_model, solver_options=N for exp in pulse_sim_desc.experiments: start = time.time() - rng = np.random.RandomState(exp['seed']) + rng = np.random.RandomState(exp["seed"]) seeds = rng.randint(np.iinfo(np.int32).max - 1, size=pulse_sim_desc.shots) - exp_res = parallel_map(monte_carlo_evolution, - seeds, - task_args=(exp, - y0, - pulse_sim_desc, - pulse_de_model, - solver_options, ), - **map_kwargs) + exp_res = parallel_map( + monte_carlo_evolution, + seeds, + task_args=( + exp, + y0, + pulse_sim_desc, + pulse_de_model, + solver_options, + ), + **map_kwargs, + ) # exp_results is a list for each shot # so transform back to an array of shots @@ -100,13 +104,8 @@ def run_monte_carlo_experiments(pulse_sim_desc, pulse_de_model, solver_options=N return exp_results, exp_times -def monte_carlo_evolution(seed, - exp, - y0, - pulse_sim_desc, - pulse_de_model, - solver_options=None): - """ Performs a single monte carlo run for the given op_system, experiment, and seed +def monte_carlo_evolution(seed, exp, y0, pulse_sim_desc, pulse_de_model, solver_options=None): + """Performs a single monte carlo run for the given op_system, experiment, and seed Parameters: seed (int): seed for random number generation @@ -126,12 +125,12 @@ def monte_carlo_evolution(seed, solver_options = PulseSimOptions() if solver_options is None else solver_options rng = np.random.RandomState(seed) - tlist = exp['tlist'] + tlist = exp["tlist"] # Init memory memory = np.zeros((1, pulse_sim_desc.memory_slots), dtype=np.uint8) # Get number of acquire - num_acq = len(exp['acquire']) + num_acq = len(exp["acquire"]) acq_idx = 0 collapse_times = [] @@ -167,18 +166,16 @@ def monte_carlo_evolution(seed, t_final = ODE.t while ii < solver_options.norm_steps: ii += 1 - t_guess = t_prev + \ - log(norm2_prev / rand_vals[0]) / \ - log(norm2_prev / norm2_psi) * (t_final - t_prev) + t_guess = t_prev + log(norm2_prev / rand_vals[0]) / log( + norm2_prev / norm2_psi + ) * (t_final - t_prev) ODE.y = y_prev ODE.t = t_prev ODE.integrate(t_guess, step=0) if not ODE.successful(): - raise Exception( - "Integration failed after adjusting step size!") - norm2_guess = dznrm2(ODE.y)**2 - if (abs(rand_vals[0] - norm2_guess) < - solver_options.norm_tol * rand_vals[0]): + raise Exception("Integration failed after adjusting step size!") + norm2_guess = dznrm2(ODE.y) ** 2 + if abs(rand_vals[0] - norm2_guess) < solver_options.norm_tol * rand_vals[0]: break if norm2_guess < rand_vals[0]: @@ -191,9 +188,11 @@ def monte_carlo_evolution(seed, y_prev = ODE.y norm2_prev = norm2_guess if ii > solver_options.norm_steps: - raise Exception("Norm tolerance not reached. " + - "Increase accuracy of ODE solver or " + - "Options.norm_steps.") + raise Exception( + "Norm tolerance not reached. " + + "Increase accuracy of ODE solver or " + + "Options.norm_steps." + ) collapse_times.append(ODE.t) # all constant collapse operators. @@ -214,8 +213,8 @@ def monte_carlo_evolution(seed, out_psi = ODE.y / dznrm2(ODE.y) for aind in range(acq_idx, num_acq): - if exp['acquire'][aind][0] == stop_time: - current_acq = exp['acquire'][aind] + if exp["acquire"][aind][0] == stop_time: + current_acq = exp["acquire"][aind] qubits = current_acq[1] memory_slots = current_acq[2] probs = occ_probabilities(qubits, out_psi, pulse_sim_desc.measurement_ops) diff --git a/qiskit_aer/pulse/controllers/pulse_controller.py b/qiskit_aer/pulse/controllers/pulse_controller.py index 0e06c48adc..74b4e8ff40 100644 --- a/qiskit_aer/pulse/controllers/pulse_controller.py +++ b/qiskit_aer/pulse/controllers/pulse_controller.py @@ -32,7 +32,7 @@ def pulse_controller(qobj): - """ Interprets PulseQobj input, runs simulations, and returns results + """Interprets PulseQobj input, runs simulations, and returns results Parameters: qobj (PulseQobj): pulse qobj containing a list of pulse schedules @@ -59,12 +59,12 @@ def pulse_controller(qobj): # Get qubit list and number qubit_list = system_model.subsystem_list if qubit_list is None: - raise ValueError('Model must have a qubit list to simulate.') + raise ValueError("Model must have a qubit list to simulate.") n_qubits = len(qubit_list) # get Hamiltonian if system_model.hamiltonian is None: - raise ValueError('Model must have a Hamiltonian to simulate.') + raise ValueError("Model must have a Hamiltonian to simulate.") ham_model = system_model.hamiltonian # Extract DE model information @@ -80,19 +80,19 @@ def pulse_controller(qobj): estates = [op_gen.state(state) for state in ham_model._estates.T[:]] # initial state set here - if getattr(config, 'initial_state', None) is not None: + if getattr(config, "initial_state", None) is not None: pulse_sim_desc.initial_state = op_gen.state(config.initial_state) else: pulse_sim_desc.initial_state = estates[0] # Get dt if system_model.dt is None: - raise ValueError('System model must have a dt value to simulate.') + raise ValueError("System model must have a dt value to simulate.") pulse_de_model.dt = system_model.dt # Parse noise - noise_model = getattr(config, 'noise_model', None) + noise_model = getattr(config, "noise_model", None) # post warnings for unsupported features _unsupported_warnings(noise_model) @@ -108,10 +108,7 @@ def pulse_controller(qobj): # ############################### # ### Parse qobj_config settings # ############################### - digested_qobj = digest_pulse_qobj(qobj, - pulse_de_model.channels, - system_model.dt, - qubit_list) + digested_qobj = digest_pulse_qobj(qobj, pulse_de_model.channels, system_model.dt, qubit_list) # extract simulation-description level qobj content pulse_sim_desc.shots = digested_qobj.shots @@ -133,16 +130,18 @@ def pulse_controller(qobj): # if it wasn't specified in the PulseQobj, draw from system_model if qubit_lo_freq is None: - default_freq = getattr(config, 'qubit_freq_est', [np.inf]) + default_freq = getattr(config, "qubit_freq_est", [np.inf]) if default_freq != [np.inf]: qubit_lo_freq = default_freq # if still None, or is the placeholder value draw from the Hamiltonian if qubit_lo_freq is None: qubit_lo_freq = system_model.hamiltonian.get_qubit_lo_from_drift() - if getattr(qobj.config, 'schedule_los', None) is None: - warn('Warning: qubit_lo_freq was not specified in PulseQobj and there is no default, ' - 'so it is being automatically determined from the drift Hamiltonian.') + if getattr(qobj.config, "schedule_los", None) is None: + warn( + "Warning: qubit_lo_freq was not specified in PulseQobj and there is no default, " + "so it is being automatically determined from the drift Hamiltonian." + ) pulse_de_model.freqs = system_model.calculate_channel_frequencies(qubit_lo_freq=qubit_lo_freq) pulse_de_model.calculate_channel_frequencies = system_model.calculate_channel_frequencies @@ -152,24 +151,31 @@ def pulse_controller(qobj): # # solver-specific information should be extracted in the solver # ############################### - pulse_sim_desc.seed = int(config.seed) if hasattr(config, 'seed') else None - pulse_sim_desc.q_level_meas = int(getattr(config, 'q_level_meas', 1)) + pulse_sim_desc.seed = int(config.seed) if hasattr(config, "seed") else None + pulse_sim_desc.q_level_meas = int(getattr(config, "q_level_meas", 1)) # solver options - allowed_solver_options = ['atol', 'rtol', 'nsteps', 'max_step', - 'num_cpus', 'norm_tol', 'norm_steps', - 'method'] - solver_options = getattr(config, 'solver_options', {}) + allowed_solver_options = [ + "atol", + "rtol", + "nsteps", + "max_step", + "num_cpus", + "norm_tol", + "norm_steps", + "method", + ] + solver_options = getattr(config, "solver_options", {}) for key in solver_options: if key not in allowed_solver_options: - raise Exception('Invalid solver_option: {}'.format(key)) + raise Exception("Invalid solver_option: {}".format(key)) solver_options = PulseSimOptions(**solver_options) # Set the ODE solver max step to be the half the # width of the smallest pulse min_width = np.iinfo(np.int32).max for key, val in pulse_de_model.pulse_to_int.items(): - if key != 'pv': + if key != "pv": stop = pulse_de_model.pulse_indices[val + 1] start = pulse_de_model.pulse_indices[val] min_width = min(min_width, stop - start) @@ -181,27 +187,24 @@ def pulse_controller(qobj): pulse_sim_desc.measurement_ops = [None] * n_qubits for exp in pulse_sim_desc.experiments: - # Add in measurement operators # Not sure if this will work for multiple measurements # Note: the extraction of multiple measurements works, but the simulation routines # themselves implicitly assume there is only one measurement at the end - if any(exp['acquire']): - for acq in exp['acquire']: + if any(exp["acquire"]): + for acq in exp["acquire"]: for jj in acq[1]: if jj > qubit_list[-1]: continue if not pulse_sim_desc.measurement_ops[qubit_list.index(jj)]: q_level_meas = pulse_sim_desc.q_level_meas - pulse_sim_desc.measurement_ops[qubit_list.index(jj)] = \ - op_gen.qubit_occ_oper_dressed(jj, - estates, - h_osc=dim_osc, - h_qub=dim_qub, - level=q_level_meas - ) - - if not exp['can_sample']: + pulse_sim_desc.measurement_ops[ + qubit_list.index(jj) + ] = op_gen.qubit_occ_oper_dressed( + jj, estates, h_osc=dim_osc, h_qub=dim_qub, level=q_level_meas + ) + + if not exp["can_sample"]: pulse_sim_desc.can_sample = False # trim measurement operators to relevant qubits once constructed @@ -211,20 +214,21 @@ def pulse_controller(qobj): meas_ops_reduced.append(op) pulse_sim_desc.measurement_ops = meas_ops_reduced - run_experiments = (run_unitary_experiments if pulse_sim_desc.can_sample - else run_monte_carlo_experiments) + run_experiments = ( + run_unitary_experiments if pulse_sim_desc.can_sample else run_monte_carlo_experiments + ) exp_results, exp_times = run_experiments(pulse_sim_desc, pulse_de_model, solver_options) output = { - 'results': format_exp_results(exp_results, exp_times, pulse_sim_desc), - 'success': True, - 'qobj_id': qobj.qobj_id + "results": format_exp_results(exp_results, exp_times, pulse_sim_desc), + "success": True, + "qobj_id": qobj.qobj_id, } return output def format_exp_results(exp_results, exp_times, pulse_sim_desc): - """ format simulation results + """format simulation results Parameters: exp_results (list): simulation results @@ -238,28 +242,28 @@ def format_exp_results(exp_results, exp_times, pulse_sim_desc): # format the data into the proper output all_results = [] for idx_exp, exp in enumerate(pulse_sim_desc.experiments): - m_lev = pulse_sim_desc.meas_level m_ret = pulse_sim_desc.meas_return # populate the results dictionary - results = {'seed_simulator': exp['seed'], - 'shots': pulse_sim_desc.shots, - 'status': 'DONE', - 'success': True, - 'time_taken': exp_times[idx_exp], - 'header': exp['header'], - 'meas_level': m_lev, - 'meas_return': m_ret, - 'data': {}} + results = { + "seed_simulator": exp["seed"], + "shots": pulse_sim_desc.shots, + "status": "DONE", + "success": True, + "time_taken": exp_times[idx_exp], + "header": exp["header"], + "meas_level": m_lev, + "meas_return": m_ret, + "data": {}, + } if pulse_sim_desc.can_sample: memory = exp_results[idx_exp][0] - results['data']['statevector'] = [] + results["data"]["statevector"] = [] for coef in exp_results[idx_exp][1]: - results['data']['statevector'].append([np.real(coef), - np.imag(coef)]) - results['header']['ode_t'] = exp_results[idx_exp][2] + results["data"]["statevector"].append([np.real(coef), np.imag(coef)]) + results["header"]["ode_t"] = exp_results[idx_exp][2] else: memory = exp_results[idx_exp] @@ -268,13 +272,12 @@ def format_exp_results(exp_results, exp_times, pulse_sim_desc): # convert the memory **array** into a n # integer # e.g. [1,0] -> 2 - int_mem = memory.dot(np.power(2.0, - np.arange(memory.shape[1]))).astype(int) + int_mem = memory.dot(np.power(2.0, np.arange(memory.shape[1]))).astype(int) # if the memory flag is set return each shot if pulse_sim_desc.memory: hex_mem = [hex(val) for val in int_mem] - results['data']['memory'] = hex_mem + results["data"]["memory"] = hex_mem # Get hex counts dict unique = np.unique(int_mem, return_counts=True) @@ -282,32 +285,29 @@ def format_exp_results(exp_results, exp_times, pulse_sim_desc): for kk in range(unique[0].shape[0]): key = hex(unique[0][kk]) hex_dict[key] = unique[1][kk] - results['data']['counts'] = hex_dict + results["data"]["counts"] = hex_dict # meas_level 1 returns the elif m_lev == 1: - - if m_ret == 'avg': - + if m_ret == "avg": memory = [np.mean(memory, 0)] # convert into the right [real, complex] pair form for json - results['data']['memory'] = [] + results["data"]["memory"] = [] for mem_shot in memory: - results['data']['memory'].append([]) + results["data"]["memory"].append([]) for mem_slot in mem_shot: - results['data']['memory'][-1].append( - [np.real(mem_slot), np.imag(mem_slot)]) + results["data"]["memory"][-1].append([np.real(mem_slot), np.imag(mem_slot)]) - if m_ret == 'avg': - results['data']['memory'] = results['data']['memory'][0] + if m_ret == "avg": + results["data"]["memory"] = results["data"]["memory"][0] all_results.append(results) return all_results def _unsupported_warnings(noise_model): - """ Warns the user about untested/unsupported features. + """Warns the user about untested/unsupported features. Parameters: noise_model (dict): backend_options for simulation @@ -317,14 +317,13 @@ def _unsupported_warnings(noise_model): """ # Warnings that don't stop execution - warning_str = '{} are an untested feature, and therefore may not behave as expected.' + warning_str = "{} are an untested feature, and therefore may not behave as expected." if noise_model is not None: - warn(warning_str.format('Noise models')) + warn(warning_str.format("Noise models")) class PulseInternalDEModel: - """Container of information required for de RHS construction - """ + """Container of information required for de RHS construction""" def __init__(self): # The system Hamiltonian in numerical format @@ -372,8 +371,7 @@ def __init__(self): self._rhs_dict = None def _config_internal_data(self): - """Preps internal data into format required by RHS function. - """ + """Preps internal data into format required by RHS function.""" self.vars = list(self.variables.values()) # Need this info for evaluating the hamiltonian vars in the c++ solver @@ -411,14 +409,16 @@ def _config_internal_data(self): # construct data sets self.h_ops_data = [-1.0j * hpart.data for hpart in H] - self._rhs_dict = {'freqs': list(self.freqs.values()), - 'pulse_array': self.pulse_array, - 'pulse_indices': self.pulse_indices, - 'vars': self.vars, - 'vars_names': self.vars_names, - 'num_h_terms': self.num_h_terms, - 'h_ops_data': self.h_ops_data, - 'h_diag_elems': self.h_diag_elems} + self._rhs_dict = { + "freqs": list(self.freqs.values()), + "pulse_array": self.pulse_array, + "pulse_indices": self.pulse_indices, + "vars": self.vars, + "vars_names": self.vars_names, + "num_h_terms": self.num_h_terms, + "h_ops_data": self.h_ops_data, + "h_diag_elems": self.h_diag_elems, + } def init_rhs(self, exp): """Set up and return rhs function corresponding to this model for a given @@ -443,9 +443,9 @@ def rhs(t, y): return rhs -def setup_rhs_dict_freqs(default_rhs_dict: dict, - exp: dict, - calculate_channel_frequencies: Callable): +def setup_rhs_dict_freqs( + default_rhs_dict: dict, exp: dict, calculate_channel_frequencies: Callable +): """Standalone function for overriding channel frequencies in a given experiment. Args: @@ -458,19 +458,20 @@ def setup_rhs_dict_freqs(default_rhs_dict: dict, dict: Dictionary with frequencies potentially overriden by those in exp. """ - if 'qubit_lo_freq' in exp and exp['qubit_lo_freq'] is not None: + if "qubit_lo_freq" in exp and exp["qubit_lo_freq"] is not None: # copy to not overwrite defaults default_rhs_dict = copy(default_rhs_dict) - freqs_dict = calculate_channel_frequencies(exp['qubit_lo_freq']) - default_rhs_dict['freqs'] = list(freqs_dict.values()) + freqs_dict = calculate_channel_frequencies(exp["qubit_lo_freq"]) + default_rhs_dict["freqs"] = list(freqs_dict.values()) return default_rhs_dict class PulseSimDescription: - """ Object for holding any/all information required for simulation. + """Object for holding any/all information required for simulation. Needs to be refactored into different pieces. """ + def __init__(self): self.initial_state = None # Channels in the Hamiltonian string diff --git a/qiskit_aer/pulse/controllers/pulse_de_solver.py b/qiskit_aer/pulse/controllers/pulse_de_solver.py index 16c93b790b..ab6081f06b 100644 --- a/qiskit_aer/pulse/controllers/pulse_de_solver.py +++ b/qiskit_aer/pulse/controllers/pulse_de_solver.py @@ -24,7 +24,7 @@ def setup_de_solver(exp, y0, pulse_de_model, de_options): - """ Constructs a scipy ODE solver for a given exp and op_system + """Constructs a scipy ODE solver for a given exp and op_system Parameters: exp (dict): dict containing experiment description diff --git a/qiskit_aer/pulse/controllers/pulse_sim_options.py b/qiskit_aer/pulse/controllers/pulse_sim_options.py index 9357078803..5ceefb7b9c 100644 --- a/qiskit_aer/pulse/controllers/pulse_sim_options.py +++ b/qiskit_aer/pulse/controllers/pulse_sim_options.py @@ -17,7 +17,7 @@ from ..de.DE_Options import DE_Options -class PulseSimOptions(): +class PulseSimOptions: """ Class of options for pulse solver routines. Options can be specified either as arguments to the constructor:: @@ -54,35 +54,38 @@ class PulseSimOptions(): of the evolution. """ - def __init__(self, - method='zvode-adams', - atol=1e-8, - rtol=1e-6, - order=12, - nsteps=10**6, - first_step=None, - max_step=None, - min_step=None, - max_dt=10**-3, - num_cpus=0, - norm_tol=1e-3, - norm_steps=5, - progress_bar=True, - shots=1024, - store_final_state=False, - seeds=None, - reuse_seeds=False): - + def __init__( + self, + method="zvode-adams", + atol=1e-8, + rtol=1e-6, + order=12, + nsteps=10**6, + first_step=None, + max_step=None, + min_step=None, + max_dt=10**-3, + num_cpus=0, + norm_tol=1e-3, + norm_steps=5, + progress_bar=True, + shots=1024, + store_final_state=False, + seeds=None, + reuse_seeds=False, + ): # set DE specific options - self.de_options = DE_Options(method=method, - atol=atol, - rtol=rtol, - order=order, - nsteps=nsteps, - first_step=first_step, - max_step=max_step, - min_step=min_step, - max_dt=max_dt) + self.de_options = DE_Options( + method=method, + atol=atol, + rtol=rtol, + order=order, + nsteps=nsteps, + first_step=first_step, + max_step=max_step, + min_step=min_step, + max_dt=max_dt, + ) self.shots = shots self.seeds = seeds @@ -95,23 +98,25 @@ def __init__(self, def copy(self): """Create a copy.""" - return PulseSimOptions(method=self.de_options.method, - atol=self.de_options.atol, - rtol=self.de_options.rtol, - order=self.de_options.order, - nsteps=self.de_options.nsteps, - first_step=self.de_options.first_step, - max_step=self.de_options.max_step, - min_step=self.de_options.min_step, - max_dt=self.de_options.max_dt, - num_cpus=self.num_cpus, - norm_tol=self.norm_tol, - norm_steps=self.norm_steps, - progress_bar=self.progress_bar, - shots=self.shots, - store_final_state=self.store_final_state, - seeds=self.seeds, - reuse_seeds=self.reuse_seeds) + return PulseSimOptions( + method=self.de_options.method, + atol=self.de_options.atol, + rtol=self.de_options.rtol, + order=self.de_options.order, + nsteps=self.de_options.nsteps, + first_step=self.de_options.first_step, + max_step=self.de_options.max_step, + min_step=self.de_options.min_step, + max_dt=self.de_options.max_dt, + num_cpus=self.num_cpus, + norm_tol=self.norm_tol, + norm_steps=self.norm_steps, + progress_bar=self.progress_bar, + shots=self.shots, + store_final_state=self.store_final_state, + seeds=self.seeds, + reuse_seeds=self.reuse_seeds, + ) def __str__(self): return str(vars(self)) diff --git a/qiskit_aer/pulse/controllers/unitary_controller.py b/qiskit_aer/pulse/controllers/unitary_controller.py index 0397e12f25..29a8afb8e5 100644 --- a/qiskit_aer/pulse/controllers/unitary_controller.py +++ b/qiskit_aer/pulse/controllers/unitary_controller.py @@ -42,7 +42,7 @@ def _full_simulation(exp, y0, pulse_sim_desc, pulse_de_model, solver_options=Non # ############### # do measurement # ############### - rng = np.random.RandomState(exp['seed']) + rng = np.random.RandomState(exp["seed"]) shots = pulse_sim_desc.shots # Init memory @@ -50,13 +50,13 @@ def _full_simulation(exp, y0, pulse_sim_desc, pulse_de_model, solver_options=Non qubits = [] memory_slots = [] - tlist = exp['tlist'] - for acq in exp['acquire']: + tlist = exp["tlist"] + for acq in exp["acquire"]: if acq[0] == tlist[-1]: qubits += list(acq[1]) memory_slots += list(acq[2]) - qubits = np.array(qubits, dtype='uint32') - memory_slots = np.array(memory_slots, dtype='uint32') + qubits = np.array(qubits, dtype="uint32") + memory_slots = np.array(memory_slots, dtype="uint32") probs = occ_probabilities(qubits, psi, pulse_sim_desc.measurement_ops) rand_vals = rng.rand(memory_slots.shape[0] * shots) @@ -66,7 +66,7 @@ def _full_simulation(exp, y0, pulse_sim_desc, pulse_de_model, solver_options=Non def run_unitary_experiments(pulse_sim_desc, pulse_de_model, solver_options=None): - """ Runs unitary experiments for a given op_system + """Runs unitary experiments for a given op_system Parameters: pulse_sim_desc (PulseSimDescription): description of pulse simulation @@ -95,20 +95,27 @@ def run_unitary_experiments(pulse_sim_desc, pulse_de_model, solver_options=None) seed = pulse_sim_desc.seed or np.random.randint(np.iinfo(np.int32).max - 1) prng = np.random.RandomState(seed) for exp in pulse_sim_desc.experiments: - exp['seed'] = prng.randint(np.iinfo(np.int32).max - 1) + exp["seed"] = prng.randint(np.iinfo(np.int32).max - 1) - map_kwargs = {'num_processes': solver_options.num_cpus} + map_kwargs = {"num_processes": solver_options.num_cpus} # run simulation on each experiment in parallel start = time.time() - exp_results = parallel_map(_full_simulation, - pulse_sim_desc.experiments, - task_args=(y0, pulse_sim_desc, pulse_de_model, solver_options, ), - **map_kwargs - ) + exp_results = parallel_map( + _full_simulation, + pulse_sim_desc.experiments, + task_args=( + y0, + pulse_sim_desc, + pulse_de_model, + solver_options, + ), + **map_kwargs, + ) end = time.time() - exp_times = (np.ones(len(pulse_sim_desc.experiments)) * - (end - start) / len(pulse_sim_desc.experiments)) + exp_times = ( + np.ones(len(pulse_sim_desc.experiments)) * (end - start) / len(pulse_sim_desc.experiments) + ) return exp_results, exp_times @@ -135,14 +142,14 @@ def unitary_evolution(exp, y0, pulse_de_model, solver_options=None): ODE = setup_de_solver(exp, y0, pulse_de_model, solver_options.de_options) - tlist = exp['tlist'] + tlist = exp["tlist"] for t in tlist[1:]: ODE.integrate(t) if ODE.successful(): psi = ODE.y / dznrm2(ODE.y) else: - err_msg = 'ODE method exited with status: %s' % ODE.return_code() + err_msg = "ODE method exited with status: %s" % ODE.return_code() raise Exception(err_msg) # apply final rotation to come out of rotating frame diff --git a/qiskit_aer/pulse/de/DE_Methods.py b/qiskit_aer/pulse/de/DE_Methods.py index f0994c4aaa..812cd53618 100644 --- a/qiskit_aer/pulse/de/DE_Methods.py +++ b/qiskit_aer/pulse/de/DE_Methods.py @@ -45,10 +45,9 @@ class ODE_Method(ABC): rhs (dict): rhs-related functions as values Currently supports key 'rhs'. """ - method_spec = {'inner_state_spec': {'type': 'array'}} + method_spec = {"inner_state_spec": {"type": "array"}} def __init__(self, t0=None, y0=None, rhs=None, options=None): - # set_options is first as options may influence the behaviour of other functions self.set_options(options) @@ -110,14 +109,14 @@ def y(self, new_y): self.set_y(new_y) def set_y(self, new_y, reset=True): - """Method for logic of setting internal state of solver with more control - """ + """Method for logic of setting internal state of solver with more control""" # instantiate internal StateTypeConverter based on the provided new_y and the # general type required internally by the solver - type_spec = self.method_spec.get('inner_state_spec') - self._state_type_converter = \ - StateTypeConverter.from_outer_instance_inner_type_spec(new_y, type_spec) + type_spec = self.method_spec.get("inner_state_spec") + self._state_type_converter = StateTypeConverter.from_outer_instance_inner_type_spec( + new_y, type_spec + ) # set internal state self._y = self._state_type_converter.outer_to_inner(new_y) @@ -138,13 +137,13 @@ def set_rhs(self, rhs=None, reset=True): """ if rhs is None: - rhs = {'rhs': None} + rhs = {"rhs": None} if callable(rhs): - rhs = {'rhs': rhs} + rhs = {"rhs": rhs} - if 'rhs' not in rhs: - raise Exception('ODE_Method requires at minimum a specification of an rhs function.') + if "rhs" not in rhs: + raise Exception("ODE_Method requires at minimum a specification of an rhs function.") # transform rhs function into a function that accepts/returns inner state type self.rhs = self._state_type_converter.transform_rhs_funcs(rhs) @@ -198,26 +197,29 @@ class ScipyODE(ODE_Method): do not handle complex types """ - method_spec = {'inner_state_spec': {'type': 'array', 'ndim': 1}} + method_spec = {"inner_state_spec": {"type": "array", "ndim": 1}} def integrate(self, tf, **kwargs): - """Integrate up to a time tf. - """ + """Integrate up to a time tf.""" t0 = self.t y0 = self._y - rhs = self.rhs.get('rhs') + rhs = self.rhs.get("rhs") # solve problem and silence warnings for options that don't apply to a given method kept_warnings = [] with warnings.catch_warnings(record=True) as ws: - results = solve_ivp(rhs, (t0, tf), y0, - method=self.options.method, - atol=self.options.atol, - rtol=self.options.rtol, - max_step=self.options.max_step, - min_step=self.options.min_step, - first_step=self.options.first_step, - **kwargs) + results = solve_ivp( + rhs, + (t0, tf), + y0, + method=self.options.method, + atol=self.options.atol, + rtol=self.options.rtol, + max_step=self.options.max_step, + min_step=self.options.min_step, + first_step=self.options.first_step, + **kwargs, + ) # update the internal state self._y = results.y[:, -1] @@ -225,7 +227,7 @@ def integrate(self, tf, **kwargs): # discard warnings for arguments with no effect for w in ws: - if 'The following arguments have no effect' not in str(w.message): + if "The following arguments have no effect" not in str(w.message): kept_warnings.append(w) # display warnings we don't want to silence @@ -236,10 +238,10 @@ def set_options(self, options): # establish method if options is None: options = DE_Options() - options.method = 'RK45' + options.method = "RK45" else: options = options.copy() - if 'scipy-' in options.method: + if "scipy-" in options.method: options.method = options.method[6:] self.options = options @@ -256,13 +258,12 @@ class QiskitZVODE(ODE_Method): - Internally this """ - method_spec = {'inner_state_spec': {'type': 'array', 'ndim': 1}} + method_spec = {"inner_state_spec": {"type": "array", "ndim": 1}} def __init__(self, t0=None, y0=None, rhs=None, options=None): - # all de specification arguments are necessary to instantiate scipy ode object if (t0 is None) or (y0 is None) or (rhs is None): - raise Exception('QiskitZVODE solver requires t0, y0, and rhs at instantiation.') + raise Exception("QiskitZVODE solver requires t0, y0, and rhs at instantiation.") # initialize internal attribute for storing scipy ode object self._ODE = None @@ -280,11 +281,11 @@ def t(self, new_t): self._reset_method() def set_y(self, new_y, reset=True): - """Method for logic of setting internal state of solver with more control - """ - type_spec = self.method_spec.get('inner_state_spec') - self._state_type_converter = \ - StateTypeConverter.from_outer_instance_inner_type_spec(new_y, type_spec) + """Method for logic of setting internal state of solver with more control""" + type_spec = self.method_spec.get("inner_state_spec") + self._state_type_converter = StateTypeConverter.from_outer_instance_inner_type_spec( + new_y, type_spec + ) self._y = self._state_type_converter.outer_to_inner(new_y) @@ -297,27 +298,28 @@ def set_rhs(self, rhs=None, reset=True): """This set_rhs function fully instantiates the scipy ode object behind the scenes.""" if rhs is None: - rhs = {'rhs': None} + rhs = {"rhs": None} if callable(rhs): - rhs = {'rhs': rhs} + rhs = {"rhs": rhs} - if 'rhs' not in rhs: - raise Exception('ODE_Method requires at minimum a specification of an rhs function.') + if "rhs" not in rhs: + raise Exception("ODE_Method requires at minimum a specification of an rhs function.") self.rhs = self._state_type_converter.transform_rhs_funcs(rhs) - self._ODE = ode(self.rhs['rhs']) + self._ODE = ode(self.rhs["rhs"]) - self._ODE._integrator = qiskit_zvode(method=self.options.method, - order=self.options.order, - atol=self.options.atol, - rtol=self.options.rtol, - nsteps=self.options.nsteps, - first_step=self.options.first_step, - min_step=self.options.min_step, - max_step=self.options.max_step - ) + self._ODE._integrator = qiskit_zvode( + method=self.options.method, + order=self.options.order, + atol=self.options.atol, + rtol=self.options.rtol, + nsteps=self.options.nsteps, + first_step=self.options.first_step, + min_step=self.options.min_step, + max_step=self.options.max_step, + ) # Forces complex ODE solving if not self._ODE._y: @@ -339,7 +341,7 @@ def integrate(self, tf, **kwargs): single step of the solver """ - step = kwargs.get('step', False) + step = kwargs.get("step", False) self._ODE.integrate(tf, step=step) @@ -359,10 +361,10 @@ def _reset_method(self, reset=True): def set_options(self, options): # establish method if options is None: - options = DE_Options(method='adams') + options = DE_Options(method="adams") else: options = options.copy() - if 'zvode-' in options.method: + if "zvode-" in options.method: options.method = options.method[6:] # handle None-type defaults @@ -383,6 +385,7 @@ class qiskit_zvode(zvode): it always stops at a given time in tlist; by default, it over shoots the time. """ + def step(self, *args): itask = self.call_args[2] self.rwork[0] = args[4] @@ -399,8 +402,7 @@ class RK4(ODE_Method): """ def integrate(self, tf, **kwargs): - """Integrate up to a time tf. - """ + """Integrate up to a time tf.""" delta_t = tf - self.t steps = int((delta_t // self._max_dt) + 1) @@ -409,11 +411,10 @@ def integrate(self, tf, **kwargs): self._integration_step(h) def _integration_step(self, h): - """Integration step for RK4 - """ + """Integration step for RK4""" y0 = self._y t0 = self._t - rhs = self.rhs.get('rhs') + rhs = self.rhs.get("rhs") k1 = rhs(t0, y0) t_mid = t0 + (h / 2) @@ -421,7 +422,7 @@ def _integration_step(self, h): k3 = rhs(t_mid, y0 + (h * k2 / 2)) t_end = t0 + h k4 = rhs(t_end, y0 + h * k3) - self._y = y0 + (1. / 6) * h * (k1 + (2 * k2) + (2 * k3) + k4) + self._y = y0 + (1.0 / 6) * h * (k1 + (2 * k2) + (2 * k3) + k4) self._t = t_end def set_options(self, options): @@ -438,14 +439,12 @@ def method_from_string(method_str): method: instance of an ODE_Method object """ - if 'scipy-' in method_str: + if "scipy-" in method_str: return ScipyODE - if 'zvode-' in method_str: + if "zvode-" in method_str: return QiskitZVODE - method_dict = {'RK4': RK4, - 'scipy': ScipyODE, - 'zvode': QiskitZVODE} + method_dict = {"RK4": RK4, "scipy": ScipyODE, "zvode": QiskitZVODE} return method_dict.get(method_str) diff --git a/qiskit_aer/pulse/de/DE_Options.py b/qiskit_aer/pulse/de/DE_Options.py index 2825000d99..5fe1081326 100644 --- a/qiskit_aer/pulse/de/DE_Options.py +++ b/qiskit_aer/pulse/de/DE_Options.py @@ -45,17 +45,18 @@ class DE_Options: max_dt (float, 1e-3): Max step size for fixed step solver. """ - def __init__(self, - method='zvode-adams', - atol=1e-8, - rtol=1e-6, - order=12, - nsteps=10**6, - first_step=None, - max_step=None, - min_step=None, - max_dt=10**-3): - + def __init__( + self, + method="zvode-adams", + atol=1e-8, + rtol=1e-6, + order=12, + nsteps=10**6, + first_step=None, + max_step=None, + min_step=None, + max_dt=10**-3, + ): self.method = method self.atol = atol self.rtol = rtol @@ -68,15 +69,17 @@ def __init__(self, def copy(self): """Create a copy of the object.""" - return DE_Options(method=self.method, - atol=self.atol, - rtol=self.rtol, - order=self.order, - nsteps=self.nsteps, - first_step=self.first_step, - max_step=self.max_step, - min_step=self.min_step, - max_dt=self.max_dt) + return DE_Options( + method=self.method, + atol=self.atol, + rtol=self.rtol, + order=self.order, + nsteps=self.nsteps, + first_step=self.first_step, + max_step=self.max_step, + min_step=self.min_step, + max_dt=self.max_dt, + ) def __str__(self): return str(vars(self)) diff --git a/qiskit_aer/pulse/de/type_utils.py b/qiskit_aer/pulse/de/type_utils.py index 5d671c0637..e445c81df1 100644 --- a/qiskit_aer/pulse/de/type_utils.py +++ b/qiskit_aer/pulse/de/type_utils.py @@ -90,27 +90,27 @@ def from_outer_instance_inner_type_spec(cls, outer_y, inner_type_spec=None): if inner_type_spec is None: return cls.from_instances(outer_y) - inner_type = inner_type_spec.get('type') + inner_type = inner_type_spec.get("type") if inner_type is None: raise Exception("inner_type_spec needs a 'type' key.") - if inner_type == 'array': + if inner_type == "array": outer_y_as_array = np.array(outer_y) # if a specific shape is given attempt to instantiate from a reshaped outer_y - shape = inner_type_spec.get('shape') + shape = inner_type_spec.get("shape") if shape is not None: return cls.from_instances(outer_y_as_array.reshape(shape), outer_y) # handle the case that ndim == 1 is given - ndim = inner_type_spec.get('ndim') + ndim = inner_type_spec.get("ndim") if ndim == 1: return cls.from_instances(outer_y_as_array.flatten(), outer_y) # if neither shape nor ndim is given, assume it can be an array of any shape return cls.from_instances(outer_y_as_array, outer_y) - raise Exception('inner_type_spec not a handled type.') + raise Exception("inner_type_spec not a handled type.") def inner_to_outer(self, y): """Convert a state of inner type to one of outer type.""" @@ -137,15 +137,16 @@ def transform_rhs_funcs(self, rhs_funcs): new_rhs_funcs = {} # transform standard rhs function - rhs = rhs_funcs.get('rhs') + rhs = rhs_funcs.get("rhs") if rhs is not None: + def new_rhs(t, y): outer_y = self.inner_to_outer(y) rhs_val = rhs(t, outer_y) return self.outer_to_inner(rhs_val) - new_rhs_funcs['rhs'] = new_rhs + new_rhs_funcs["rhs"] = new_rhs return new_rhs_funcs @@ -156,11 +157,11 @@ def convert_state(y, type_spec): new_y = None - if type_spec['type'] == 'array': + if type_spec["type"] == "array": # default array data type to complex - new_y = np.array(y, dtype=type_spec.get('dtype', 'complex')) + new_y = np.array(y, dtype=type_spec.get("dtype", "complex")) - shape = type_spec.get('shape') + shape = type_spec.get("shape") if shape is not None: new_y = new_y.reshape(shape) @@ -171,7 +172,7 @@ def type_spec_from_instance(y): """Determine type spec from an instance.""" type_spec = {} if isinstance(y, np.ndarray): - type_spec['type'] = 'array' - type_spec['shape'] = y.shape + type_spec["type"] = "array" + type_spec["shape"] = y.shape return type_spec diff --git a/qiskit_aer/pulse/system_models/duffing_model_generators.py b/qiskit_aer/pulse/system_models/duffing_model_generators.py index 4fc5431971..fd1cc09039 100644 --- a/qiskit_aer/pulse/system_models/duffing_model_generators.py +++ b/qiskit_aer/pulse/system_models/duffing_model_generators.py @@ -22,12 +22,9 @@ from .pulse_system_model import PulseSystemModel -def duffing_system_model(dim_oscillators, - oscillator_freqs, - anharm_freqs, - drive_strengths, - coupling_dict, - dt): +def duffing_system_model( + dim_oscillators, oscillator_freqs, anharm_freqs, drive_strengths, coupling_dict, dt +): r"""Returns a :class:`PulseSystemModel` representing a physical model for a collection of Duffing oscillators. @@ -120,25 +117,27 @@ def duffing_system_model(dim_oscillators, """ # set symbols for string generation - freq_symbol = 'v' - anharm_symbol = 'alpha' - drive_symbol = 'r' - coupling_symbol = 'j' + freq_symbol = "v" + anharm_symbol = "alpha" + drive_symbol = "r" + coupling_symbol = "j" coupling_edges = coupling_dict.keys() # construct coupling graph, and raise warning if coupling_edges contains duplicate edges coupling_graph = CouplingGraph(coupling_edges) if len(coupling_graph.graph) < len(coupling_edges): - warn('Warning: The coupling_dict contains diplicate edges, and the second appearance of \ - the same edge will be ignored.') + warn( + "Warning: The coupling_dict contains diplicate edges, and the second appearance of \ + the same edge will be ignored." + ) # construct the HamiltonianModel num_oscillators = len(oscillator_freqs) oscillators = list(range(num_oscillators)) oscillator_dims = [dim_oscillators] * num_oscillators - freq_symbols = _str_list_generator(freq_symbol + '{0}', oscillators) - anharm_symbols = _str_list_generator(anharm_symbol + '{0}', oscillators) - drive_symbols = _str_list_generator(drive_symbol + '{0}', oscillators) + freq_symbols = _str_list_generator(freq_symbol + "{0}", oscillators) + anharm_symbols = _str_list_generator(anharm_symbol + "{0}", oscillators) + drive_symbols = _str_list_generator(drive_symbol + "{0}", oscillators) sorted_coupling_edges = coupling_graph.sorted_graph # populate coupling strengths in sorted order (vertex indices are now also sorted within edges, # so this needs to be accounted for when retrieving weights from coupling_dict) @@ -149,21 +148,23 @@ def duffing_system_model(dim_oscillators, edge_strength = coupling_dict.get((edge[1], edge[0])) coupling_strengths.append(edge_strength) - coupling_symbols = _str_list_generator(coupling_symbol + '{0}{1}', *zip(*sorted_coupling_edges)) + coupling_symbols = _str_list_generator(coupling_symbol + "{0}{1}", *zip(*sorted_coupling_edges)) cr_idx_dict = coupling_graph.two_way_graph_dict - hamiltonian_dict = _duffing_hamiltonian_dict(oscillators=oscillators, - oscillator_dims=oscillator_dims, - oscillator_freqs=oscillator_freqs, - freq_symbols=freq_symbols, - anharm_freqs=anharm_freqs, - anharm_symbols=anharm_symbols, - drive_strengths=drive_strengths, - drive_symbols=drive_symbols, - ordered_coupling_edges=sorted_coupling_edges, - coupling_strengths=coupling_strengths, - coupling_symbols=coupling_symbols, - cr_idx_dict=cr_idx_dict) + hamiltonian_dict = _duffing_hamiltonian_dict( + oscillators=oscillators, + oscillator_dims=oscillator_dims, + oscillator_freqs=oscillator_freqs, + freq_symbols=freq_symbols, + anharm_freqs=anharm_freqs, + anharm_symbols=anharm_symbols, + drive_strengths=drive_strengths, + drive_symbols=drive_symbols, + ordered_coupling_edges=sorted_coupling_edges, + coupling_strengths=coupling_strengths, + coupling_symbols=coupling_symbols, + cr_idx_dict=cr_idx_dict, + ) hamiltonian_model = HamiltonianModel.from_dict(hamiltonian_dict) @@ -171,28 +172,32 @@ def duffing_system_model(dim_oscillators, u_channel_lo = _cr_lo_list(cr_idx_dict) # construct and return the PulseSystemModel - return PulseSystemModel(hamiltonian=hamiltonian_model, - u_channel_lo=u_channel_lo, - control_channel_labels=coupling_graph.sorted_two_way_graph, - subsystem_list=oscillators, - dt=dt) + return PulseSystemModel( + hamiltonian=hamiltonian_model, + u_channel_lo=u_channel_lo, + control_channel_labels=coupling_graph.sorted_two_way_graph, + subsystem_list=oscillators, + dt=dt, + ) # Helper functions for creating pieces necessary to construct oscillator system models -def _duffing_hamiltonian_dict(oscillators, - oscillator_dims, - oscillator_freqs, - freq_symbols, - anharm_freqs, - anharm_symbols, - drive_strengths, - drive_symbols, - ordered_coupling_edges, - coupling_strengths, - coupling_symbols, - cr_idx_dict): +def _duffing_hamiltonian_dict( + oscillators, + oscillator_dims, + oscillator_freqs, + freq_symbols, + anharm_freqs, + anharm_symbols, + drive_strengths, + drive_symbols, + ordered_coupling_edges, + coupling_strengths, + coupling_symbols, + cr_idx_dict, +): """Creates a hamiltonian string dict for a duffing oscillator model Note, this function makes the following assumptions: @@ -254,7 +259,7 @@ def _duffing_hamiltonian_dict(oscillators, dim_dict = {str(oscillator): dim for oscillator, dim in zip(oscillators, oscillator_dims)} - return {'h_str': hamiltonian_str, 'vars': var_dict, 'qub': dim_dict} + return {"h_str": hamiltonian_str, "vars": var_dict, "qub": dim_dict} def _cr_lo_list(cr_idx_dict): @@ -293,13 +298,10 @@ def _single_duffing_drift_terms(freq_symbols, anharm_symbols, system_list): list: drift term strings """ - harm_terms = _str_list_generator('np.pi*(2*{0}-{1})*O{2}', - freq_symbols, - anharm_symbols, - system_list) - anharm_terms = _str_list_generator('np.pi*{0}*O{1}*O{1}', - anharm_symbols, - system_list) + harm_terms = _str_list_generator( + "np.pi*(2*{0}-{1})*O{2}", freq_symbols, anharm_symbols, system_list + ) + anharm_terms = _str_list_generator("np.pi*{0}*O{1}*O{1}", anharm_symbols, system_list) return harm_terms + anharm_terms @@ -314,9 +316,7 @@ def _drive_terms(drive_symbols, system_list): list: drive term strings """ - return _str_list_generator('2*np.pi*{0}*X{1}||D{1}', - drive_symbols, - system_list) + return _str_list_generator("2*np.pi*{0}*X{1}||D{1}", drive_symbols, system_list) def _exchange_coupling_terms(coupling_symbols, ordered_edges): @@ -331,10 +331,9 @@ def _exchange_coupling_terms(coupling_symbols, ordered_edges): idx1_list, idx2_list = zip(*list(ordered_edges)) - return _str_list_generator('2*np.pi*{0}*(Sp{1}*Sm{2}+Sm{1}*Sp{2})', - coupling_symbols, - idx1_list, - idx2_list) + return _str_list_generator( + "2*np.pi*{0}*(Sp{1}*Sm{2}+Sm{1}*Sp{2})", coupling_symbols, idx1_list, idx2_list + ) def _cr_terms(drive_symbols, driven_system_indices, u_channel_indices): @@ -348,10 +347,9 @@ def _cr_terms(drive_symbols, driven_system_indices, u_channel_indices): list: cr term strings """ - return _str_list_generator('2*np.pi*{0}*X{1}||U{2}', - drive_symbols, - driven_system_indices, - u_channel_indices) + return _str_list_generator( + "2*np.pi*{0}*X{1}||U{2}", drive_symbols, driven_system_indices, u_channel_indices + ) def _str_list_generator(str_template, *args): @@ -451,8 +449,9 @@ def __init__(self, edges): self.sorted_two_way_graph = two_way_graph_list # create the dictionary version - self.two_way_graph_dict = {self.sorted_two_way_graph[k]: k - for k in range(len(self.sorted_two_way_graph))} + self.two_way_graph_dict = { + self.sorted_two_way_graph[k]: k for k in range(len(self.sorted_two_way_graph)) + } def sorted_edge_index(self, edge): """Given an edge, returns the index in self.sorted_graph. Order in edge does not matter. diff --git a/qiskit_aer/pulse/system_models/hamiltonian_model.py b/qiskit_aer/pulse/system_models/hamiltonian_model.py index a4b6c90f1d..90978b3419 100644 --- a/qiskit_aer/pulse/system_models/hamiltonian_model.py +++ b/qiskit_aer/pulse/system_models/hamiltonian_model.py @@ -22,13 +22,10 @@ from .string_model_parser.string_model_parser import HamiltonianParser -class HamiltonianModel(): +class HamiltonianModel: """Hamiltonian model for pulse simulator.""" - def __init__(self, - system=None, - variables=None, - subsystem_dims=None): + def __init__(self, system=None, variables=None, subsystem_dims=None): """Initialize a Hamiltonian model. Args: @@ -65,7 +62,7 @@ def __init__(self, self._calculate_hamiltonian_channels() if len(self._channels) == 0: - raise AerError('HamiltonianModel must contain channels to simulate.') + raise AerError("HamiltonianModel must contain channels to simulate.") # populate self._h_diag, self._evals, self._estates self._compute_drift_data() @@ -89,51 +86,42 @@ def from_dict(cls, hamiltonian, subsystem_list=None): # get variables variables = OrderedDict() - if 'vars' in hamiltonian: - variables = OrderedDict(hamiltonian['vars']) + if "vars" in hamiltonian: + variables = OrderedDict(hamiltonian["vars"]) # Get qubit subspace dimensions - if 'qub' in hamiltonian: + if "qub" in hamiltonian: if subsystem_list is None: - subsystem_list = [int(qubit) for qubit in hamiltonian['qub']] + subsystem_list = [int(qubit) for qubit in hamiltonian["qub"]] else: # if user supplied, make a copy and sort it subsystem_list = subsystem_list.copy() subsystem_list.sort() # force keys in hamiltonian['qub'] to be ints - qub_dict = { - int(key): val - for key, val in hamiltonian['qub'].items() - } - - subsystem_dims = { - int(qubit): qub_dict[int(qubit)] - for qubit in subsystem_list - } + qub_dict = {int(key): val for key, val in hamiltonian["qub"].items()} + + subsystem_dims = {int(qubit): qub_dict[int(qubit)] for qubit in subsystem_list} else: subsystem_dims = {} # Get oscillator subspace dimensions - if 'osc' in hamiltonian: - oscillator_dims = { - int(key): val - for key, val in hamiltonian['osc'].items() - } + if "osc" in hamiltonian: + oscillator_dims = {int(key): val for key, val in hamiltonian["osc"].items()} else: oscillator_dims = {} # Parse the Hamiltonian - system = HamiltonianParser(h_str=hamiltonian['h_str'], - dim_osc=oscillator_dims, - dim_qub=subsystem_dims) + system = HamiltonianParser( + h_str=hamiltonian["h_str"], dim_osc=oscillator_dims, dim_qub=subsystem_dims + ) system.parse(subsystem_list) system = system.compiled return cls(system, variables, subsystem_dims) def get_qubit_lo_from_drift(self): - """ Computes a list of qubit frequencies corresponding to the exact energy + """Computes a list of qubit frequencies corresponding to the exact energy gap between the ground and first excited states of each qubit. If the keys in self._subsystem_dims skips over a qubit, it will default to outputting @@ -150,14 +138,13 @@ def get_qubit_lo_from_drift(self): min_eval = np.min(self._evals) for q_idx in self._subsystem_dims.keys(): single_excite = _first_excited_state(q_idx, self._subsystem_dims) - dressed_eval = _eval_for_max_espace_overlap( - single_excite, self._evals, self._estates) + dressed_eval = _eval_for_max_espace_overlap(single_excite, self._evals, self._estates) qubit_lo_freq[q_idx] = (dressed_eval - min_eval) / (2 * np.pi) return qubit_lo_freq def _calculate_hamiltonian_channels(self): - """ Get all the qubit channels D_i and U_i in the string + """Get all the qubit channels D_i and U_i in the string representation of a system Hamiltonian. Raises: @@ -165,13 +152,10 @@ def _calculate_hamiltonian_channels(self): """ channels = [] for _, ham_str in self._system: - chan_idx = [ - i for i, letter in enumerate(ham_str) if letter in ['D', 'U'] - ] + chan_idx = [i for i, letter in enumerate(ham_str) if letter in ["D", "U"]] for ch in chan_idx: if (ch + 1) == len(ham_str) or not ham_str[ch + 1].isdigit(): - raise Exception('Channel name must include' + - 'an integer labeling the qubit.') + raise Exception("Channel name must include" + "an integer labeling the qubit.") for kk in chan_idx: done = False offset = 0 @@ -183,7 +167,7 @@ def _calculate_hamiltonian_channels(self): elif (kk + offset + 1) == len(ham_str): done = True offset += 1 - temp_chan = ham_str[kk:kk + offset] + temp_chan = ham_str[kk : kk + offset] if temp_chan not in channels: channels.append(temp_chan) channels.sort(key=lambda x: (int(x[1:]), x[0])) @@ -206,12 +190,12 @@ def _compute_drift_data(self): # Get the diagonal elements of the hamiltonian with all the # drive terms set to zero for chan in self._channels: - exec('%s=0' % chan) + exec("%s=0" % chan) # might be a better solution to replace the 'var' in the hamiltonian # string with 'op_system.vars[var]' for var in self._variables: - exec('%s=%f' % (var, self._variables[var])) + exec("%s=%f" % (var, self._variables[var])) full_dim = np.prod(list(self._subsystem_dims.values())) @@ -234,7 +218,7 @@ def _compute_drift_data(self): pos = np.argmax(np.abs(estate_copy)) pos_list.append(pos) - min_overlap = min(np.abs(estate_copy)[pos]**2, min_overlap) + min_overlap = min(np.abs(estate_copy)[pos] ** 2, min_overlap) evals_mapped[pos] = evals[i] estates_mapped[:, pos] = estate @@ -254,15 +238,15 @@ def _hamiltonian_pre_parse_exceptions(hamiltonian): AerError: if some part of the hamiltonian dictionary is unsupported """ - ham_str = hamiltonian.get('h_str', []) - if ham_str in ([], ['']): + ham_str = hamiltonian.get("h_str", []) + if ham_str in ([], [""]): raise AerError("Hamiltonian dict requires a non-empty 'h_str' entry.") - if hamiltonian.get('qub', {}) == {}: + if hamiltonian.get("qub", {}) == {}: raise AerError("Hamiltonian dict requires non-empty 'qub' entry with subsystem dimensions.") - if hamiltonian.get('osc', {}) != {}: - raise AerError('Oscillator-type systems are not supported.') + if hamiltonian.get("osc", {}) != {}: + raise AerError("Oscillator-type systems are not supported.") def _first_excited_state(qubit_idx, subsystem_dims): @@ -279,7 +263,7 @@ def _first_excited_state(qubit_idx, subsystem_dims): Returns: vector: the state with qubit_idx in state 1, and the rest in state 0 """ - vector = np.array([1.]) + vector = np.array([1.0]) # iterate through qubits, tensoring on the state qubit_indices = [int(qubit) for qubit in subsystem_dims] qubit_indices.sort() diff --git a/qiskit_aer/pulse/system_models/pulse_system_model.py b/qiskit_aer/pulse/system_models/pulse_system_model.py index 74e8dde177..c4741d991f 100644 --- a/qiskit_aer/pulse/system_models/pulse_system_model.py +++ b/qiskit_aer/pulse/system_models/pulse_system_model.py @@ -22,7 +22,7 @@ from .hamiltonian_model import HamiltonianModel -class PulseSystemModel(): +class PulseSystemModel: r"""Physical model object for pulse simulator. This class contains model information required by the @@ -51,12 +51,15 @@ class PulseSystemModel(): system_model = PulseSystemModel.from_backend(armonk_backend) """ - def __init__(self, - hamiltonian=None, - u_channel_lo=None, - control_channel_labels=None, - subsystem_list=None, - dt=None): + + def __init__( + self, + hamiltonian=None, + u_channel_lo=None, + control_channel_labels=None, + subsystem_list=None, + dt=None, + ): """Initialize a PulseSystemModel. Args: @@ -101,7 +104,7 @@ def from_backend(cls, backend, subsystem_list=None): config = backend.configuration() if not config.open_pulse: - raise AerError('{} is not an open pulse backend'.format(backend)) + raise AerError("{} is not an open pulse backend".format(backend)) return cls.from_config(config, subsystem_list) @@ -114,8 +117,8 @@ def from_config(cls, configuration, subsystem_list=None): subsystem_list = subsystem_list or list(range(configuration.n_qubits)) ham_string = configuration.hamiltonian hamiltonian = HamiltonianModel.from_dict(ham_string, subsystem_list) - u_channel_lo = getattr(configuration, 'u_channel_lo', None) - dt = getattr(configuration, 'dt', None) + u_channel_lo = getattr(configuration, "u_channel_lo", None) + dt = getattr(configuration, "dt", None) control_channel_labels = [None] * len(u_channel_lo) # populate control_channel_dict @@ -126,12 +129,12 @@ def from_config(cls, configuration, subsystem_list=None): # find drive index drive_idx = None while drive_idx is None: - u_str_label = 'U{0}'.format(str(u_idx)) - for h_term_str in ham_string['h_str']: + u_str_label = "U{0}".format(str(u_idx)) + for h_term_str in ham_string["h_str"]: # check if this string corresponds to this u channel if u_str_label in h_term_str: # get index of X operator drive term - x_idx = h_term_str.find('X') + x_idx = h_term_str.find("X") # if 'X' is found, and is not at the end of the string, drive_idx # is the subsequent character if x_idx != -1 and x_idx + 1 < len(h_term_str): @@ -139,23 +142,25 @@ def from_config(cls, configuration, subsystem_list=None): if drive_idx is not None: # construct string for u channel - u_string = '' + u_string = "" for u_term_dict in u_lo: - scale = getattr(u_term_dict, 'scale', [1.0, 0]) - q_idx = getattr(u_term_dict, 'q') + scale = getattr(u_term_dict, "scale", [1.0, 0]) + q_idx = getattr(u_term_dict, "q") if len(u_string) > 0: - u_string += ' + ' + u_string += " + " if isinstance(scale, complex): - u_string += str(scale) + 'q' + str(q_idx) + u_string += str(scale) + "q" + str(q_idx) else: - u_string += str(scale[0] + scale[1] * 1j) + 'q' + str(q_idx) - control_channel_labels[u_idx] = {'driven_q': drive_idx, 'freq': u_string} + u_string += str(scale[0] + scale[1] * 1j) + "q" + str(q_idx) + control_channel_labels[u_idx] = {"driven_q": drive_idx, "freq": u_string} - return cls(hamiltonian=hamiltonian, - u_channel_lo=u_channel_lo, - control_channel_labels=control_channel_labels, - subsystem_list=subsystem_list, - dt=dt) + return cls( + hamiltonian=hamiltonian, + u_channel_lo=u_channel_lo, + control_channel_labels=control_channel_labels, + subsystem_list=subsystem_list, + dt=dt, + ) def control_channel_index(self, label): """Return the index of the control channel with identifying label. @@ -167,7 +172,7 @@ def control_channel_index(self, label): int or None: index of the ControlChannel """ if label not in self.control_channel_labels: - warn('There is no listed ControlChannel matching the provided label.') + warn("There is no listed ControlChannel matching the provided label.") return None else: return self.control_channel_labels.index(label) @@ -195,9 +200,9 @@ def calculate_channel_frequencies(self, qubit_lo_freq=None): freqs = OrderedDict() for key in self.hamiltonian._channels: chidx = int(key[1:]) - if key[0] == 'D': + if key[0] == "D": freqs[key] = qubit_lo_freq[chidx] - elif key[0] == 'U': + elif key[0] == "U": freqs[key] = 0 for u_lo_idx in self.u_channel_lo[chidx]: if u_lo_idx.q < len(qubit_lo_freq): diff --git a/qiskit_aer/pulse/system_models/string_model_parser/apply_str_func_to_qobj.py b/qiskit_aer/pulse/system_models/string_model_parser/apply_str_func_to_qobj.py index 43cf12757a..4e4646fc26 100644 --- a/qiskit_aer/pulse/system_models/string_model_parser/apply_str_func_to_qobj.py +++ b/qiskit_aer/pulse/system_models/string_model_parser/apply_str_func_to_qobj.py @@ -19,16 +19,14 @@ def dag(qobj): - """ Qiskit wrapper of adjoint - """ + """Qiskit wrapper of adjoint""" return qobj.dag() def apply_func(name, qobj): - """ Apply function of given name, or do nothing if func not found - """ + """Apply function of given name, or do nothing if func not found""" return __funcdict.get(name, lambda x: x)(qobj) # pylint: disable=invalid-name -__funcdict = {'dag': dag} +__funcdict = {"dag": dag} diff --git a/qiskit_aer/pulse/system_models/string_model_parser/gen_operator.py b/qiskit_aer/pulse/system_models/string_model_parser/gen_operator.py index 0c04087e68..9c957ec486 100644 --- a/qiskit_aer/pulse/system_models/string_model_parser/gen_operator.py +++ b/qiskit_aer/pulse/system_models/string_model_parser/gen_operator.py @@ -64,7 +64,7 @@ def sigmax(): Returns: Operator: Operator representation for sigma x. """ - return Operator.from_label('X') + return Operator.from_label("X") def sigmay(): @@ -72,7 +72,7 @@ def sigmay(): Returns: Operator: Operator representation for sigma y. """ - return Operator.from_label('Y') + return Operator.from_label("Y") def sigmaz(): @@ -80,7 +80,7 @@ def sigmaz(): Returns: Operator: Operator representation for sigma z. """ - return Operator.from_label('Z') + return Operator.from_label("Z") def identity(dim): diff --git a/qiskit_aer/pulse/system_models/string_model_parser/operator_from_string.py b/qiskit_aer/pulse/system_models/string_model_parser/operator_from_string.py index dc485f9d22..16a8509cf3 100644 --- a/qiskit_aer/pulse/system_models/string_model_parser/operator_from_string.py +++ b/qiskit_aer/pulse/system_models/string_model_parser/operator_from_string.py @@ -35,26 +35,23 @@ def gen_oper(opname, index, h_osc, h_qub, states=None): opr_tmp = None # get number of levels in Hilbert space - if opname in ['X', 'Y', 'Z', 'Sp', 'Sm', 'I', 'O', 'P']: + if opname in ["X", "Y", "Z", "Sp", "Sm", "I", "O", "P"]: is_qubit = True dim = h_qub.get(index, 2) - if opname in ['X', 'Y', 'Z'] and dim > 2: - if opname == 'X': - opr_tmp = (op_gen.get_oper('A', dim) + - op_gen.get_oper('C', dim)) - elif opname == 'Y': - opr_tmp = (-1j * op_gen.get_oper('A', dim) + - 1j * op_gen.get_oper('C', dim)) + if opname in ["X", "Y", "Z"] and dim > 2: + if opname == "X": + opr_tmp = op_gen.get_oper("A", dim) + op_gen.get_oper("C", dim) + elif opname == "Y": + opr_tmp = -1j * op_gen.get_oper("A", dim) + 1j * op_gen.get_oper("C", dim) else: - opr_tmp = (op_gen.get_oper('I', dim) - - 2 * op_gen.get_oper('N', dim)) + opr_tmp = op_gen.get_oper("I", dim) - 2 * op_gen.get_oper("N", dim) else: is_qubit = False dim = h_osc.get(index, 5) - if opname == 'P': + if opname == "P": opr_tmp = op_gen.get_oper(opname, dim, states) else: if opr_tmp is None: diff --git a/qiskit_aer/pulse/system_models/string_model_parser/operator_generators.py b/qiskit_aer/pulse/system_models/string_model_parser/operator_generators.py index 3fbcd770fb..755100d146 100644 --- a/qiskit_aer/pulse/system_models/string_model_parser/operator_generators.py +++ b/qiskit_aer/pulse/system_models/string_model_parser/operator_generators.py @@ -21,99 +21,85 @@ def sigmax(dim=2): - """Qiskit wrapper of sigma-X operator. - """ + """Qiskit wrapper of sigma-X operator.""" if dim == 2: return gen_operator.sigmax() else: - raise Exception('Invalid level specification of the qubit subspace') + raise Exception("Invalid level specification of the qubit subspace") def sigmay(dim=2): - """Qiskit wrapper of sigma-Y operator. - """ + """Qiskit wrapper of sigma-Y operator.""" if dim == 2: return gen_operator.sigmay() else: - raise Exception('Invalid level specification of the qubit subspace') + raise Exception("Invalid level specification of the qubit subspace") def sigmaz(dim=2): - """Qiskit wrapper of sigma-Z operator. - """ + """Qiskit wrapper of sigma-Z operator.""" if dim == 2: return gen_operator.sigmaz() else: - raise Exception('Invalid level specification of the qubit subspace') + raise Exception("Invalid level specification of the qubit subspace") def sigmap(dim=2): - """Qiskit wrapper of sigma-plus operator. - """ + """Qiskit wrapper of sigma-plus operator.""" return gen_operator.create(dim) def sigmam(dim=2): - """Qiskit wrapper of sigma-minus operator. - """ + """Qiskit wrapper of sigma-minus operator.""" return gen_operator.destroy(dim) def create(dim): - """Qiskit wrapper of creation operator. - """ + """Qiskit wrapper of creation operator.""" return gen_operator.create(dim) def destroy(dim): - """Qiskit wrapper of annihilation operator. - """ + """Qiskit wrapper of annihilation operator.""" return gen_operator.destroy(dim) def num(dim): - """Qiskit wrapper of number operator. - """ + """Qiskit wrapper of number operator.""" return gen_operator.num(dim) def qeye(dim): - """Qiskit wrapper of identity operator. - """ + """Qiskit wrapper of identity operator.""" return gen_operator.identity(dim) def project(dim, states): - """Qiskit wrapper of projection operator. - """ + """Qiskit wrapper of projection operator.""" ket, bra = states if ket in range(dim) and bra in range(dim): return gen_operator.basis(dim, ket) * gen_operator.basis(dim, bra).adjoint() else: - raise Exception('States are specified on the outside of Hilbert space %s' % states) + raise Exception("States are specified on the outside of Hilbert space %s" % states) def tensor(list_qobj): - """ Qiskit wrapper of tensor product - """ + """Qiskit wrapper of tensor product""" return gen_operator.tensor(list_qobj) def basis(level, pos): - """ Qiskit wrapper of basis - """ + """Qiskit wrapper of basis""" return gen_operator.basis(level, pos) def state(state_vec): - """ Qiskit wrapper of qobj - """ + """Qiskit wrapper of qobj""" return gen_operator.state(state_vec) def fock_dm(level, eigv): - """ Qiskit wrapper of fock_dm - """ + """Qiskit wrapper of fock_dm""" return gen_operator.fock_dm(level, eigv) @@ -158,12 +144,20 @@ def qubit_occ_oper_dressed(target_qubit, estates, h_osc, h_qub, level=0): def get_oper(name, *args): - """ Return quantum operator of given name - """ + """Return quantum operator of given name""" return __operdict.get(name, qeye)(*args) -__operdict = {'X': sigmax, 'Y': sigmay, 'Z': sigmaz, - 'Sp': create, 'Sm': destroy, 'I': qeye, - 'O': num, 'P': project, 'A': destroy, - 'C': create, 'N': num} +__operdict = { + "X": sigmax, + "Y": sigmay, + "Z": sigmaz, + "Sp": create, + "Sm": destroy, + "I": qeye, + "O": num, + "P": project, + "A": destroy, + "C": create, + "N": num, +} diff --git a/qiskit_aer/pulse/system_models/string_model_parser/string_model_parser.py b/qiskit_aer/pulse/system_models/string_model_parser/string_model_parser.py index 312f4338f1..7b3337fca1 100644 --- a/qiskit_aer/pulse/system_models/string_model_parser/string_model_parser.py +++ b/qiskit_aer/pulse/system_models/string_model_parser/string_model_parser.py @@ -24,7 +24,7 @@ from .operator_from_string import gen_oper -Token = namedtuple('Token', ('type', 'name')) +Token = namedtuple("Token", ("type", "name")) ham_elements = OrderedDict( QubOpr=re.compile(r"(?PO|Sp|Sm|X|Y|Z|I)(?P[0-9]+)"), @@ -37,15 +37,15 @@ MathOrd0=re.compile(r"[*/]"), MathOrd1=re.compile(r"[+-]"), BrkL=re.compile(r"\("), - BrkR=re.compile(r"\)") + BrkR=re.compile(r"\)"), ) class HamiltonianParser: - """ Generate QuTip hamiltonian object from string - """ + """Generate QuTip hamiltonian object from string""" + def __init__(self, h_str, dim_osc, dim_qub): - """ Create new quantum operator generator + """Create new quantum operator generator Parameters: h_str (list): list of Hamiltonian string @@ -61,13 +61,11 @@ def __init__(self, h_str, dim_osc, dim_qub): @property def compiled(self): - """ Return Hamiltonian in OpenPulse handler format - """ + """Return Hamiltonian in OpenPulse handler format""" return self.__tc_hams + self.__td_hams def parse(self, qubit_list=None): - """ Parse and generate quantum class object - """ + """Parse and generate quantum class object""" self.__td_hams = [] self.__tc_hams = [] @@ -82,14 +80,14 @@ def parse(self, qubit_list=None): # find time-dependent term if p_td: - coef, token = self._tokenizer(p_td.group('opr'), qubit_list) + coef, token = self._tokenizer(p_td.group("opr"), qubit_list) if token is None: continue # combine coefficient to time-dependent term if coef: - td = '*'.join([coef, p_td.group('ch')]) + td = "*".join([coef, p_td.group("ch")]) else: - td = p_td.group('ch') + td = p_td.group("ch") token = self._shunting_yard(token) _td = self._token2qobj(token), td @@ -100,16 +98,15 @@ def parse(self, qubit_list=None): continue token = self._shunting_yard(token) - if (coef == '') or (coef is None): - coef = '1.' + if (coef == "") or (coef is None): + coef = "1." _tc = self._token2qobj(token), coef self.__tc_hams.append(_tc) def _expand_sum(self): - """ Takes a string-based Hamiltonian list and expands the _SUM action items out. - """ + """Takes a string-based Hamiltonian list and expands the _SUM action items out.""" sum_str = re.compile(r"_SUM\[(?P[a-z]),(?P[a-z\d{}+-]+),(?P[a-z\d{}+-]+),") brk_str = re.compile(r"]") @@ -121,15 +118,15 @@ def _expand_sum(self): p_sums = list(sum_str.finditer(ham)) p_brks = list(brk_str.finditer(ham)) if len(p_sums) != len(p_brks): - raise Exception('Missing correct number of brackets in %s' % ham) + raise Exception("Missing correct number of brackets in %s" % ham) # find correct sum-bracket correspondence if any(p_sums) == 0: ham_out.append(ham) else: - itr = p_sums[0].group('itr') - _l = int(p_sums[0].group('l')) - _u = int(p_sums[0].group('u')) + itr = p_sums[0].group("itr") + _l = int(p_sums[0].group("l")) + _u = int(p_sums[0].group("u")) for ii in range(len(p_sums) - 1): if p_sums[ii + 1].end() > p_brks[ii].start(): break @@ -139,20 +136,21 @@ def _expand_sum(self): # substitute iterator value _temp = [] for kk in range(_l, _u + 1): - trg_s = ham[p_sums[0].end():p_brks[ii].start()] + trg_s = ham[p_sums[0].end() : p_brks[ii].start()] # generate replacement pattern pattern = {} for p in re.finditer(r"\{(?P[a-z0-9*/+-]+)\}", trg_s): if p.group() not in pattern: - sub = parse_binop(p.group('op_str'), operands={itr: str(kk)}) + sub = parse_binop(p.group("op_str"), operands={itr: str(kk)}) if sub.isdecimal(): pattern[p.group()] = sub else: pattern[p.group()] = "{%s}" % sub for key, val in pattern.items(): trg_s = trg_s.replace(key, val) - _temp.append(''.join([ham[:p_sums[0].start()], - trg_s, ham[p_brks[ii].end():]])) + _temp.append( + "".join([ham[: p_sums[0].start()], trg_s, ham[p_brks[ii].end() :]]) + ) ham_list.extend(_temp) self.h_str = ham_out @@ -160,98 +158,97 @@ def _expand_sum(self): return ham_out def _tokenizer(self, op_str, qubit_list=None): - """ Convert string to token and coefficient + """Convert string to token and coefficient Check if the index is in qubit_list """ # generate token _op_str = copy.copy(op_str) token_list = [] - prev = 'none' + prev = "none" while any(_op_str): for key, parser in ham_elements.items(): p = parser.match(_op_str) if p: # find quantum operators - if key in ['QubOpr', 'CavOpr']: + if key in ["QubOpr", "CavOpr"]: _key = key _name = p.group() if p.group() not in self.__str2qopr.keys(): - idx = int(p.group('idx')) + idx = int(p.group("idx")) if qubit_list is not None and idx not in qubit_list: return 0, None - name = p.group('opr') + name = p.group("opr") opr = gen_oper(name, idx, self.dim_osc, self.dim_qub) self.__str2qopr[p.group()] = opr - elif key == 'PrjOpr': + elif key == "PrjOpr": _key = key _name = p.group() if p.group() not in self.__str2qopr.keys(): - idx = int(p.group('idx')) - name = 'P' - lvs = int(p.group('ket')), int(p.group('bra')) + idx = int(p.group("idx")) + name = "P" + lvs = int(p.group("ket")), int(p.group("bra")) opr = gen_oper(name, idx, self.dim_osc, self.dim_qub, lvs) self.__str2qopr[p.group()] = opr - elif key in ['Func', 'Ext']: - _name = p.group('name') + elif key in ["Func", "Ext"]: + _name = p.group("name") _key = key - elif key == 'MathOrd1': + elif key == "MathOrd1": _name = p.group() - if prev not in ['QubOpr', 'PrjOpr', 'CavOpr', 'Var', 'Num']: - _key = 'MathUnitary' + if prev not in ["QubOpr", "PrjOpr", "CavOpr", "Var", "Num"]: + _key = "MathUnitary" else: _key = key else: _name = p.group() _key = key token_list.append(Token(_key, _name)) - _op_str = _op_str[p.end():] + _op_str = _op_str[p.end() :] prev = _key break else: - raise Exception('Invalid input string %s is found' % op_str) + raise Exception("Invalid input string %s is found" % op_str) # split coefficient - coef = '' - if any([k.type == 'Var' for k in token_list]): + coef = "" + if any([k.type == "Var" for k in token_list]): for ii, _ in enumerate(token_list): - if token_list[ii].name == '*': - if all([k.type != 'Var' for k in token_list[ii + 1:]]): - coef = ''.join([k.name for k in token_list[:ii]]) - token_list = token_list[ii + 1:] + if token_list[ii].name == "*": + if all([k.type != "Var" for k in token_list[ii + 1 :]]): + coef = "".join([k.name for k in token_list[:ii]]) + token_list = token_list[ii + 1 :] break else: - raise Exception('Invalid order of operators and coefficients in %s' % op_str) + raise Exception("Invalid order of operators and coefficients in %s" % op_str) return coef, token_list def _shunting_yard(self, token_list): - """ Reformat token to reverse Polish notation - """ + """Reformat token to reverse Polish notation""" stack = [] queue = [] while any(token_list): token = token_list.pop(0) - if token.type in ['QubOpr', 'PrjOpr', 'CavOpr', 'Num']: + if token.type in ["QubOpr", "PrjOpr", "CavOpr", "Num"]: queue.append(token) - elif token.type in ['Func', 'Ext']: + elif token.type in ["Func", "Ext"]: stack.append(token) - elif token.type in ['MathUnitary', 'MathOrd0', 'MathOrd1']: + elif token.type in ["MathUnitary", "MathOrd0", "MathOrd1"]: while stack and math_priority(token, stack[-1]): queue.append(stack.pop(-1)) stack.append(token) - elif token.type in ['BrkL']: + elif token.type in ["BrkL"]: stack.append(token) - elif token.type in ['BrkR']: - while stack[-1].type not in ['BrkL', 'Func']: + elif token.type in ["BrkR"]: + while stack[-1].type not in ["BrkL", "Func"]: queue.append(stack.pop(-1)) if not any(stack): - raise Exception('Missing correct number of brackets') + raise Exception("Missing correct number of brackets") pop = stack.pop(-1) - if pop.type == 'Func': + if pop.type == "Func": queue.append(pop) else: - raise Exception('Invalid token %s is found' % token.name) + raise Exception("Invalid token %s is found" % token.name) while any(stack): queue.append(stack.pop(-1)) @@ -259,44 +256,43 @@ def _shunting_yard(self, token_list): return queue def _token2qobj(self, tokens): - """ Generate quantum class object from tokens - """ + """Generate quantum class object from tokens""" stack = [] for token in tokens: - if token.type in ['QubOpr', 'PrjOpr', 'CavOpr']: + if token.type in ["QubOpr", "PrjOpr", "CavOpr"]: stack.append(self.__str2qopr[token.name]) - elif token.type == 'Num': + elif token.type == "Num": stack.append(float(token.name)) - elif token.type in ['MathUnitary']: - if token.name == '-': + elif token.type in ["MathUnitary"]: + if token.name == "-": stack.append(-stack.pop(-1)) - elif token.type in ['MathOrd0', 'MathOrd1']: + elif token.type in ["MathOrd0", "MathOrd1"]: op2 = stack.pop(-1) op1 = stack.pop(-1) - if token.name == '+': + if token.name == "+": stack.append(op1 + op2) - elif token.name == '-': + elif token.name == "-": stack.append(op1 - op2) - elif token.name == '*': + elif token.name == "*": if isinstance(op1, Operator) and isinstance(op2, Operator): stack.append(op1 & op2) else: stack.append(op1 * op2) - elif token.name == '/': + elif token.name == "/": stack.append(op1 / op2) - elif token.type in ['Func', 'Ext']: + elif token.type in ["Func", "Ext"]: stack.append(apply_func(token.name, stack.pop(-1))) else: - raise Exception('Invalid token %s is found' % token.name) + raise Exception("Invalid token %s is found" % token.name) if len(stack) > 1: - raise Exception('Invalid mathematical operation in ' % tokens) + raise Exception("Invalid mathematical operation in " % tokens) return stack[0] class NoiseParser: - """ Generate QuTip noise object from dictionary + """Generate QuTip noise object from dictionary Qubit noise is given in the format of nested dictionary: "qubit": { "0": { @@ -314,59 +310,57 @@ class NoiseParser: } these configurations are combined in the same dictionary """ + def __init__(self, noise_dict, dim_osc, dim_qub): - """ Create new quantum operator generator + """Create new quantum operator generator Parameters: noise_dict (dict): dictionary of noise configuration dim_osc (dict): dimension of oscillator subspace dim_qub (dict): dimension of qubit subspace """ - self.noise_osc = noise_dict.get('oscillator', {'n_th': {}, 'coupling': {}}) - self.noise_qub = noise_dict.get('qubit', {}) + self.noise_osc = noise_dict.get("oscillator", {"n_th": {}, "coupling": {}}) + self.noise_qub = noise_dict.get("qubit", {}) self.dim_osc = dim_osc self.dim_qub = dim_qub self.__c_list = [] @property def compiled(self): - """ Return noise configuration in OpenPulse handler format - """ + """Return noise configuration in OpenPulse handler format""" return self.__c_list def parse(self): - """ Parse and generate quantum class object - """ + """Parse and generate quantum class object""" # Qubit noise for index, config in self.noise_qub.items(): for opname, coef in config.items(): # TODO: support noise in multi-dimensional system # TODO: support noise with math operation - if opname in ['X', 'Y', 'Z', 'Sp', 'Sm']: + if opname in ["X", "Y", "Z", "Sp", "Sm"]: opr = gen_oper(opname, int(index), self.dim_osc, self.dim_qub) else: - raise Exception('Unsupported noise operator %s is given' % opname) + raise Exception("Unsupported noise operator %s is given" % opname) self.__c_list.append(np.sqrt(coef) * opr) # Oscillator noise - ndic = self.noise_osc['n_th'] - cdic = self.noise_osc['coupling'] + ndic = self.noise_osc["n_th"] + cdic = self.noise_osc["coupling"] for (n_ii, n_coef), (c_ii, c_coef) in zip(ndic.items(), cdic.items()): if n_ii == c_ii: if c_coef > 0: - opr = gen_oper('A', int(n_ii), self.dim_osc, self.dim_qub) + opr = gen_oper("A", int(n_ii), self.dim_osc, self.dim_qub) if n_coef: self.__c_list.append(np.sqrt(c_coef * (1 + n_coef)) * opr) self.__c_list.append(np.sqrt(c_coef * n_coef) * opr.dag()) else: self.__c_list.append(np.sqrt(c_coef) * opr) else: - raise Exception('Invalid oscillator index in noise dictionary.') + raise Exception("Invalid oscillator index in noise dictionary.") def math_priority(o1, o2): - """ Check priority of given math operation - """ - rank = {'MathUnitary': 2, 'MathOrd0': 1, 'MathOrd1': 0} + """Check priority of given math operation""" + rank = {"MathUnitary": 2, "MathOrd0": 1, "MathOrd1": 0} diff_ops = rank.get(o1.type, -1) - rank.get(o2.type, -1) if diff_ops > 0: @@ -377,51 +371,50 @@ def math_priority(o1, o2): # pylint: disable=dangerous-default-value def parse_binop(op_str, operands={}, cast_str=True): - """ Calculate binary operation in string format - """ + """Calculate binary operation in string format""" oprs = OrderedDict( sum=r"(?P[a-zA-Z0-9]+)\+(?P[a-zA-Z0-9]+)", sub=r"(?P[a-zA-Z0-9]+)\-(?P[a-zA-Z0-9]+)", mul=r"(?P[a-zA-Z0-9]+)\*(?P[a-zA-Z0-9]+)", div=r"(?P[a-zA-Z0-9]+)\/(?P[a-zA-Z0-9]+)", - non=r"(?P[a-zA-Z0-9]+)" + non=r"(?P[a-zA-Z0-9]+)", ) for key, regr in oprs.items(): p = re.match(regr, op_str) if p: - val0 = operands.get(p.group('v0'), p.group('v0')) - if key == 'non': + val0 = operands.get(p.group("v0"), p.group("v0")) + if key == "non": # substitution retv = val0 else: - val1 = operands.get(p.group('v1'), p.group('v1')) + val1 = operands.get(p.group("v1"), p.group("v1")) # binary operation - if key == 'sum': + if key == "sum": if val0.isdecimal() and val1.isdecimal(): retv = int(val0) + int(val1) else: - retv = '+'.join([str(val0), str(val1)]) - elif key == 'sub': + retv = "+".join([str(val0), str(val1)]) + elif key == "sub": if val0.isdecimal() and val1.isdecimal(): retv = int(val0) - int(val1) else: - retv = '-'.join([str(val0), str(val1)]) - elif key == 'mul': + retv = "-".join([str(val0), str(val1)]) + elif key == "mul": if val0.isdecimal() and val1.isdecimal(): retv = int(val0) * int(val1) else: - retv = '*'.join([str(val0), str(val1)]) - elif key == 'div': + retv = "*".join([str(val0), str(val1)]) + elif key == "div": if val0.isdecimal() and val1.isdecimal(): retv = int(val0) / int(val1) else: - retv = '/'.join([str(val0), str(val1)]) + retv = "/".join([str(val0), str(val1)]) else: retv = 0 break else: - raise Exception('Invalid string %s' % op_str) + raise Exception("Invalid string %s" % op_str) if cast_str: return str(retv) diff --git a/qiskit_aer/quantum_info/states/aer_densitymatrix.py b/qiskit_aer/quantum_info/states/aer_densitymatrix.py index a7b4c1c77c..6bc4ce45c4 100644 --- a/qiskit_aer/quantum_info/states/aer_densitymatrix.py +++ b/qiskit_aer/quantum_info/states/aer_densitymatrix.py @@ -53,14 +53,14 @@ def __init__(self, data, dims=None, **configs): Additional Information: The ``dims`` kwarg is used to ``AerDensityMatrix`` constructor. """ - if '_aer_state' in configs: - self._aer_state = configs.pop('_aer_state') + if "_aer_state" in configs: + self._aer_state = configs.pop("_aer_state") else: - if 'method' not in configs: - configs['method'] = 'density_matrix' - elif configs['method'] != 'density_matrix': - method = configs['method'] - raise AerError(f'Method {method} is not supported') + if "method" not in configs: + configs["method"] = "density_matrix" + elif configs["method"] != "density_matrix": + method = configs["method"] + raise AerError(f"Method {method} is not supported") if isinstance(data, (QuantumCircuit, Instruction)): data, aer_state = AerDensityMatrix._from_instruction(data, None, configs) elif isinstance(data, list): @@ -75,9 +75,10 @@ def __init__(self, data, dims=None, **configs): dims = data._op_shape._dims_l data = data._data.copy() elif isinstance(data, DensityMatrix): - data, aer_state = AerDensityMatrix._from_ndarray(np.array(data.data, - dtype=complex), configs) - elif hasattr(data, 'to_operator'): + data, aer_state = AerDensityMatrix._from_ndarray( + np.array(data.data, dtype=complex), configs + ) + elif hasattr(data, "to_operator"): # If the data object has a 'to_operator' attribute this is given # higher preference than the 'to_matrix' method for initializing # an Operator object. @@ -85,14 +86,15 @@ def __init__(self, data, dims=None, **configs): data, aer_state = AerDensityMatrix._from_ndarray(op.data, configs) if dims is None: dims = op.output_dims() - elif hasattr(data, 'to_matrix'): + elif hasattr(data, "to_matrix"): # If no 'to_operator' attribute exists we next look for a # 'to_matrix' attribute to a matrix that will be cast into # a complex numpy matrix. data, aer_state = AerDensityMatrix._from_ndarray( - np.asarray(data.to_matrix(), dtype=complex), configs) + np.asarray(data.to_matrix(), dtype=complex), configs + ) else: - raise AerError(f'Input data is not supported: type={data.__class__}, data={data}') + raise AerError(f"Input data is not supported: type={data.__class__}, data={data}") self._aer_state = aer_state @@ -106,7 +108,7 @@ def seed(self, value=None): if value is None or isinstance(value, int): self._aer_state.set_seed(value) else: - raise AerError(f'This seed is not supported: type={value.__class__}, value={value}') + raise AerError(f"This seed is not supported: type={value.__class__}, value={value}") def _last_result(self): if self._result is None: @@ -116,8 +118,8 @@ def _last_result(self): def metadata(self): """Return result metadata of an operation that executed lastly.""" if self._last_result() is None: - raise AerError('AerState was not used and metdata does not exist.') - return self._last_result()['metadata'] + raise AerError("AerState was not used and metdata does not exist.") + return self._last_result()["metadata"] def __copy__(self): return copy.deepcopy(self) @@ -210,7 +212,7 @@ def _from_1d_array(data): @staticmethod def _from_ndarray(init_data, configs): - aer_state = AerState(method='density_matrix') + aer_state = AerState(method="density_matrix") options = AerSimulator._default_options() for config_key, config_value in configs.items(): @@ -218,7 +220,7 @@ def _from_ndarray(init_data, configs): aer_state.configure(config_key, config_value) if len(init_data) == 0: - raise AerError('initial data must be larger than 0') + raise AerError("initial data must be larger than 0") num_qubits = int(np.log2(len(init_data))) @@ -233,12 +235,12 @@ def from_instruction(cls, instruction): @staticmethod def _from_instruction(inst, init_data, configs): - aer_state = AerState(method='density_matrix') + aer_state = AerState(method="density_matrix") for config_key, config_value in configs.items(): aer_state.configure(config_key, config_value) - basis_gates = BASIS_GATES['density_matrix'] + basis_gates = BASIS_GATES["density_matrix"] aer_state.allocate_qubits(inst.num_qubits) num_qubits = inst.num_qubits @@ -294,13 +296,13 @@ def to_statevector(self, atol=None, rtol=None): rtol = self.rtol if not is_hermitian_matrix(self.data, atol=atol, rtol=rtol): - raise QiskitError('Not a valid density matrix (non-hermitian).') + raise QiskitError("Not a valid density matrix (non-hermitian).") evals, evecs = np.linalg.eig(self.data) nonzero_evals = evals[abs(evals) > atol] if len(nonzero_evals) != 1 or not np.isclose(nonzero_evals[0], 1, atol=atol, rtol=rtol): - raise QiskitError('Density matrix is not a pure state') + raise QiskitError("Density matrix is not a pure state") psi = evecs[:, np.argmax(evals)] # eigenvectors returned in columns. return AerStatevector(psi) diff --git a/qiskit_aer/quantum_info/states/aer_state.py b/qiskit_aer/quantum_info/states/aer_state.py index 0f21602751..0dd0d47fbe 100644 --- a/qiskit_aer/quantum_info/states/aer_state.py +++ b/qiskit_aer/quantum_info/states/aer_state.py @@ -14,6 +14,7 @@ """ from enum import Enum import numpy as np + # pylint: disable=import-error, no-name-in-module from qiskit_aer.backends.controller_wrappers import AerStateWrapper from ...backends.aerbackend import AerError @@ -69,57 +70,57 @@ def renew(self): def _assert_initializing(self): if self._state != _STATE.INITIALIZING: - raise AerError('AerState was already initialized.') + raise AerError("AerState was already initialized.") def _assert_allocated_or_mapped_or_moved(self): if self._state == _STATE.INITIALIZING: - raise AerError('AerState has not been initialized yet.') + raise AerError("AerState has not been initialized yet.") if self._state == _STATE.CLOSED: - raise AerError('AerState has already been closed.') + raise AerError("AerState has already been closed.") def _assert_allocated_or_mapped(self): if self._state == _STATE.INITIALIZING: - raise AerError('AerState has not been initialized yet.') + raise AerError("AerState has not been initialized yet.") if self._state == _STATE.MOVED: - raise AerError('AerState has already been moved.') + raise AerError("AerState has already been moved.") if self._state == _STATE.CLOSED: - raise AerError('AerState has already been closed.') + raise AerError("AerState has already been closed.") def _assert_mapped_or_moved(self): if self._state == _STATE.INITIALIZING: - raise AerError('AerState has not been initialized yet.') + raise AerError("AerState has not been initialized yet.") if self._state == _STATE.ALLOCATED: - raise AerError('AerState has not been moved yet.') + raise AerError("AerState has not been moved yet.") if self._state == _STATE.CLOSED: - raise AerError('AerState has already been closed.') + raise AerError("AerState has already been closed.") def _assert_closed(self): if self._state != _STATE.CLOSED: - raise AerError('AerState is not closed.') + raise AerError("AerState is not closed.") def _allocated(self): if self._state != _STATE.INITIALIZING: - raise AerError('unexpected state transition: {self._state}->{_STATE.ALLOCATED}') + raise AerError("unexpected state transition: {self._state}->{_STATE.ALLOCATED}") self._state = _STATE.ALLOCATED def _mapped(self): if self._state != _STATE.INITIALIZING: - raise AerError('unexpected state transition: {self._state}->{_STATE.MAPPED}') + raise AerError("unexpected state transition: {self._state}->{_STATE.MAPPED}") self._state = _STATE.MAPPED def _released(self): if self._state != _STATE.MAPPED: - raise AerError('unexpected state transition: {self._state}->{_STATE.RELEASED}') + raise AerError("unexpected state transition: {self._state}->{_STATE.RELEASED}") self._state = _STATE.RELEASED def _moved(self): if self._state != _STATE.ALLOCATED: - raise AerError('unexpected state transition: {self._state}->{_STATE.MOVED}') + raise AerError("unexpected state transition: {self._state}->{_STATE.MOVED}") self._state = _STATE.MOVED def _closed(self): if self._state not in (_STATE.MOVED, _STATE.MAPPED, _STATE.RELEASED): - raise AerError('unexpected state transition: {self._state}->{_STATE.CLOSED}') + raise AerError("unexpected state transition: {self._state}->{_STATE.CLOSED}") self._state = _STATE.CLOSED def configure(self, key, value): @@ -127,7 +128,7 @@ def configure(self, key, value): self._assert_initializing() if not isinstance(key, str): - raise AerError('AerState is configured with a str key') + raise AerError("AerState is configured with a str key") if not isinstance(value, str): value = str(value) @@ -146,7 +147,7 @@ def initialize(self, data=None, copy=True): self._assert_initializing() if not self._method: - raise AerError('method is not configured yet.') + raise AerError("method is not configured yet.") if data is None: self._native_state.initialize() @@ -155,22 +156,22 @@ def initialize(self, data=None, copy=True): elif isinstance(data, np.ndarray): return self._initialize_with_ndarray(data, copy) else: - raise AerError(f'unsupported init data: {data.__class__}') + raise AerError(f"unsupported init data: {data.__class__}") def _initialize_with_ndarray(self, data, copy): if AerState._is_in_use(data) and not copy: - raise AerError('another AerState owns this data') + raise AerError("another AerState owns this data") num_of_qubits = int(np.log2(len(data))) if len(data) != np.power(2, num_of_qubits): - raise AerError('length of init data must be power of two') + raise AerError("length of init data must be power of two") init = False - if self._method == 'statevector': + if self._method == "statevector": init = self._native_state.initialize_statevector(num_of_qubits, data, copy) - elif self._method == 'density_matrix': + elif self._method == "density_matrix": if data.shape != (len(data), len(data)): - raise AerError('shape of init data must be a pair of power of two') + raise AerError("shape of init data must be a pair of power of two") init = self._native_state.initialize_density_matrix(num_of_qubits, data, copy) if init: @@ -186,9 +187,9 @@ def _initialize_with_ndarray(self, data, copy): self._native_state.initialize() if not data.flags.c_contiguous and not data.flags.f_contiguous: data = np.ascontiguousarray(data) - if self._method == 'statevector': + if self._method == "statevector": self._native_state.apply_initialize(range(num_of_qubits), data) - elif self._method == 'density_matrix': + elif self._method == "density_matrix": self._native_state.set_density_matrix(range(num_of_qubits), data) else: self._native_state.apply_initialize(range(num_of_qubits), data) @@ -241,7 +242,7 @@ def move_to_ndarray(self): elif self._state == _STATE.MOVED: ret = self._moved_data else: - if self._method == 'density_matrix': + if self._method == "density_matrix": self._moved_data = self._native_state.move_to_matrix() else: self._moved_data = self._native_state.move_to_ndarray() @@ -253,16 +254,16 @@ def allocate_qubits(self, num_of_qubits): """allocate qubits.""" self._assert_initializing() if num_of_qubits <= 0: - raise AerError(f'invalid number of qubits: {num_of_qubits}') + raise AerError(f"invalid number of qubits: {num_of_qubits}") allocated = self._native_state.allocate_qubits(num_of_qubits) self._last_qubit = allocated[len(allocated) - 1] def _assert_in_allocated_qubits(self, qubit): - if hasattr(qubit, '__iter__'): + if hasattr(qubit, "__iter__"): for q in qubit: self._assert_in_allocated_qubits(q) elif qubit < 0 or qubit > self._last_qubit: - raise AerError(f'invalid qubit: index={qubit}') + raise AerError(f"invalid qubit: index={qubit}") @property def num_qubits(self): diff --git a/qiskit_aer/quantum_info/states/aer_statevector.py b/qiskit_aer/quantum_info/states/aer_statevector.py index d27a6a53ac..f5b91d322d 100644 --- a/qiskit_aer/quantum_info/states/aer_statevector.py +++ b/qiskit_aer/quantum_info/states/aer_statevector.py @@ -55,19 +55,20 @@ def __init__(self, data, dims=None, **configs): The ``dims`` kwarg is used to ``Statevector`` constructor. """ - if '_aer_state' in configs: - self._aer_state = configs.pop('_aer_state') + if "_aer_state" in configs: + self._aer_state = configs.pop("_aer_state") else: - if 'method' not in configs: - configs['method'] = 'statevector' - elif configs['method'] not in ('statevector', 'matrix_product_state'): - method = configs['method'] - raise AerError(f'Method {method} is not supported') + if "method" not in configs: + configs["method"] = "statevector" + elif configs["method"] not in ("statevector", "matrix_product_state"): + method = configs["method"] + raise AerError(f"Method {method} is not supported") if isinstance(data, (QuantumCircuit, Instruction)): data, aer_state = AerStatevector._from_instruction(data, None, configs) elif isinstance(data, list): - data, aer_state = AerStatevector._from_ndarray(np.array(data, dtype=complex), - configs) + data, aer_state = AerStatevector._from_ndarray( + np.array(data, dtype=complex), configs + ) elif isinstance(data, np.ndarray): data, aer_state = AerStatevector._from_ndarray(data, configs) elif isinstance(data, AerStatevector): @@ -76,10 +77,11 @@ def __init__(self, data, dims=None, **configs): dims = data._op_shape._dims_l data = data._data.copy() elif isinstance(data, Statevector): - data, aer_state = AerStatevector._from_ndarray(np.array(data.data, dtype=complex), - configs) + data, aer_state = AerStatevector._from_ndarray( + np.array(data.data, dtype=complex), configs + ) else: - raise AerError(f'Input data is not supported: type={data.__class__}, data={data}') + raise AerError(f"Input data is not supported: type={data.__class__}, data={data}") self._aer_state = aer_state @@ -93,7 +95,7 @@ def seed(self, value=None): if value is None or isinstance(value, int): self._aer_state.set_seed(value) else: - raise AerError(f'This seed is not supported: type={value.__class__}, value={value}') + raise AerError(f"This seed is not supported: type={value.__class__}, value={value}") def _last_result(self): if self._result is None: @@ -103,8 +105,8 @@ def _last_result(self): def metadata(self): """Return result metadata of an operation that executed lastly.""" if self._last_result() is None: - raise AerError('AerState was not used and metdata does not exist.') - return self._last_result()['metadata'] + raise AerError("AerState was not used and metdata does not exist.") + return self._last_result()["metadata"] def __copy__(self): return copy.deepcopy(self) @@ -134,7 +136,7 @@ def sample_memory(self, shots, qargs=None): @staticmethod def _from_ndarray(init_data, configs): do_copy = True - if not init_data.flags['C_CONTIGUOUS']: + if not init_data.flags["C_CONTIGUOUS"]: init_data = np.ascontiguousarray(init_data) do_copy = False @@ -146,7 +148,7 @@ def _from_ndarray(init_data, configs): aer_state.configure(config_key, config_value) if len(init_data) == 0: - raise AerError('initial data must be larger than 0') + raise AerError("initial data must be larger than 0") num_qubits = int(np.log2(len(init_data))) @@ -166,11 +168,11 @@ def _from_instruction(inst, init_data, configs): for config_key, config_value in configs.items(): aer_state.configure(config_key, config_value) - if 'method' in configs: - method = configs['method'] + if "method" in configs: + method = configs["method"] else: - method = 'statevector' - aer_state.configure('method', method) + method = "statevector" + aer_state.configure("method", method) basis_gates = BASIS_GATES[method] @@ -202,9 +204,12 @@ def _aer_evolve_circuit(aer_state, circuit, qubits, basis_gates=None): ) inst = instruction.operation qargs = instruction.qubits - AerStatevector._aer_evolve_instruction(aer_state, inst, - [qubits[circuit.find_bit(qarg).index] - for qarg in qargs], basis_gates) + AerStatevector._aer_evolve_instruction( + aer_state, + inst, + [qubits[circuit.find_bit(qarg).index] for qarg in qargs], + basis_gates, + ) @staticmethod def _aer_evolve_instruction(aer_state, inst, qubits, basis_gates=None): @@ -214,46 +219,52 @@ def _aer_evolve_instruction(aer_state, inst, qubits, basis_gates=None): applied = True if basis_gates and inst.name in basis_gates: - if inst.name in ['u3', 'u']: + if inst.name in ["u3", "u"]: aer_state.apply_u(qubits[0], params[0], params[1], params[2]) - elif inst.name == 'h': + elif inst.name == "h": aer_state.apply_h(qubits[0]) - elif inst.name == 'x': + elif inst.name == "x": aer_state.apply_x(qubits[0]) - elif inst.name == 'cx': + elif inst.name == "cx": aer_state.apply_cx(qubits[0], qubits[1]) - elif inst.name == 'y': + elif inst.name == "y": aer_state.apply_y(qubits[0]) - elif inst.name == 'cy': + elif inst.name == "cy": aer_state.apply_cy(qubits[0], qubits[1]) - elif inst.name == 'z': + elif inst.name == "z": aer_state.apply_z(qubits[0]) - elif inst.name == 'cz': + elif inst.name == "cz": aer_state.apply_cz(qubits[0], qubits[1]) - elif inst.name == 'unitary': + elif inst.name == "unitary": aer_state.apply_unitary(qubits, inst.params[0]) - elif inst.name == 'diagonal': + elif inst.name == "diagonal": aer_state.apply_diagonal(qubits, inst.params) - elif inst.name == 'cu': + elif inst.name == "cu": aer_state.apply_cu(qubits[0], qubits[1], params[0], params[1], params[2], params[3]) - elif inst.name == 'mcu': - aer_state.apply_mcu(qubits[0:len(qubits) - 1], qubits[len(qubits) - 1], - params[0], params[1], params[2], params[3]) - elif inst.name in 'mcx': - aer_state.apply_mcx(qubits[0:len(qubits) - 1], qubits[len(qubits) - 1]) - elif inst.name in 'mcy': - aer_state.apply_mcy(qubits[0:len(qubits) - 1], qubits[len(qubits) - 1]) - elif inst.name in 'mcz': - aer_state.apply_mcz(qubits[0:len(qubits) - 1], qubits[len(qubits) - 1]) - elif inst.name == 'id': + elif inst.name == "mcu": + aer_state.apply_mcu( + qubits[0 : len(qubits) - 1], + qubits[len(qubits) - 1], + params[0], + params[1], + params[2], + params[3], + ) + elif inst.name in "mcx": + aer_state.apply_mcx(qubits[0 : len(qubits) - 1], qubits[len(qubits) - 1]) + elif inst.name in "mcy": + aer_state.apply_mcy(qubits[0 : len(qubits) - 1], qubits[len(qubits) - 1]) + elif inst.name in "mcz": + aer_state.apply_mcz(qubits[0 : len(qubits) - 1], qubits[len(qubits) - 1]) + elif inst.name == "id": pass else: applied = False - elif inst.name == 'kraus': + elif inst.name == "kraus": aer_state.apply_kraus(qubits, inst.params) - elif inst.name == 'reset': + elif inst.name == "reset": aer_state.apply_reset(qubits) - elif inst.name == 'barrier': + elif inst.name == "barrier": pass else: applied = False @@ -261,7 +272,7 @@ def _aer_evolve_instruction(aer_state, inst, qubits, basis_gates=None): if not applied: definition = inst.definition if definition is inst or definition is None: - raise AerError('cannot decompose ' + inst.name) + raise AerError("cannot decompose " + inst.name) AerStatevector._aer_evolve_circuit(aer_state, definition, qubits, basis_gates) @classmethod diff --git a/qiskit_aer/utils/noise_model_inserter.py b/qiskit_aer/utils/noise_model_inserter.py index 3ab5ea266e..f5bca2576f 100644 --- a/qiskit_aer/utils/noise_model_inserter.py +++ b/qiskit_aer/utils/noise_model_inserter.py @@ -42,12 +42,13 @@ def insert_noise(circuits, noise_model, transpile=False): default_errors = noise_model._default_quantum_errors for circuit in circuits: if transpile: - transpiled_circuit = qiskit.compiler.transpile(circuit, - basis_gates=noise_model.basis_gates) + transpiled_circuit = qiskit.compiler.transpile( + circuit, basis_gates=noise_model.basis_gates + ) else: transpiled_circuit = circuit qubit_indices = {bit: index for index, bit in enumerate(transpiled_circuit.qubits)} - result_circuit = transpiled_circuit.copy(name=transpiled_circuit.name + '_with_noise') + result_circuit = transpiled_circuit.copy(name=transpiled_circuit.name + "_with_noise") result_circuit.data = [] for inst, qargs, cargs in transpiled_circuit.data: result_circuit.data.append((inst, qargs, cargs)) diff --git a/qiskit_aer/utils/noise_transformation.py b/qiskit_aer/utils/noise_transformation.py index dd00df0947..41d2044065 100644 --- a/qiskit_aer/utils/noise_transformation.py +++ b/qiskit_aer/utils/noise_transformation.py @@ -35,8 +35,13 @@ from qiskit.circuit import Reset from qiskit.circuit.library.standard_gates import ( - IGate, XGate, YGate, ZGate, - HGate, SGate, SdgGate, + IGate, + XGate, + YGate, + ZGate, + HGate, + SGate, + SdgGate, ) from qiskit.compiler import transpile from qiskit.exceptions import MissingOptionalLibraryError @@ -126,16 +131,16 @@ def transpile_noise_model(noise_model: NoiseModel, **transpile_kwargs) -> NoiseM Raises: NoiseError: if the transformation failed. """ + def func(error): return transpile_quantum_error(error, **transpile_kwargs) return transform_noise_model(noise_model, func) -def approximate_quantum_error(error, *, - operator_string=None, - operator_dict=None, - operator_list=None): +def approximate_quantum_error( + error, *, operator_string=None, operator_dict=None, operator_list=None +): r""" Return a ``QuantumError`` object that approximates an error as a mixture of specified operators (channels). @@ -182,28 +187,36 @@ def approximate_quantum_error(error, *, raise NoiseError(f"Invalid input error type: {error.__class__.__name__}") if error.num_qubits > 2: - raise NoiseError("Only 1-qubit and 2-qubit noises can be converted, " - f"{error.num_qubits}-qubit noise found in model") + raise NoiseError( + "Only 1-qubit and 2-qubit noises can be converted, " + f"{error.num_qubits}-qubit noise found in model" + ) if operator_string is not None: valid_operator_strings = _PRESET_OPERATOR_TABLE.keys() operator_string = operator_string.lower() if operator_string not in valid_operator_strings: - raise NoiseError(f"{operator_string} is not a valid operator_string. " - f"It must be one of {valid_operator_strings}") + raise NoiseError( + f"{operator_string} is not a valid operator_string. " + f"It must be one of {valid_operator_strings}" + ) try: operator_list = _PRESET_OPERATOR_TABLE[operator_string][error.num_qubits] except KeyError as err: - raise NoiseError(f"Preset '{operator_string}' operators do not support the " - f"approximation of errors with {error.num_qubits} qubits") from err + raise NoiseError( + f"Preset '{operator_string}' operators do not support the " + f"approximation of errors with {error.num_qubits} qubits" + ) from err if operator_dict is not None: _, operator_list = zip(*operator_dict.items()) if operator_list is not None: if not isinstance(operator_list, Sequence): raise NoiseError(f"operator_list is not a sequence: {operator_list}") try: - channel_list = [op if isinstance(op, QuantumChannel) else QuantumError([(op, 1)]) - for op in operator_list] # preserve operator_list + channel_list = [ + op if isinstance(op, QuantumChannel) else QuantumError([(op, 1)]) + for op in operator_list + ] # preserve operator_list except NoiseError as err: raise NoiseError(f"Invalid type found in operator list: {operator_list}") from err @@ -212,19 +225,14 @@ def approximate_quantum_error(error, *, if identity_prob < 0 or identity_prob > 1: raise NoiseError(f"Channel probabilities sum to {1 - identity_prob}") noise_ops = [((IGate(), [0]), identity_prob)] - for (operator, probability) in zip(operator_list, probabilities): + for operator, probability in zip(operator_list, probabilities): noise_ops.append((operator, probability)) return QuantumError(noise_ops) - raise NoiseError( - "Quantum error approximation failed - no approximating operators detected" - ) + raise NoiseError("Quantum error approximation failed - no approximating operators detected") -def approximate_noise_model(model, *, - operator_string=None, - operator_dict=None, - operator_list=None): +def approximate_noise_model(model, *, operator_string=None, operator_dict=None, operator_list=None): """ Replace all noises in a noise model with ones approximated by a mixture of operators (channels). @@ -257,13 +265,15 @@ def approximate_noise_model(model, *, its possible values are ``'pauli'``, ``'reset'``, ``'clifford'``. The ``'clifford'`` does not support 2-qubit errors. """ + def approximate(noise): return approximate_quantum_error( noise, operator_string=operator_string, operator_dict=operator_dict, - operator_list=operator_list + operator_list=operator_list, ) + return transform_noise_model(model, approximate) @@ -281,12 +291,12 @@ def approximate(noise): _RESET_Q0Q1 = [op_q0 + op_q1 for op_q0 in _RESET_Q0 for op_q1 in _RESET_Q1] # clifford operators _CLIFFORD_GATES = [ - (IGate(), ), - (SGate(), ), - (SdgGate(), ), - (ZGate(), ), + (IGate(),), + (SGate(),), + (SdgGate(),), + (ZGate(),), # u2 gates - (HGate(), ), + (HGate(),), (HGate(), ZGate()), (ZGate(), HGate()), (HGate(), SGate()), @@ -303,10 +313,10 @@ def approximate(noise): (SdgGate(), HGate(), ZGate()), (ZGate(), HGate(), ZGate()), # u3 gates - (XGate(), ), - (YGate(), ), + (XGate(),), + (YGate(),), (SGate(), XGate()), - (SdgGate(), XGate()) + (SdgGate(), XGate()), ] # preset operator table _PRESET_OPERATOR_TABLE = { @@ -320,12 +330,14 @@ def approximate(noise): }, "clifford": { 1: [[(gate, [0]) for gate in _CLIFFORD_GATES[j]] for j in range(1, 24)], - } + }, } -def _transform_by_operator_list(basis_ops: Sequence[Union[QuantumChannel, QuantumError]], - target: Union[QuantumChannel, QuantumError]) -> List[float]: +def _transform_by_operator_list( + basis_ops: Sequence[Union[QuantumChannel, QuantumError]], + target: Union[QuantumChannel, QuantumError], +) -> List[float]: r""" Transform (or approximate) the target quantum channel into a mixture of basis operators (channels) and return the mixing probabilities. @@ -395,13 +407,13 @@ def fidelity(channel): # fidelity w.r.t. identity omitting the N^-2 factor name="Transformation/Approximation of noise", pip_install="pip install cvxpy", msg="CVXPY is required to solve an optimization problem of" - " approximating a noise channel." + " approximating a noise channel.", ) from err # create quadratic program x = cvxpy.Variable(n) prob = cvxpy.Problem( cvxpy.Minimize(cvxpy.quad_form(x, A) + b.T @ x), - constraints=[cvxpy.sum(x) <= 1, x >= 0, source_fids.T @ x <= target_fid] + constraints=[cvxpy.sum(x) <= 1, x >= 0, source_fids.T @ x <= target_fid], ) # solve quadratic program prob.solve() diff --git a/qiskit_aer/version.py b/qiskit_aer/version.py index 237d02af7e..341b876974 100644 --- a/qiskit_aer/version.py +++ b/qiskit_aer/version.py @@ -23,17 +23,21 @@ def _minimal_ext_cmd(cmd): # construct minimal environment env = {} - for k in ['SYSTEMROOT', 'PATH']: + for k in ["SYSTEMROOT", "PATH"]: v = os.environ.get(k) if v is not None: env[k] = v # LANGUAGE is used on win32 - env['LANGUAGE'] = 'C' - env['LANG'] = 'C' - env['LC_ALL'] = 'C' - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, env=env, - cwd=os.path.join(os.path.dirname(ROOT_DIR))) + env["LANGUAGE"] = "C" + env["LANG"] = "C" + env["LC_ALL"] = "C" + proc = subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=env, + cwd=os.path.join(os.path.dirname(ROOT_DIR)), + ) out = proc.communicate()[0] if proc.returncode > 0: raise OSError @@ -44,8 +48,8 @@ def git_version(): """Get the current git head sha1.""" # Determine if we're at main try: - out = _minimal_ext_cmd(['git', 'rev-parse', 'HEAD']) - git_revision = out.strip().decode('ascii') + out = _minimal_ext_cmd(["git", "rev-parse", "HEAD"]) + git_revision = out.strip().decode("ascii") except OSError: git_revision = "Unknown" @@ -63,16 +67,17 @@ def get_version_info(): # up the build under Python 3. full_version = VERSION - if not os.path.exists(os.path.join(os.path.dirname(os.path.dirname( - os.path.dirname(ROOT_DIR))), '.git')): + if not os.path.exists( + os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(ROOT_DIR))), ".git") + ): return full_version try: - release = _minimal_ext_cmd(['git', 'tag', '-l', '--points-at', 'HEAD']) + release = _minimal_ext_cmd(["git", "tag", "-l", "--points-at", "HEAD"]) except Exception: # pylint: disable=broad-except return full_version if not release: git_revision = git_version() - full_version += '.dev0+' + git_revision[:7] + full_version += ".dev0+" + git_revision[:7] return full_version diff --git a/requirements-dev.txt b/requirements-dev.txt index 87dfcda37d..cd10ade82f 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -5,7 +5,8 @@ scikit-build>=0.11.0 asv cvxpy>=1.0.0,<1.1.15;platform_system != 'Windows' and python_version < '3.11' pylint -pycodestyle +black[jupyter]~=23.0 +clang-format~=15.0.7 Sphinx>=1.8.3 jupyter-sphinx reno>=3.4.0 diff --git a/setup.py b/setup.py index 9901c915e1..d35d076c23 100644 --- a/setup.py +++ b/setup.py @@ -10,31 +10,27 @@ from skbuild import setup -PACKAGE_NAME = os.getenv('QISKIT_AER_PACKAGE_NAME', 'qiskit-aer') +PACKAGE_NAME = os.getenv("QISKIT_AER_PACKAGE_NAME", "qiskit-aer") -extras_requirements = { - "dask": ["dask", "distributed"] -} +extras_requirements = {"dask": ["dask", "distributed"]} requirements = [ - 'qiskit-terra>=0.21.0', - 'numpy>=1.16.3', - 'scipy>=1.0', + "qiskit-terra>=0.21.0", + "numpy>=1.16.3", + "scipy>=1.0", ] -VERSION_PATH = os.path.join(os.path.dirname(__file__), - "qiskit_aer", "VERSION.txt") +VERSION_PATH = os.path.join(os.path.dirname(__file__), "qiskit_aer", "VERSION.txt") with open(VERSION_PATH, "r") as version_file: VERSION = version_file.read().strip() -README_PATH = os.path.join(os.path.abspath(os.path.dirname(__file__)), - 'README.md') +README_PATH = os.path.join(os.path.abspath(os.path.dirname(__file__)), "README.md") with open(README_PATH) as readme_file: README = readme_file.read() cmake_args = [] -is_win_32_bit = (platform.system() == 'Windows' and platform.architecture()[0] == "32bit") +is_win_32_bit = platform.system() == "Windows" and platform.architecture()[0] == "32bit" if is_win_32_bit: cmake_args.append("-DCMAKE_GENERATOR_PLATFORM=Win32") @@ -42,10 +38,10 @@ name=PACKAGE_NAME, version=VERSION, packages=setuptools.find_packages(exclude=["test*"]), - cmake_source_dir='.', + cmake_source_dir=".", description="Qiskit Aer - High performance simulators for Qiskit", long_description=README, - long_description_content_type='text/markdown', + long_description_content_type="text/markdown", url="https://github.com/Qiskit/qiskit-aer", author="AER Development Team", author_email="hello@qiskit.org", @@ -74,5 +70,5 @@ extras_require=extras_requirements, cmake_args=cmake_args, keywords="qiskit aer simulator quantum addon backend", - zip_safe=False + zip_safe=False, ) diff --git a/src/controllers/aer_controller.hpp b/src/controllers/aer_controller.hpp index 405e827392..f0ee3acd31 100644 --- a/src/controllers/aer_controller.hpp +++ b/src/controllers/aer_controller.hpp @@ -41,12 +41,12 @@ #include #endif +#include "framework/config.hpp" #include "framework/creg.hpp" #include "framework/qobj.hpp" #include "framework/results/experiment_result.hpp" #include "framework/results/result.hpp" #include "framework/rng.hpp" -#include "framework/config.hpp" #include "noise/noise_model.hpp" #include "transpile/cacheblocking.hpp" @@ -59,8 +59,8 @@ #include "simulators/statevector/qubitvector.hpp" #include "simulators/statevector/statevector_state.hpp" #include "simulators/superoperator/superoperator_state.hpp" -#include "simulators/unitary/unitary_state.hpp" #include "simulators/tensor_network/tensor_net_state.hpp" +#include "simulators/unitary/unitary_state.hpp" namespace AER { @@ -85,8 +85,7 @@ class Controller { template Result execute(const inputdata_t &qobj); - Result execute(std::vector &circuits, - Noise::NoiseModel &noise_model, + Result execute(std::vector &circuits, Noise::NoiseModel &noise_model, const Config &config); //----------------------------------------------------------------------- @@ -124,16 +123,15 @@ class Controller { enum class Precision { Double, Single }; const std::unordered_map method_names_ = { - {Method::automatic, "automatic"}, - {Method::statevector, "statevector"}, - {Method::density_matrix, "density_matrix"}, - {Method::matrix_product_state, "matrix_product_state"}, - {Method::stabilizer, "stabilizer"}, - {Method::extended_stabilizer, "extended_stabilizer"}, - {Method::unitary, "unitary"}, - {Method::superop, "superop"}, - {Method::tensor_network, "tensor_network"} - }; + {Method::automatic, "automatic"}, + {Method::statevector, "statevector"}, + {Method::density_matrix, "density_matrix"}, + {Method::matrix_product_state, "matrix_product_state"}, + {Method::stabilizer, "stabilizer"}, + {Method::extended_stabilizer, "extended_stabilizer"}, + {Method::unitary, "unitary"}, + {Method::superop, "superop"}, + {Method::tensor_network, "tensor_network"}}; //----------------------------------------------------------------------- // Config @@ -169,7 +167,8 @@ class Controller { // This method must initialize a state and return output data for // the required number of shots. void run_circuit(const Circuit &circ, const Noise::NoiseModel &noise, - const Method method, const Config &config, ExperimentResult &result) const; + const Method method, const Config &config, + ExperimentResult &result) const; //---------------------------------------------------------------- // Run circuit helpers @@ -178,7 +177,7 @@ class Controller { // Execute n-shots of a circuit on the input state template void run_circuit_helper(const Circuit &circ, const Noise::NoiseModel &noise, - const Config &config, const Method method, + const Config &config, const Method method, ExperimentResult &result) const; // Execute a single shot a of circuit by initializing the state vector, @@ -192,12 +191,9 @@ class Controller { // running all ops in circ, and updating data with // simulation output. template - void run_with_sampling(const Circuit &circ, - State_t &state, - ExperimentResult &result, - RngEngine &rng, - const uint_t block_bits, - const uint_t shots) const; + void run_with_sampling(const Circuit &circ, State_t &state, + ExperimentResult &result, RngEngine &rng, + const uint_t block_bits, const uint_t shots) const; // Execute multiple shots a of circuit by initializing the state vector, // running all ops in circ, and updating data with @@ -212,8 +208,7 @@ class Controller { template void run_circuit_with_sampled_noise(const Circuit &circ, const Noise::NoiseModel &noise, - const Config &config, - const Method method, + const Config &config, const Method method, ExperimentResult &result) const; //---------------------------------------------------------------- @@ -225,7 +220,7 @@ class Controller { template void measure_sampler(InputIterator first_meas, InputIterator last_meas, uint_t shots, State_t &state, ExperimentResult &result, - RngEngine &rng , int_t shot_index = -1) const; + RngEngine &rng, int_t shot_index = -1) const; // Check if measure sampling optimization is valid for the input circuit // for the given method. This checks if operation types before @@ -243,11 +238,10 @@ 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 Circuit &circ, + bool validate_method(Method method, const Circuit &circ, const Noise::NoiseModel &noise, bool throw_except = false) const; - + template bool validate_state(const state_t &state, const Circuit &circ, const Noise::NoiseModel &noise, @@ -261,7 +255,7 @@ class Controller { //---------------------------------------------------------------- // Utility functions //---------------------------------------------------------------- - + // Return a vector of simulation methods for each circuit. // If the default method is automatic this will be computed based on the // circuit and noise model. @@ -285,14 +279,13 @@ class Controller { // Return cache blocking transpiler pass Transpile::CacheBlocking - transpile_cache_blocking(Controller::Method method, - const Circuit &circ, + transpile_cache_blocking(Controller::Method method, const Circuit &circ, const Noise::NoiseModel &noise, const Config &config) const; - //return maximum number of qubits for matrix + // return maximum number of qubits for matrix int_t get_max_matrix_qubits(const Circuit &circ) const; - int_t get_matrix_bits(const Operations::Op& op) const; + int_t get_matrix_bits(const Operations::Op &op) const; bool has_statevector_ops(const Circuit &circuit) const; @@ -304,10 +297,9 @@ class Controller { void clear_parallelization(); // Set parallelization for experiments - void - set_parallelization_experiments(const std::vector &circuits, - const Noise::NoiseModel &noise, - const std::vector &methods); + void set_parallelization_experiments(const std::vector &circuits, + const Noise::NoiseModel &noise, + const std::vector &methods); // Set circuit parallelization void set_parallelization_circuit(const Circuit &circ, @@ -355,7 +347,8 @@ class Controller { bool parallel_nested_ = false; - //max number of states can be stored on memory for batched multi-shots/experiments optimization + // max number of states can be stored on memory for batched + // multi-shots/experiments optimization int max_batched_states_; // max number of qubits in given circuits @@ -371,15 +364,18 @@ class Controller { uint_t cache_block_qubit_ = 0; - //multi-chunks are required to simulate circuits + // multi-chunks are required to simulate circuits bool multi_chunk_required_ = false; - //config setting for multi-shot parallelization + // config setting for multi-shot parallelization bool batched_shots_gpu_ = true; - int_t batched_shots_gpu_max_qubits_ = 16; //multi-shot parallelization is applied if qubits is less than max qubits - bool enable_batch_multi_shots_ = false; //multi-shot parallelization can be applied + int_t batched_shots_gpu_max_qubits_ = + 16; // multi-shot parallelization is applied if qubits is less than max + // qubits + bool enable_batch_multi_shots_ = + false; // multi-shot parallelization can be applied - //settings for cuStateVec + // settings for cuStateVec bool cuStateVec_enable_ = false; }; @@ -455,13 +451,13 @@ void Controller::set_config(const Config &config) { // enable multiple qregs if cache blocking is enabled if (config.blocking_qubits.has_value()) - cache_block_qubit_ = config.blocking_qubits.value(); + cache_block_qubit_ = config.blocking_qubits.value(); - //enable batched multi-shots/experiments optimization + // enable batched multi-shots/experiments optimization batched_shots_gpu_ = config.batched_shots_gpu; batched_shots_gpu_max_qubits_ = config.batched_shots_gpu_max_qubits; - //cuStateVec configs + // cuStateVec configs cuStateVec_enable_ = false; if (config.cuStateVec_enable.has_value()) cuStateVec_enable_ = config.cuStateVec_enable.value(); @@ -486,10 +482,10 @@ void Controller::set_config(const Config &config) { method_ = Method::tensor_network; } else if (config.method != "automatic") { throw std::runtime_error(std::string("Invalid simulation method (") + - method + std::string(").")); + method + std::string(").")); } - if(method_ == Method::density_matrix || method_ == Method::unitary) + if (method_ == Method::density_matrix || method_ == Method::unitary) batched_shots_gpu_max_qubits_ /= 2; // Override automatic simulation method with a fixed method @@ -510,30 +506,31 @@ void Controller::set_config(const Config &config) { #else #ifndef AER_CUSTATEVEC - if(cuStateVec_enable_){ - //Aer is not built for cuStateVec - throw std::runtime_error( - "Simulation device \"GPU\" does not support cuStateVec on this system"); + if (cuStateVec_enable_) { + // Aer is not built for cuStateVec + throw std::runtime_error("Simulation device \"GPU\" does not support " + "cuStateVec on this system"); } #endif int nDev; if (cudaGetDeviceCount(&nDev) != cudaSuccess) { - cudaGetLastError(); - throw std::runtime_error("No CUDA device available!"); + cudaGetLastError(); + throw std::runtime_error("No CUDA device available!"); } sim_device_ = Device::GPU; #endif - } - else { + } else { throw std::runtime_error(std::string("Invalid simulation device (\"") + - sim_device_name_ + std::string("\").")); + sim_device_name_ + std::string("\").")); } - if(method_ == Method::tensor_network){ + if (method_ == Method::tensor_network) { #if defined(AER_THRUST_CUDA) && defined(AER_CUTENSORNET) - if(sim_device_ != Device::GPU) + if (sim_device_ != Device::GPU) #endif - throw std::runtime_error("Invalid combination of simulation method and device, \"tensor_network\" only supports \"device=GPU\""); + throw std::runtime_error( + "Invalid combination of simulation method and device, " + "\"tensor_network\" only supports \"device=GPU\""); } std::string precision = config.precision; @@ -543,7 +540,7 @@ void Controller::set_config(const Config &config) { sim_precision_ = Precision::Single; } else { throw std::runtime_error(std::string("Invalid simulation precision (") + - precision + std::string(").")); + precision + std::string(").")); } } @@ -576,40 +573,41 @@ void Controller::clear_parallelization() { } void Controller::set_parallelization_experiments( - const std::vector &circuits, - const Noise::NoiseModel &noise, - const std::vector &methods) -{ + const std::vector &circuits, const Noise::NoiseModel &noise, + const std::vector &methods) { std::vector required_memory_mb_list(circuits.size()); max_qubits_ = 0; for (size_t j = 0; j < circuits.size(); j++) { - if(circuits[j].num_qubits > max_qubits_) + if (circuits[j].num_qubits > max_qubits_) max_qubits_ = circuits[j].num_qubits; - required_memory_mb_list[j] = required_memory_mb(circuits[j], noise, methods[j]); + required_memory_mb_list[j] = + required_memory_mb(circuits[j], noise, methods[j]); } std::sort(required_memory_mb_list.begin(), required_memory_mb_list.end(), std::greater<>()); - //set max batchable number of circuits - if(batched_shots_gpu_){ - if(required_memory_mb_list[0] == 0 || max_qubits_ == 0) + // set max batchable number of circuits + if (batched_shots_gpu_) { + if (required_memory_mb_list[0] == 0 || max_qubits_ == 0) max_batched_states_ = 1; - else{ - if(sim_device_ == Device::GPU){ - max_batched_states_ = ((max_gpu_memory_mb_/num_gpus_*8/10) / required_memory_mb_list[0])*num_gpus_; - } - else{ - max_batched_states_ = (max_memory_mb_*8/10) / required_memory_mb_list[0]; + else { + if (sim_device_ == Device::GPU) { + max_batched_states_ = ((max_gpu_memory_mb_ / num_gpus_ * 8 / 10) / + required_memory_mb_list[0]) * + num_gpus_; + } else { + max_batched_states_ = + (max_memory_mb_ * 8 / 10) / required_memory_mb_list[0]; } } } - if(max_qubits_ == 0) + if (max_qubits_ == 0) max_qubits_ = 1; - if(explicit_parallelization_ ) + if (explicit_parallelization_) return; - if(circuits.size() == 1){ + if (circuits.size() == 1) { parallel_experiments_ = 1; return; } @@ -647,55 +645,56 @@ void Controller::set_parallelization_experiments( void Controller::set_parallelization_circuit(const Circuit &circ, const Noise::NoiseModel &noise, - const Method method) -{ + const Method method) { enable_batch_multi_shots_ = false; - if(batched_shots_gpu_ && sim_device_ == Device::GPU && - circ.shots > 1 && max_batched_states_ >= num_gpus_ && - batched_shots_gpu_max_qubits_ >= circ.num_qubits ){ - enable_batch_multi_shots_ = true; + if (batched_shots_gpu_ && sim_device_ == Device::GPU && circ.shots > 1 && + max_batched_states_ >= num_gpus_ && + batched_shots_gpu_max_qubits_ >= circ.num_qubits) { + enable_batch_multi_shots_ = true; } - if(sim_device_ == Device::GPU && cuStateVec_enable_){ - enable_batch_multi_shots_ = false; //cuStateVec does not support batch execution of multi-shots + if (sim_device_ == Device::GPU && cuStateVec_enable_) { + enable_batch_multi_shots_ = + false; // cuStateVec does not support batch execution of multi-shots return; } - if(explicit_parallelization_) + if (explicit_parallelization_) return; // Check for trivial parallelization conditions switch (method) { - case Method::statevector: - case Method::stabilizer: - case Method::unitary: - case Method::matrix_product_state: { - if (circ.shots == 1 || num_process_per_experiment_ > 1 || - (!noise.has_quantum_errors() && - check_measure_sampling_opt(circ, method))) { - parallel_shots_ = 1; - parallel_state_update_ = - std::max({1, max_parallel_threads_ / parallel_experiments_}); - return; - } - break; + case Method::statevector: + case Method::stabilizer: + case Method::unitary: + case Method::matrix_product_state: { + if (circ.shots == 1 || num_process_per_experiment_ > 1 || + (!noise.has_quantum_errors() && + check_measure_sampling_opt(circ, method))) { + parallel_shots_ = 1; + parallel_state_update_ = + std::max({1, max_parallel_threads_ / parallel_experiments_}); + return; } - case Method::density_matrix: - case Method::superop: - case Method::tensor_network: { - if (circ.shots == 1 || num_process_per_experiment_ > 1 || - check_measure_sampling_opt(circ, method)) { - parallel_shots_ = 1; - parallel_state_update_ = - std::max({1, max_parallel_threads_ / parallel_experiments_}); - return; - } - break; + break; + } + case Method::density_matrix: + case Method::superop: + case Method::tensor_network: { + if (circ.shots == 1 || num_process_per_experiment_ > 1 || + check_measure_sampling_opt(circ, method)) { + parallel_shots_ = 1; + parallel_state_update_ = + std::max({1, max_parallel_threads_ / parallel_experiments_}); + return; } - case Method::extended_stabilizer: - break; - default: - throw std::invalid_argument("Cannot set parallelization for unresolved method."); + break; + } + case Method::extended_stabilizer: + break; + default: + throw std::invalid_argument( + "Cannot set parallelization for unresolved method."); } // Use a local variable to not override stored maximum based @@ -715,7 +714,8 @@ void Controller::set_parallelization_circuit(const Circuit &circ, // And assign the remaining threads to state update int circ_memory_mb = required_memory_mb(circ, noise, method) / num_process_per_experiment_; - size_t mem_size = (sim_device_ == Device::GPU) ? max_gpu_memory_mb_ : max_memory_mb_; + size_t mem_size = + (sim_device_ == Device::GPU) ? max_gpu_memory_mb_ : max_memory_mb_; if (mem_size < circ_memory_mb) throw std::runtime_error( "a circuit requires more memory than max_memory_mb."); @@ -724,7 +724,7 @@ void Controller::set_parallelization_circuit(const Circuit &circ, int shots = circ.shots; parallel_shots_ = std::min( - {static_cast(mem_size/(circ_memory_mb*2)), max_shots, shots}); + {static_cast(mem_size / (circ_memory_mb * 2)), max_shots, shots}); } parallel_state_update_ = (parallel_shots_ > 1) @@ -734,21 +734,23 @@ void Controller::set_parallelization_circuit(const Circuit &circ, bool Controller::multiple_chunk_required(const Circuit &circ, const Noise::NoiseModel &noise, - const Method method) const -{ + const Method method) const { if (circ.num_qubits < 3) return false; if (cache_block_qubit_ >= 2 && cache_block_qubit_ < circ.num_qubits) return true; - if(num_process_per_experiment_ == 1 && sim_device_ == Device::GPU && num_gpus_ > 0){ - return (max_gpu_memory_mb_ / num_gpus_ < required_memory_mb(circ, noise, method)); + if (num_process_per_experiment_ == 1 && sim_device_ == Device::GPU && + num_gpus_ > 0) { + return (max_gpu_memory_mb_ / num_gpus_ < + required_memory_mb(circ, noise, method)); } - if(num_process_per_experiment_ > 1){ + if (num_process_per_experiment_ > 1) { size_t total_mem = max_memory_mb_; - if(sim_device_ == Device::GPU) + if (sim_device_ == Device::GPU) total_mem += max_gpu_memory_mb_; - if(total_mem*num_process_per_experiment_ > required_memory_mb(circ, noise, method)) + if (total_mem * num_process_per_experiment_ > + required_memory_mb(circ, noise, method)) return true; } @@ -757,27 +759,24 @@ bool Controller::multiple_chunk_required(const Circuit &circ, bool Controller::multiple_shots_required(const Circuit &circ, const Noise::NoiseModel &noise, - const Method method) const -{ + const Method method) const { if (circ.shots < 2) return false; - if (method == Method::density_matrix || - method == Method::superop || + if (method == Method::density_matrix || method == Method::superop || method == Method::unitary) { return false; } bool can_sample = check_measure_sampling_opt(circ, method); - if (noise.is_ideal()){ - return !can_sample; + if (noise.is_ideal()) { + return !can_sample; } return true; } -size_t Controller::get_system_memory_mb() -{ +size_t Controller::get_system_memory_mb() { size_t total_physical_memory = Utils::get_system_memory_mb(); #ifdef AER_MPI // get minimum memory size per process @@ -821,19 +820,16 @@ size_t Controller::get_gpu_memory_mb() { return total_physical_memory >> 20; } - -Transpile::CacheBlocking -Controller::transpile_cache_blocking(Controller::Method method, const Circuit &circ, - const Noise::NoiseModel &noise, - const Config &config) const -{ +Transpile::CacheBlocking Controller::transpile_cache_blocking( + Controller::Method method, const Circuit &circ, + const Noise::NoiseModel &noise, const Config &config) const { Transpile::CacheBlocking cache_block_pass; - const bool is_matrix = (method == Method::density_matrix - || method == Method::unitary); + const bool is_matrix = + (method == Method::density_matrix || method == Method::unitary); const auto complex_size = (sim_precision_ == Precision::Single) - ? sizeof(std::complex) - : sizeof(std::complex); + ? sizeof(std::complex) + : sizeof(std::complex); cache_block_pass.set_num_processes(num_process_per_experiment_); cache_block_pass.set_config(config); @@ -842,7 +838,7 @@ Controller::transpile_cache_blocking(Controller::Method method, const Circuit &c // if blocking is not set by config, automatically set if required if (multiple_chunk_required(circ, noise, method)) { int nplace = num_process_per_experiment_; - if(sim_device_ == Device::GPU && num_gpus_ > 0) + if (sim_device_ == Device::GPU && num_gpus_ > 0) nplace *= num_gpus_; cache_block_pass.set_blocking(circ.num_qubits, get_min_memory_mb() << 20, nplace, complex_size, is_matrix); @@ -908,8 +904,7 @@ Result Controller::execute(const inputdata_t &input_qobj) { Result Controller::execute(std::vector &circuits, Noise::NoiseModel &noise_model, - const Config &config) -{ + const Config &config) { // Start QOBJ timer auto timer_start = myclock_t::now(); @@ -922,15 +917,15 @@ Result Controller::execute(std::vector &circuits, // Execute each circuit in a try block try { - //check if multi-chunk distribution is required + // check if multi-chunk distribution is required bool multi_chunk_required_ = false; - for (size_t j = 0; j < circuits.size(); j++){ - if(circuits[j].num_qubits > 0){ - if(multiple_chunk_required(circuits[j], noise_model, methods[j])) + for (size_t j = 0; j < circuits.size(); j++) { + if (circuits[j].num_qubits > 0) { + if (multiple_chunk_required(circuits[j], noise_model, methods[j])) multi_chunk_required_ = true; } } - if(multi_chunk_required_) + if (multi_chunk_required_) num_process_per_experiment_ = num_processes_; else num_process_per_experiment_ = 1; @@ -955,7 +950,8 @@ Result Controller::execute(std::vector &circuits, // store rank and number of processes, if no distribution rank=0 procs=1 is // set - result.metadata.add(num_process_per_experiment_, "num_processes_per_experiments"); + result.metadata.add(num_process_per_experiment_, + "num_processes_per_experiments"); result.metadata.add(num_processes_, "num_mpi_processes"); result.metadata.add(myrank_, "mpi_rank"); @@ -966,7 +962,7 @@ Result Controller::execute(std::vector &circuits, // Nested parallel experiments parallel_nested_ = true; - //nested should be set to zero if num_threads clause will be used + // nested should be set to zero if num_threads clause will be used omp_set_nested(0); result.metadata.add(parallel_nested_, "omp_nested"); @@ -976,33 +972,35 @@ Result Controller::execute(std::vector &circuits, #endif #ifdef AER_MPI - //average random seed to set the same seed to each process (when seed_simulator is not set) - if(num_processes_ > 1){ + // average random seed to set the same seed to each process (when + // seed_simulator is not set) + if (num_processes_ > 1) { reg_t seeds(circuits.size()); reg_t avg_seeds(circuits.size()); - for(int_t i=0;i &circuits, //------------------------------------------------------------------------- // Base class override //------------------------------------------------------------------------- -void Controller::run_circuit(const Circuit &circ, const Noise::NoiseModel &noise, - const Method method,const Config &config, ExperimentResult &result) const -{ +void Controller::run_circuit(const Circuit &circ, + const Noise::NoiseModel &noise, + const Method method, const Config &config, + ExperimentResult &result) const { // Run the circuit switch (method) { case Method::statevector: { @@ -1052,13 +1051,11 @@ void Controller::run_circuit(const Circuit &circ, const Noise::NoiseModel &noise // Chunk based simualtion if (sim_precision_ == Precision::Double) { // Double-precision Statevector simulation - return run_circuit_helper< - Statevector::State>>( + return run_circuit_helper>>( circ, noise, config, Method::statevector, result); } else { // Single-precision Statevector simulation - return run_circuit_helper< - Statevector::State>>( + return run_circuit_helper>>( circ, noise, config, Method::statevector, result); } } else { @@ -1150,8 +1147,8 @@ void Controller::run_circuit(const Circuit &circ, const Noise::NoiseModel &noise case Method::stabilizer: // Stabilizer simulation // TODO: Stabilizer doesn't yet support custom state initialization - return run_circuit_helper( - circ, noise, config, Method::stabilizer, result); + return run_circuit_helper(circ, noise, config, + Method::stabilizer, result); case Method::extended_stabilizer: return run_circuit_helper( circ, noise, config, Method::extended_stabilizer, result); @@ -1267,7 +1264,7 @@ Transpile::Fusion Controller::transpile_fusion(Method method, } case Method::matrix_product_state: { fusion_pass.active = false; - return fusion_pass; // Do not allow the config to set active for MPS + return fusion_pass; // Do not allow the config to set active for MPS } case Method::statevector: { if (fusion_pass.allow_kraus) { @@ -1282,13 +1279,13 @@ Transpile::Fusion Controller::transpile_fusion(Method method, break; } case Method::tensor_network: { - if(opset.contains(Operations::OpType::save_statevec) || opset.contains(Operations::OpType::save_statevec_dict)){ + if (opset.contains(Operations::OpType::save_statevec) || + opset.contains(Operations::OpType::save_statevec_dict)) { if (fusion_pass.allow_kraus) { // Halve default max fused qubits for Kraus noise fusion fusion_pass.max_qubit /= 2; } - } - else{ + } else { // Halve the default threshold and max fused qubits for density matrix fusion_pass.threshold /= 2; fusion_pass.max_qubit /= 2; @@ -1312,10 +1309,8 @@ Transpile::Fusion Controller::transpile_fusion(Method method, template void Controller::run_circuit_helper(const Circuit &circ, const Noise::NoiseModel &noise, - const Config &config, - const Method method, - ExperimentResult &result) const -{ + const Config &config, const Method method, + ExperimentResult &result) const { // Start individual circuit timer auto timer_start = myclock_t::now(); // state circuit timer @@ -1348,7 +1343,7 @@ void Controller::run_circuit_helper(const Circuit &circ, result.metadata.add(false, "measure_sampling"); result.metadata.add(false, "batched_shots_optimization"); - if(circ.num_qubits > 0){ //do nothing for query steps + if (circ.num_qubits > 0) { // do nothing for query steps // Choose execution method based on noise and method Circuit opt_circ; bool noise_sampling = false; @@ -1364,35 +1359,40 @@ void Controller::run_circuit_helper(const Circuit &circ, result.metadata.add("readout", "noise"); } // Superop noise sampling - else if (method == Method::density_matrix || method == Method::superop || (method == Method::tensor_network && !has_statevector_ops(circ))) { + else if (method == Method::density_matrix || method == Method::superop || + (method == Method::tensor_network && + !has_statevector_ops(circ))) { // Sample noise using SuperOp method - opt_circ = noise.sample_noise(circ, rng, Noise::NoiseModel::Method::superop); + opt_circ = + noise.sample_noise(circ, rng, Noise::NoiseModel::Method::superop); result.metadata.add("superop", "noise"); } // Kraus noise sampling else if (noise.opset().contains(Operations::OpType::kraus) || noise.opset().contains(Operations::OpType::superop)) { - opt_circ = noise.sample_noise(circ, rng, Noise::NoiseModel::Method::kraus); + opt_circ = + noise.sample_noise(circ, rng, Noise::NoiseModel::Method::kraus); result.metadata.add("kraus", "noise"); } // General circuit noise sampling else { - if(enable_batch_multi_shots_ && !multi_chunk_required_){ - //batched optimization samples noise at runtime - opt_circ = noise.sample_noise(circ, rng, Noise::NoiseModel::Method::circuit, true); - } - else{ + if (enable_batch_multi_shots_ && !multi_chunk_required_) { + // batched optimization samples noise at runtime + opt_circ = noise.sample_noise( + circ, rng, Noise::NoiseModel::Method::circuit, true); + } else { noise_sampling = true; } result.metadata.add("circuit", "noise"); } - if(noise_sampling){ - run_circuit_with_sampled_noise(circ, noise, config, method, result); - } - else{ + if (noise_sampling) { + run_circuit_with_sampled_noise(circ, noise, config, method, + result); + } else { // Run multishot simulation without noise sampling - run_circuit_without_sampled_noise(opt_circ, noise, config, method, result); + run_circuit_without_sampled_noise(opt_circ, noise, config, + method, result); } } @@ -1430,13 +1430,11 @@ void Controller::run_single_shot(const Circuit &circ, State_t &state, } template -void Controller::run_with_sampling(const Circuit &circ, - State_t &state, - ExperimentResult &result, - RngEngine &rng, +void Controller::run_with_sampling(const Circuit &circ, State_t &state, + ExperimentResult &result, RngEngine &rng, const uint_t block_bits, const uint_t shots) const { - auto& ops = circ.ops; + auto &ops = circ.ops; auto first_meas = circ.first_measure_pos; // Position of first measurement op bool final_ops = (first_meas == ops.size()); @@ -1447,22 +1445,22 @@ void Controller::run_with_sampling(const Circuit &circ, state.initialize_qreg(circ.num_qubits); state.initialize_creg(circ.num_memory, circ.num_registers); - state.apply_ops(ops.cbegin(), ops.cbegin() + first_meas, result, rng, final_ops); + state.apply_ops(ops.cbegin(), ops.cbegin() + first_meas, result, rng, + final_ops); // Get measurement operations and set of measured qubits - measure_sampler(circ.ops.begin() + first_meas, circ.ops.end(), shots, state, result, rng); + measure_sampler(circ.ops.begin() + first_meas, circ.ops.end(), shots, state, + result, rng); } template -void Controller::run_circuit_without_sampled_noise(Circuit &circ, - const Noise::NoiseModel &noise, - const Config &config, - const Method method, - ExperimentResult &result) const -{ +void Controller::run_circuit_without_sampled_noise( + Circuit &circ, const Noise::NoiseModel &noise, const Config &config, + const Method method, ExperimentResult &result) const { State_t state; - // Validate gateset and memory requirements, raise exception if they're exceeded + // Validate gateset and memory requirements, raise exception if they're + // exceeded validate_state(state, circ, noise, true); // Set state config @@ -1481,8 +1479,9 @@ void Controller::run_circuit_without_sampled_noise(Circuit &circ, // Cache blocking pass uint_t block_bits = circ.num_qubits; - if(state.multi_chunk_distribution_supported()){ - auto cache_block_pass = transpile_cache_blocking(method, circ, dummy_noise, config); + if (state.multi_chunk_distribution_supported()) { + auto cache_block_pass = + transpile_cache_blocking(method, circ, dummy_noise, config); cache_block_pass.set_sample_measure(can_sample); cache_block_pass.optimize_circuit(circ, dummy_noise, state.opset(), result); if (cache_block_pass.enabled()) { @@ -1508,8 +1507,8 @@ void Controller::run_circuit_without_sampled_noise(Circuit &circ, #pragma omp parallel for num_threads(parallel_shots_) for (int i = 0; i < parallel_shots_; i++) { - uint_t i_shot = circ.shots*i/parallel_shots_; - uint_t shot_end = circ.shots*(i+1)/parallel_shots_; + uint_t i_shot = circ.shots * i / parallel_shots_; + uint_t shot_end = circ.shots * (i + 1) / parallel_shots_; uint_t this_shot = shot_end - i_shot; State_t shot_state; @@ -1524,7 +1523,8 @@ void Controller::run_circuit_without_sampled_noise(Circuit &circ, RngEngine rng; rng.set_seed(circ.seed + i); - run_with_sampling(circ, shot_state, par_results[i], rng, block_bits, this_shot); + run_with_sampling(circ, shot_state, par_results[i], rng, block_bits, + this_shot); shot_state.add_metadata(par_results[i]); } @@ -1532,8 +1532,8 @@ void Controller::run_circuit_without_sampled_noise(Circuit &circ, result.combine(std::move(res)); } - if (sim_device_name_ == "GPU"){ - if(parallel_shots_ >= num_gpus_) + if (sim_device_name_ == "GPU") { + if (parallel_shots_ >= num_gpus_) result.metadata.add(num_gpus_, "gpu_parallel_shots_"); else result.metadata.add(parallel_shots_, "gpu_parallel_shots_"); @@ -1542,67 +1542,71 @@ void Controller::run_circuit_without_sampled_noise(Circuit &circ, // Add measure sampling metadata result.metadata.add(true, "measure_sampling"); - } - else{ + } else { // Perform standard execution if we cannot apply the // measurement sampling optimization - if(block_bits == circ.num_qubits && enable_batch_multi_shots_ && state.multi_shot_parallelization_supported()){ - //apply batched multi-shots optimization (currenly only on GPU) + if (block_bits == circ.num_qubits && enable_batch_multi_shots_ && + state.multi_shot_parallelization_supported()) { + // apply batched multi-shots optimization (currenly only on GPU) state.set_max_bached_shots(max_batched_states_); state.set_distribution(num_processes_); state.set_max_matrix_qubits(max_bits); state.set_num_creg_bits(circ.num_memory, circ.num_registers); - state.allocate(circ.num_qubits, circ.num_qubits, circ.shots); //allocate multiple-shots + state.allocate(circ.num_qubits, circ.num_qubits, + circ.shots); // allocate multiple-shots - //qreg is initialized inside state class + // qreg is initialized inside state class state.initialize_creg(circ.num_memory, circ.num_registers); - state.apply_ops_multi_shots(circ.ops.cbegin(), circ.ops.cend(), noise, result, circ.seed, true); + state.apply_ops_multi_shots(circ.ops.cbegin(), circ.ops.cend(), noise, + result, circ.seed, true); result.save_count_data(state.cregs(), save_creg_memory_); // Add batched multi-shots optimizaiton metadata result.metadata.add(true, "batched_shots_optimization"); - } - else{ + } else { std::vector par_results(parallel_shots_); int_t par_shots = parallel_shots_; - if(block_bits != circ.num_qubits) + if (block_bits != circ.num_qubits) par_shots = 1; - auto run_circuit_without_sampled_noise_lambda = [this,&par_results,circ,noise,config,method,block_bits,max_bits,par_shots](int_t i){ - uint_t i_shot,shot_end; - i_shot = circ.shots*i/par_shots; - shot_end = circ.shots*(i+1)/par_shots; - - State_t par_state; - // Set state config - par_state.set_config(config); - par_state.set_parallelization(parallel_state_update_); - par_state.set_global_phase(circ.global_phase_angle); - par_state.enable_density_matrix(!has_statevector_ops(circ)); - - par_state.set_distribution(num_process_per_experiment_); - par_state.set_max_matrix_qubits(max_bits ); - - // allocate qubit register - par_state.allocate(circ.num_qubits, block_bits); - - for(;i_shot 1),0,par_shots,run_circuit_without_sampled_noise_lambda); + auto run_circuit_without_sampled_noise_lambda = + [this, &par_results, circ, noise, config, method, block_bits, + max_bits, par_shots](int_t i) { + uint_t i_shot, shot_end; + i_shot = circ.shots * i / par_shots; + shot_end = circ.shots * (i + 1) / par_shots; + + State_t par_state; + // Set state config + par_state.set_config(config); + par_state.set_parallelization(parallel_state_update_); + par_state.set_global_phase(circ.global_phase_angle); + par_state.enable_density_matrix(!has_statevector_ops(circ)); + + par_state.set_distribution(num_process_per_experiment_); + par_state.set_max_matrix_qubits(max_bits); + + // allocate qubit register + par_state.allocate(circ.num_qubits, block_bits); + + for (; i_shot < shot_end; i_shot++) { + RngEngine rng; + rng.set_seed(circ.seed + i_shot); + run_single_shot(circ, par_state, par_results[i], rng); + } + par_state.add_metadata(par_results[i]); + }; + Utils::apply_omp_parallel_for((par_shots > 1), 0, par_shots, + run_circuit_without_sampled_noise_lambda); for (auto &res : par_results) { result.combine(std::move(res)); } - if (sim_device_name_ == "GPU"){ - if(par_shots >= num_gpus_) + if (sim_device_name_ == "GPU") { + if (par_shots >= num_gpus_) result.metadata.add(num_gpus_, "gpu_parallel_shots_"); else result.metadata.add(par_shots, "gpu_parallel_shots_"); @@ -1615,16 +1619,17 @@ void Controller::run_circuit_without_sampled_noise(Circuit &circ, template void Controller::run_circuit_with_sampled_noise( const Circuit &circ, const Noise::NoiseModel &noise, const Config &config, - const Method method, ExperimentResult &result) const -{ + const Method method, ExperimentResult &result) const { std::vector par_results(parallel_shots_); - auto run_circuit_with_sampled_noise_lambda = [this,&par_results,circ,noise,config,method](int_t i){ + auto run_circuit_with_sampled_noise_lambda = [this, &par_results, circ, noise, + config, method](int_t i) { State_t state; - uint_t i_shot,shot_end; + uint_t i_shot, shot_end; Noise::NoiseModel dummy_noise; - // Validate gateset and memory requirements, raise exception if they're exceeded + // Validate gateset and memory requirements, raise exception if they're + // exceeded validate_state(state, circ, noise, true); // Set state config @@ -1635,12 +1640,13 @@ void Controller::run_circuit_with_sampled_noise( // Transpilation for circuit noise method auto fusion_pass = transpile_fusion(method, circ.opset(), config); - auto cache_block_pass = transpile_cache_blocking(method, circ, noise, config); + auto cache_block_pass = + transpile_cache_blocking(method, circ, noise, config); - i_shot = circ.shots*i/parallel_shots_; - shot_end = circ.shots*(i+1)/parallel_shots_; + i_shot = circ.shots * i / parallel_shots_; + shot_end = circ.shots * (i + 1) / parallel_shots_; - for(;i_shot 1),0,parallel_shots_,run_circuit_with_sampled_noise_lambda); + Utils::apply_omp_parallel_for((parallel_shots_ > 1), 0, parallel_shots_, + run_circuit_with_sampled_noise_lambda); for (auto &res : par_results) { result.combine(std::move(res)); } - if (sim_device_name_ == "GPU"){ - if(parallel_shots_ >= num_gpus_) + if (sim_device_name_ == "GPU") { + if (parallel_shots_ >= num_gpus_) result.metadata.add(num_gpus_, "gpu_parallel_shots_"); else result.metadata.add(parallel_shots_, "gpu_parallel_shots_"); @@ -1695,20 +1702,19 @@ bool Controller::check_measure_sampling_opt(const Circuit &circ, // If density matrix, unitary, superop method all supported instructions // allow sampling - if (method == Method::density_matrix || - method == Method::superop || + if (method == Method::density_matrix || method == Method::superop || method == Method::unitary) { return true; } - if(method == Method::tensor_network){ - //if there are no save statevec ops, tensor network simulator runs as density matrix simulator - if((!circ.opset().contains(Operations::OpType::save_statevec)) && - (!circ.opset().contains(Operations::OpType::save_statevec_dict)) ){ - return true; + if (method == Method::tensor_network) { + // if there are no save statevec ops, tensor network simulator runs as + // density matrix simulator + if ((!circ.opset().contains(Operations::OpType::save_statevec)) && + (!circ.opset().contains(Operations::OpType::save_statevec_dict))) { + return true; } } - // If circuit contains a non-initial initialize that is not a full width // instruction we can't sample if (circ.can_sample_initialize == false) { @@ -1724,7 +1730,7 @@ bool Controller::check_measure_sampling_opt(const Circuit &circ, circ.opset().contains(Operations::OpType::kraus) || circ.opset().contains(Operations::OpType::superop) || circ.opset().contains(Operations::OpType::jump) || - circ.opset().contains(Operations::OpType::mark )) { + circ.opset().contains(Operations::OpType::mark)) { return false; } // Otherwise true @@ -1732,10 +1738,10 @@ bool Controller::check_measure_sampling_opt(const Circuit &circ, } template -void Controller::measure_sampler( - InputIterator first_meas, InputIterator last_meas, uint_t shots, - State_t &state, ExperimentResult &result, RngEngine &rng, int_t shot_index) const -{ +void Controller::measure_sampler(InputIterator first_meas, + InputIterator last_meas, uint_t shots, + State_t &state, ExperimentResult &result, + RngEngine &rng, int_t shot_index) const { // Check if meas_circ is empty, and if so return initial creg if (first_meas == last_meas) { while (shots-- > 0) { @@ -1766,7 +1772,7 @@ void Controller::measure_sampler( // Generate the samples uint_t shots_or_index; - if(shot_index < 0) + if (shot_index < 0) shots_or_index = shots; else shots_or_index = shot_index; @@ -1797,8 +1803,10 @@ void Controller::measure_sampler( } // Process samples - uint_t num_memory = (memory_map.empty()) ? 0ULL : 1 + memory_map.rbegin()->first; - uint_t num_registers = (register_map.empty()) ? 0ULL : 1 + register_map.rbegin()->first; + uint_t num_memory = + (memory_map.empty()) ? 0ULL : 1 + memory_map.rbegin()->first; + uint_t num_registers = + (register_map.empty()) ? 0ULL : 1 + register_map.rbegin()->first; ClassicalRegister creg; while (!all_samples.empty()) { auto sample = all_samples.back(); @@ -1821,14 +1829,13 @@ void Controller::measure_sampler( } // Save count data - result.save_count_data(creg, save_creg_memory_); + result.save_count_data(creg, save_creg_memory_); // pop off processed sample all_samples.pop_back(); } } - //------------------------------------------------------------------------- // Validation //------------------------------------------------------------------------- @@ -1837,22 +1844,28 @@ std::vector Controller::simulation_methods(std::vector &circuits, Noise::NoiseModel &noise_model) const { // Does noise model contain kraus noise - bool kraus_noise = (noise_model.opset().contains(Operations::OpType::kraus) || - noise_model.opset().contains(Operations::OpType::superop)); + bool kraus_noise = + (noise_model.opset().contains(Operations::OpType::kraus) || + noise_model.opset().contains(Operations::OpType::superop)); if (method_ == Method::automatic) { // Determine simulation methods for each circuit and noise model std::vector sim_methods; bool superop_enabled = false; bool kraus_enabled = false; - for (const auto& circ: circuits) { + for (const auto &circ : circuits) { auto method = automatic_simulation_method(circ, noise_model); sim_methods.push_back(method); - if (!superop_enabled && (method == Method::density_matrix || method == Method::superop || (method == Method::tensor_network && !has_statevector_ops(circ)) )) { + if (!superop_enabled && + (method == Method::density_matrix || method == Method::superop || + (method == Method::tensor_network && !has_statevector_ops(circ)))) { noise_model.enable_superop_method(max_parallel_threads_); superop_enabled = true; } else if (kraus_noise && !kraus_enabled && - (method == Method::statevector || method == Method::matrix_product_state || (method == Method::tensor_network && has_statevector_ops(circ))) ) { + (method == Method::statevector || + method == Method::matrix_product_state || + (method == Method::tensor_network && + has_statevector_ops(circ)))) { noise_model.enable_kraus_method(max_parallel_threads_); kraus_enabled = true; } @@ -1864,29 +1877,26 @@ Controller::simulation_methods(std::vector &circuits, std::vector sim_methods(circuits.size(), method_); if (method_ == Method::density_matrix || method_ == Method::superop) { noise_model.enable_superop_method(max_parallel_threads_); - } else if (kraus_noise && ( - method_ == Method::statevector - || method_ == Method::matrix_product_state)) { + } else if (kraus_noise && (method_ == Method::statevector || + method_ == Method::matrix_product_state)) { noise_model.enable_kraus_method(max_parallel_threads_); - } - else if(method_ == Method::tensor_network){ + } else if (method_ == Method::tensor_network) { bool has_save_statevec = false; - for (const auto& circ: circuits) { + for (const auto &circ : circuits) { has_save_statevec |= has_statevector_ops(circ); - if(has_save_statevec) + if (has_save_statevec) break; } - if(!has_save_statevec) + if (!has_save_statevec) noise_model.enable_superop_method(max_parallel_threads_); - else if(kraus_noise) + else if (kraus_noise) noise_model.enable_kraus_method(max_parallel_threads_); } return sim_methods; } -Controller::Method -Controller::automatic_simulation_method(const Circuit &circ, - const Noise::NoiseModel &noise_model) const { +Controller::Method Controller::automatic_simulation_method( + 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; @@ -1908,12 +1918,10 @@ Controller::automatic_simulation_method(const Circuit &circ, // operations only with preference given by memory requirements // statevector > density matrix > matrix product state > unitary > superop // typically any save state instructions will decide the method. - const std::vector methods({Method::statevector, - Method::density_matrix, - Method::matrix_product_state, - Method::unitary, - Method::superop}); - for (const auto& method : methods) { + const std::vector methods( + {Method::statevector, Method::density_matrix, + Method::matrix_product_state, Method::unitary, Method::superop}); + for (const auto &method : methods) { if (validate_method(method, circ, noise_model, false)) return method; } @@ -1925,34 +1933,40 @@ Controller::automatic_simulation_method(const Circuit &circ, return Method::statevector; } -bool Controller::validate_method(Method method, - const Circuit &circ, +bool Controller::validate_method(Method method, const Circuit &circ, const Noise::NoiseModel &noise_model, bool throw_except) const { // Switch wrapper for templated function validate_state switch (method) { - case Method::stabilizer: - return validate_state(Stabilizer::State(), circ, noise_model, throw_except); - case Method::extended_stabilizer: - return validate_state(ExtendedStabilizer::State(), circ, noise_model, throw_except); - case Method::matrix_product_state: - return validate_state(MatrixProductState::State(), circ, noise_model, throw_except); - case Method::statevector: - return validate_state(Statevector::State<>(), circ, noise_model, throw_except); - case Method::density_matrix: - return validate_state(DensityMatrix::State<>(), circ, noise_model, throw_except); - case Method::unitary: - return validate_state(QubitUnitary::State<>(), circ, noise_model, throw_except); - case Method::superop: - return validate_state(QubitSuperoperator::State<>(), circ, noise_model, throw_except); - case Method::tensor_network: - return validate_state(TensorNetwork::State<>(), circ, noise_model, throw_except); - case Method::automatic: - throw std::runtime_error("Cannot validate circuit for unresolved simulation method."); + case Method::stabilizer: + return validate_state(Stabilizer::State(), circ, noise_model, throw_except); + case Method::extended_stabilizer: + return validate_state(ExtendedStabilizer::State(), circ, noise_model, + throw_except); + case Method::matrix_product_state: + return validate_state(MatrixProductState::State(), circ, noise_model, + throw_except); + case Method::statevector: + return validate_state(Statevector::State<>(), circ, noise_model, + throw_except); + case Method::density_matrix: + return validate_state(DensityMatrix::State<>(), circ, noise_model, + throw_except); + case Method::unitary: + return validate_state(QubitUnitary::State<>(), circ, noise_model, + throw_except); + case Method::superop: + return validate_state(QubitSuperoperator::State<>(), circ, noise_model, + throw_except); + case Method::tensor_network: + return validate_state(TensorNetwork::State<>(), circ, noise_model, + throw_except); + case Method::automatic: + throw std::runtime_error( + "Cannot validate circuit for unresolved simulation method."); } } - template bool Controller::validate_state(const state_t &state, const Circuit &circ, const Noise::NoiseModel &noise, @@ -1980,13 +1994,17 @@ bool Controller::validate_state(const state_t &state, const Circuit &circ, // Validate memory requirements bool memory_valid = true; if (max_memory_mb_ > 0) { - size_t required_mb = state.required_memory_mb(circ.num_qubits, circ.ops) / num_process_per_experiment_; - size_t mem_size = (sim_device_ == Device::GPU) ? max_memory_mb_ + max_gpu_memory_mb_ : max_memory_mb_; + size_t required_mb = state.required_memory_mb(circ.num_qubits, circ.ops) / + num_process_per_experiment_; + size_t mem_size = (sim_device_ == Device::GPU) + ? max_memory_mb_ + max_gpu_memory_mb_ + : max_memory_mb_; memory_valid = (required_mb <= mem_size); if (throw_except && !memory_valid) { error_msg << "Insufficient memory to run circuit " << circ_name; error_msg << " using the " << state.name() << " simulator."; - error_msg << " Required memory: " << required_mb << "M, max memory: " << max_memory_mb_ << "M"; + error_msg << " Required memory: " << required_mb + << "M, max memory: " << max_memory_mb_ << "M"; if (sim_device_ == Device::GPU) { error_msg << " (Host) + " << max_gpu_memory_mb_ << "M (GPU)"; } @@ -2014,13 +2032,15 @@ void Controller::save_exception_to_results(Result &result, } } -int_t Controller::get_matrix_bits(const Operations::Op& op) const -{ +int_t Controller::get_matrix_bits(const Operations::Op &op) const { int_t bit = 1; - if(op.type == Operations::OpType::matrix || op.type == Operations::OpType::diagonal_matrix || op.type == Operations::OpType::initialize) + if (op.type == Operations::OpType::matrix || + op.type == Operations::OpType::diagonal_matrix || + op.type == Operations::OpType::initialize) bit = op.qubits.size(); - else if(op.type == Operations::OpType::kraus || op.type == Operations::OpType::superop){ - if(method_ == Method::density_matrix) + else if (op.type == Operations::OpType::kraus || + op.type == Operations::OpType::superop) { + if (method_ == Method::density_matrix) bit = op.qubits.size() * 2; else bit = op.qubits.size(); @@ -2028,22 +2048,22 @@ int_t Controller::get_matrix_bits(const Operations::Op& op) const return bit; } -int_t Controller::get_max_matrix_qubits(const Circuit &circ) const -{ +int_t Controller::get_max_matrix_qubits(const Circuit &circ) const { int_t max_bits = 0; int_t i; - for(i=0;i #include "misc/hacks.hpp" +#include -#include "framework/results/result.hpp" -#include "framework/python_parser.hpp" -#include "framework/matrix.hpp" #include "framework/config.hpp" +#include "framework/matrix.hpp" +#include "framework/python_parser.hpp" +#include "framework/results/result.hpp" //========================================================================= // Controller Execute interface @@ -30,22 +30,24 @@ namespace AER { template -Result controller_execute(const inputdata_t& qobj) { +Result controller_execute(const inputdata_t &qobj) { controller_t controller; // Fix for MacOS and OpenMP library double initialization crash. // Issue: https://github.com/Qiskit/qiskit-aer/issues/1 if (Parser::check_key("config", qobj)) { - std::string path; - const auto& config = Parser::get_value("config", qobj); - Parser::get_value(path, "library_dir", config); - Hacks::maybe_load_openmp(path); + std::string path; + const auto &config = Parser::get_value("config", qobj); + Parser::get_value(path, "library_dir", config); + Hacks::maybe_load_openmp(path); } return controller.execute(qobj); } template -Result controller_execute(std::vector& input_circs, AER::Noise::NoiseModel &noise_model, AER::Config &config) { +Result controller_execute(std::vector &input_circs, + AER::Noise::NoiseModel &noise_model, + AER::Config &config) { controller_t controller; bool truncate = config.enable_truncation; @@ -77,8 +79,8 @@ Result controller_execute(std::vector& input_circs, AER::Noise::NoiseMo try { // Load circuits - for (size_t i=0; i& input_circs, AER::Noise::NoiseMo 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(); - for (size_t j=0; j& input_circs, AER::Noise::NoiseMo const auto param_pos = params.first.second; // Validation if (instr_pos >= num_instr) { - throw std::invalid_argument(R"(Invalid parameterized qobj: instruction position out of range)"); + throw std::invalid_argument( + R"(Invalid parameterized qobj: instruction position out of range)"); } auto &op = param_circ.ops[instr_pos]; if (param_pos >= op.params.size()) { - throw std::invalid_argument(R"(Invalid parameterized qobj: instruction param position out of range)"); + throw std::invalid_argument( + R"(Invalid parameterized qobj: instruction param position out of range)"); } if (j >= params.second.size()) { - throw std::invalid_argument(R"(Invalid parameterized qobj: parameterization value out of range)"); + throw std::invalid_argument( + R"(Invalid parameterized qobj: 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. + // 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); @@ -140,7 +146,7 @@ Result controller_execute(std::vector& input_circs, AER::Noise::NoiseMo else seed = circs[0].seed; - for (auto& circ: circs) { + for (auto &circ : circs) { circ.seed = seed + seed_shift; seed_shift += 2113; } @@ -152,6 +158,5 @@ Result controller_execute(std::vector& input_circs, AER::Noise::NoiseMo return controller.execute(circs, noise_model, config); } - } // end namespace AER #endif diff --git a/src/controllers/state_controller.hpp b/src/controllers/state_controller.hpp index fd54a581d0..bb7ac166e7 100644 --- a/src/controllers/state_controller.hpp +++ b/src/controllers/state_controller.hpp @@ -15,11 +15,11 @@ #ifndef _aer_state_hpp_ #define _aer_state_hpp_ -#include +#include #include +#include #include #include -#include #include "framework/rng.hpp" #include "misc/warnings.hpp" @@ -37,11 +37,11 @@ DISABLE_WARNING_PUSH DISABLE_WARNING_POP #include "framework/creg.hpp" +#include "framework/linalg/vector.hpp" #include "framework/qobj.hpp" #include "framework/results/experiment_result.hpp" #include "framework/results/result.hpp" #include "framework/rng.hpp" -#include "framework/linalg/vector.hpp" #include "noise/noise_model.hpp" @@ -56,8 +56,8 @@ DISABLE_WARNING_POP #include "simulators/statevector/qubitvector.hpp" #include "simulators/statevector/statevector_state.hpp" #include "simulators/superoperator/superoperator_state.hpp" -#include "simulators/unitary/unitarymatrix.hpp" #include "simulators/unitary/unitary_state.hpp" +#include "simulators/unitary/unitarymatrix.hpp" #ifdef AER_THRUST_SUPPORTED #include "simulators/density_matrix/densitymatrix_thrust.hpp" @@ -103,7 +103,7 @@ class AerState { //----------------------------------------------------------------------- AerState() { set_random_seed(); }; - virtual ~AerState() { }; + virtual ~AerState(){}; //----------------------------------------------------------------------- // Configuration @@ -111,28 +111,28 @@ class AerState { // set configuration. // All of the configuration must be done before calling any gate operations. - virtual void configure(const std::string& key, const std::string& value); + virtual void configure(const std::string &key, const std::string &value); // configure a method. - virtual bool set_method(const std::string& name); + virtual bool set_method(const std::string &name); // configure a device. - virtual bool set_device(const std::string& name); + virtual bool set_device(const std::string &name); // configure a precision. - virtual bool set_precision(const std::string& name); + virtual bool set_precision(const std::string &name); // configure custatevec enabled or not - virtual bool set_custatevec(const bool& enabled); + virtual bool set_custatevec(const bool &enabled); // configure number of threads to update state - virtual bool set_parallel_state_update(const uint_t& parallel_state_update); + virtual bool set_parallel_state_update(const uint_t ¶llel_state_update); // configure max number of qubits for a gate - virtual bool set_max_gate_qubits(const uint_t& max_gate_qubits); + virtual bool set_max_gate_qubits(const uint_t &max_gate_qubits); // configure cache blocking qubits - virtual bool set_blocking_qubits(const uint_t& blocking_qubits); + virtual bool set_blocking_qubits(const uint_t &blocking_qubits); // Return true if gate operations have been performed and no configuration // is permitted. @@ -154,7 +154,7 @@ class AerState { // Clear state and buffered ops virtual void clear(); - virtual ExperimentResult& last_result() { return last_result_; }; + virtual ExperimentResult &last_result() { return last_result_; }; //----------------------------------------------------------------------- // Initialization @@ -170,14 +170,16 @@ class AerState { void set_seed(int_t seed); // Allocate qubits with inputted complex array - // method must be statevector and the length of the array must be 2^{num_qubits} - // given data will not be freed in this class - virtual reg_t initialize_statevector(uint_t num_qubits, complex_t* data, bool copy); + // method must be statevector and the length of the array must be + // 2^{num_qubits} given data will not be freed in this class + virtual reg_t initialize_statevector(uint_t num_qubits, complex_t *data, + bool copy); // Allocate qubits with inputted complex array - // method must be densitymatrix and the length of the array must be 4^{num_qubits} - // given data will not be freed in this class - virtual reg_t initialize_density_matrix(uint_t num_qubits, complex_t* data, bool f_order, bool copy); + // method must be densitymatrix and the length of the array must be + // 4^{num_qubits} given data will not be freed in this class + virtual reg_t initialize_density_matrix(uint_t num_qubits, complex_t *data, + bool f_order, bool copy); // Release internal statevector as a vector virtual AER::Vector move_to_vector(); @@ -208,8 +210,11 @@ class AerState { // Apply a N-qubit matrix to the state vector. virtual void apply_unitary(const reg_t &qubits, const cmatrix_t &mat); - // Apply a stacked set of 2^control_count target_count--qubit matrix to the state vector. - virtual void apply_multiplexer(const reg_t &control_qubits, const reg_t &target_qubits, const std::vector &mats); + // Apply a stacked set of 2^control_count target_count--qubit matrix to the + // state vector. + virtual void apply_multiplexer(const reg_t &control_qubits, + const reg_t &target_qubits, + const std::vector &mats); // Apply a N-qubit diagonal matrix to the state vector. virtual void apply_diagonal_matrix(const reg_t &qubits, const cvector_t &mat); @@ -259,22 +264,28 @@ class AerState { // If N=1 this implements an optimized single-qubit phase gate // If N=2 this implements an optimized CPhase gate // If N=3 this implements an optimized CCPhase gate - virtual void apply_mcphase(const reg_t &qubits, const std::complex phase); + virtual void apply_mcphase(const reg_t &qubits, + const std::complex phase); // Apply an optimized H gate virtual void apply_h(const uint_t qubit); // Apply an optimized single-qubit U gate - virtual void apply_u(const uint_t qubit, const double theta, const double phi, const double lambda); + virtual void apply_u(const uint_t qubit, const double theta, const double phi, + const double lambda); // Apply an optimized CU gate - virtual void apply_cu(const reg_t &qubits, const double theta, const double phi, const double lambda, const double gammma); + virtual void apply_cu(const reg_t &qubits, const double theta, + const double phi, const double lambda, + const double gammma); // Apply a general multi-controlled single-qubit unitary gate // If N=1 this implements an optimized single-qubit U gate // If N=2 this implements an optimized CU gate // If N=3 this implements an optimized CCU gate - virtual void apply_mcu(const reg_t &qubits, const double theta, const double phi, const double lambda, const double gammma); + virtual void apply_mcu(const reg_t &qubits, const double theta, + const double phi, const double lambda, + const double gammma); // Apply a general multi-controlled SWAP gate // If N=2 this implements an optimized SWAP gate @@ -341,19 +352,21 @@ class AerState { // The input is a length M list of random reals between [0, 1) used for // generating samples. // The returned value is unordered sampled outcomes - virtual std::vector sample_memory(const reg_t &qubits, uint_t shots); + virtual std::vector sample_memory(const reg_t &qubits, + uint_t shots); // Return M sampled outcomes for Z-basis measurement of specified qubits // The input is a length M list of random reals between [0, 1) used for // generating samples. // The returned value is a map from outcome to its number of samples. - virtual std::unordered_map sample_counts(const reg_t &qubits, uint_t shots); + virtual std::unordered_map sample_counts(const reg_t &qubits, + uint_t shots); //----------------------------------------------------------------------- // Operation management //----------------------------------------------------------------------- // Buffer Operations::Op - virtual void buffer_op(const Operations::Op&& op); + virtual void buffer_op(const Operations::Op &&op); // Flush buffered Operations::Op virtual void flush_ops(); @@ -384,22 +397,20 @@ class AerState { Method method_ = Method::statevector; const std::unordered_map method_names_ = { - {Method::statevector, "statevector"}, - {Method::density_matrix, "density_matrix"}, - {Method::matrix_product_state, "matrix_product_state"}, - {Method::stabilizer, "stabilizer"}, - {Method::extended_stabilizer, "extended_stabilizer"}, - {Method::unitary, "unitary"}, - {Method::superop, "superop"} - }; + {Method::statevector, "statevector"}, + {Method::density_matrix, "density_matrix"}, + {Method::matrix_product_state, "matrix_product_state"}, + {Method::stabilizer, "stabilizer"}, + {Method::extended_stabilizer, "extended_stabilizer"}, + {Method::unitary, "unitary"}, + {Method::superop, "superop"}}; Device device_ = Device::CPU; const std::unordered_map device_names_ = { - {Device::CPU, "CPU"}, - {Device::GPU, "GPU"}, - {Device::ThrustCPU, "ThrustCPU"} - }; + {Device::CPU, "CPU"}, + {Device::GPU, "GPU"}, + {Device::ThrustCPU, "ThrustCPU"}}; Precision precision_ = Precision::Double; @@ -430,22 +441,24 @@ class AerState { bool AerState::is_gpu(bool raise_error) const { #ifndef AER_THRUST_CUDA if (raise_error) - throw std::runtime_error("Simulation device \"GPU\" is not supported on this system"); + throw std::runtime_error( + "Simulation device \"GPU\" is not supported on this system"); else return false; #else int nDev; if (cudaGetDeviceCount(&nDev) != cudaSuccess) { - if (raise_error) { - cudaGetLastError(); - throw std::runtime_error("No CUDA device available!"); - } else return false; + if (raise_error) { + cudaGetLastError(); + throw std::runtime_error("No CUDA device available!"); + } else + return false; } #endif return true; } -void AerState::configure(const std::string& _key, const std::string& _value) { +void AerState::configure(const std::string &_key, const std::string &_value) { std::string key = _key; std::transform(key.begin(), key.end(), key.begin(), ::tolower); @@ -477,44 +490,67 @@ void AerState::configure(const std::string& _key, const std::string& _value) { throw std::runtime_error(msg.str()); } - static std::unordered_set str_config = { "method", "device", "precision", "extended_stabilizer_sampling_method", - "mps_sample_measure_algorithm", "mps_log_data", "mps_swap_direction"}; - static std::unordered_set int_config = { "seed_simulator", "max_parallel_threads", "max_memory_mb", "parallel_state_update", - "blocking_qubits", "batched_shots_gpu_max_qubits", "statevector_parallel_threshold", - "statevector_sample_measure_opt", "stabilizer_max_snapshot_probabilities", - "extended_stabilizer_metropolis_mixing_time", "extended_stabilizer_norm_estimation_samples", - "extended_stabilizer_norm_estimation_repetitions", "extended_stabilizer_parallel_threshold", - "extended_stabilizer_probabilities_snapshot_samples", "matrix_product_state_max_bond_dimension", - "fusion_max_qubit", "fusion_threshold"}; - static std::unordered_set double_config = { "extended_stabilizer_approximation_error", "matrix_product_state_truncation_threshold", - }; - static std::unordered_set bool_config = { "custatevec_enable", "blocking_enable", "batched_shots_gpu", "fusion_enable", "fusion_verbose"}; - - if (str_config.find(key) != str_config.end() ) { + static std::unordered_set str_config = { + "method", + "device", + "precision", + "extended_stabilizer_sampling_method", + "mps_sample_measure_algorithm", + "mps_log_data", + "mps_swap_direction"}; + static std::unordered_set int_config = { + "seed_simulator", + "max_parallel_threads", + "max_memory_mb", + "parallel_state_update", + "blocking_qubits", + "batched_shots_gpu_max_qubits", + "statevector_parallel_threshold", + "statevector_sample_measure_opt", + "stabilizer_max_snapshot_probabilities", + "extended_stabilizer_metropolis_mixing_time", + "extended_stabilizer_norm_estimation_samples", + "extended_stabilizer_norm_estimation_repetitions", + "extended_stabilizer_parallel_threshold", + "extended_stabilizer_probabilities_snapshot_samples", + "matrix_product_state_max_bond_dimension", + "fusion_max_qubit", + "fusion_threshold"}; + static std::unordered_set double_config = { + "extended_stabilizer_approximation_error", + "matrix_product_state_truncation_threshold", + }; + static std::unordered_set bool_config = { + "custatevec_enable", "blocking_enable", "batched_shots_gpu", + "fusion_enable", "fusion_verbose"}; + + if (str_config.find(key) != str_config.end()) { configs_[_key] = _value; - } else if (int_config.find(key) != int_config.end() ) { + } else if (int_config.find(key) != int_config.end()) { configs_[_key] = std::stoi(value); - } else if (bool_config.find(key) != bool_config.end() ) { + } else if (bool_config.find(key) != bool_config.end()) { configs_[_key] = "true" == value; - } else if (double_config.find(key) != double_config.end() ) { + } else if (double_config.find(key) != double_config.end()) { configs_[_key] = std::stod(value); } else { std::stringstream msg; msg << "not supported configuration: " << key << "=" << value << std::endl; throw std::runtime_error(msg.str()); } - }; -bool AerState::set_method(const std::string& method_name) { +bool AerState::set_method(const std::string &method_name) { assert_not_initialized(); - auto it = find_if(method_names_.begin(), method_names_.end(), [method_name](const auto& vt) { return vt.second == method_name; }); - if (it == method_names_.end()) return false; + auto it = find_if( + method_names_.begin(), method_names_.end(), + [method_name](const auto &vt) { return vt.second == method_name; }); + if (it == method_names_.end()) + return false; method_ = it->first; return true; }; -bool AerState::set_device(const std::string& device_name) { +bool AerState::set_device(const std::string &device_name) { assert_not_initialized(); if (device_name == "cpu") device_ = Device::CPU; @@ -527,7 +563,7 @@ bool AerState::set_device(const std::string& device_name) { return true; }; -bool AerState::set_precision(const std::string& precision_name) { +bool AerState::set_precision(const std::string &precision_name) { assert_not_initialized(); if (precision_name == "single") precision_ = Precision::Single; @@ -538,26 +574,25 @@ bool AerState::set_precision(const std::string& precision_name) { return true; }; -bool AerState::set_custatevec(const bool& enabled) { +bool AerState::set_custatevec(const bool &enabled) { assert_not_initialized(); cuStateVec_enable_ = enabled; return true; }; -bool AerState::set_parallel_state_update(const uint_t& parallel_state_update) { +bool AerState::set_parallel_state_update(const uint_t ¶llel_state_update) { assert_not_initialized(); parallel_state_update_ = parallel_state_update; return true; }; -bool AerState::set_max_gate_qubits(const uint_t& max_gate_qubits) { +bool AerState::set_max_gate_qubits(const uint_t &max_gate_qubits) { assert_not_initialized(); max_gate_qubits_ = max_gate_qubits; return true; }; -bool AerState::set_blocking_qubits(const uint_t& blocking_qubits) -{ +bool AerState::set_blocking_qubits(const uint_t &blocking_qubits) { assert_not_initialized(); cache_block_qubits_ = blocking_qubits; return true; @@ -579,9 +614,7 @@ void AerState::assert_not_initialized() const { } }; -void AerState::set_random_seed() { - set_seed(std::random_device()()); -}; +void AerState::set_random_seed() { set_seed(std::random_device()()); }; void AerState::set_seed(int_t seed) { seed_ = seed; @@ -592,7 +625,7 @@ reg_t AerState::allocate_qubits(uint_t num_qubits) { assert_not_initialized(); reg_t ret; for (auto i = 0; i < num_qubits; ++i) - ret.push_back(num_of_qubits_++); + ret.push_back(num_of_qubits_++); return ret; }; @@ -618,85 +651,108 @@ void AerState::initialize_state_controller() { cache_block_pass_.set_config(configs_); }; -void AerState::initialize_qreg_state(std::shared_ptr state) { +void AerState::initialize_qreg_state( + std::shared_ptr state) { if (!state) { if (method_ == Method::statevector) { if (device_ == Device::CPU) if (precision_ == Precision::Double) - state_ = std::make_shared>>(); + state_ = + std::make_shared>>(); else - state_ = std::make_shared>>(); + state_ = + std::make_shared>>(); else // if (device_ == Device::GPU) - #ifdef AER_THRUST_SUPPORTED - if (precision_ == Precision::Double) - state_ = std::make_shared>>(); - else - state_ = std::make_shared>>(); - #else - throw std::runtime_error("specified method does not support non-CPU device: method=statevector"); - #endif +#ifdef AER_THRUST_SUPPORTED + if (precision_ == Precision::Double) + state_ = std::make_shared< + Statevector::State>>(); + else + state_ = std::make_shared< + Statevector::State>>(); +#else + throw std::runtime_error("specified method does not support non-CPU " + "device: method=statevector"); +#endif } else if (method_ == Method::density_matrix) { if (device_ == Device::CPU) if (precision_ == Precision::Double) - state_ = std::make_shared>>(); + state_ = std::make_shared< + DensityMatrix::State>>(); else - state_ = std::make_shared>>(); + state_ = std::make_shared< + DensityMatrix::State>>(); else // if (device_ == Device::GPU) - #ifdef AER_THRUST_SUPPORTED - if (precision_ == Precision::Double) - state_ = std::make_shared>>(); - else - state_ = std::make_shared>>(); - #else - throw std::runtime_error("specified method does not support non-CPU device: method=density_matrix"); - #endif +#ifdef AER_THRUST_SUPPORTED + if (precision_ == Precision::Double) + state_ = std::make_shared< + DensityMatrix::State>>(); + else + state_ = std::make_shared< + DensityMatrix::State>>(); +#else + throw std::runtime_error("specified method does not support non-CPU " + "device: method=density_matrix"); +#endif } else if (method_ == Method::unitary) { if (device_ == Device::CPU) if (precision_ == Precision::Double) - state_ = std::make_shared>>(); + state_ = std::make_shared< + QubitUnitary::State>>(); else - state_ = std::make_shared>>(); + state_ = + std::make_shared>>(); else // if (device_ == Device::GPU) - #ifdef AER_THRUST_SUPPORTED - if (precision_ == Precision::Double) - state_ = std::make_shared>>(); - else - state_ = std::make_shared>>(); - #else - throw std::runtime_error("specified method does not support non-CPU device: method=unitary"); - #endif +#ifdef AER_THRUST_SUPPORTED + if (precision_ == Precision::Double) + state_ = std::make_shared< + QubitUnitary::State>>(); + else + state_ = std::make_shared< + QubitUnitary::State>>(); +#else + throw std::runtime_error( + "specified method does not support non-CPU device: method=unitary"); +#endif } else if (method_ == Method::matrix_product_state) { if (device_ == Device::CPU) state_ = std::make_shared(); else // if (device_ == Device::GPU) - throw std::runtime_error("specified method does not support non-CPU device: method=matrix_product_state"); + throw std::runtime_error("specified method does not support non-CPU " + "device: method=matrix_product_state"); } else if (method_ == Method::stabilizer) { if (device_ == Device::CPU) state_ = std::make_shared(); else // if (device_ == Device::GPU) - throw std::runtime_error("specified method does not support non-CPU device: method=stabilizer"); + throw std::runtime_error("specified method does not support non-CPU " + "device: method=stabilizer"); } else if (method_ == Method::extended_stabilizer) { if (device_ == Device::CPU) state_ = std::make_shared(); else // if (device_ == Device::GPU) - throw std::runtime_error("specified method does not support non-CPU device: method=extended_stabilizer"); + throw std::runtime_error("specified method does not support non-CPU " + "device: method=extended_stabilizer"); } else if (method_ == Method::superop) { if (device_ == Device::CPU) if (precision_ == Precision::Double) - state_ = std::make_shared>>(); + state_ = std::make_shared< + QubitSuperoperator::State>>(); else - state_ = std::make_shared>>(); + state_ = std::make_shared< + QubitSuperoperator::State>>(); else // if (device_ == Device::GPU) - throw std::runtime_error("specified method does not support non-CPU device: method=superop"); + throw std::runtime_error( + "specified method does not support non-CPU device: method=superop"); } else { - throw std::runtime_error("not supported method."); + throw std::runtime_error("not supported method."); } } else { state_ = state; } uint_t block_qubits = cache_block_qubits_; - if(!cache_block_pass_.enabled() || !state_->multi_chunk_distribution_supported()) + if (!cache_block_pass_.enabled() || + !state_->multi_chunk_distribution_supported()) block_qubits = num_of_qubits_; state_->set_config(configs_); state_->set_distribution(num_process_per_experiment_); @@ -719,7 +775,8 @@ void AerState::initialize() { initialized_ = true; }; -reg_t AerState::initialize_statevector(uint_t num_of_qubits, complex_t* data, bool copy) { +reg_t AerState::initialize_statevector(uint_t num_of_qubits, complex_t *data, + bool copy) { assert_not_initialized(); num_of_qubits_ = num_of_qubits; @@ -728,9 +785,11 @@ reg_t AerState::initialize_statevector(uint_t num_of_qubits, complex_t* data, bo initialize_state_controller(); if (device_ != Device::CPU) - throw std::runtime_error("only CPU device supports initialize_statevector()"); + throw std::runtime_error( + "only CPU device supports initialize_statevector()"); if (precision_ != Precision::Double) - throw std::runtime_error("only Double precision supports initialize_statevector()"); + throw std::runtime_error( + "only Double precision supports initialize_statevector()"); auto state = std::make_shared>>(); @@ -739,8 +798,8 @@ reg_t AerState::initialize_statevector(uint_t num_of_qubits, complex_t* data, bo if (cache_block_qubits_ > 0) copy = true; - auto vec = copy? AER::Vector::copy_from_buffer(data_size, data) - : AER::Vector::move_from_buffer(data_size, data); + auto vec = copy ? AER::Vector::copy_from_buffer(data_size, data) + : AER::Vector::move_from_buffer(data_size, data); auto qv = QV::QubitVector(); qv.move_from_vector(std::move(vec)); @@ -756,7 +815,8 @@ reg_t AerState::initialize_statevector(uint_t num_of_qubits, complex_t* data, bo return ret; }; -reg_t AerState::initialize_density_matrix(uint_t num_of_qubits, complex_t* data, bool f_order, bool copy) { +reg_t AerState::initialize_density_matrix(uint_t num_of_qubits, complex_t *data, + bool f_order, bool copy) { assert_not_initialized(); num_of_qubits_ = num_of_qubits; @@ -765,19 +825,22 @@ reg_t AerState::initialize_density_matrix(uint_t num_of_qubits, complex_t* data, initialize_state_controller(); if (device_ != Device::CPU) - throw std::runtime_error("only CPU device supports initialize_density_matrix()"); + throw std::runtime_error( + "only CPU device supports initialize_density_matrix()"); if (precision_ != Precision::Double) - throw std::runtime_error("only Double precision supports initialize_density_matrix()"); + throw std::runtime_error( + "only Double precision supports initialize_density_matrix()"); - auto state = std::make_shared>>(); + auto state = + std::make_shared>>(); initialize_qreg_state(state); if (cache_block_qubits_ > 0) copy = true; - auto vec = copy? AER::Vector::copy_from_buffer(data_size, data) - : AER::Vector::move_from_buffer(data_size, data); + auto vec = copy ? AER::Vector::copy_from_buffer(data_size, data) + : AER::Vector::move_from_buffer(data_size, data); auto dm = QV::DensityMatrix(); dm.move_from_vector(std::move(vec)); @@ -812,14 +875,16 @@ AER::Vector AerState::move_to_vector() { flush_ops(); Operations::Op op; - if (method_ == Method::statevector || method_ == Method::matrix_product_state) { + if (method_ == Method::statevector || + method_ == Method::matrix_product_state) { op.type = Operations::OpType::save_statevec; op.name = "save_statevec"; } else if (method_ == Method::density_matrix) { op.type = Operations::OpType::save_state; op.name = "save_density_matrix"; } else { - throw std::runtime_error("move_to_vector() supports only statevector or matrix_product_state or density_matrix methods"); + throw std::runtime_error("move_to_vector() supports only statevector or " + "matrix_product_state or density_matrix methods"); } for (auto i = 0; i < num_of_qubits_; ++i) op.qubits.push_back(i); @@ -829,17 +894,27 @@ AER::Vector AerState::move_to_vector() { ExperimentResult ret; state_->apply_op(op, ret, rng_, true); - if (method_ == Method::statevector || method_ == Method::matrix_product_state) { - auto vec = std::move(static_cast>>(std::move(ret).data).value()["s"].value()); + if (method_ == Method::statevector || + method_ == Method::matrix_product_state) { + auto vec = std::move( + static_cast>>(std::move(ret).data) + .value()["s"] + .value()); clear(); return std::move(vec); } else if (method_ == Method::density_matrix) { - auto mat = std::move(static_cast, 1>>(std::move(ret).data).value()["s"].value()); - auto vec = Vector::move_from_buffer(mat.GetColumns() * mat.GetRows(), mat.move_to_buffer()); + auto mat = + std::move(static_cast, 1>>( + std::move(ret).data) + .value()["s"] + .value()); + auto vec = Vector::move_from_buffer( + mat.GetColumns() * mat.GetRows(), mat.move_to_buffer()); clear(); return std::move(vec); } else { - throw std::runtime_error("move_to_vector() supports only statevector or matrix_product_state or density_matrix methods"); + throw std::runtime_error("move_to_vector() supports only statevector or " + "matrix_product_state or density_matrix methods"); } }; @@ -849,14 +924,16 @@ matrix AerState::move_to_matrix() { flush_ops(); Operations::Op op; - if (method_ == Method::statevector || method_ == Method::matrix_product_state) { + if (method_ == Method::statevector || + method_ == Method::matrix_product_state) { op.type = Operations::OpType::save_statevec; op.name = "save_statevec"; } else if (method_ == Method::density_matrix) { op.type = Operations::OpType::save_state; op.name = "save_density_matrix"; } else { - throw std::runtime_error("move_to_matrix() supports only statevector or matrix_product_state or density_matrix methods"); + throw std::runtime_error("move_to_matrix() supports only statevector or " + "matrix_product_state or density_matrix methods"); } for (auto i = 0; i < num_of_qubits_; ++i) op.qubits.push_back(i); @@ -866,41 +943,35 @@ matrix AerState::move_to_matrix() { ExperimentResult ret; state_->apply_op(op, ret, rng_, true); - if (method_ == Method::statevector || method_ == Method::matrix_product_state) { + if (method_ == Method::statevector || + method_ == Method::matrix_product_state) { auto vec = std::move( - std::move( - std::move( - static_cast>>( - std::move(ret).data - ) - ).value() - )["s"].value() - ); + std::move(std::move(static_cast>>( + std::move(ret).data)) + .value())["s"] + .value()); clear(); return matrix((1ULL << num_of_qubits_), 1, vec.move_to_buffer()); } else if (method_ == Method::density_matrix) { auto mat = std::move( - std::move( - std::move( - static_cast, 1>>( - std::move(ret).data - ) - ).value() - )["s"].value() - ); + std::move( + std::move(static_cast, 1>>( + std::move(ret).data)) + .value())["s"] + .value()); clear(); return std::move(mat); } else { - throw std::runtime_error("move_to_matrix() supports only statevector or matrix_product_state or density_matrix methods"); + throw std::runtime_error("move_to_matrix() supports only statevector or " + "matrix_product_state or density_matrix methods"); } }; - //----------------------------------------------------------------------- // Apply Initialization //----------------------------------------------------------------------- -void AerState::apply_initialize(const reg_t &qubits, cvector_t && vec) { +void AerState::apply_initialize(const reg_t &qubits, cvector_t &&vec) { assert_initialized(); Operations::Op op; op.type = Operations::OpType::initialize; @@ -912,7 +983,7 @@ void AerState::apply_initialize(const reg_t &qubits, cvector_t && vec) { state_->apply_op(op, last_result_, rng_); }; -void AerState::set_statevector(const reg_t &qubits, cvector_t && vec) { +void AerState::set_statevector(const reg_t &qubits, cvector_t &&vec) { assert_initialized(); Operations::Op op; op.type = Operations::OpType::set_statevec; @@ -956,7 +1027,8 @@ void AerState::apply_unitary(const reg_t &qubits, const cmatrix_t &mat) { buffer_op(std::move(op)); } -void AerState::apply_diagonal_matrix(const reg_t &qubits, const cvector_t &mat) { +void AerState::apply_diagonal_matrix(const reg_t &qubits, + const cvector_t &mat) { assert_initialized(); Operations::Op op; op.type = Operations::OpType::diagonal_matrix; @@ -967,7 +1039,9 @@ void AerState::apply_diagonal_matrix(const reg_t &qubits, const cvector_t &mat) buffer_op(std::move(op)); } -void AerState::apply_multiplexer(const reg_t &control_qubits, const reg_t &target_qubits, const std::vector &mats) { +void AerState::apply_multiplexer(const reg_t &control_qubits, + const reg_t &target_qubits, + const std::vector &mats) { assert_initialized(); if (mats.empty()) @@ -1105,7 +1179,8 @@ void AerState::apply_mcz(const reg_t &qubits) { buffer_op(std::move(op)); } -void AerState::apply_mcphase(const reg_t &qubits, const std::complex phase) { +void AerState::apply_mcphase(const reg_t &qubits, + const std::complex phase) { assert_initialized(); Operations::Op op; @@ -1129,7 +1204,8 @@ void AerState::apply_h(const uint_t qubit) { buffer_op(std::move(op)); } -void AerState::apply_u(const uint_t qubit, const double theta, const double phi, const double lambda) { +void AerState::apply_u(const uint_t qubit, const double theta, const double phi, + const double lambda) { assert_initialized(); Operations::Op op; @@ -1141,7 +1217,9 @@ void AerState::apply_u(const uint_t qubit, const double theta, const double phi, buffer_op(std::move(op)); } -void AerState::apply_cu(const reg_t &qubits, const double theta, const double phi, const double lambda, const double gamma) { +void AerState::apply_cu(const reg_t &qubits, const double theta, + const double phi, const double lambda, + const double gamma) { assert_initialized(); Operations::Op op; @@ -1153,7 +1231,9 @@ void AerState::apply_cu(const reg_t &qubits, const double theta, const double ph buffer_op(std::move(op)); } -void AerState::apply_mcu(const reg_t &qubits, const double theta, const double phi, const double lambda, const double gamma) { +void AerState::apply_mcu(const reg_t &qubits, const double theta, + const double phi, const double lambda, + const double gamma) { assert_initialized(); Operations::Op op; @@ -1233,7 +1313,7 @@ uint_t AerState::apply_measure(const reg_t &qubits) { uint_t bitstring = 0; uint_t bit = 1; - for (const auto& qubit: qubits) { + for (const auto &qubit : qubits) { if (state_->creg().creg_memory()[qubit] == '1') bitstring |= bit; bit <<= 1; @@ -1255,7 +1335,8 @@ void AerState::apply_reset(const reg_t &qubits) { state_->apply_op(op, last_result_, rng_); } -void AerState::apply_kraus(const reg_t &qubits, const std::vector &krausops) { +void AerState::apply_kraus(const reg_t &qubits, + const std::vector &krausops) { assert_initialized(); Operations::Op op; @@ -1286,7 +1367,9 @@ double AerState::probability(const uint_t outcome) { last_result_ = ExperimentResult(); state_->apply_op(op, last_result_, rng_); - return ((DataMap)last_result_.data).value()["s"].value()[0][0]; + return ((DataMap)last_result_.data) + .value()["s"] + .value()[0][0]; } // Return the probability amplitude for outcome in [0, 2^num_qubits - 1] @@ -1305,7 +1388,9 @@ complex_t AerState::amplitude(const uint_t outcome) { last_result_ = ExperimentResult(); state_->apply_op(op, last_result_, rng_); - return ((DataMap>)last_result_.data).value()["s"].value()[0][0]; + return ((DataMap>)last_result_.data) + .value()["s"] + .value()[0][0]; }; std::vector AerState::probabilities() { @@ -1322,7 +1407,9 @@ std::vector AerState::probabilities() { last_result_ = ExperimentResult(); state_->apply_op(op, last_result_, rng_); - return ((DataMap)last_result_.data).value()["s"].value()[0]; + return ((DataMap)last_result_.data) + .value()["s"] + .value()[0]; } std::vector AerState::probabilities(const reg_t &qubits) { @@ -1340,10 +1427,13 @@ std::vector AerState::probabilities(const reg_t &qubits) { last_result_ = ExperimentResult(); state_->apply_op(op, last_result_, rng_); - return ((DataMap)last_result_.data).value()["s"].value()[0]; + return ((DataMap)last_result_.data) + .value()["s"] + .value()[0]; } -std::vector AerState::sample_memory(const reg_t &qubits, uint_t shots) { +std::vector AerState::sample_memory(const reg_t &qubits, + uint_t shots) { assert_initialized(); flush_ops(); @@ -1351,24 +1441,27 @@ std::vector AerState::sample_memory(const reg_t &qubits, uint_t sho std::vector ret; ret.reserve(shots); std::vector samples = state_->sample_measure(qubits, shots, rng_); - for (auto& sample : samples) { - ret.push_back(Utils::int2string(Utils::reg2int(sample, 2), 2, qubits.size())); + for (auto &sample : samples) { + ret.push_back( + Utils::int2string(Utils::reg2int(sample, 2), 2, qubits.size())); } return ret; } -std::unordered_map AerState::sample_counts(const reg_t &qubits, uint_t shots) { +std::unordered_map AerState::sample_counts(const reg_t &qubits, + uint_t shots) { assert_initialized(); flush_ops(); std::vector samples = state_->sample_measure(qubits, shots, rng_); std::unordered_map ret; - for(const auto & sample: samples) { + for (const auto &sample : samples) { uint_t sample_u = 0ULL; uint_t mask = 1ULL; - for (const auto b: sample) { - if (b) sample_u |= mask; + for (const auto b : sample) { + if (b) + sample_u |= mask; mask <<= 1; } if (ret.find(sample_u) == ret.end()) @@ -1382,7 +1475,7 @@ std::unordered_map AerState::sample_counts(const reg_t &qubits, //----------------------------------------------------------------------- // Operation management //----------------------------------------------------------------------- -void AerState::buffer_op(const Operations::Op&& op) { +void AerState::buffer_op(const Operations::Op &&op) { assert_initialized(); buffer_.ops.push_back(std::move(op)); }; @@ -1391,7 +1484,8 @@ void AerState::initialize_experiment_result() { last_result_ = ExperimentResult(); last_result_.set_config(configs_); last_result_.metadata.add(method_names_.at(method_), "method"); - if (method_ == Method::statevector || method_ == Method::density_matrix || method_ == Method::unitary) + if (method_ == Method::statevector || method_ == Method::density_matrix || + method_ == Method::unitary) last_result_.metadata.add(device_names_.at(device_), "device"); else last_result_.metadata.add("CPU", "device"); @@ -1404,14 +1498,16 @@ void AerState::initialize_experiment_result() { }; void AerState::finalize_experiment_result(bool success, double time_taken) { - last_result_.status = success? ExperimentResult::Status::completed : ExperimentResult::Status::error; + last_result_.status = success ? ExperimentResult::Status::completed + : ExperimentResult::Status::error; last_result_.time_taken = time_taken; }; void AerState::flush_ops() { assert_initialized(); - if (buffer_.ops.empty()) return; + if (buffer_.ops.empty()) + return; auto timer_start = myclock_t::now(); @@ -1421,7 +1517,9 @@ void AerState::flush_ops() { transpile_ops(); state_->apply_ops(buffer_.ops.begin(), buffer_.ops.end(), last_result_, rng_); - finalize_experiment_result(true, std::chrono::duration(myclock_t::now() - timer_start).count()); + finalize_experiment_result( + true, + std::chrono::duration(myclock_t::now() - timer_start).count()); clear_ops(); }; @@ -1469,12 +1567,17 @@ void AerState::transpile_ops() { } // Override default fusion settings with custom config fusion_pass_.set_config(configs_); - fusion_pass_.optimize_circuit(buffer_, noise_model_, state_->opset(), last_result_); - - //cache blocking - if(cache_block_pass_.enabled() && state_->multi_chunk_distribution_supported()){ - cache_block_pass_.set_restore_qubit_map(true); //restore swapped qubits because buffer_ does not include output qubits - cache_block_pass_.optimize_circuit(buffer_, noise_model_, state_->opset(), last_result_); + fusion_pass_.optimize_circuit(buffer_, noise_model_, state_->opset(), + last_result_); + + // cache blocking + if (cache_block_pass_.enabled() && + state_->multi_chunk_distribution_supported()) { + cache_block_pass_.set_restore_qubit_map( + true); // restore swapped qubits because buffer_ does not include output + // qubits + cache_block_pass_.optimize_circuit(buffer_, noise_model_, state_->opset(), + last_result_); } } diff --git a/src/framework/avx2_detect.hpp b/src/framework/avx2_detect.hpp index 49f5d73955..2287782f38 100644 --- a/src/framework/avx2_detect.hpp +++ b/src/framework/avx2_detect.hpp @@ -16,63 +16,59 @@ #define _aer_controller_avx2_detect_hpp_ #include -#include #include +#include #include "misc/common_macros.hpp" #if defined(_MSC_VER) - #include +#include #elif defined(GNUC_AVX2) - #include +#include #endif - namespace { -inline void ccpuid(int cpu_info[4], int function_id){ +inline void ccpuid(int cpu_info[4], int function_id) { #if defined(_MSC_VER) __cpuid(cpu_info, function_id); #elif defined(GNUC_AVX2) - __cpuid(function_id, - cpu_info[0], - cpu_info[1], - cpu_info[2], - cpu_info[3]); + __cpuid(function_id, cpu_info[0], cpu_info[1], cpu_info[2], cpu_info[3]); #else // We don't support this platform intrinsics cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0; #endif } -inline void cpuidex(int cpu_info[4], int function_id, int subfunction_id){ +inline void cpuidex(int cpu_info[4], int function_id, int subfunction_id) { #if defined(_MSC_VER) __cpuidex(cpu_info, function_id, subfunction_id); #elif defined(GNUC_AVX2) - __cpuid_count(function_id, subfunction_id, cpu_info[0], cpu_info[1], cpu_info[2], cpu_info[3]); + __cpuid_count(function_id, subfunction_id, cpu_info[0], cpu_info[1], + cpu_info[2], cpu_info[3]); #else // We don't support this platform intrinsics - cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0; + cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0; #endif } -} +} // namespace namespace AER { -inline bool is_avx2_supported(){ +inline bool is_avx2_supported() { #if defined(GNUC_AVX2) || defined(_MSC_VER) static bool cached = false; static bool is_supported = false; - if(cached) + if (cached) return is_supported; std::array cpui; ccpuid(cpui.data(), 0); auto num_ids = cpui[0]; - if(num_ids < 7){ + if (num_ids < 7) { cached = true; is_supported = false; return false; } std::vector> data; - for (int i = 0; i <= num_ids; ++i){ + for (int i = 0; i <= num_ids; ++i) { cpuidex(cpui.data(), i, 0); data.push_back(cpui); } @@ -87,11 +83,9 @@ inline bool is_avx2_supported(){ is_supported = is_fma_supported && is_avx2_supported; return is_supported; #else - return false; + return false; #endif } // end namespace AER -} +} // namespace AER #endif - - diff --git a/src/framework/blas_protos.hpp b/src/framework/blas_protos.hpp old mode 100755 new mode 100644 index d2803c66eb..dc17a25ac8 --- a/src/framework/blas_protos.hpp +++ b/src/framework/blas_protos.hpp @@ -19,10 +19,10 @@ #ifndef _aer_framework_blas_protos_hpp #define _aer_framework_blas_protos_hpp +#include #include #include #include -#include #ifdef __cplusplus extern "C" { @@ -79,45 +79,43 @@ void zgemm_(const char *TransA, const char *TransB, const size_t *M, const std::complex *beta, std::complex *C, size_t *ldc); -// Reduces a Single-Precison Complex Hermitian matrix A to real symmetric tridiagonal form -void chetrd_(char *TRANS, int *N, std::complex *A, - int *LDA, float *d, float *e, std::complex *tau, - std::complex *work, int *lwork, int *info); +// Reduces a Single-Precison Complex Hermitian matrix A to real symmetric +// tridiagonal form +void chetrd_(char *TRANS, int *N, std::complex *A, int *LDA, float *d, + float *e, std::complex *tau, std::complex *work, + int *lwork, int *info); -// Reduces a Double-Precison Complex Hermitian matrix A to real symmetric tridiagonal form T -void zhetrd_(char *TRANS, int *N, std::complex *A, - int *LDA, double *d, double *e, std::complex *tau, - std::complex *work, int *lwork, int *info); +// Reduces a Double-Precison Complex Hermitian matrix A to real symmetric +// tridiagonal form T +void zhetrd_(char *TRANS, int *N, std::complex *A, int *LDA, double *d, + double *e, std::complex *tau, std::complex *work, + int *lwork, int *info); // Computes all eigenvalues and, optionally, eigenvectors of a // Single-Precison Complex symmetric positive definite tridiagonal matrix -void cpteqr_(char* compz, int *n, float *d, float *e, - std::complex *z, int* ldz, - std::complex *work, int *info); +void cpteqr_(char *compz, int *n, float *d, float *e, std::complex *z, + int *ldz, std::complex *work, int *info); // Computes all eigenvalues and, optionally, eigenvectors of a // Double-Precison Complex symmetric positive definite tridiagonal matrix -void zpteqr_(char* compz, int *n, double *d, double *e, - std::complex *z, int* ldz, - std::complex *work, int *info); +void zpteqr_(char *compz, int *n, double *d, double *e, std::complex *z, + int *ldz, std::complex *work, int *info); // Computes selected eigenvalues and, optionally, eigenvectors // of a Single-Precison Complex Hermitian matrix A void cheevx_(char *jobz, char *range, char *uplo, int *n, - std::complex *a, int *lda, float *vl, - float *vu, int *il, int *iu, float *abstol, - int *m, float *w, std::complex *z, int *ldz, - std::complex *work, int *lwork, float *rwork, + std::complex *a, int *lda, float *vl, float *vu, int *il, + int *iu, float *abstol, int *m, float *w, std::complex *z, + int *ldz, std::complex *work, int *lwork, float *rwork, int *iwork, int *ifail, int *info); // Computes selected eigenvalues and, optionally, eigenvectors // of a Double-Precison Complex Hermitian matrix A void zheevx_(char *jobz, char *range, char *uplo, int *n, - std::complex *a, int *lda, double *vl, - double *vu, int *il, int *iu, double *abstol, - int *m, double *w, std::complex *z, int *ldz, - std::complex *work, int *lwork, double *rwork, - int *iwork, int *ifail, int *info); + std::complex *a, int *lda, double *vl, double *vu, int *il, + int *iu, double *abstol, int *m, double *w, + std::complex *z, int *ldz, std::complex *work, + int *lwork, double *rwork, int *iwork, int *ifail, int *info); // Determines Single-Precision machine parameters. float slamch_(char *cmach); diff --git a/src/framework/circuit.hpp b/src/framework/circuit.hpp old mode 100755 new mode 100644 index b5471e4e43..58154a81e9 --- a/src/framework/circuit.hpp +++ b/src/framework/circuit.hpp @@ -17,9 +17,9 @@ #include +#include "framework/config.hpp" #include "framework/operations.hpp" #include "framework/opset.hpp" -#include "framework/config.hpp" using complex_t = std::complex; @@ -40,59 +40,62 @@ class Circuit { std::vector ops; // Circuit parameters updated by from ops by set_params - uint_t num_qubits = 0; // maximum number of qubits needed for ops - uint_t num_memory = 0; // maximum number of memory clbits needed for ops - uint_t num_registers = 0; // maximum number of registers clbits needed for ops - + uint_t num_qubits = 0; // maximum number of qubits needed for ops + uint_t num_memory = 0; // maximum number of memory clbits needed for ops + uint_t num_registers = 0; // maximum number of registers clbits needed for ops + // Measurement params - bool has_conditional = false; // True if any ops are conditional - bool can_sample = true; // True if circuit tail contains measure, roerror, barrier. - size_t first_measure_pos = 0; // Position of first measure instruction - bool can_sample_initialize = true; // True if circuit contains at most 1 initialize - // and it is the first instruction in the circuit + bool has_conditional = false; // True if any ops are conditional + bool can_sample = + true; // True if circuit tail contains measure, roerror, barrier. + size_t first_measure_pos = 0; // Position of first measure instruction + bool can_sample_initialize = + true; // True if circuit contains at most 1 initialize + // and it is the first instruction in the circuit // Circuit metadata constructed from json QobjExperiment uint_t shots = 1; uint_t seed; json_t header; double global_phase_angle = 0; - bool remapped_qubits = false; // True if qubits have been remapped + bool remapped_qubits = false; // True if qubits have been remapped // Constructor - // The constructor automatically calculates the num_qubits, num_memory, num_registers - // parameters by scanning the input list of ops. - Circuit() {set_random_seed();} + // The constructor automatically calculates the num_qubits, num_memory, + // num_registers parameters by scanning the input list of ops. + Circuit() { set_random_seed(); } Circuit(const std::vector &_ops, bool truncation = false); Circuit(std::vector &&_ops, bool truncation = false); // Construct a circuit from JSON - template - Circuit(const inputdata_t& circ, bool truncation = false); + template + Circuit(const inputdata_t &circ, bool truncation = false); - template - Circuit(const inputdata_t& circ, const json_t& qobj_config, bool truncation = false); + template + Circuit(const inputdata_t &circ, const json_t &qobj_config, + bool truncation = false); //----------------------------------------------------------------------- // Set containers //----------------------------------------------------------------------- // Return the opset for the circuit - inline const auto& opset() const {return opset_;} + inline const auto &opset() const { return opset_; } // Return the used qubits for the circuit - inline const auto& qubits() const {return qubitset_;} + inline const auto &qubits() const { return qubitset_; } // Return the used memory for the circuit - inline const auto& memory() const {return memoryset_;} + inline const auto &memory() const { return memoryset_; } // Return the used registers for the circuit - inline const auto& registers() const {return registerset_;} + inline const auto ®isters() const { return registerset_; } // Return the mapping of input op qubits to circuit qubits - inline const auto& qubit_map() const {return qubitmap_;} + inline const auto &qubit_map() const { return qubitmap_; } //----------------------------------------------------------------------- - // Utility methods + // Utility methods //----------------------------------------------------------------------- // Automatically set the number of qubits, memory, registers, and check @@ -110,35 +113,32 @@ class Circuit { void set_metadata(const AER::Config &config, bool truncation); // Set the circuit rng seed to random value - inline void set_random_seed() {seed = std::random_device()();} + inline void set_random_seed() { seed = std::random_device()(); } //----------------------------------------------------------------------- // Op insert helpers //----------------------------------------------------------------------- - void bfunc(const std::string &mask, const std::string &val, const std::string &relation, const uint_t regidx) { + void bfunc(const std::string &mask, const std::string &val, + const std::string &relation, const uint_t regidx) { ops.push_back(Operations::make_bfunc(mask, val, relation, regidx)); } - void gate(const std::string &name, - const reg_t &qubits, + 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::string label="") { - ops.push_back(Operations::make_gate(name, qubits, params, string_params, cond_regidx, label)); + const int_t cond_regidx = -1, const std::string label = "") { + ops.push_back(Operations::make_gate(name, qubits, params, string_params, + cond_regidx, label)); } - void diagonal(const reg_t &qubits, - const cvector_t &vec, + void diagonal(const reg_t &qubits, const cvector_t &vec, 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::string label="") { + void unitary(const reg_t &qubits, const cmatrix_t &mat, + const int_t cond_regidx = -1, const std::string label = "") { ops.push_back(Operations::make_unitary(qubits, mat, cond_regidx, label)); } @@ -152,87 +152,88 @@ class Circuit { ops.push_back(Operations::make_roerror(memory, probabilities)); } - void multiplexer(const reg_t &qubits, - const std::vector &mats, - const int_t cond_regidx = -1, - std::string label="") { - ops.push_back(Operations::make_multiplexer(qubits, mats, cond_regidx, label)); + void multiplexer(const reg_t &qubits, const std::vector &mats, + const int_t cond_regidx = -1, std::string label = "") { + ops.push_back( + Operations::make_multiplexer(qubits, mats, cond_regidx, label)); } - void kraus(const reg_t &qubits, - const std::vector &mats, + void kraus(const reg_t &qubits, const std::vector &mats, 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, + void superop(const reg_t &qubits, const cmatrix_t &mat, 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, + void save_state(const reg_t &qubits, const std::string &name, const std::string &snapshot_type, - const std::string &label="") { - ops.push_back(Operations::make_save_state(qubits, name, snapshot_type, label)); + const std::string &label = "") { + ops.push_back( + Operations::make_save_state(qubits, name, snapshot_type, label)); } - void save_amplitudes(const reg_t &qubits, - const std::string &name, + void save_amplitudes(const reg_t &qubits, const std::string &name, const std::vector &basis_state, const std::string &snapshot_type, - const std::string &label="") { - ops.push_back(Operations::make_save_amplitudes(qubits, name, basis_state, snapshot_type, label)); + const std::string &label = "") { + ops.push_back(Operations::make_save_amplitudes(qubits, name, basis_state, + snapshot_type, label)); } - void save_expval(const reg_t &qubits, - const std::string &name, + void save_expval(const reg_t &qubits, const std::string &name, const std::vector pauli_strings, const std::vector coeff_reals, const std::vector coeff_imags, const std::string &snapshot_type, - const std::string label="") { - ops.push_back(Operations::make_save_expval(qubits, name, pauli_strings, coeff_reals, coeff_imags, snapshot_type, label)); + const std::string label = "") { + ops.push_back(Operations::make_save_expval(qubits, name, pauli_strings, + coeff_reals, coeff_imags, + snapshot_type, label)); } - void set_qerror_loc(const reg_t &qubits, - const std::string &label, + void set_qerror_loc(const reg_t &qubits, const std::string &label, const int_t conditional = -1) { ops.push_back(Operations::make_qerror_loc(qubits, label, conditional)); } - template + template void set_statevector(const reg_t &qubits, const inputdata_t ¶m) { - ops.push_back(Operations::make_set_vector(qubits, "set_statevector", param)); + ops.push_back( + Operations::make_set_vector(qubits, "set_statevector", param)); } - template + template void set_density_matrix(const reg_t &qubits, const inputdata_t ¶m) { - ops.push_back(Operations::make_set_matrix(qubits, "set_density_matrix", param)); + ops.push_back( + Operations::make_set_matrix(qubits, "set_density_matrix", param)); } - template + template void set_unitary(const reg_t &qubits, const inputdata_t ¶m) { ops.push_back(Operations::make_set_matrix(qubits, "set_unitary", param)); } - template + template void set_superop(const reg_t &qubits, const inputdata_t ¶m) { ops.push_back(Operations::make_set_matrix(qubits, "set_superop", param)); } - template + template void set_matrix_product_state(const reg_t &qubits, const inputdata_t ¶m) { - ops.push_back(Operations::make_set_mps(qubits, "set_matrix_product_state", param)); + ops.push_back( + Operations::make_set_mps(qubits, "set_matrix_product_state", param)); } - template + template void set_clifford(const reg_t &qubits, const inputdata_t ¶m) { ops.push_back(Operations::make_set_clifford(qubits, "set_clifford", param)); } - void jump(const reg_t &qubits, const std::vector ¶ms, const int_t cond_regidx = -1) { + void jump(const reg_t &qubits, const std::vector ¶ms, + const int_t cond_regidx = -1) { ops.push_back(Operations::make_jump(qubits, params, cond_regidx)); } @@ -240,7 +241,8 @@ class Circuit { ops.push_back(Operations::make_mark(qubits, params)); } - void measure(const reg_t &qubits, const reg_t &memory, const reg_t ®isters) { + void measure(const reg_t &qubits, const reg_t &memory, + const reg_t ®isters) { ops.push_back(Operations::make_measure(qubits, memory, registers)); } @@ -259,23 +261,21 @@ class Circuit { std::unordered_map qubitmap_; // Add type, qubit, memory, conditional metadata information from op - void add_op_metadata(const Op& op); + void add_op_metadata(const Op &op); // Reset circuit metadata void reset_metadata(); // Helper function for optimized set params - bool check_result_ancestor(const Op& op, - std::unordered_set& ancestor_qubits) const; - + bool check_result_ancestor(const Op &op, + std::unordered_set &ancestor_qubits) const; + // Helper function for optimized set params - void remap_qubits(Op& op) const; + void remap_qubits(Op &op) const; }; - // Json conversion function -inline void from_json(const json_t& js, Circuit &circ) {circ = Circuit(js);} - +inline void from_json(const json_t &js, Circuit &circ) { circ = Circuit(js); } //============================================================================ // Implementation: Circuit methods @@ -291,11 +291,14 @@ Circuit::Circuit(std::vector &&_ops, bool truncation) : Circuit() { set_params(truncation); } -template -Circuit::Circuit(const inputdata_t &circ, bool truncation) : Circuit(circ, json_t(), truncation) {} +template +Circuit::Circuit(const inputdata_t &circ, bool truncation) + : Circuit(circ, json_t(), truncation) {} -template -Circuit::Circuit(const inputdata_t &circ, const json_t &qobj_config, bool truncation) : Circuit() { +template +Circuit::Circuit(const inputdata_t &circ, const json_t &qobj_config, + bool truncation) + : Circuit() { // Get config auto config = qobj_config; if (Parser::check_key("config", circ)) { @@ -305,23 +308,24 @@ Circuit::Circuit(const inputdata_t &circ, const json_t &qobj_config, bool trunca config[it.key()] = it.value(); // overwrite circuit level config values } } - + // Set header Parser::get_value(header, "header", circ); Parser::get_value(global_phase_angle, "global_phase", header); - + // Load instructions if (Parser::check_key("instructions", circ) == false) { - throw std::invalid_argument("Invalid Qobj experiment: no \"instructions\" field."); + throw std::invalid_argument( + "Invalid Qobj experiment: no \"instructions\" field."); } const auto input_ops = Parser::get_list("instructions", circ); - + // Convert to Ops - // TODO: If parser could support reverse iteration through the list of ops without - // conversion we could call `get_reversed_ops` on the inputdata without first - // converting. + // TODO: If parser could support reverse iteration through the list of ops + // without conversion we could call `get_reversed_ops` on the inputdata + // without first converting. std::vector converted_ops; - for(auto the_op: input_ops){ + for (auto the_op : input_ops) { converted_ops.emplace_back(Operations::input_to_op(the_op)); } ops = std::move(converted_ops); @@ -337,7 +341,8 @@ void Circuit::set_metadata(const AER::Config &config, bool truncation) { // Check for specified memory slots uint_t memory_slots = config.memory_slots; if (memory_slots < num_memory) { - throw std::invalid_argument("Invalid Qobj experiment: not enough memory slots."); + throw std::invalid_argument( + "Invalid Qobj experiment: not enough memory slots."); } // override memory slot number num_memory = memory_slots; @@ -346,7 +351,8 @@ void Circuit::set_metadata(const AER::Config &config, bool truncation) { if (config.n_qubits.has_value()) { uint_t n_qubits = config.n_qubits.value(); if (n_qubits < num_qubits) { - throw std::invalid_argument("Invalid Qobj experiment: n_qubits < instruction qubits."); + throw std::invalid_argument( + "Invalid Qobj experiment: n_qubits < instruction qubits."); } if (!truncation) { // Override minimal circuit qubit number with qobj number if truncation @@ -372,14 +378,14 @@ void Circuit::reset_metadata() { num_qubits = 0; num_memory = 0; num_registers = 0; - + has_conditional = false; can_sample = true; first_measure_pos = 0; can_sample_initialize = true; } -void Circuit::add_op_metadata(const Op& op) { +void Circuit::add_op_metadata(const Op &op) { has_conditional |= op.conditional; opset_.insert(op); qubitset_.insert(op.qubits.begin(), op.qubits.end()); @@ -396,11 +402,11 @@ void Circuit::add_op_metadata(const Op& op) { } } - void Circuit::set_params(bool truncation) { - // Clear current circuit metadata + // Clear current circuit metadata reset_metadata(); - if (ops.empty()) return; + if (ops.empty()) + return; // Analyze input ops from tail to head to get locations of ancestor, // first measurement position and last initialize position @@ -414,11 +420,11 @@ void Circuit::set_params(bool truncation) { bool ops_to_remove = false; std::unordered_set ancestor_qubits; - for (size_t i = 0; i < size; ++ i) { + for (size_t i = 0; i < size; ++i) { const size_t rpos = size - i - 1; - const auto& op = ops[rpos]; + const auto &op = ops[rpos]; if (op.type == OpType::mark && last_ancestor_pos == 0) - last_ancestor_pos = rpos; + last_ancestor_pos = rpos; if (!truncation || check_result_ancestor(op, ancestor_qubits)) { add_op_metadata(op); ancestor[rpos] = true; @@ -432,7 +438,7 @@ void Circuit::set_params(bool truncation) { if (last_ancestor_pos == 0) { last_ancestor_pos = rpos; } - } else if (truncation && !ops_to_remove){ + } else if (truncation && !ops_to_remove) { ops_to_remove = true; } } @@ -442,7 +448,7 @@ void Circuit::set_params(bool truncation) { if (truncation) { // Generate mapping of original qubits to ancestor set uint_t idx = 0; - for (const auto& qubit: qubitset_) { + for (const auto &qubit : qubitset_) { if (!remapped_qubits && idx != qubit) { // qubits will be remapped remapped_qubits = true; @@ -481,47 +487,46 @@ void Circuit::set_params(bool truncation) { continue; } - const auto& op = ops[pos]; + const auto &op = ops[pos]; if (op.conditional) { can_sample = false; break; } switch (op.type) { - case OpType::measure: - case OpType::roerror: { - meas_qubits.insert(op.qubits.begin(), op.qubits.end()); - tail_meas_ops.push_back(op); - break; - } - case OpType::save_state: - case OpType::save_expval: - case OpType::save_expval_var: - case OpType::save_statevec: - case OpType::save_statevec_dict: - case OpType::save_densmat: - case OpType::save_probs: - case OpType::save_probs_ket: - case OpType::save_amps: - case OpType::save_amps_sq: - case OpType::save_stabilizer: - case OpType::save_clifford: - case OpType::save_unitary: - case OpType::save_mps: - case OpType::save_superop: - { - can_sample = false; - break; - } - default: { - for (const auto &qubit : op.qubits) { - if (meas_qubits.find(qubit) != meas_qubits.end()) { - can_sample = false; - break; - } + case OpType::measure: + case OpType::roerror: { + meas_qubits.insert(op.qubits.begin(), op.qubits.end()); + tail_meas_ops.push_back(op); + break; + } + case OpType::save_state: + case OpType::save_expval: + case OpType::save_expval_var: + case OpType::save_statevec: + case OpType::save_statevec_dict: + case OpType::save_densmat: + case OpType::save_probs: + case OpType::save_probs_ket: + case OpType::save_amps: + case OpType::save_amps_sq: + case OpType::save_stabilizer: + case OpType::save_clifford: + case OpType::save_unitary: + case OpType::save_mps: + case OpType::save_superop: { + can_sample = false; + break; + } + default: { + for (const auto &qubit : op.qubits) { + if (meas_qubits.find(qubit) != meas_qubits.end()) { + can_sample = false; + break; } - tail_pos.push_back(pos); } + tail_pos.push_back(pos); + } } if (!can_sample) { break; @@ -540,7 +545,8 @@ void Circuit::set_params(bool truncation) { head_end = last_ancestor_pos + 1; } for (size_t pos = 0; pos < head_end; ++pos) { - if (ops_to_remove && !ancestor[pos] && ops[pos].type != OpType::mark && ops[pos].type != OpType::jump) { + if (ops_to_remove && !ancestor[pos] && ops[pos].type != OpType::mark && + ops[pos].type != OpType::jump) { // Skip if not ancestor continue; } @@ -553,10 +559,11 @@ void Circuit::set_params(bool truncation) { if (ops[op_idx].type == OpType::jump) { dests.insert(ops[op_idx].string_params[0]); } else if (ops[op_idx].type == OpType::mark) { - auto& mark_name = ops[op_idx].string_params[0]; + auto &mark_name = ops[op_idx].string_params[0]; if (marks.find(mark_name) != marks.end()) { std::stringstream msg; - msg << "Duplicated mark destination:\"" << mark_name << "\"." << std::endl; + msg << "Duplicated mark destination:\"" << mark_name << "\"." + << std::endl; throw std::runtime_error(msg.str()); } marks.insert(mark_name); @@ -582,7 +589,7 @@ void Circuit::set_params(bool truncation) { if (!ops_to_remove && !ancestor[tpos]) { continue; } - auto& op = ops[tpos]; + auto &op = ops[tpos]; if (remapped_qubits) { remap_qubits(ops[tpos]); } @@ -593,7 +600,7 @@ void Circuit::set_params(bool truncation) { } // Now add remaining delayed measure ops first_measure_pos = op_idx; - for (auto & op : tail_meas_ops) { + for (auto &op : tail_meas_ops) { if (remapped_qubits) { remap_qubits(op); } @@ -608,55 +615,54 @@ void Circuit::set_params(bool truncation) { ops.resize(op_idx); } - -void Circuit::remap_qubits(Op& op) const { +void Circuit::remap_qubits(Op &op) const { reg_t new_qubits; - for (auto& qubit : op.qubits) { + for (auto &qubit : op.qubits) { new_qubits.push_back(qubitmap_.at(qubit)); } op.qubits = std::move(new_qubits); } - -bool Circuit::check_result_ancestor(const Op& op, std::unordered_set& ancestor_qubits) const { +bool Circuit::check_result_ancestor( + const Op &op, std::unordered_set &ancestor_qubits) const { switch (op.type) { - case OpType::barrier: - case OpType::nop: { - return false; - } - case OpType::bfunc: { - return true; - } - // Result generating types - case OpType::measure: - case OpType::roerror: - case OpType::save_state: - case OpType::save_expval: - case OpType::save_expval_var: - case OpType::save_statevec: - case OpType::save_statevec_dict: - case OpType::save_densmat: - case OpType::save_probs: - case OpType::save_probs_ket: - case OpType::save_amps: - case OpType::save_amps_sq: - case OpType::save_stabilizer: - case OpType::save_clifford: - case OpType::save_unitary: - case OpType::save_mps: - case OpType::save_superop: { - ancestor_qubits.insert(op.qubits.begin(), op.qubits.end()); - return true; - } - default: { - for (const auto& qubit : op.qubits) { - if (ancestor_qubits.find(qubit) != ancestor_qubits.end()) { - ancestor_qubits.insert(op.qubits.begin(), op.qubits.end()); - return true; - } + case OpType::barrier: + case OpType::nop: { + return false; + } + case OpType::bfunc: { + return true; + } + // Result generating types + case OpType::measure: + case OpType::roerror: + case OpType::save_state: + case OpType::save_expval: + case OpType::save_expval_var: + case OpType::save_statevec: + case OpType::save_statevec_dict: + case OpType::save_densmat: + case OpType::save_probs: + case OpType::save_probs_ket: + case OpType::save_amps: + case OpType::save_amps_sq: + case OpType::save_stabilizer: + case OpType::save_clifford: + case OpType::save_unitary: + case OpType::save_mps: + case OpType::save_superop: { + ancestor_qubits.insert(op.qubits.begin(), op.qubits.end()); + return true; + } + default: { + for (const auto &qubit : op.qubits) { + if (ancestor_qubits.find(qubit) != ancestor_qubits.end()) { + ancestor_qubits.insert(op.qubits.begin(), op.qubits.end()); + return true; } - return false; } + return false; + } } } diff --git a/src/framework/config.hpp b/src/framework/config.hpp index 59b0c76004..2890747a22 100644 --- a/src/framework/config.hpp +++ b/src/framework/config.hpp @@ -15,9 +15,10 @@ #ifndef _aer_framework_config_hpp_ #define _aer_framework_config_hpp_ -#include -#include +#include "json.hpp" #include "types.hpp" +#include +#include namespace AER { @@ -33,26 +34,22 @@ struct optional { return val; } - void value(const T& input) { + void value(const T &input) { exist = true; val = input; } - void clear() { - exist = false; - } + void clear() { exist = false; } - // operator bool() const { + // operator bool() const { // return exist; // } - bool has_value() const { - return exist; - } + bool has_value() const { return exist; } }; template -bool get_value(optional &var, const std::string& key, const json_t &js) { +bool get_value(optional &var, const std::string &key, const json_t &js) { if (JSON::check_key(key, js)) { var.value(js[key].get()); return true; @@ -63,7 +60,7 @@ bool get_value(optional &var, const std::string& key, const json_t &js) { } template -bool get_value(T &var, const std::string& key, const json_t &js) { +bool get_value(T &var, const std::string &key, const json_t &js) { return JSON::get_value(var, key, js); } @@ -74,7 +71,7 @@ struct Config { uint_t shots = 1024; std::string method = "automatic"; std::string device = "CPU"; - std::string precision ="double"; + std::string precision = "double"; // executor=None, // max_job_size=None, // max_shot_size=None, @@ -85,8 +82,8 @@ struct Config { optional max_parallel_experiments; optional max_parallel_shots; optional max_memory_mb; - bool fusion_enable=true; - bool fusion_verbose=false; + bool fusion_enable = true; + bool fusion_verbose = false; optional fusion_max_qubit; optional fusion_threshold; optional accept_distributed_results; @@ -173,7 +170,7 @@ struct Config { shots = 1024; method = "automatic"; device = "CPU"; - precision ="double"; + precision = "double"; // executor=None, // max_job_size=None, // max_shot_size=None, @@ -184,8 +181,8 @@ struct Config { max_parallel_experiments.clear(); max_parallel_shots.clear(); max_memory_mb.clear(); - fusion_enable=true; - fusion_verbose=false; + fusion_enable = true; + fusion_verbose = false; fusion_max_qubit.clear(); fusion_threshold.clear(); accept_distributed_results.clear(); @@ -266,7 +263,7 @@ struct Config { extended_stabilizer_norm_estimation_default_samples.clear(); } - void merge(const Config& other) { + void merge(const Config &other) { shots = other.shots; method = other.method; device = other.device; @@ -277,44 +274,69 @@ struct Config { enable_truncation = other.enable_truncation; zero_threshold = other.zero_threshold; validation_threshold = other.validation_threshold; - if (other.max_parallel_threads.has_value()) max_parallel_threads.value(other.max_parallel_threads.value()); - if (other.max_parallel_experiments.has_value()) max_parallel_experiments.value(other.max_parallel_experiments.value()); - if (other.max_parallel_shots.has_value()) max_parallel_shots.value(other.max_parallel_shots.value()); - if (other.max_memory_mb.has_value()) max_memory_mb.value(other.max_memory_mb.value()); + if (other.max_parallel_threads.has_value()) + max_parallel_threads.value(other.max_parallel_threads.value()); + if (other.max_parallel_experiments.has_value()) + max_parallel_experiments.value(other.max_parallel_experiments.value()); + if (other.max_parallel_shots.has_value()) + max_parallel_shots.value(other.max_parallel_shots.value()); + if (other.max_memory_mb.has_value()) + max_memory_mb.value(other.max_memory_mb.value()); fusion_enable = other.fusion_enable; fusion_verbose = other.fusion_verbose; - if (other.fusion_max_qubit.has_value()) fusion_max_qubit.value(other.fusion_max_qubit.value()); - if (other.fusion_threshold.has_value()) fusion_threshold.value(other.fusion_threshold.value()); - if (other.accept_distributed_results.has_value()) accept_distributed_results.value(other.accept_distributed_results.value()); - if (other.memory.has_value()) memory.value(other.memory.value()); + if (other.fusion_max_qubit.has_value()) + fusion_max_qubit.value(other.fusion_max_qubit.value()); + if (other.fusion_threshold.has_value()) + fusion_threshold.value(other.fusion_threshold.value()); + if (other.accept_distributed_results.has_value()) + accept_distributed_results.value( + other.accept_distributed_results.value()); + if (other.memory.has_value()) + memory.value(other.memory.value()); // noise_model=None, - if (other.seed_simulator.has_value()) seed_simulator.value(other.seed_simulator.value()); + if (other.seed_simulator.has_value()) + seed_simulator.value(other.seed_simulator.value()); // # cuStateVec (cuQuantum) option - if (other.cuStateVec_enable.has_value()) cuStateVec_enable.value(other.cuStateVec_enable.value()); + if (other.cuStateVec_enable.has_value()) + cuStateVec_enable.value(other.cuStateVec_enable.value()); // # cache blocking for multi-GPUs/MPI options - if (other.blocking_qubits.has_value()) blocking_qubits.value(other.blocking_qubits.value()); + if (other.blocking_qubits.has_value()) + blocking_qubits.value(other.blocking_qubits.value()); blocking_enable = other.blocking_enable; - if (other.chunk_swap_buffer_qubits.has_value()) chunk_swap_buffer_qubits.value(other.chunk_swap_buffer_qubits.value()); + if (other.chunk_swap_buffer_qubits.has_value()) + chunk_swap_buffer_qubits.value(other.chunk_swap_buffer_qubits.value()); // # multi-shots optimization options (GPU only) batched_shots_gpu = other.batched_shots_gpu; batched_shots_gpu_max_qubits = other.batched_shots_gpu_max_qubits; - if (other.num_threads_per_device.has_value()) num_threads_per_device.value(other.num_threads_per_device.value()); + if (other.num_threads_per_device.has_value()) + num_threads_per_device.value(other.num_threads_per_device.value()); // # statevector options statevector_parallel_threshold = other.statevector_parallel_threshold; statevector_sample_measure_opt = other.statevector_sample_measure_opt; // # stabilizer options - stabilizer_max_snapshot_probabilities = other.stabilizer_max_snapshot_probabilities; + stabilizer_max_snapshot_probabilities = + other.stabilizer_max_snapshot_probabilities; // # extended stabilizer options - extended_stabilizer_sampling_method = other.extended_stabilizer_sampling_method; - extended_stabilizer_metropolis_mixing_time = other.extended_stabilizer_metropolis_mixing_time; - extended_stabilizer_approximation_error = other.extended_stabilizer_approximation_error; - extended_stabilizer_norm_estimation_samples = other.extended_stabilizer_norm_estimation_samples; - extended_stabilizer_norm_estimation_repetitions = other.extended_stabilizer_norm_estimation_repetitions; - extended_stabilizer_parallel_threshold = other.extended_stabilizer_parallel_threshold; - extended_stabilizer_probabilities_snapshot_samples = other.extended_stabilizer_probabilities_snapshot_samples; + extended_stabilizer_sampling_method = + other.extended_stabilizer_sampling_method; + extended_stabilizer_metropolis_mixing_time = + other.extended_stabilizer_metropolis_mixing_time; + extended_stabilizer_approximation_error = + other.extended_stabilizer_approximation_error; + extended_stabilizer_norm_estimation_samples = + other.extended_stabilizer_norm_estimation_samples; + extended_stabilizer_norm_estimation_repetitions = + other.extended_stabilizer_norm_estimation_repetitions; + extended_stabilizer_parallel_threshold = + other.extended_stabilizer_parallel_threshold; + extended_stabilizer_probabilities_snapshot_samples = + other.extended_stabilizer_probabilities_snapshot_samples; // # MPS options - matrix_product_state_truncation_threshold = other.matrix_product_state_truncation_threshold; - if (other.matrix_product_state_max_bond_dimension.has_value()) matrix_product_state_max_bond_dimension.value(other.matrix_product_state_max_bond_dimension.value()); + matrix_product_state_truncation_threshold = + other.matrix_product_state_truncation_threshold; + if (other.matrix_product_state_max_bond_dimension.has_value()) + matrix_product_state_max_bond_dimension.value( + other.matrix_product_state_max_bond_dimension.value()); mps_sample_measure_algorithm = other.mps_sample_measure_algorithm; mps_log_data = other.mps_log_data; mps_swap_direction = other.mps_swap_direction; @@ -322,40 +344,66 @@ struct Config { mps_parallel_threshold = other.mps_parallel_threshold; mps_omp_threads = other.mps_omp_threads; // # tensor network options - tensor_network_num_sampling_qubits = other.tensor_network_num_sampling_qubits; + tensor_network_num_sampling_qubits = + other.tensor_network_num_sampling_qubits; use_cuTensorNet_autotuning = other.use_cuTensorNet_autotuning; // system configurations param_table = other.param_table; library_dir = other.library_dir; - if (other.n_qubits.has_value()) n_qubits.value(other.n_qubits.value()); + if (other.n_qubits.has_value()) + n_qubits.value(other.n_qubits.value()); global_phase = other.global_phase; memory_slots = other.memory_slots; - if (other._parallel_experiments.has_value()) _parallel_experiments.value(other._parallel_experiments.value()); - if (other._parallel_shots.has_value()) _parallel_shots.value(other._parallel_shots.value()); - if (other._parallel_state_update.has_value()) _parallel_state_update.value(other._parallel_state_update.value()); - if (other._parallel_experiments.has_value()) _parallel_experiments.value(other._parallel_experiments.value()); - if (other.fusion_allow_kraus.has_value()) fusion_allow_kraus.value(other.fusion_allow_kraus.value()); - if (other.fusion_allow_superop.has_value()) fusion_allow_superop.value(other.fusion_allow_superop.value()); - if (other.fusion_parallelization_threshold.has_value()) fusion_parallelization_threshold.value(other.fusion_parallelization_threshold.value()); - if (other._fusion_enable_n_qubits.has_value()) _fusion_enable_n_qubits.value(other._fusion_enable_n_qubits.value()); - if (other._fusion_enable_n_qubits_1.has_value()) _fusion_enable_n_qubits_1.value(other._fusion_enable_n_qubits_1.value()); - if (other._fusion_enable_n_qubits_2.has_value()) _fusion_enable_n_qubits_2.value(other._fusion_enable_n_qubits_2.value()); - if (other._fusion_enable_n_qubits_3.has_value()) _fusion_enable_n_qubits_3.value(other._fusion_enable_n_qubits_3.value()); - if (other._fusion_enable_n_qubits_4.has_value()) _fusion_enable_n_qubits_4.value(other._fusion_enable_n_qubits_4.value()); - if (other._fusion_enable_n_qubits_5.has_value()) _fusion_enable_n_qubits_5.value(other._fusion_enable_n_qubits_5.value()); - if (other._fusion_enable_diagonal.has_value()) _fusion_enable_diagonal.value(other._fusion_enable_diagonal.value()); - if (other._fusion_min_qubit.has_value()) _fusion_min_qubit.value(other._fusion_min_qubit.value()); - if (other.fusion_cost_factor.has_value()) fusion_cost_factor.value(other.fusion_cost_factor.value()); + if (other._parallel_experiments.has_value()) + _parallel_experiments.value(other._parallel_experiments.value()); + if (other._parallel_shots.has_value()) + _parallel_shots.value(other._parallel_shots.value()); + if (other._parallel_state_update.has_value()) + _parallel_state_update.value(other._parallel_state_update.value()); + if (other._parallel_experiments.has_value()) + _parallel_experiments.value(other._parallel_experiments.value()); + if (other.fusion_allow_kraus.has_value()) + fusion_allow_kraus.value(other.fusion_allow_kraus.value()); + if (other.fusion_allow_superop.has_value()) + fusion_allow_superop.value(other.fusion_allow_superop.value()); + if (other.fusion_parallelization_threshold.has_value()) + fusion_parallelization_threshold.value( + other.fusion_parallelization_threshold.value()); + if (other._fusion_enable_n_qubits.has_value()) + _fusion_enable_n_qubits.value(other._fusion_enable_n_qubits.value()); + if (other._fusion_enable_n_qubits_1.has_value()) + _fusion_enable_n_qubits_1.value(other._fusion_enable_n_qubits_1.value()); + if (other._fusion_enable_n_qubits_2.has_value()) + _fusion_enable_n_qubits_2.value(other._fusion_enable_n_qubits_2.value()); + if (other._fusion_enable_n_qubits_3.has_value()) + _fusion_enable_n_qubits_3.value(other._fusion_enable_n_qubits_3.value()); + if (other._fusion_enable_n_qubits_4.has_value()) + _fusion_enable_n_qubits_4.value(other._fusion_enable_n_qubits_4.value()); + if (other._fusion_enable_n_qubits_5.has_value()) + _fusion_enable_n_qubits_5.value(other._fusion_enable_n_qubits_5.value()); + if (other._fusion_enable_diagonal.has_value()) + _fusion_enable_diagonal.value(other._fusion_enable_diagonal.value()); + if (other._fusion_min_qubit.has_value()) + _fusion_min_qubit.value(other._fusion_min_qubit.value()); + if (other.fusion_cost_factor.has_value()) + fusion_cost_factor.value(other.fusion_cost_factor.value()); - if (other.superoperator_parallel_threshold.has_value()) superoperator_parallel_threshold.value(other.superoperator_parallel_threshold.value()); - if (other.unitary_parallel_threshold.has_value()) unitary_parallel_threshold.value(other.unitary_parallel_threshold.value()); - if (other.memory_blocking_bits.has_value()) memory_blocking_bits.value(other.memory_blocking_bits.value()); - 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.superoperator_parallel_threshold.has_value()) + superoperator_parallel_threshold.value( + other.superoperator_parallel_threshold.value()); + if (other.unitary_parallel_threshold.has_value()) + unitary_parallel_threshold.value( + other.unitary_parallel_threshold.value()); + if (other.memory_blocking_bits.has_value()) + memory_blocking_bits.value(other.memory_blocking_bits.value()); + 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()); } }; // Json conversion function -inline void from_json(const json_t& js, Config &config) { +inline void from_json(const json_t &js, Config &config) { get_value(config.shots, "shots", js); get_value(config.method, "method", js); get_value(config.device, "device", js); @@ -374,7 +422,8 @@ inline void from_json(const json_t& js, Config &config) { get_value(config.fusion_verbose, "fusion_verbose", js); get_value(config.fusion_max_qubit, "fusion_max_qubit", js); get_value(config.fusion_threshold, "fusion_threshold", js); - get_value(config.accept_distributed_results, "accept_distributed_results", js); + get_value(config.accept_distributed_results, "accept_distributed_results", + js); get_value(config.memory, "memory", js); // noise_model=None, get_value(config.seed_simulator, "seed_simulator", js); @@ -386,33 +435,49 @@ inline void from_json(const json_t& js, Config &config) { get_value(config.chunk_swap_buffer_qubits, "chunk_swap_buffer_qubits", js); // # multi-shots optimization options (GPU only) get_value(config.batched_shots_gpu, "batched_shots_gpu", js); - get_value(config.batched_shots_gpu_max_qubits, "batched_shots_gpu_max_qubits", js); + get_value(config.batched_shots_gpu_max_qubits, "batched_shots_gpu_max_qubits", + js); get_value(config.num_threads_per_device, "num_threads_per_device", js); // # statevector options - get_value(config.statevector_parallel_threshold, "statevector_parallel_threshold", js); - get_value(config.statevector_sample_measure_opt, "statevector_sample_measure_opt", js); + get_value(config.statevector_parallel_threshold, + "statevector_parallel_threshold", js); + get_value(config.statevector_sample_measure_opt, + "statevector_sample_measure_opt", js); // # stabilizer options - get_value(config.stabilizer_max_snapshot_probabilities, "stabilizer_max_snapshot_probabilities", js); + get_value(config.stabilizer_max_snapshot_probabilities, + "stabilizer_max_snapshot_probabilities", js); // # extended stabilizer options - get_value(config.extended_stabilizer_sampling_method, "extended_stabilizer_sampling_method", js); - get_value(config.extended_stabilizer_metropolis_mixing_time, "extended_stabilizer_metropolis_mixing_time", js); - get_value(config.extended_stabilizer_approximation_error, "extended_stabilizer_approximation_error", js); - get_value(config.extended_stabilizer_norm_estimation_samples, "extended_stabilizer_norm_estimation_samples", js); - get_value(config.extended_stabilizer_norm_estimation_repetitions, "extended_stabilizer_norm_estimation_repetitions", js); - get_value(config.extended_stabilizer_parallel_threshold, "extended_stabilizer_parallel_threshold", js); - get_value(config.extended_stabilizer_probabilities_snapshot_samples, "extended_stabilizer_probabilities_snapshot_samples", js); + get_value(config.extended_stabilizer_sampling_method, + "extended_stabilizer_sampling_method", js); + get_value(config.extended_stabilizer_metropolis_mixing_time, + "extended_stabilizer_metropolis_mixing_time", js); + get_value(config.extended_stabilizer_approximation_error, + "extended_stabilizer_approximation_error", js); + get_value(config.extended_stabilizer_norm_estimation_samples, + "extended_stabilizer_norm_estimation_samples", js); + get_value(config.extended_stabilizer_norm_estimation_repetitions, + "extended_stabilizer_norm_estimation_repetitions", js); + get_value(config.extended_stabilizer_parallel_threshold, + "extended_stabilizer_parallel_threshold", js); + get_value(config.extended_stabilizer_probabilities_snapshot_samples, + "extended_stabilizer_probabilities_snapshot_samples", js); // # MPS options - get_value(config.matrix_product_state_truncation_threshold, "matrix_product_state_truncation_threshold", js); - get_value(config.matrix_product_state_max_bond_dimension, "matrix_product_state_max_bond_dimension", js); - get_value(config.mps_sample_measure_algorithm, "mps_sample_measure_algorithm", js); + get_value(config.matrix_product_state_truncation_threshold, + "matrix_product_state_truncation_threshold", js); + get_value(config.matrix_product_state_max_bond_dimension, + "matrix_product_state_max_bond_dimension", js); + get_value(config.mps_sample_measure_algorithm, "mps_sample_measure_algorithm", + js); get_value(config.mps_log_data, "mps_log_data", js); get_value(config.mps_swap_direction, "mps_swap_direction", js); 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); // # tensor network options - get_value(config.tensor_network_num_sampling_qubits, "tensor_network_num_sampling_qubits", js); - get_value(config.use_cuTensorNet_autotuning, "use_cuTensorNet_autotuning", js); + get_value(config.tensor_network_num_sampling_qubits, + "tensor_network_num_sampling_qubits", js); + get_value(config.use_cuTensorNet_autotuning, "use_cuTensorNet_autotuning", + js); // system configurations get_value(config.param_table, "parameterizations", js); get_value(config.library_dir, "library_dir", js); @@ -425,7 +490,8 @@ inline void from_json(const json_t& js, Config &config) { get_value(config.fusion_allow_kraus, "fusion_allow_kraus", js); get_value(config.fusion_allow_superop, "fusion_allow_superop", js); - get_value(config.fusion_parallelization_threshold, "fusion_parallelization_threshold", js); + get_value(config.fusion_parallelization_threshold, + "fusion_parallelization_threshold", js); get_value(config._fusion_enable_n_qubits, "_fusion_enable_n_qubits", js); get_value(config._fusion_enable_n_qubits_1, "_fusion_enable_n_qubits_1", js); get_value(config._fusion_enable_n_qubits_2, "_fusion_enable_n_qubits_2", js); @@ -436,12 +502,15 @@ inline void from_json(const json_t& js, Config &config) { get_value(config._fusion_min_qubit, "_fusion_min_qubit", js); get_value(config.fusion_cost_factor, "fusion_cost_factor", js); - get_value(config.superoperator_parallel_threshold, "superoperator_parallel_threshold", js); - get_value(config.unitary_parallel_threshold, "unitary_parallel_threshold", js); + get_value(config.superoperator_parallel_threshold, + "superoperator_parallel_threshold", js); + get_value(config.unitary_parallel_threshold, "unitary_parallel_threshold", + js); get_value(config.memory_blocking_bits, "memory_blocking_bits", js); - get_value(config.extended_stabilizer_norm_estimation_default_samples, "extended_stabilizer_norm_estimation_default_samples", js); + get_value(config.extended_stabilizer_norm_estimation_default_samples, + "extended_stabilizer_norm_estimation_default_samples", js); } -} +} // namespace AER #endif \ No newline at end of file diff --git a/src/framework/creg.hpp b/src/framework/creg.hpp old mode 100755 new mode 100644 index 2a79a0e871..1a0d012865 --- a/src/framework/creg.hpp +++ b/src/framework/creg.hpp @@ -16,8 +16,8 @@ #define _aer_framework_creg_hpp_ #include "framework/operations.hpp" -#include "framework/utils.hpp" #include "framework/rng.hpp" +#include "framework/utils.hpp" namespace AER { @@ -29,39 +29,39 @@ namespace AER { class ClassicalRegister { public: - // Return the current value of the memory as little-endian hex-string - inline std::string memory_hex() const {return Utils::bin2hex(creg_memory_);} + inline std::string memory_hex() const { return Utils::bin2hex(creg_memory_); } // Return the current value of the memory as little-endian bit-string - inline std::string memory_bin() const {return "0b" + creg_memory_;} + inline std::string memory_bin() const { return "0b" + creg_memory_; } // Return the current value of the memory as little-endian hex-string - inline std::string register_hex() const {return Utils::bin2hex(creg_register_);} + inline std::string register_hex() const { + return Utils::bin2hex(creg_register_); + } // Return the current value of the memory as little-endian bit-string - inline std::string register_bin() const {return "0b" + creg_register_;} + inline std::string register_bin() const { return "0b" + creg_register_; } // Return the size of the memory bits - size_t memory_size() const {return creg_memory_.size();} + size_t memory_size() const { return creg_memory_.size(); } // Return the size of the register bits - size_t register_size() const {return creg_register_.size();} + size_t register_size() const { return creg_register_.size(); } // Return a reference to the current value of the memory // this is a bit-string without the "0b" prefix. - inline auto& creg_memory() {return creg_memory_;} + inline auto &creg_memory() { return creg_memory_; } // Return a reference to the current value of the memory // this is a bit-string without the "0b" prefix. - inline auto& creg_register() {return creg_register_;} + inline auto &creg_register() { return creg_register_; } // Initialize the memory and register bits to default values (all 0) void initialize(size_t num_memory, size_t num_registers); // Initialize the memory and register bits to specific values - void initialize(size_t num_memory, - size_t num_registers, + void initialize(size_t num_memory, size_t num_registers, const std::string &memory_hex, const std::string ®ister_hex); @@ -76,17 +76,18 @@ class ClassicalRegister { // Apply readout error instruction to classical registers void apply_roerror(const Operations::Op &op, RngEngine &rng); - // Store a measurement outcome in the specified memory and register bit locations - void store_measure(const reg_t &outcome, const reg_t &memory, const reg_t ®isters); + // Store a measurement outcome in the specified memory and register bit + // locations + void store_measure(const reg_t &outcome, const reg_t &memory, + const reg_t ®isters); protected: - // Classical registers std::string creg_memory_; // standard classical bit memory std::string creg_register_; // optional classical bit register // Measurement config settings - bool return_hex_strings_ = true; // Set to false for bit-string output + bool return_hex_strings_ = true; // Set to false for bit-string output }; //============================================================================ @@ -99,9 +100,7 @@ void ClassicalRegister::initialize(size_t num_memory, size_t num_register) { creg_register_ = std::string(num_register, '0'); } - -void ClassicalRegister::initialize(size_t num_memory, - size_t num_register, +void ClassicalRegister::initialize(size_t num_memory, size_t num_register, const std::string &memory_hex, const std::string ®ister_hex) { // Convert to bit-string for internal storage @@ -109,74 +108,77 @@ void ClassicalRegister::initialize(size_t num_memory, creg_memory_ = std::move(Utils::padleft_inplace(memory_bin, '0', num_memory)); std::string register_bin = Utils::hex2bin(register_hex, false); - creg_register_ = std::move(Utils::padleft_inplace(memory_bin, '0', num_register)); + creg_register_ = + std::move(Utils::padleft_inplace(memory_bin, '0', num_register)); } - -void ClassicalRegister::store_measure(const reg_t &outcome, - const reg_t &memory, +void ClassicalRegister::store_measure(const reg_t &outcome, const reg_t &memory, const reg_t ®isters) { // Assumes memory and registers are either empty or same size as outcome! bool use_mem = !memory.empty(); bool use_reg = !registers.empty(); - for (size_t j=0; j < outcome.size(); j++) { + for (size_t j = 0; j < outcome.size(); j++) { if (use_mem) { // least significant bit first ordering - const size_t pos = creg_memory_.size() - memory[j] - 1; + const size_t pos = creg_memory_.size() - memory[j] - 1; creg_memory_[pos] = std::to_string(outcome[j])[0]; // int->string->char } if (use_reg) { // least significant bit first ordering - const size_t pos = creg_register_.size() - registers[j] - 1; - creg_register_[pos] = std::to_string(outcome[j])[0]; // int->string->char + const size_t pos = creg_register_.size() - registers[j] - 1; + creg_register_[pos] = std::to_string(outcome[j])[0]; // int->string->char } } } - bool ClassicalRegister::check_conditional(const Operations::Op &op) const { // Check if op is conditional if (op.conditional) - return (creg_register_[creg_register_.size() - op.conditional_reg - 1] == '1'); + return (creg_register_[creg_register_.size() - op.conditional_reg - 1] == + '1'); // Op is not conditional return true; } - void ClassicalRegister::apply_bfunc(const Operations::Op &op) { // Check input is boolean function op if (op.type != Operations::OpType::bfunc) { - throw std::invalid_argument("ClassicalRegister::apply_bfunc: Input is not a bfunc op."); + throw std::invalid_argument( + "ClassicalRegister::apply_bfunc: Input is not a bfunc op."); } const std::string &mask = op.string_params[0]; const std::string &target_val = op.string_params[1]; - int_t compared; // if equal this should be 0, if less than -1, if greater than +1 + int_t compared; // if equal this should be 0, if less than -1, if greater than + // +1 // Check if register size fits into a 64-bit integer if (creg_register_.size() <= 64) { - uint_t reg_int = std::stoull(creg_register_, nullptr, 2); // stored as bitstring + uint_t reg_int = + std::stoull(creg_register_, nullptr, 2); // stored as bitstring uint_t mask_int = std::stoull(mask, nullptr, 16); // stored as hexstring - uint_t target_int = std::stoull(target_val, nullptr, 16); // stored as hexstring + uint_t target_int = + std::stoull(target_val, nullptr, 16); // stored as hexstring compared = (reg_int & mask_int) - target_int; } else { - // We need to use big ints so we implement the bit-mask via the binary string - // representation rather than using a big integer class + // We need to use big ints so we implement the bit-mask via the binary + // string representation rather than using a big integer class std::string mask_bin = Utils::hex2bin(mask, false); size_t length = std::min(mask_bin.size(), creg_register_.size()); std::string masked_val = std::string(length, '0'); for (size_t rev_pos = 0; rev_pos < length; rev_pos++) { - masked_val[length - 1 - rev_pos] = (mask_bin[mask_bin.size() - 1 - rev_pos] - & creg_register_[creg_register_.size() - 1 - rev_pos]); + masked_val[length - 1 - rev_pos] = + (mask_bin[mask_bin.size() - 1 - rev_pos] & + creg_register_[creg_register_.size() - 1 - rev_pos]); } // remove leading 0's size_t end_i = masked_val.find('1'); if (end_i == std::string::npos) - masked_val = "0"; + masked_val = "0"; else - masked_val.erase(0, end_i); + masked_val.erase(0, end_i); masked_val = Utils::bin2hex(masked_val); // convert to hex string // Using string comparison to compare to target value @@ -185,51 +187,53 @@ void ClassicalRegister::apply_bfunc(const Operations::Op &op) { // check value of compared integer for different comparison operations bool outcome; switch (op.bfunc) { - case Operations::RegComparison::Equal: - outcome = (compared == 0); - break; - case Operations::RegComparison::NotEqual: - outcome = (compared != 0); - break; - case Operations::RegComparison::Less: - outcome = (compared < 0); - break; - case Operations::RegComparison::LessEqual: - outcome = (compared <= 0); - break; - case Operations::RegComparison::Greater: - outcome = (compared > 0); - break; - case Operations::RegComparison::GreaterEqual: - outcome = (compared >= 0); - break; - default: - // we shouldn't ever get here - throw std::invalid_argument("Invalid boolean function relation."); + case Operations::RegComparison::Equal: + outcome = (compared == 0); + break; + case Operations::RegComparison::NotEqual: + outcome = (compared != 0); + break; + case Operations::RegComparison::Less: + outcome = (compared < 0); + break; + case Operations::RegComparison::LessEqual: + outcome = (compared <= 0); + break; + case Operations::RegComparison::Greater: + outcome = (compared > 0); + break; + case Operations::RegComparison::GreaterEqual: + outcome = (compared >= 0); + break; + default: + // we shouldn't ever get here + throw std::invalid_argument("Invalid boolean function relation."); } // Store outcome in register if (op.registers.size() > 0) { - const size_t pos = creg_register_.size() - op.registers[0] - 1; + const size_t pos = creg_register_.size() - op.registers[0] - 1; creg_register_[pos] = (outcome) ? '1' : '0'; } // Optionally store outcome in memory if (op.memory.size() > 0) { - const size_t pos = creg_memory_.size() - op.memory[0] - 1; + const size_t pos = creg_memory_.size() - op.memory[0] - 1; creg_memory_[pos] = (outcome) ? '1' : '0'; } } // Apply readout error instruction to classical registers -void ClassicalRegister::apply_roerror(const Operations::Op &op, RngEngine &rng) { - +void ClassicalRegister::apply_roerror(const Operations::Op &op, + RngEngine &rng) { + // Check input is readout error op if (op.type != Operations::OpType::roerror) { - throw std::invalid_argument("ClassicalRegister::apply_roerror Input is not a readout error op."); + throw std::invalid_argument( + "ClassicalRegister::apply_roerror Input is not a readout error op."); } - + // Get current classical bit (and optionally register bit) values std::string mem_str; - + // Get values of bits as binary string // We iterate from the end of the list of memory bits for (auto it = op.memory.rbegin(); it < op.memory.rend(); ++it) { @@ -241,12 +245,14 @@ void ClassicalRegister::apply_roerror(const Operations::Op &op, RngEngine &rng) auto noise_str = Utils::int2string(outcome, 2, op.memory.size()); for (size_t pos = 0; pos < op.memory.size(); ++pos) { auto bit = op.memory[pos]; - creg_memory_[creg_memory_.size() - 1 - bit] = noise_str[noise_str.size() - 1 - pos]; + creg_memory_[creg_memory_.size() - 1 - bit] = + noise_str[noise_str.size() - 1 - pos]; } // and the same error to register classical bits if they are used for (size_t pos = 0; pos < op.registers.size(); ++pos) { auto bit = op.registers[pos]; - creg_register_[creg_register_.size() - 1 - bit] = noise_str[noise_str.size() - 1 - pos]; + creg_register_[creg_register_.size() - 1 - bit] = + noise_str[noise_str.size() - 1 - pos]; } } diff --git a/src/framework/json.hpp b/src/framework/json.hpp old mode 100755 new mode 100644 index f6f79113f3..172f4eb1ee --- a/src/framework/json.hpp +++ b/src/framework/json.hpp @@ -29,8 +29,8 @@ DISABLE_WARNING_PUSH #include DISABLE_WARNING_POP -#include "framework/matrix.hpp" #include "framework/linalg/vector.hpp" +#include "framework/matrix.hpp" namespace nl = nlohmann; using json_t = nlohmann::json; @@ -48,7 +48,7 @@ namespace JSON { * @param name: file name to load. * @returns: the loaded json. */ -inline json_t load(const std::string& name); +inline json_t load(const std::string &name); /** * Check if a key exists in a json_t object. @@ -56,7 +56,7 @@ inline json_t load(const std::string& name); * @param js: the json_t to search for key. * @returns: true if the key exists, false otherwise. */ -inline bool check_key(const std::string& key, const json_t &js); +inline bool check_key(const std::string &key, const json_t &js); /** * Check if all keys exists in a json_t object. @@ -64,7 +64,7 @@ inline bool check_key(const std::string& key, const json_t &js); * @param js: the json_t to search for keys. * @returns: true if all keys exists, false otherwise. */ -inline bool check_keys(const std::vector& keys, const json_t &js); +inline bool check_keys(const std::vector &keys, const json_t &js); /** * Load a json_t object value into a variable if the key name exists. @@ -73,9 +73,10 @@ inline bool check_keys(const std::vector& keys, const json_t &js); * @param js: the json_t to search for key. * @returns: true if the keys exists and val was set, false otherwise. */ -template bool get_value(T &var, const std::string& key, const json_t &js); +template +bool get_value(T &var, const std::string &key, const json_t &js); -const json_t& get_value(const std::string& key, const json_t &js); +const json_t &get_value(const std::string &key, const json_t &js); } // end namespace JSON @@ -90,7 +91,8 @@ namespace std { * @param js a json_t object to contain converted type. * @param z a complex number to convert. */ -template void to_json(json_t &js, const std::complex &z); +template +void to_json(json_t &js, const std::complex &z); /** * Convert a JSON value to a complex number z. If the json value is a float @@ -99,7 +101,8 @@ template void to_json(json_t &js, const std::complex &z); * @param js a json_t object to convert. * @param z a complex number to contain result. */ -template void from_json(const json_t &js, std::complex &z); +template +void from_json(const json_t &js, std::complex &z); /** * Convert a complex vector to a json list @@ -150,9 +153,9 @@ void to_json(json_t &js, const std::map &map); * @param js a json_t object to contain converted type. * @param mat a matrix to convert. */ -template +template void from_json(const json_t &js, matrix &mat); -template +template void to_json(json_t &js, const matrix &mat); /******************************************************************************* @@ -165,7 +168,7 @@ void to_json(json_t &js, const matrix &mat); // JSON Helper Functions //------------------------------------------------------------------------------ -json_t JSON::load(const std::string& name) { +json_t JSON::load(const std::string &name) { if (name == "") { json_t js; return js; // Return empty node if no config file @@ -186,7 +189,7 @@ json_t JSON::load(const std::string& name) { return js; } -bool JSON::check_key(const std::string& key, const json_t &js) { +bool JSON::check_key(const std::string &key, const json_t &js) { // returns false if the value is 'null' if (js.find(key) != js.end() && !js[key].is_null()) return true; @@ -194,15 +197,15 @@ bool JSON::check_key(const std::string& key, const json_t &js) { return false; } -bool JSON::check_keys(const std::vector& keys, const json_t &js) { +bool JSON::check_keys(const std::vector &keys, const json_t &js) { bool pass = true; - for (const auto& s : keys) + for (const auto &s : keys) pass &= check_key(s, js); return pass; } template -bool JSON::get_value(T &var, const std::string& key, const json_t &js) { +bool JSON::get_value(T &var, const std::string &key, const json_t &js) { if (check_key(key, js)) { var = js[key].get(); return true; @@ -211,8 +214,8 @@ bool JSON::get_value(T &var, const std::string& key, const json_t &js) { } } -const json_t& JSON::get_value(const std::string& key, const json_t &js){ - return js[key]; +const json_t &JSON::get_value(const std::string &key, const json_t &js) { + return js[key]; } //------------------------------------------------------------------------------ @@ -231,8 +234,7 @@ void std::from_json(const json_t &js, std::complex &z) { else if (js.is_array() && js.size() == 2) { z = std::complex{js[0].get(), js[1].get()}; } else { - throw std::invalid_argument( - std::string("JSON: invalid complex number")); + throw std::invalid_argument(std::string("JSON: invalid complex number")); } } @@ -246,16 +248,15 @@ void std::to_json(json_t &js, const std::vector> &vec) { } template -void std::from_json(const json_t &js, std::vector> &vec) { +void std::from_json(const json_t &js, + std::vector> &vec) { std::vector> ret; if (js.is_array()) { for (auto &elt : js) ret.push_back(elt); vec = ret; - } - else { - throw std::invalid_argument( - std::string("JSON: invalid complex vector.")); + } else { + throw std::invalid_argument(std::string("JSON: invalid complex vector.")); } } @@ -263,7 +264,7 @@ template void std::to_json(json_t &js, const AER::Vector> &vec) { std::vector> out; for (int64_t i = 0; i < vec.size(); ++i) { - auto& z = vec[i]; + auto &z = vec[i]; out.push_back(std::vector{real(z), imag(z)}); } js = out; @@ -294,7 +295,8 @@ void std::to_json(json_t &js, const std::map &map) { // Implementation: JSON Conversion //------------------------------------------------------------------------------ -template void to_json(json_t &js, const matrix &mat) { +template +void to_json(json_t &js, const matrix &mat) { js = json_t(); size_t rows = mat.GetRows(); size_t cols = mat.GetColumns(); @@ -306,15 +308,15 @@ template void to_json(json_t &js, const matrix &mat) { } } - -template void from_json(const json_t &js, matrix &mat) { +template +void from_json(const json_t &js, matrix &mat) { // Check JSON is an array - if(!js.is_array()) { + if (!js.is_array()) { throw std::invalid_argument( std::string("JSON: invalid matrix (not array).")); } // Check JSON isn't empty - if(js.empty()) { + if (js.empty()) { throw std::invalid_argument( std::string("JSON: invalid matrix (empty array).")); } @@ -325,7 +327,7 @@ template void from_json(const json_t &js, matrix &mat) { size_t nrows = js.size(); for (auto &row : js) rows_valid &= (row.is_array() && row.size() == ncols); - if(!rows_valid) { + if (!rows_valid) { throw std::invalid_argument( std::string("JSON: invalid matrix (rows different sizes).")); } diff --git a/src/framework/json_parser.hpp b/src/framework/json_parser.hpp index 882af3efe0..d9576338e8 100644 --- a/src/framework/json_parser.hpp +++ b/src/framework/json_parser.hpp @@ -17,8 +17,7 @@ #include "json.hpp" - -namespace AER{ +namespace AER { // This structure is to avoid overload resolving to the wron function, // as py::objects can always be implicitly converted to json, though // can break at runtime, or even worse trasnform to json and then to c++ @@ -28,61 +27,57 @@ struct Parser {}; template <> struct Parser { - Parser() = delete; + Parser() = delete; - template - static bool get_value(T &var, const std::string& key, const json_t &js){ - return JSON::get_value(var, key, js); - } + template + static bool get_value(T &var, const std::string &key, const json_t &js) { + return JSON::get_value(var, key, js); + } - static bool check_key(const std::string& key, const json_t &js){ - return JSON::check_key(key, js); - } + static bool check_key(const std::string &key, const json_t &js) { + return JSON::check_key(key, js); + } - static const json_t& get_value(const std::string& key, const json_t &js){ - return JSON::get_value(key, js); - } + static const json_t &get_value(const std::string &key, const json_t &js) { + return JSON::get_value(key, js); + } - static bool check_keys(const std::vector& keys, const json_t &js) { - return JSON::check_keys(keys, js); - } + static bool check_keys(const std::vector &keys, + const json_t &js) { + return JSON::check_keys(keys, js); + } - static bool is_array(const json_t &js){ - return js.is_array(); - } + static bool is_array(const json_t &js) { return js.is_array(); } - static bool is_array(const std::string& key, const json_t &js){ - return js[key].is_array(); - } + static bool is_array(const std::string &key, const json_t &js) { + return js[key].is_array(); + } - static const json_t& get_as_list(const json_t& js){ - if(!is_array(js)){ - throw std::runtime_error("Object is not a list!"); - } - return js; + static const json_t &get_as_list(const json_t &js) { + if (!is_array(js)) { + throw std::runtime_error("Object is not a list!"); } + return js; + } - static const json_t& get_list(const std::string& key, const json_t &js){ - if(!is_array(key, js)){ - throw std::runtime_error("Object " + key + "is not a list!"); - } - return JSON::get_value(key, js); + static const json_t &get_list(const std::string &key, const json_t &js) { + if (!is_array(key, js)) { + throw std::runtime_error("Object " + key + "is not a list!"); } + return JSON::get_value(key, js); + } + static bool is_number(const std::string &key, const json_t &js) { + return js[key].is_number(); + } - static bool is_number(const std::string& key, const json_t &js){ - return js[key].is_number(); - } + static std::string dump(const json_t &js) { return js.dump(); } - static std::string dump(const json_t& js){ - return js.dump(); - } - - template - static T get_list_elem(const json_t& js, unsigned int i){ - return js[i]; - } + template + static T get_list_elem(const json_t &js, unsigned int i) { + return js[i]; + } }; -} +} // namespace AER #endif // _aer_framework_json_parser_hpp_ diff --git a/src/framework/linalg/almost_equal.hpp b/src/framework/linalg/almost_equal.hpp old mode 100755 new mode 100644 index 387cd9d3bc..f4a645d455 --- a/src/framework/linalg/almost_equal.hpp +++ b/src/framework/linalg/almost_equal.hpp @@ -29,27 +29,28 @@ namespace Linalg { // If we have numbers closer to 0, then max_diff can be set to a value // way smaller than epsilon. For numbers larger than 1.0, epsilon will // scale (the bigger the number, the bigger the epsilon). -template ::value, T>::type > -bool almost_equal(T f1, T f2, - T max_diff = std::numeric_limits::epsilon(), +template ::value, T>::type> +bool almost_equal(T f1, T f2, T max_diff = std::numeric_limits::epsilon(), T max_relative_diff = std::numeric_limits::epsilon()) { - T diff = std::abs(f1 - f2); - if (diff <= max_diff) return true; + T diff = std::abs(f1 - f2); + if (diff <= max_diff) + return true; - return diff <= max_relative_diff * std::max(std::abs(f1), std::abs(f2)); + return diff <= max_relative_diff * std::max(std::abs(f1), std::abs(f2)); } template -bool almost_equal(const std::complex& f1, const std::complex& f2, +bool almost_equal(const std::complex &f1, const std::complex &f2, T max_diff = std::numeric_limits::epsilon(), T max_relative_diff = std::numeric_limits::epsilon()) { - return almost_equal(f1.real(), f2.real(), max_diff, max_relative_diff) - && almost_equal(f1.imag(), f2.imag(), max_diff, max_relative_diff); + return almost_equal(f1.real(), f2.real(), max_diff, max_relative_diff) && + almost_equal(f1.imag(), f2.imag(), max_diff, max_relative_diff); } //------------------------------------------------------------------------------ -} // namespace Linalg +} // namespace Linalg //------------------------------------------------------------------------------ -} // end namespace AER +} // end namespace AER //------------------------------------------------------------------------------ #endif diff --git a/src/framework/linalg/eigensystem.hpp b/src/framework/linalg/eigensystem.hpp index da0cc10d58..3f7d463b31 100644 --- a/src/framework/linalg/eigensystem.hpp +++ b/src/framework/linalg/eigensystem.hpp @@ -15,66 +15,65 @@ #ifndef _aer_framework_linalg_eigensystem_hpp_ #define _aer_framework_linalg_eigensystem_hpp_ -#include #include "framework/blas_protos.hpp" #include "framework/matrix.hpp" - +#include /** * Returns the eigenvalues and eigenvectors * of a Hermitian matrix. * Uses the blas function ?heevx * @param hermitian_matrix: The Hermitian matrix. - * @param eigenvalues: On output: vector with the eignevalues of the matrix (input is overwritten) - * @param eigenvectors: On output: matrix with the eigenvectors stored as columns. + * @param eigenvalues: On output: vector with the eignevalues of the matrix + * (input is overwritten) + * @param eigenvectors: On output: matrix with the eigenvectors stored as + * columns. * * @returns: void */ template -void eigensystem_hermitian(const matrix>& hermitian_matrix, - /* out */ std::vector& eigenvalues, - /* out */ matrix>& eigenvectors); +void eigensystem_hermitian(const matrix> &hermitian_matrix, + /* out */ std::vector &eigenvalues, + /* out */ matrix> &eigenvectors); - -template +template struct HeevxFuncs; -template<> -struct HeevxFuncs{ +template <> +struct HeevxFuncs { HeevxFuncs() = delete; - static decltype(zheevx_)& heevx; - static decltype(dlamch_)& lamch; + static decltype(zheevx_) &heevx; + static decltype(dlamch_) &lamch; }; -decltype(zheevx_)& HeevxFuncs::heevx = zheevx_; -decltype(dlamch_)& HeevxFuncs::lamch = dlamch_; +decltype(zheevx_) &HeevxFuncs::heevx = zheevx_; +decltype(dlamch_) &HeevxFuncs::lamch = dlamch_; -template<> -struct HeevxFuncs{ +template <> +struct HeevxFuncs { HeevxFuncs() = delete; - static decltype(cheevx_)& heevx; - static decltype(slamch_)& lamch; + static decltype(cheevx_) &heevx; + static decltype(slamch_) &lamch; }; -decltype(cheevx_)& HeevxFuncs::heevx = cheevx_; -decltype(slamch_)& HeevxFuncs::lamch = slamch_; - +decltype(cheevx_) &HeevxFuncs::heevx = cheevx_; +decltype(slamch_) &HeevxFuncs::lamch = slamch_; template -void eigensystem_hermitian(const matrix>& hermitian_matrix, - std::vector& eigenvalues, - matrix>& eigenvectors) { - if ( hermitian_matrix.GetRows() != hermitian_matrix.GetColumns() ) { +void eigensystem_hermitian(const matrix> &hermitian_matrix, + std::vector &eigenvalues, + matrix> &eigenvectors) { + if (hermitian_matrix.GetRows() != hermitian_matrix.GetColumns()) { throw std::runtime_error("Input matrix in eigensystem_hermitian " "function is not a square matrix."); } 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 ldz{n}, lda{n}, lwork{2 * n}; + int il{0}, iu{0}; // not referenced if range='A' T vl{0.0}, vu{0.0}; // not referenced if range='A' char cmach{'S'}; - T abstol{static_cast(2.0*HeevxFuncs::lamch(&cmach))}; + T abstol{static_cast(2.0 * HeevxFuncs::lamch(&cmach))}; int m{0}; // number of eigenvalues found int info{0}; @@ -83,18 +82,20 @@ void eigensystem_hermitian(const matrix>& hermitian_matrix, eigenvalues.resize(n); 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 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, &m, eigenvalues.data(), eigenvectors.data(), &ldz, work.data(), - &lwork, rwork.data(), iwork.data(), ifail.data(), &info); + HeevxFuncs::heevx(&AerBlas::Jobz[0], &AerBlas::Range[0], &AerBlas::UpLo[0], + &n, heevx_copy.data(), &lda, &vl, &vu, &il, &iu, &abstol, + &m, eigenvalues.data(), eigenvectors.data(), &ldz, + work.data(), &lwork, rwork.data(), iwork.data(), + ifail.data(), &info); - if(info){ - throw std::runtime_error("Something went wrong in heevx call within eigensystem_hermitian funcion. " - "Check that input matrix is really hermitian"); + if (info) { + throw std::runtime_error("Something went wrong in heevx call within " + "eigensystem_hermitian funcion. " + "Check that input matrix is really hermitian"); } } diff --git a/src/framework/linalg/linops/linops_aer_vector.hpp b/src/framework/linalg/linops/linops_aer_vector.hpp old mode 100755 new mode 100644 index ba6ebc190f..708d04cfae --- a/src/framework/linalg/linops/linops_aer_vector.hpp +++ b/src/framework/linalg/linops/linops_aer_vector.hpp @@ -31,23 +31,23 @@ namespace Linalg { // Linear operations //---------------------------------------------------------------------------- template > -Vector add(const Vector& lhs, const Vector& rhs) { +Vector add(const Vector &lhs, const Vector &rhs) { return lhs + rhs; } template > -Vector& iadd(Vector& lhs, const Vector& rhs) { +Vector &iadd(Vector &lhs, const Vector &rhs) { lhs += rhs; return lhs; } template > -Vector sub(const Vector& lhs, const Vector& rhs) { +Vector sub(const Vector &lhs, const Vector &rhs) { return lhs - rhs; } template > -Vector& isub(Vector& lhs, const Vector& rhs) { +Vector &isub(Vector &lhs, const Vector &rhs) { lhs -= rhs; return lhs; } @@ -57,30 +57,29 @@ Vector& isub(Vector& lhs, const Vector& rhs) { //---------------------------------------------------------------------------- template , typename = enable_if_numeric_t> -Vector& iadd(Vector& data, const Scalar& val) { +Vector &iadd(Vector &data, const Scalar &val) { const T cast_val(val); std::for_each(data.data(), data.data() + data.size(), - [&cast_val](T& a)->T{ a += cast_val; }); + [&cast_val](T &a) -> T { a += cast_val; }); return data; } template , typename = enable_if_numeric_t> -Vector add(const Vector& data, const Scalar& val) { +Vector add(const Vector &data, const Scalar &val) { auto ret = data; return iadd(data, val); } - template , typename = enable_if_numeric_t> -Vector sub(const Vector& data, const Scalar& val) { +Vector sub(const Vector &data, const Scalar &val) { return add(data, -val); } template , typename = enable_if_numeric_t> -Vector& isub(Vector& data, const Scalar& val) { +Vector &isub(Vector &data, const Scalar &val) { return iadd(data, -val); } @@ -89,7 +88,7 @@ Vector& isub(Vector& data, const Scalar& val) { //---------------------------------------------------------------------------- template , typename = enable_if_numeric_t> -Vector& imul(Vector& data, const Scalar& val) { +Vector &imul(Vector &data, const Scalar &val) { if (almost_equal(val, 1)) { return data; } @@ -99,14 +98,14 @@ Vector& imul(Vector& data, const Scalar& val) { template , typename = enable_if_numeric_t> -Vector mul(const Vector& data, const Scalar& val) { +Vector mul(const Vector &data, const Scalar &val) { auto ret = data; return imul(ret, val); } template , typename = enable_if_numeric_t> -Vector& idiv(Vector& data, const Scalar& val) { +Vector &idiv(Vector &data, const Scalar &val) { if (almost_equal(val, 1)) { return data; } @@ -114,17 +113,16 @@ Vector& idiv(Vector& data, const Scalar& val) { return data; } - template , typename = enable_if_numeric_t> -Vector div(const Vector& data, const Scalar& val) { +Vector div(const Vector &data, const Scalar &val) { auto ret = data; return idiv(ret, val); } //------------------------------------------------------------------------------ -} // end namespace Linalg +} // end namespace Linalg //------------------------------------------------------------------------------ -} // end namespace AER +} // end namespace AER //------------------------------------------------------------------------------ #endif \ No newline at end of file diff --git a/src/framework/linalg/linops/linops_array.hpp b/src/framework/linalg/linops/linops_array.hpp old mode 100755 new mode 100644 index 1211cb7dbe..4c1df3bac0 --- a/src/framework/linalg/linops/linops_array.hpp +++ b/src/framework/linalg/linops/linops_array.hpp @@ -31,27 +31,27 @@ namespace Linalg { // Linear operations //---------------------------------------------------------------------------- template > -std::array& iadd(std::array& lhs, const std::array& rhs) { +std::array &iadd(std::array &lhs, const std::array &rhs) { std::transform(lhs.begin(), lhs.end(), rhs.begin(), lhs.begin(), std::plus()); return lhs; } template > -std::array add(const std::array& lhs, const std::array& rhs) { +std::array add(const std::array &lhs, const std::array &rhs) { std::array result = lhs; return iadd(result, rhs); } template > -std::array& isub(std::array& lhs, const std::array& rhs) { +std::array &isub(std::array &lhs, const std::array &rhs) { std::transform(lhs.begin(), lhs.end(), rhs.begin(), lhs.begin(), std::minus()); return lhs; } template > -std::array sub(const std::array& lhs, const std::array& rhs) { +std::array sub(const std::array &lhs, const std::array &rhs) { std::array result = lhs; return isub(result, rhs); } @@ -61,7 +61,7 @@ std::array sub(const std::array& lhs, const std::array& rhs) { //---------------------------------------------------------------------------- template , typename = enable_if_numeric_t> -std::array& iadd(std::array& data, const Scalar& val) { +std::array &iadd(std::array &data, const Scalar &val) { std::transform(data.begin(), data.end(), data.begin(), std::bind(std::plus(), std::placeholders::_1, val)); return data; @@ -69,14 +69,14 @@ std::array& iadd(std::array& data, const Scalar& val) { template , typename = enable_if_numeric_t> -std::array add(const std::array& data, const Scalar& val) { +std::array add(const std::array &data, const Scalar &val) { std::array result = data; return iadd(result, val); } template , typename = enable_if_numeric_t> -std::array& isub(std::array& data, const Scalar& val) { +std::array &isub(std::array &data, const Scalar &val) { std::transform(data.begin(), data.end(), data.begin(), std::bind(std::minus(), std::placeholders::_1, val)); return data; @@ -84,7 +84,7 @@ std::array& isub(std::array& data, const Scalar& val) { template , typename = enable_if_numeric_t> -std::array sub(const std::array& data, const Scalar& val) { +std::array sub(const std::array &data, const Scalar &val) { std::array result = data; return isub(result, val); } @@ -94,7 +94,7 @@ std::array sub(const std::array& data, const Scalar& val) { //---------------------------------------------------------------------------- template , typename = enable_if_numeric_t> -std::array& imul(std::array& data, const Scalar& val) { +std::array &imul(std::array &data, const Scalar &val) { std::transform(data.begin(), data.end(), data.begin(), std::bind(std::multiplies(), std::placeholders::_1, val)); return data; @@ -102,14 +102,14 @@ std::array& imul(std::array& data, const Scalar& val) { template , typename = enable_if_numeric_t> -std::array mul(const std::array& data, const Scalar& val) { +std::array mul(const std::array &data, const Scalar &val) { std::array result = data; return imul(result, val); } template , typename = enable_if_numeric_t> -std::array& idiv(std::array& data, const Scalar& val) { +std::array &idiv(std::array &data, const Scalar &val) { std::transform(data.begin(), data.end(), data.begin(), std::bind(std::divides(), std::placeholders::_1, val)); return data; @@ -117,14 +117,14 @@ std::array& idiv(std::array& data, const Scalar& val) { template , typename = enable_if_numeric_t> -std::array div(const std::array& data, const Scalar& val) { +std::array div(const std::array &data, const Scalar &val) { std::array result = data; return idiv(result, val); } //------------------------------------------------------------------------------ -} // end namespace Linalg +} // end namespace Linalg //------------------------------------------------------------------------------ -} // end namespace AER +} // end namespace AER //------------------------------------------------------------------------------ #endif \ No newline at end of file diff --git a/src/framework/linalg/linops/linops_generic.hpp b/src/framework/linalg/linops/linops_generic.hpp old mode 100755 new mode 100644 index f85b04e370..11ae56cd04 --- a/src/framework/linalg/linops/linops_generic.hpp +++ b/src/framework/linalg/linops/linops_generic.hpp @@ -30,23 +30,23 @@ namespace Linalg { // Linear operations //---------------------------------------------------------------------------- template -T add(const T& lhs, const T& rhs) { +T add(const T &lhs, const T &rhs) { return std::plus()(lhs, rhs); } template -T& iadd(T& lhs, const T& rhs) { +T &iadd(T &lhs, const T &rhs) { lhs = std::plus()(lhs, rhs); return lhs; } template -T sub(const T& lhs, const T& rhs) { +T sub(const T &lhs, const T &rhs) { return std::minus()(lhs, rhs); } template -T& isub(T& lhs, const T& rhs) { +T &isub(T &lhs, const T &rhs) { lhs = std::minus()(lhs, rhs); return lhs; } @@ -55,23 +55,23 @@ T& isub(T& lhs, const T& rhs) { // Affine operations //---------------------------------------------------------------------------- template > -T add(const T& data, const Scalar& val) { +T add(const T &data, const Scalar &val) { return std::plus()(data, val); } template > -T& iadd(T& data, const Scalar& val) { +T &iadd(T &data, const Scalar &val) { data = std::plus()(data, val); return data; } template > -T sub(const T& data, const Scalar& val) { +T sub(const T &data, const Scalar &val) { return std::minus()(data, val); } template > -T& isub(T& data, const Scalar& val) { +T &isub(T &data, const Scalar &val) { data = std::minus()(data, val); return data; } @@ -80,7 +80,7 @@ T& isub(T& data, const Scalar& val) { // Scalar operations //---------------------------------------------------------------------------- template > -T mul(const T& data, const Scalar& val) { +T mul(const T &data, const Scalar &val) { if (almost_equal(val, 1)) { return data; } @@ -88,7 +88,7 @@ T mul(const T& data, const Scalar& val) { } template > -T& imul(T& data, const Scalar& val) { +T &imul(T &data, const Scalar &val) { if (!almost_equal(val, 1)) { data = std::multiplies()(data, val); } @@ -96,7 +96,7 @@ T& imul(T& data, const Scalar& val) { } template > -T div(const T& data, const Scalar& val) { +T div(const T &data, const Scalar &val) { if (almost_equal(val, 1)) { return data; } @@ -104,7 +104,7 @@ T div(const T& data, const Scalar& val) { } template > -T& idiv(T& data, const Scalar& val) { +T &idiv(T &data, const Scalar &val) { if (!almost_equal(val, 1)) { data = std::divides()(data, val); } @@ -112,8 +112,8 @@ T& idiv(T& data, const Scalar& val) { } //------------------------------------------------------------------------------ -} // end namespace Linalg +} // end namespace Linalg //------------------------------------------------------------------------------ -} // end namespace AER +} // end namespace AER //------------------------------------------------------------------------------ #endif \ No newline at end of file diff --git a/src/framework/linalg/linops/linops_json.hpp b/src/framework/linalg/linops/linops_json.hpp old mode 100755 new mode 100644 index 8473bfbb82..1d8adb3a6b --- a/src/framework/linalg/linops/linops_json.hpp +++ b/src/framework/linalg/linops/linops_json.hpp @@ -28,7 +28,7 @@ namespace Linalg { //---------------------------------------------------------------------------- // Linear operations //---------------------------------------------------------------------------- -inline json_t& iadd(json_t& lhs, const json_t& rhs) { +inline json_t &iadd(json_t &lhs, const json_t &rhs) { // Null case if (lhs.is_null()) { lhs = rhs; @@ -57,12 +57,12 @@ inline json_t& iadd(json_t& lhs, const json_t& rhs) { return lhs; } -inline json_t add(const json_t& lhs, const json_t& rhs) { +inline json_t add(const json_t &lhs, const json_t &rhs) { json_t result = lhs; return iadd(result, rhs); } -inline json_t& isub(json_t& lhs, const json_t& rhs) { +inline json_t &isub(json_t &lhs, const json_t &rhs) { // Null case if (rhs.is_null()) { return lhs; @@ -88,7 +88,7 @@ inline json_t& isub(json_t& lhs, const json_t& rhs) { } template -json_t sub(const T& lhs, const json_t& rhs) { +json_t sub(const T &lhs, const json_t &rhs) { json_t result = lhs; return isub(result, rhs); } @@ -97,7 +97,7 @@ json_t sub(const T& lhs, const json_t& rhs) { // Affine operations //---------------------------------------------------------------------------- template > -json_t& iadd(json_t& data, const Scalar& val) { +json_t &iadd(json_t &data, const Scalar &val) { // Null case if (val == 0) { return data; @@ -123,13 +123,13 @@ json_t& iadd(json_t& data, const Scalar& val) { } template > -json_t add(const json_t& data, const Scalar& val) { +json_t add(const json_t &data, const Scalar &val) { json_t result = data; return iadd(result, val); } template > -json_t& isub(json_t& data, const Scalar& val) { +json_t &isub(json_t &data, const Scalar &val) { // Null case if (val == 0) { return data; @@ -156,7 +156,7 @@ json_t& isub(json_t& data, const Scalar& val) { } template > -json_t sub(const json_t& data, const Scalar& val) { +json_t sub(const json_t &data, const Scalar &val) { json_t result = data; return isub(result, val); } @@ -166,7 +166,7 @@ json_t sub(const json_t& data, const Scalar& val) { //---------------------------------------------------------------------------- template > -json_t& imul(json_t& data, const Scalar& val) { +json_t &imul(json_t &data, const Scalar &val) { // Trival case if (almost_equal(val, 1)) { return data; @@ -194,14 +194,14 @@ json_t& imul(json_t& data, const Scalar& val) { } template > -json_t mul(const json_t& data, const Scalar& val) { +json_t mul(const json_t &data, const Scalar &val) { // Null case json_t result = data; return imul(result, val); } template > -json_t& idiv(json_t& data, const Scalar& val) { +json_t &idiv(json_t &data, const Scalar &val) { // Trival case if (almost_equal(val, 1)) { return data; @@ -228,15 +228,15 @@ json_t& idiv(json_t& data, const Scalar& val) { } template > -json_t div(const json_t& data, const Scalar& val) { +json_t div(const json_t &data, const Scalar &val) { // Null case json_t result = data; return idiv(result, val); } //------------------------------------------------------------------------------ -} // end namespace Linalg +} // end namespace Linalg //------------------------------------------------------------------------------ -} // end namespace AER +} // end namespace AER //------------------------------------------------------------------------------ #endif \ No newline at end of file diff --git a/src/framework/linalg/linops/linops_map.hpp b/src/framework/linalg/linops/linops_map.hpp old mode 100755 new mode 100644 index f42cb80c6c..f69c8a675d --- a/src/framework/linalg/linops/linops_map.hpp +++ b/src/framework/linalg/linops/linops_map.hpp @@ -15,10 +15,10 @@ #ifndef _aer_framework_linalg_linops_map_hpp_ #define _aer_framework_linalg_linops_map_hpp_ -#include -#include #include "framework/linalg/almost_equal.hpp" #include "framework/linalg/enable_if_numeric.hpp" +#include +#include namespace AER { namespace Linalg { @@ -31,8 +31,8 @@ namespace Linalg { //---------------------------------------------------------------------------- template > -std::map add(const std::map& lhs, - const std::map& rhs) { +std::map add(const std::map &lhs, + const std::map &rhs) { std::map result = lhs; for (const auto &pair : rhs) { result[pair.first] = std::plus()(result[pair.first], pair.second); @@ -42,8 +42,8 @@ std::map add(const std::map& lhs, template > -std::map& iadd(std::map& lhs, - const std::map& rhs) { +std::map &iadd(std::map &lhs, + const std::map &rhs) { for (const auto &pair : rhs) { lhs[pair.first] = std::plus()(lhs[pair.first], pair.second); } @@ -52,8 +52,8 @@ std::map& iadd(std::map& lhs, template > -std::map sub(const std::map& lhs, - const std::map& rhs) { +std::map sub(const std::map &lhs, + const std::map &rhs) { std::map result = lhs; for (const auto &pair : rhs) { result[pair.first] = std::minus()(result[pair.first], pair.second); @@ -63,8 +63,8 @@ std::map sub(const std::map& lhs, template > -std::map& isub(std::map& lhs, - const std::map& rhs) { +std::map &isub(std::map &lhs, + const std::map &rhs) { for (const auto &pair : rhs) { lhs[pair.first] = std::minus()(lhs[pair.first], pair.second); } @@ -77,8 +77,8 @@ std::map& isub(std::map& lhs, template , typename = enable_if_numeric_t> -std::map add(const std::map& data, - const Scalar& val) { +std::map add(const std::map &data, + const Scalar &val) { std::map result; for (const auto &pair : data) { result[pair.first] = std::plus()(pair.second, val); @@ -89,8 +89,8 @@ std::map add(const std::map& data, template , typename = enable_if_numeric_t> -std::map& iadd(std::map& data, - const Scalar& val) { +std::map &iadd(std::map &data, + const Scalar &val) { for (const auto &pair : data) { data[pair.first] = std::plus()(data[pair.first], val); } @@ -100,8 +100,8 @@ std::map& iadd(std::map& data, template , typename = enable_if_numeric_t> -std::map sub(const std::map& data, - const Scalar& val) { +std::map sub(const std::map &data, + const Scalar &val) { std::map result; for (const auto &pair : data) { result[pair.first] = std::minus()(pair.second, val); @@ -112,8 +112,8 @@ std::map sub(const std::map& data, template , typename = enable_if_numeric_t> -std::map& isub(std::map& data, - const Scalar& val) { +std::map &isub(std::map &data, + const Scalar &val) { for (const auto &pair : data) { data[pair.first] = std::plus()(data[pair.first], val); } @@ -127,8 +127,8 @@ std::map& isub(std::map& data, template , typename = enable_if_numeric_t> -std::map mul(const std::map& data, - const Scalar& val) { +std::map mul(const std::map &data, + const Scalar &val) { if (almost_equal(val, 1)) { return data; } @@ -142,8 +142,8 @@ std::map mul(const std::map& data, template , typename = enable_if_numeric_t> -std::map& imul(std::map& data, - const Scalar& val) { +std::map &imul(std::map &data, + const Scalar &val) { if (almost_equal(val, 1)) { return data; } @@ -156,8 +156,8 @@ std::map& imul(std::map& data, template , typename = enable_if_numeric_t> -std::map div(const std::map& data, - const Scalar& val) { +std::map div(const std::map &data, + const Scalar &val) { if (almost_equal(val, 1)) { return data; } @@ -171,8 +171,8 @@ std::map div(const std::map& data, template , typename = enable_if_numeric_t> -std::map& idiv(std::map& data, - const Scalar& val) { +std::map &idiv(std::map &data, + const Scalar &val) { if (almost_equal(val, 1)) { return data; } @@ -183,8 +183,8 @@ std::map& idiv(std::map& data, } //------------------------------------------------------------------------------ -} // end namespace Linalg +} // end namespace Linalg //------------------------------------------------------------------------------ -} // end namespace AER +} // end namespace AER //------------------------------------------------------------------------------ #endif \ No newline at end of file diff --git a/src/framework/linalg/linops/linops_matrix.hpp b/src/framework/linalg/linops/linops_matrix.hpp old mode 100755 new mode 100644 index 4b510389c3..7fdac60fd7 --- a/src/framework/linalg/linops/linops_matrix.hpp +++ b/src/framework/linalg/linops/linops_matrix.hpp @@ -31,23 +31,23 @@ namespace Linalg { // Linear operations //---------------------------------------------------------------------------- template > -matrix add(const matrix& lhs, const matrix& rhs) { +matrix add(const matrix &lhs, const matrix &rhs) { return lhs + rhs; } template > -matrix& iadd(matrix& lhs, const matrix& rhs) { +matrix &iadd(matrix &lhs, const matrix &rhs) { lhs = lhs + rhs; return lhs; } template > -matrix sub(const matrix& lhs, const matrix& rhs) { +matrix sub(const matrix &lhs, const matrix &rhs) { return lhs - rhs; } template > -matrix& isub(matrix& lhs, const matrix& rhs) { +matrix &isub(matrix &lhs, const matrix &rhs) { lhs = lhs - rhs; return lhs; } @@ -57,7 +57,7 @@ matrix& isub(matrix& lhs, const matrix& rhs) { //---------------------------------------------------------------------------- template , typename = enable_if_numeric_t> -matrix& iadd(matrix& data, const Scalar& val) { +matrix &iadd(matrix &data, const Scalar &val) { if (val == 0) { return data; } @@ -69,20 +69,20 @@ matrix& iadd(matrix& data, const Scalar& val) { template , typename = enable_if_numeric_t> -matrix add(const matrix& data, const Scalar& val) { +matrix add(const matrix &data, const Scalar &val) { matrix result(data); return iadd(result, val); } template , typename = enable_if_numeric_t> -matrix sub(const matrix& data, const Scalar& val) { +matrix sub(const matrix &data, const Scalar &val) { return add(data, -val); } template , typename = enable_if_numeric_t> -matrix& isub(matrix& data, const Scalar& val) { +matrix &isub(matrix &data, const Scalar &val) { return iadd(data, -val); } @@ -92,7 +92,7 @@ matrix& isub(matrix& data, const Scalar& val) { template , typename = enable_if_numeric_t> -matrix& imul(matrix& data, const Scalar& val) { +matrix &imul(matrix &data, const Scalar &val) { if (almost_equal(val, 1)) { return data; } @@ -104,7 +104,7 @@ matrix& imul(matrix& data, const Scalar& val) { template , typename = enable_if_numeric_t> -matrix mul(const matrix& data, const Scalar& val) { +matrix mul(const matrix &data, const Scalar &val) { if (almost_equal(val, 1)) { return data; } @@ -115,7 +115,7 @@ matrix mul(const matrix& data, const Scalar& val) { template , typename = enable_if_numeric_t> -matrix& idiv(matrix& data, const Scalar& val) { +matrix &idiv(matrix &data, const Scalar &val) { if (almost_equal(val, 1)) { return data; } @@ -127,7 +127,7 @@ matrix& idiv(matrix& data, const Scalar& val) { template , typename = enable_if_numeric_t> -matrix div(const matrix& data, const Scalar& val) { +matrix div(const matrix &data, const Scalar &val) { if (almost_equal(val, 1)) { return data; } @@ -137,8 +137,8 @@ matrix div(const matrix& data, const Scalar& val) { } //------------------------------------------------------------------------------ -} // end namespace Linalg +} // end namespace Linalg //------------------------------------------------------------------------------ -} // end namespace AER +} // end namespace AER //------------------------------------------------------------------------------ #endif \ No newline at end of file diff --git a/src/framework/linalg/linops/linops_unordered_map.hpp b/src/framework/linalg/linops/linops_unordered_map.hpp old mode 100755 new mode 100644 index 7df754b5de..2245172f0c --- a/src/framework/linalg/linops/linops_unordered_map.hpp +++ b/src/framework/linalg/linops/linops_unordered_map.hpp @@ -31,9 +31,9 @@ namespace Linalg { //---------------------------------------------------------------------------- template > -std::unordered_map add( - const std::unordered_map& lhs, - const std::unordered_map& rhs) { +std::unordered_map +add(const std::unordered_map &lhs, + const std::unordered_map &rhs) { std::unordered_map result = lhs; for (const auto &pair : rhs) { result[pair.first] = std::plus()(result[pair.first], pair.second); @@ -43,9 +43,9 @@ std::unordered_map add( template > -std::unordered_map& iadd( - std::unordered_map& lhs, - const std::unordered_map& rhs) { +std::unordered_map & +iadd(std::unordered_map &lhs, + const std::unordered_map &rhs) { for (const auto &pair : rhs) { lhs[pair.first] = std::plus()(lhs[pair.first], pair.second); } @@ -54,9 +54,9 @@ std::unordered_map& iadd( template > -std::unordered_map sub( - const std::unordered_map& lhs, - const std::unordered_map& rhs) { +std::unordered_map +sub(const std::unordered_map &lhs, + const std::unordered_map &rhs) { std::unordered_map result = lhs; for (const auto &pair : rhs) { result[pair.first] = std::minus()(result[pair.first], pair.second); @@ -66,9 +66,9 @@ std::unordered_map sub( template > -std::unordered_map& isub( - std::unordered_map& lhs, - const std::unordered_map& rhs) { +std::unordered_map & +isub(std::unordered_map &lhs, + const std::unordered_map &rhs) { for (const auto &pair : rhs) { lhs[pair.first] = std::minus()(lhs[pair.first], pair.second); } @@ -81,8 +81,8 @@ std::unordered_map& isub( template , typename = enable_if_numeric_t> -std::unordered_map add( - const std::unordered_map& data, const Scalar& val) { +std::unordered_map +add(const std::unordered_map &data, const Scalar &val) { std::unordered_map result; for (const auto &pair : data) { result[pair.first] = std::plus()(pair.second, val); @@ -93,8 +93,8 @@ std::unordered_map add( template , typename = enable_if_numeric_t> -std::unordered_map& iadd( - std::unordered_map& data, const Scalar& val) { +std::unordered_map & +iadd(std::unordered_map &data, const Scalar &val) { for (const auto &pair : data) { data[pair.first] = std::plus()(data[pair.first], val); } @@ -104,8 +104,8 @@ std::unordered_map& iadd( template , typename = enable_if_numeric_t> -std::unordered_map sub( - const std::unordered_map& data, const Scalar& val) { +std::unordered_map +sub(const std::unordered_map &data, const Scalar &val) { std::unordered_map result; for (const auto &pair : data) { result[pair.first] = std::minus()(pair.second, val); @@ -116,8 +116,8 @@ std::unordered_map sub( template , typename = enable_if_numeric_t> -std::unordered_map& isub( - std::unordered_map& data, const Scalar& val) { +std::unordered_map & +isub(std::unordered_map &data, const Scalar &val) { for (const auto &pair : data) { data[pair.first] = std::plus()(data[pair.first], val); } @@ -131,8 +131,8 @@ std::unordered_map& isub( template , typename = enable_if_numeric_t> -std::unordered_map mul( - const std::unordered_map& data, const Scalar& val) { +std::unordered_map +mul(const std::unordered_map &data, const Scalar &val) { if (almost_equal(val, 1)) { return data; } @@ -146,8 +146,8 @@ std::unordered_map mul( template , typename = enable_if_numeric_t> -std::unordered_map& imul( - std::unordered_map& data, const Scalar& val) { +std::unordered_map & +imul(std::unordered_map &data, const Scalar &val) { if (almost_equal(val, 1)) { return data; } @@ -160,8 +160,8 @@ std::unordered_map& imul( template , typename = enable_if_numeric_t> -std::unordered_map div( - const std::unordered_map& data, const Scalar& val) { +std::unordered_map +div(const std::unordered_map &data, const Scalar &val) { if (almost_equal(val, 1)) { return data; } @@ -175,8 +175,8 @@ std::unordered_map div( template , typename = enable_if_numeric_t> -std::unordered_map& idiv( - std::unordered_map& data, const Scalar& val) { +std::unordered_map & +idiv(std::unordered_map &data, const Scalar &val) { if (almost_equal(val, 1)) { return data; } @@ -187,8 +187,8 @@ std::unordered_map& idiv( } //------------------------------------------------------------------------------ -} // end namespace Linalg +} // end namespace Linalg //------------------------------------------------------------------------------ -} // end namespace AER +} // end namespace AER //------------------------------------------------------------------------------ #endif \ No newline at end of file diff --git a/src/framework/linalg/linops/linops_vector.hpp b/src/framework/linalg/linops/linops_vector.hpp old mode 100755 new mode 100644 index 759442d9f4..c1b86d79d8 --- a/src/framework/linalg/linops/linops_vector.hpp +++ b/src/framework/linalg/linops/linops_vector.hpp @@ -31,7 +31,7 @@ namespace Linalg { // Linear operations //---------------------------------------------------------------------------- template > -std::vector add(const std::vector& lhs, const std::vector& rhs) { +std::vector add(const std::vector &lhs, const std::vector &rhs) { if (lhs.size() != rhs.size()) { throw std::runtime_error("Cannot add two vectors of different sizes."); } @@ -43,7 +43,7 @@ std::vector add(const std::vector& lhs, const std::vector& rhs) { } template > -std::vector& iadd(std::vector& lhs, const std::vector& rhs) { +std::vector &iadd(std::vector &lhs, const std::vector &rhs) { if (lhs.size() != rhs.size()) { throw std::runtime_error("Cannot add two vectors of different sizes."); } @@ -53,7 +53,7 @@ std::vector& iadd(std::vector& lhs, const std::vector& rhs) { } template > -std::vector sub(const std::vector& lhs, const std::vector& rhs) { +std::vector sub(const std::vector &lhs, const std::vector &rhs) { if (lhs.size() != rhs.size()) { throw std::runtime_error("Cannot add two vectors of different sizes."); } @@ -65,7 +65,7 @@ std::vector sub(const std::vector& lhs, const std::vector& rhs) { } template > -std::vector& isub(std::vector& lhs, const std::vector& rhs) { +std::vector &isub(std::vector &lhs, const std::vector &rhs) { if (lhs.size() != rhs.size()) { throw std::runtime_error("Cannot add two vectors of different sizes."); } @@ -79,7 +79,7 @@ std::vector& isub(std::vector& lhs, const std::vector& rhs) { //---------------------------------------------------------------------------- template , typename = enable_if_numeric_t> -std::vector add(const std::vector& data, const Scalar& val) { +std::vector add(const std::vector &data, const Scalar &val) { std::vector result; result.reserve(data.size()); std::transform(data.begin(), data.end(), std::back_inserter(result), @@ -89,7 +89,7 @@ std::vector add(const std::vector& data, const Scalar& val) { template , typename = enable_if_numeric_t> -std::vector& iadd(std::vector& data, const Scalar& val) { +std::vector &iadd(std::vector &data, const Scalar &val) { std::transform(data.begin(), data.end(), data.begin(), std::bind(std::plus(), std::placeholders::_1, val)); return data; @@ -97,7 +97,7 @@ std::vector& iadd(std::vector& data, const Scalar& val) { template , typename = enable_if_numeric_t> -std::vector sub(const std::vector& data, const Scalar& val) { +std::vector sub(const std::vector &data, const Scalar &val) { std::vector result; result.reserve(data.size()); std::transform(data.begin(), data.end(), std::back_inserter(result), @@ -107,7 +107,7 @@ std::vector sub(const std::vector& data, const Scalar& val) { template , typename = enable_if_numeric_t> -std::vector& isub(std::vector& data, const Scalar& val) { +std::vector &isub(std::vector &data, const Scalar &val) { std::transform(data.begin(), data.end(), data.begin(), std::bind(std::minus(), std::placeholders::_1, val)); return data; @@ -118,7 +118,7 @@ std::vector& isub(std::vector& data, const Scalar& val) { //---------------------------------------------------------------------------- template , typename = enable_if_numeric_t> -std::vector mul(const std::vector& data, const Scalar& val) { +std::vector mul(const std::vector &data, const Scalar &val) { if (almost_equal(val, 1)) { return data; } @@ -131,7 +131,7 @@ std::vector mul(const std::vector& data, const Scalar& val) { template , typename = enable_if_numeric_t> -std::vector& imul(std::vector& data, const Scalar& val) { +std::vector &imul(std::vector &data, const Scalar &val) { if (almost_equal(val, 1)) { return data; } @@ -142,7 +142,7 @@ std::vector& imul(std::vector& data, const Scalar& val) { template , typename = enable_if_numeric_t> -std::vector div(const std::vector& data, const Scalar& val) { +std::vector div(const std::vector &data, const Scalar &val) { if (almost_equal(val, 1)) { return data; } @@ -155,7 +155,7 @@ std::vector div(const std::vector& data, const Scalar& val) { template , typename = enable_if_numeric_t> -std::vector& idiv(std::vector& data, const Scalar& val) { +std::vector &idiv(std::vector &data, const Scalar &val) { if (almost_equal(val, 1)) { return data; } @@ -165,8 +165,8 @@ std::vector& idiv(std::vector& data, const Scalar& val) { } //------------------------------------------------------------------------------ -} // end namespace Linalg +} // end namespace Linalg //------------------------------------------------------------------------------ -} // end namespace AER +} // end namespace AER //------------------------------------------------------------------------------ #endif \ No newline at end of file diff --git a/src/framework/linalg/matrix_utils.hpp b/src/framework/linalg/matrix_utils.hpp old mode 100755 new mode 100644 index bd6903dde4..d557abd898 --- a/src/framework/linalg/matrix_utils.hpp +++ b/src/framework/linalg/matrix_utils.hpp @@ -16,7 +16,7 @@ #define _aer_framework_linalg_matrix_utils_hpp_ #include "framework/linalg/matrix_utils/matrix_defs.hpp" -#include "framework/linalg/matrix_utils/vmatrix_defs.hpp" #include "framework/linalg/matrix_utils/smatrix_defs.hpp" +#include "framework/linalg/matrix_utils/vmatrix_defs.hpp" #endif \ No newline at end of file diff --git a/src/framework/linalg/matrix_utils/matrix_defs.hpp b/src/framework/linalg/matrix_utils/matrix_defs.hpp old mode 100755 new mode 100644 index 9e82e9dd4d..db67b95163 --- a/src/framework/linalg/matrix_utils/matrix_defs.hpp +++ b/src/framework/linalg/matrix_utils/matrix_defs.hpp @@ -33,18 +33,18 @@ namespace Linalg { class Matrix { public: // Single-qubit gates - const static cmatrix_t I; // name: "id" - const static cmatrix_t X; // name: "x" - const static cmatrix_t Y; // name: "y" - const static cmatrix_t Z; // name: "z" - const static cmatrix_t H; // name: "h" - const static cmatrix_t S; // name: "s" - const static cmatrix_t SDG; // name: "sdg" - const static cmatrix_t T; // name: "t" - const static cmatrix_t TDG; // name: "tdg" - const static cmatrix_t SX; // name: "sx" - const static cmatrix_t SXDG;// name: "sxdg" - const static cmatrix_t X90; // name: "x90" + const static cmatrix_t I; // name: "id" + const static cmatrix_t X; // name: "x" + const static cmatrix_t Y; // name: "y" + const static cmatrix_t Z; // name: "z" + const static cmatrix_t H; // name: "h" + const static cmatrix_t S; // name: "s" + const static cmatrix_t SDG; // name: "sdg" + const static cmatrix_t T; // name: "t" + const static cmatrix_t TDG; // name: "tdg" + const static cmatrix_t SX; // name: "sx" + const static cmatrix_t SXDG; // name: "sxdg" + const static cmatrix_t X90; // name: "x90" // Two-qubit gates const static cmatrix_t CX; // name: "cx" @@ -92,8 +92,10 @@ class Matrix { static cmatrix_t u3(complex_t theta, complex_t phi, complex_t lam) { return u3(std::real(theta), std::real(phi), std::real(lam)); }; - static cmatrix_t u4(complex_t theta, complex_t phi, complex_t lam, complex_t gamma) { - return u4(std::real(theta), std::real(phi), std::real(lam), std::real(gamma)); + static cmatrix_t u4(complex_t theta, complex_t phi, complex_t lam, + complex_t gamma) { + return u4(std::real(theta), std::real(phi), std::real(lam), + std::real(gamma)); }; static cmatrix_t r(complex_t theta, complex_t phi) { return r(std::real(theta), std::real(phi)); @@ -106,11 +108,17 @@ class Matrix { static cmatrix_t rzz(complex_t theta) { return rzz(std::real(theta)); } static cmatrix_t rzx(complex_t theta) { return rzx(std::real(theta)); } static cmatrix_t phase(complex_t theta) { return phase(std::real(theta)); } - static cmatrix_t phase_diag(complex_t theta) { return phase_diag(std::real(theta)); } + static cmatrix_t phase_diag(complex_t theta) { + return phase_diag(std::real(theta)); + } static cmatrix_t cphase(complex_t theta) { return cphase(std::real(theta)); } - static cmatrix_t cphase_diag(complex_t theta) { return cphase_diag(std::real(theta)); } - static cmatrix_t cu(complex_t theta, complex_t phi, complex_t lam, complex_t gamma) { - return cu(std::real(theta), std::real(phi), std::real(lam), std::real(gamma)); + static cmatrix_t cphase_diag(complex_t theta) { + return cphase_diag(std::real(theta)); + } + static cmatrix_t cu(complex_t theta, complex_t phi, complex_t lam, + complex_t gamma) { + return cu(std::real(theta), std::real(phi), std::real(lam), + std::real(gamma)); } // Return the matrix for a named matrix string @@ -183,7 +191,7 @@ const cmatrix_t Matrix::CY = {{0, 0}, {0, 0}, {0, 0}, {0, -1}}, {{0, 0}, {0, 0}, {1, 0}, {0, 0}}, {{0, 0}, {0, 1}, {0, 0}, {0, 0}}}); - + const cmatrix_t Matrix::CZ = Utils::make_matrix({{{1, 0}, {0, 0}, {0, 0}, {0, 0}}, {{0, 0}, {1, 0}, {0, 0}, {0, 0}}, @@ -196,20 +204,20 @@ const cmatrix_t Matrix::SWAP = {{0, 0}, {1, 0}, {0, 0}, {0, 0}}, {{0, 0}, {0, 0}, {0, 0}, {1, 0}}}); -const cmatrix_t Matrix::ECR = - Utils::make_matrix({{{0, 0}, {1. / std::sqrt(2.), 0}, {0, 0}, {0, 1. / std::sqrt(2.)}}, - {{1. / std::sqrt(2.), 0}, {0, 0}, {0, -1. / std::sqrt(2.)}, {0, 0}}, - {{0, 0}, {0, 1. / std::sqrt(2.)}, {0, 0}, {1. / std::sqrt(2.), 0}}, - {{0, -1. / std::sqrt(2.)}, {0, 0}, {1. / std::sqrt(2.), 0}, {0, 0}}}); +const cmatrix_t Matrix::ECR = Utils::make_matrix( + {{{0, 0}, {1. / std::sqrt(2.), 0}, {0, 0}, {0, 1. / std::sqrt(2.)}}, + {{1. / std::sqrt(2.), 0}, {0, 0}, {0, -1. / std::sqrt(2.)}, {0, 0}}, + {{0, 0}, {0, 1. / std::sqrt(2.)}, {0, 0}, {1. / std::sqrt(2.), 0}}, + {{0, -1. / std::sqrt(2.)}, {0, 0}, {1. / std::sqrt(2.), 0}, {0, 0}}}); // Lookup table const stringmap_t Matrix::label_map_ = { - {"id", &Matrix::I}, {"x", &Matrix::X}, {"y", &Matrix::Y}, - {"z", &Matrix::Z}, {"h", &Matrix::H}, {"s", &Matrix::S}, - {"sdg", &Matrix::SDG}, {"t", &Matrix::T}, {"tdg", &Matrix::TDG}, - {"x90", &Matrix::X90}, {"cx", &Matrix::CX}, {"cy", &Matrix::CY}, - {"cz", &Matrix::CZ}, {"swap", &Matrix::SWAP}, {"sx", &Matrix::SX}, - {"sxdg", &Matrix::SXDG}, {"delay", &Matrix::I}, {"ecr", &Matrix::ECR}}; + {"id", &Matrix::I}, {"x", &Matrix::X}, {"y", &Matrix::Y}, + {"z", &Matrix::Z}, {"h", &Matrix::H}, {"s", &Matrix::S}, + {"sdg", &Matrix::SDG}, {"t", &Matrix::T}, {"tdg", &Matrix::TDG}, + {"x90", &Matrix::X90}, {"cx", &Matrix::CX}, {"cy", &Matrix::CY}, + {"cz", &Matrix::CZ}, {"swap", &Matrix::SWAP}, {"sx", &Matrix::SX}, + {"sxdg", &Matrix::SXDG}, {"delay", &Matrix::I}, {"ecr", &Matrix::ECR}}; cmatrix_t Matrix::identity(size_t dim) { cmatrix_t mat(dim, dim); @@ -218,9 +226,7 @@ cmatrix_t Matrix::identity(size_t dim) { return mat; } -cmatrix_t Matrix::u1(double lambda) { - return phase(lambda); -} +cmatrix_t Matrix::u1(double lambda) { return phase(lambda); } cmatrix_t Matrix::u2(double phi, double lambda) { cmatrix_t mat(2, 2); diff --git a/src/framework/linalg/matrix_utils/smatrix_defs.hpp b/src/framework/linalg/matrix_utils/smatrix_defs.hpp old mode 100755 new mode 100644 index 83598fe21d..0ecaf1bde3 --- a/src/framework/linalg/matrix_utils/smatrix_defs.hpp +++ b/src/framework/linalg/matrix_utils/smatrix_defs.hpp @@ -34,18 +34,18 @@ namespace Linalg { class SMatrix { public: // Single-qubit gates - const static cmatrix_t I; // name: "id" - const static cmatrix_t X; // name: "x" - const static cmatrix_t Y; // name: "y" - const static cmatrix_t Z; // name: "z" - const static cmatrix_t H; // name: "h" - const static cmatrix_t S; // name: "s" - const static cmatrix_t SDG; // name: "sdg" - const static cmatrix_t T; // name: "t" - const static cmatrix_t TDG; // name: "tdg" - const static cmatrix_t SX; // name: "sx" - const static cmatrix_t SXDG;// name: "sxdg" - const static cmatrix_t X90; // name: "x90" + const static cmatrix_t I; // name: "id" + const static cmatrix_t X; // name: "x" + const static cmatrix_t Y; // name: "y" + const static cmatrix_t Z; // name: "z" + const static cmatrix_t H; // name: "h" + const static cmatrix_t S; // name: "s" + const static cmatrix_t SDG; // name: "sdg" + const static cmatrix_t T; // name: "t" + const static cmatrix_t TDG; // name: "tdg" + const static cmatrix_t SX; // name: "sx" + const static cmatrix_t SXDG; // name: "sxdg" + const static cmatrix_t X90; // name: "x90" // Two-qubit gates const static cmatrix_t CX; // name: "cx" @@ -93,8 +93,10 @@ class SMatrix { static cmatrix_t u3(complex_t theta, complex_t phi, complex_t lam) { return u3(std::real(theta), std::real(phi), std::real(lam)); }; - static cmatrix_t u4(complex_t theta, complex_t phi, complex_t lam, complex_t gamma) { - return u4(std::real(theta), std::real(phi), std::real(lam), std::real(gamma)); + static cmatrix_t u4(complex_t theta, complex_t phi, complex_t lam, + complex_t gamma) { + return u4(std::real(theta), std::real(phi), std::real(lam), + std::real(gamma)); } static cmatrix_t r(complex_t theta, complex_t phi) { return r(std::real(theta), std::real(phi)); @@ -107,11 +109,17 @@ class SMatrix { static cmatrix_t rzz(complex_t theta) { return rzz(std::real(theta)); } static cmatrix_t rzx(complex_t theta) { return rzx(std::real(theta)); } static cmatrix_t phase(complex_t theta) { return phase(std::real(theta)); } - static cmatrix_t phase_diag(complex_t theta) { return phase_diag(std::real(theta)); } + static cmatrix_t phase_diag(complex_t theta) { + return phase_diag(std::real(theta)); + } static cmatrix_t cphase(complex_t theta) { return cphase(std::real(theta)); } - static cmatrix_t cphase_diag(complex_t theta) { return cphase_diag(std::real(theta)); } - static cmatrix_t cu(complex_t theta, complex_t phi, complex_t lam, complex_t gamma) { - return cu(std::real(theta), std::real(phi), std::real(lam), std::real(gamma)); + static cmatrix_t cphase_diag(complex_t theta) { + return cphase_diag(std::real(theta)); + } + static cmatrix_t cu(complex_t theta, complex_t phi, complex_t lam, + complex_t gamma) { + return cu(std::real(theta), std::real(phi), std::real(lam), + std::real(gamma)); } // Return superoperator matrix for reset instruction @@ -174,22 +182,18 @@ const cmatrix_t SMatrix::SWAP = Utils::unitary_superop(Matrix::SWAP); const cmatrix_t SMatrix::ECR = Utils::unitary_superop(Matrix::ECR); - - // Lookup table const stringmap_t SMatrix::label_map_ = { - {"id", &SMatrix::I}, {"x", &SMatrix::X}, {"y", &SMatrix::Y}, - {"z", &SMatrix::Z}, {"h", &SMatrix::H}, {"s", &SMatrix::S}, - {"sdg", &SMatrix::SDG}, {"t", &SMatrix::T}, {"tdg", &SMatrix::TDG}, - {"x90", &SMatrix::X90}, {"cx", &SMatrix::CX}, {"cy", &SMatrix::CY}, - {"cz", &SMatrix::CZ}, {"swap", &SMatrix::SWAP}, {"sx", &SMatrix::SX}, - {"sxdg", &SMatrix::SXDG}, {"delay", &SMatrix::I}, {"ecr", &SMatrix::ECR}}; + {"id", &SMatrix::I}, {"x", &SMatrix::X}, {"y", &SMatrix::Y}, + {"z", &SMatrix::Z}, {"h", &SMatrix::H}, {"s", &SMatrix::S}, + {"sdg", &SMatrix::SDG}, {"t", &SMatrix::T}, {"tdg", &SMatrix::TDG}, + {"x90", &SMatrix::X90}, {"cx", &SMatrix::CX}, {"cy", &SMatrix::CY}, + {"cz", &SMatrix::CZ}, {"swap", &SMatrix::SWAP}, {"sx", &SMatrix::SX}, + {"sxdg", &SMatrix::SXDG}, {"delay", &SMatrix::I}, {"ecr", &SMatrix::ECR}}; cmatrix_t SMatrix::identity(size_t dim) { return Matrix::identity(dim * dim); } -cmatrix_t SMatrix::u1(double lambda) { - return phase(lambda); -} +cmatrix_t SMatrix::u1(double lambda) { return phase(lambda); } cmatrix_t SMatrix::u2(double phi, double lambda) { return Utils::tensor_product(Matrix::u2(-phi, -lambda), diff --git a/src/framework/linalg/matrix_utils/vmatrix_defs.hpp b/src/framework/linalg/matrix_utils/vmatrix_defs.hpp old mode 100755 new mode 100644 index 24248de12c..3c5c3ab513 --- a/src/framework/linalg/matrix_utils/vmatrix_defs.hpp +++ b/src/framework/linalg/matrix_utils/vmatrix_defs.hpp @@ -34,18 +34,18 @@ namespace Linalg { class VMatrix { public: // Single-qubit gates - const static cvector_t I; // name: "id" - const static cvector_t X; // name: "x" - const static cvector_t Y; // name: "y" - const static cvector_t Z; // name: "z" - const static cvector_t H; // name: "h" - const static cvector_t S; // name: "s" - const static cvector_t SDG; // name: "sdg" - const static cvector_t T; // name: "t" - const static cvector_t TDG; // name: "tdg" - const static cvector_t SX; // name: "sx" - const static cvector_t SXDG;// name: "sxdg" - const static cvector_t X90; // name: "x90" + const static cvector_t I; // name: "id" + const static cvector_t X; // name: "x" + const static cvector_t Y; // name: "y" + const static cvector_t Z; // name: "z" + const static cvector_t H; // name: "h" + const static cvector_t S; // name: "s" + const static cvector_t SDG; // name: "sdg" + const static cvector_t T; // name: "t" + const static cvector_t TDG; // name: "tdg" + const static cvector_t SX; // name: "sx" + const static cvector_t SXDG; // name: "sxdg" + const static cvector_t X90; // name: "x90" // Two-qubit gates const static cvector_t CX; // name: "cx" @@ -74,7 +74,7 @@ class VMatrix { static cvector_t rxx(double theta); static cvector_t ryy(double theta); static cvector_t rzz(double theta); - static cvector_t rzx(double theta); // rotation around Tensor(X, Z) + static cvector_t rzx(double theta); // rotation around Tensor(X, Z) static cvector_t rzz_diag(double theta); // return the matrix diagonal // Phase Gates @@ -95,8 +95,10 @@ class VMatrix { static cvector_t u3(complex_t theta, complex_t phi, complex_t lam) { return u3(std::real(theta), std::real(phi), std::real(lam)); }; - static cvector_t u4(complex_t theta, complex_t phi, complex_t lam, complex_t gamma) { - return u4(std::real(theta), std::real(phi), std::real(lam), std::real(gamma)); + static cvector_t u4(complex_t theta, complex_t phi, complex_t lam, + complex_t gamma) { + return u4(std::real(theta), std::real(phi), std::real(lam), + std::real(gamma)); }; static cvector_t r(complex_t theta, complex_t phi) { return r(std::real(theta), std::real(phi)); @@ -104,18 +106,28 @@ class VMatrix { static cvector_t rx(complex_t theta) { return rx(std::real(theta)); } static cvector_t ry(complex_t theta) { return ry(std::real(theta)); } static cvector_t rz(complex_t theta) { return rz(std::real(theta)); } - static cvector_t rz_diag(complex_t theta) { return rz_diag(std::real(theta)); } + static cvector_t rz_diag(complex_t theta) { + return rz_diag(std::real(theta)); + } static cvector_t rxx(complex_t theta) { return rxx(std::real(theta)); } static cvector_t ryy(complex_t theta) { return ryy(std::real(theta)); } static cvector_t rzz(complex_t theta) { return rzz(std::real(theta)); } - static cvector_t rzz_diag(complex_t theta) { return rzz_diag(std::real(theta)); } + static cvector_t rzz_diag(complex_t theta) { + return rzz_diag(std::real(theta)); + } static cvector_t rzx(complex_t theta) { return rzx(std::real(theta)); } static cvector_t phase(complex_t theta) { return phase(std::real(theta)); } - static cvector_t phase_diag(complex_t theta) { return phase_diag(std::real(theta)); } + static cvector_t phase_diag(complex_t theta) { + return phase_diag(std::real(theta)); + } static cvector_t cphase(complex_t theta) { return cphase(std::real(theta)); } - static cvector_t cphase_diag(complex_t theta) { return cphase_diag(std::real(theta)); } - static cvector_t cu(complex_t theta, complex_t phi, complex_t lam, complex_t gamma) { - return cu(std::real(theta), std::real(phi), std::real(lam), std::real(gamma)); + static cvector_t cphase_diag(complex_t theta) { + return cphase_diag(std::real(theta)); + } + static cvector_t cu(complex_t theta, complex_t phi, complex_t lam, + complex_t gamma) { + return cu(std::real(theta), std::real(phi), std::real(lam), + std::real(gamma)); } // Return the matrix for a named matrix string @@ -173,15 +185,14 @@ const cvector_t VMatrix::SWAP = Utils::vectorize_matrix(Matrix::SWAP); const cvector_t VMatrix::ECR = Utils::vectorize_matrix(Matrix::ECR); - // Lookup table const stringmap_t VMatrix::label_map_ = { - {"id", &VMatrix::I}, {"x", &VMatrix::X}, {"y", &VMatrix::Y}, - {"z", &VMatrix::Z}, {"h", &VMatrix::H}, {"s", &VMatrix::S}, - {"sdg", &VMatrix::SDG}, {"t", &VMatrix::T}, {"tdg", &VMatrix::TDG}, - {"x90", &VMatrix::X90}, {"cx", &VMatrix::CX}, {"cy", &VMatrix::CY}, - {"cz", &VMatrix::CZ}, {"swap", &VMatrix::SWAP}, {"sx", &VMatrix::SX}, - {"sxdg", &VMatrix::SXDG}, {"delay", &VMatrix::I}, {"ecr", &VMatrix::ECR}}; + {"id", &VMatrix::I}, {"x", &VMatrix::X}, {"y", &VMatrix::Y}, + {"z", &VMatrix::Z}, {"h", &VMatrix::H}, {"s", &VMatrix::S}, + {"sdg", &VMatrix::SDG}, {"t", &VMatrix::T}, {"tdg", &VMatrix::TDG}, + {"x90", &VMatrix::X90}, {"cx", &VMatrix::CX}, {"cy", &VMatrix::CY}, + {"cz", &VMatrix::CZ}, {"swap", &VMatrix::SWAP}, {"sx", &VMatrix::SX}, + {"sxdg", &VMatrix::SXDG}, {"delay", &VMatrix::I}, {"ecr", &VMatrix::ECR}}; cvector_t VMatrix::identity(size_t dim) { cvector_t mat(dim * dim); @@ -190,9 +201,7 @@ cvector_t VMatrix::identity(size_t dim) { return mat; } -cvector_t VMatrix::u1(double lambda) { - return phase(lambda); -} +cvector_t VMatrix::u1(double lambda) { return phase(lambda); } cvector_t VMatrix::u2(double phi, double lambda) { cvector_t mat(2 * 2); @@ -316,7 +325,7 @@ cvector_t VMatrix::rzz_diag(double theta) { const complex_t i(0., 1.); const complex_t exp_p = std::exp(i * 0.5 * theta); const complex_t exp_m = std::exp(-i * 0.5 * theta); - return cvector_t({exp_m, exp_p, exp_p, exp_m}); + return cvector_t({exp_m, exp_p, exp_p, exp_m}); } cvector_t VMatrix::rzx(double theta) { diff --git a/src/framework/linalg/square.hpp b/src/framework/linalg/square.hpp old mode 100755 new mode 100644 index 6baae7054f..4c2b28d180 --- a/src/framework/linalg/square.hpp +++ b/src/framework/linalg/square.hpp @@ -22,10 +22,10 @@ #include #include "framework/json.hpp" -#include "framework/matrix.hpp" +#include "framework/linalg/enable_if_numeric.hpp" #include "framework/linalg/vector.hpp" +#include "framework/matrix.hpp" #include "framework/types.hpp" -#include "framework/linalg/enable_if_numeric.hpp" namespace AER { namespace Linalg { @@ -39,14 +39,14 @@ namespace Linalg { // Return entrywise square of a vector template > -std::array square(const std::array& data) { +std::array square(const std::array &data) { std::array result = data; return isquare(result); } // Return inplace entrywise square of a vector template > -std::array& isquare(std::array& data) { +std::array &isquare(std::array &data) { std::transform(data.begin(), data.end(), data.begin(), data.begin(), std::multiplies()); return data; @@ -58,17 +58,17 @@ std::array& isquare(std::array& data) { // Return entrywise square of a vector template > -std::vector square(const std::vector& data) { +std::vector square(const std::vector &data) { std::vector result; result.reserve(data.size()); - std::transform(data.begin(), data.end(), data.begin(), std::back_inserter(result), - std::multiplies()); + std::transform(data.begin(), data.end(), data.begin(), + std::back_inserter(result), std::multiplies()); return result; } // Return inplace entrywise square of a vector template > -std::vector& isquare(std::vector& data) { +std::vector &isquare(std::vector &data) { std::transform(data.begin(), data.end(), data.begin(), data.begin(), std::multiplies()); return data; @@ -78,18 +78,20 @@ std::vector& isquare(std::vector& data) { // Entrywise square of std::map //---------------------------------------------------------------------------- -template > -std::map square(const std::map& data) { +template > +std::map square(const std::map &data) { std::map result; - for (const auto& pair : data) { + for (const auto &pair : data) { result[pair.first] = pair.second * pair.second; } return result; } -template > -std::map& isquare(std::map& data) { - for (auto& pair : data) { +template > +std::map &isquare(std::map &data) { + for (auto &pair : data) { pair.second *= pair.second; } return data; @@ -99,19 +101,22 @@ std::map& isquare(std::map& data) { // Entrywise square of std::unordered_map //---------------------------------------------------------------------------- -template > -std::unordered_map square( - const std::unordered_map& data) { +template > +std::unordered_map +square(const std::unordered_map &data) { std::unordered_map result; - for (const auto& pair : data) { + for (const auto &pair : data) { result[pair.first] = pair.second * pair.second; } return result; } -template > -std::unordered_map& isquare(std::unordered_map& data) { - for (auto& pair : data) { +template > +std::unordered_map & +isquare(std::unordered_map &data) { + for (auto &pair : data) { pair.second *= pair.second; } return data; @@ -122,7 +127,7 @@ std::unordered_map& isquare(std::unordered_map> -matrix& isquare(matrix& data) { +matrix &isquare(matrix &data) { for (size_t j = 0; j < data.size(); j++) { data[j] *= data[j]; } @@ -130,7 +135,7 @@ matrix& isquare(matrix& data) { } template > -matrix square(const matrix& data) { +matrix square(const matrix &data) { matrix result = data; return isquare(result); } @@ -140,16 +145,17 @@ matrix square(const matrix& data) { //---------------------------------------------------------------------------- template > -Vector& isquare(Vector& vec) { - std::for_each(vec.data(), vec.data() + vec.size(), [](T&val) { val *= val; }); +Vector &isquare(Vector &vec) { + std::for_each(vec.data(), vec.data() + vec.size(), + [](T &val) { val *= val; }); return vec; } template > -Vector square(const Vector& vec) { +Vector square(const Vector &vec) { Vector ret(vec.size(), false); std::transform(vec.data(), vec.data() + vec.size(), ret.data(), - [](const T&val) { return val * val; }); + [](const T &val) { return val * val; }); return ret; } @@ -157,7 +163,7 @@ Vector square(const Vector& vec) { // Entrywise square of JSON //---------------------------------------------------------------------------- -inline json_t& isquare(json_t& data) { +inline json_t &isquare(json_t &data) { // Terminating case if (data.is_number()) { double val = data; @@ -170,7 +176,7 @@ inline json_t& isquare(json_t& data) { isquare(data[pos]); } return data; - } + } if (data.is_object()) { for (auto it = data.begin(); it != data.end(); ++it) { isquare(data[it.key()]); @@ -180,7 +186,7 @@ inline json_t& isquare(json_t& data) { throw std::invalid_argument("Input JSONs cannot be squared."); } -inline json_t square(const json_t& data) { +inline json_t square(const json_t &data) { json_t result = data; return isquare(result); } @@ -190,19 +196,19 @@ inline json_t square(const json_t& data) { //---------------------------------------------------------------------------- template -T square(const T& data) { +T square(const T &data) { return data * data; } template -T& isquare(T& data) { +T &isquare(T &data) { data *= data; return data; } //------------------------------------------------------------------------------ -} // end namespace Linalg +} // end namespace Linalg //------------------------------------------------------------------------------ -} // end namespace AER +} // end namespace AER //------------------------------------------------------------------------------ #endif \ No newline at end of file diff --git a/src/framework/linalg/vector.hpp b/src/framework/linalg/vector.hpp old mode 100755 new mode 100644 index 6098943a52..985b64f5b3 --- a/src/framework/linalg/vector.hpp +++ b/src/framework/linalg/vector.hpp @@ -29,15 +29,18 @@ namespace AER { -template T *malloc_data(size_t size) { +template +T *malloc_data(size_t size) { return reinterpret_cast(malloc(sizeof(T) * size)); } -template T *calloc_data(size_t size) { +template +T *calloc_data(size_t size) { return reinterpret_cast(calloc(size, sizeof(T))); } -template class Vector { +template +class Vector { public: //----------------------------------------------------------------------- @@ -60,8 +63,7 @@ template class Vector { Vector(Vector &&other) noexcept; // Destructor - virtual ~Vector() { - free(data_); } + virtual ~Vector() { free(data_); } //----------------------------------------------------------------------- // Assignment @@ -74,7 +76,8 @@ template class Vector { Vector &operator=(Vector &&other) noexcept; // Copy and cast assignment - template Vector &operator=(const Vector &other); + template + Vector &operator=(const Vector &other); //----------------------------------------------------------------------- // Buffer conversion @@ -192,7 +195,8 @@ template class Vector { template Vector::Vector(size_t sz, bool fill) - : size_(sz), data_((fill) ? calloc_data(size_) : malloc_data(size_)) {} + : size_(sz), data_((fill) ? calloc_data(size_) : malloc_data(size_)) { +} template Vector::Vector(const Vector &other) @@ -211,7 +215,8 @@ Vector::Vector(Vector &&other) noexcept // Assignment //----------------------------------------------------------------------- -template Vector &Vector::operator=(Vector &&other) noexcept { +template +Vector &Vector::operator=(Vector &&other) noexcept { free(data_); size_ = other.size_; data_ = other.data_; @@ -220,7 +225,8 @@ template Vector &Vector::operator=(Vector &&other) noexcept { return *this; } -template Vector &Vector::operator=(const Vector &other) { +template +Vector &Vector::operator=(const Vector &other) { if (size_ != other.size_) { free(data_); size_ = other.size_; @@ -265,13 +271,15 @@ Vector Vector::move_from_buffer(size_t sz, T *buffer) { return ret; } -template T *Vector::copy_to_buffer() const { +template +T *Vector::copy_to_buffer() const { T *buffer = malloc_data(size_); std::copy(data_, data_ + size_, buffer); return buffer; } -template T *Vector::move_to_buffer() { +template +T *Vector::move_to_buffer() { T *buffer = data_; data_ = nullptr; size_ = 0; @@ -282,17 +290,20 @@ template T *Vector::move_to_buffer() { // Operations //----------------------------------------------------------------------- -template void Vector::clear() noexcept { +template +void Vector::clear() noexcept { free(data_); size_ = 0; } -template void Vector::swap(Vector &other) { +template +void Vector::swap(Vector &other) { std::swap(size_, other.size_); std::swap(data_, other.data_); } -template void Vector::resize(size_t sz) { +template +void Vector::resize(size_t sz) { if (size_ == sz) return; T *tmp = calloc_data(sz); @@ -302,7 +313,8 @@ template void Vector::resize(size_t sz) { data_ = tmp; } -template void Vector::fill(const T &val) { +template +void Vector::fill(const T &val) { std::fill(data_, data_ + size_, val); } @@ -323,7 +335,8 @@ Vector Vector::operator+(const Vector &other) const { return result; } -template Vector &Vector::operator+=(const Vector &other) { +template +Vector &Vector::operator+=(const Vector &other) { if (size_ != other.size_) { throw std::runtime_error("Cannot add two vectors of different sizes."); } @@ -345,7 +358,8 @@ Vector Vector::operator-(const Vector &other) const { return result; } -template Vector &Vector::operator-=(const Vector &other) { +template +Vector &Vector::operator-=(const Vector &other) { if (size_ != other.size_) { throw std::runtime_error("Cannot add two vectors of different sizes."); } @@ -354,7 +368,8 @@ template Vector &Vector::operator-=(const Vector &other) { return *this; } -template Vector Vector::operator*(const T &other) const { +template +Vector Vector::operator*(const T &other) const { Vector ret; ret.size_ = size_; ret.data_ = malloc_data(size_); @@ -363,13 +378,14 @@ template Vector Vector::operator*(const T &other) const { return ret; } -template Vector &Vector::operator*=(const T &other) { - std::for_each(data_, data_ + size_, - [&other](T &a) { a *= other; }); +template +Vector &Vector::operator*=(const T &other) { + std::for_each(data_, data_ + size_, [&other](T &a) { a *= other; }); return *this; } -template Vector Vector::operator/(const T &other) const { +template +Vector Vector::operator/(const T &other) const { Vector ret; ret.size_ = size_; ret.data_ = malloc_data(size_); @@ -378,12 +394,12 @@ template Vector Vector::operator/(const T &other) const { return ret; } -template Vector &Vector::operator/=(const T &other) { +template +Vector &Vector::operator/=(const T &other) { std::for_each(data_, data_ + size_, [&other](T &a) { a /= other; }); return *this; } - //------------------------------------------------------------------------------ } // end Namespace AER //------------------------------------------------------------------------------ diff --git a/src/framework/linalg/vector_json.hpp b/src/framework/linalg/vector_json.hpp old mode 100755 new mode 100644 index 8f3f8d2a67..3a03339c61 --- a/src/framework/linalg/vector_json.hpp +++ b/src/framework/linalg/vector_json.hpp @@ -24,23 +24,23 @@ namespace AER { // Implementation: JSON Conversion //------------------------------------------------------------------------------ - -template void to_json(nlohmann::json &js, const Vector &vec) { +template +void to_json(nlohmann::json &js, const Vector &vec) { js = nlohmann::json(); for (size_t i = 0; i < vec.size(); i++) { js.push_back(vec[i]); } } - -template void from_json(const nlohmann::json &js, Vector &vec) { +template +void from_json(const nlohmann::json &js, Vector &vec) { // Check JSON is an array - if(!js.is_array()) { + if (!js.is_array()) { throw std::invalid_argument( std::string("JSON: invalid Vector (not array).")); } // Check if JSON is empty - if(js.empty()) { + if (js.empty()) { return; } diff --git a/src/framework/matrix.hpp b/src/framework/matrix.hpp old mode 100755 new mode 100644 index bc22bc9306..6a0a0ffe06 --- a/src/framework/matrix.hpp +++ b/src/framework/matrix.hpp @@ -31,10 +31,10 @@ Multiplication is done with the C wrapper of the fortran blas library. #ifndef _aer_framework_matrix_hpp #define _aer_framework_matrix_hpp +#include #include #include #include -#include #include "framework/blas_protos.hpp" #include "framework/linalg/enable_if_numeric.hpp" @@ -46,16 +46,15 @@ Multiplication is done with the C wrapper of the fortran blas library. ******************************************************************************/ template -T* malloc_array(size_t size) { - return reinterpret_cast(malloc(sizeof(T) * size)); +T *malloc_array(size_t size) { + return reinterpret_cast(malloc(sizeof(T) * size)); } template -T* calloc_array(size_t size) { - return reinterpret_cast(calloc(size, sizeof(T))); +T *calloc_array(size_t size) { + return reinterpret_cast(calloc(size, sizeof(T))); } - template // define a class template class matrix { // friend functions get to use the private variables of the class as well as @@ -136,13 +135,13 @@ class matrix { matrix(size_t rows, size_t cols, bool fill = true); // Construct a matrix of specified size and an array - matrix(size_t rows, size_t cols, T* data); + matrix(size_t rows, size_t cols, T *data); // Copy construct a matrix matrix(const matrix &other); // Move construct a matrix - matrix(matrix&& other) noexcept; + matrix(matrix &&other) noexcept; // Destructor virtual ~matrix() { free(data_); } @@ -167,33 +166,33 @@ class matrix { // Copy construct a matrix from C-array buffer // The buffer should have size = rows * cols. - static matrix copy_from_buffer(size_t rows, size_t cols, const T* buffer); + static matrix copy_from_buffer(size_t rows, size_t cols, const T *buffer); // Move construct a matrix from C-array buffer // The buffer should have size = rows * cols. - static matrix move_from_buffer(size_t rows, size_t cols, T* buffer); + static matrix move_from_buffer(size_t rows, size_t cols, T *buffer); // Copy matrix to a new C-array - T* copy_to_buffer() const; + T *copy_to_buffer() const; // Move matrix to a C-array - T* move_to_buffer(); + T *move_to_buffer(); //----------------------------------------------------------------------- // Element access //----------------------------------------------------------------------- // Addressing elements by vector representation - T& operator[](size_t element); - const T& operator[](size_t element) const; + T &operator[](size_t element); + const T &operator[](size_t element) const; // Addressing elements by matrix representation - T& operator()(size_t row, size_t col); - const T& operator()(size_t row, size_t col) const; + T &operator()(size_t row, size_t col); + const T &operator()(size_t row, size_t col) const; // Access the array data pointer - const T* data() const noexcept { return data_; } - T* data() noexcept { return data_; } + const T *data() const noexcept { return data_; } + T *data() noexcept { return data_; } //----------------------------------------------------------------------- // Other methods @@ -209,7 +208,7 @@ class matrix { void clear(); // Fill with constant value - void fill(const T& val); + void fill(const T &val); // Resize the matrix and reset to zero if different size void initialize(size_t row, size_t col); @@ -245,7 +244,7 @@ class matrix { // to rows // the ptr to the vector containing the matrix - T* data_ = nullptr; + T *data_ = nullptr; }; /******************************************************************************* @@ -264,28 +263,28 @@ matrix::matrix(size_t rows, size_t cols, bool fill) data_((fill) ? calloc_array(size_) : malloc_array(size_)) {} template -matrix::matrix(const matrix &other) : matrix(other.rows_, other.cols_, false) { +matrix::matrix(const matrix &other) + : matrix(other.rows_, other.cols_, false) { std::copy(other.data_, other.data_ + other.size_, data_); } template -matrix::matrix(matrix&& other) noexcept - : rows_(other.rows_), cols_(other.cols_), size_(other.size_), LD_(rows_), - data_(other.data_) { +matrix::matrix(matrix &&other) noexcept + : rows_(other.rows_), cols_(other.cols_), size_(other.size_), LD_(rows_), + data_(other.data_) { other.data_ = nullptr; } template -matrix::matrix(size_t rows, size_t cols, T* data) - : rows_(rows), cols_(cols), size_(rows * cols), LD_(rows), - data_(data) {} +matrix::matrix(size_t rows, size_t cols, T *data) + : rows_(rows), cols_(cols), size_(rows * cols), LD_(rows), data_(data) {} //----------------------------------------------------------------------- // Assignment //----------------------------------------------------------------------- template -matrix& matrix::operator=(matrix&& other) noexcept { +matrix &matrix::operator=(matrix &&other) noexcept { free(data_); rows_ = other.rows_; cols_ = other.cols_; @@ -316,8 +315,7 @@ template template inline matrix &matrix::operator=(const matrix &other) { - if (rows_ != other.GetRows() || - cols_ != other.GetColumns()) { + if (rows_ != other.GetRows() || cols_ != other.GetColumns()) { free(data_); rows_ = other.GetRows(); cols_ = other.GetColumns(); @@ -336,7 +334,8 @@ inline matrix &matrix::operator=(const matrix &other) { //----------------------------------------------------------------------- template -matrix matrix::copy_from_buffer(size_t rows, size_t cols, const T* buffer) { +matrix matrix::copy_from_buffer(size_t rows, size_t cols, + const T *buffer) { matrix ret; ret.size_ = rows * cols; ret.rows_ = rows; @@ -348,7 +347,7 @@ matrix matrix::copy_from_buffer(size_t rows, size_t cols, const T* buffer) } template -matrix matrix::move_from_buffer(size_t rows, size_t cols, T* buffer) { +matrix matrix::move_from_buffer(size_t rows, size_t cols, T *buffer) { matrix ret; ret.size_ = rows * cols; ret.rows_ = rows; @@ -359,15 +358,15 @@ matrix matrix::move_from_buffer(size_t rows, size_t cols, T* buffer) { } template -T* matrix::copy_to_buffer() const { - T* buffer = malloc_array(size_); +T *matrix::copy_to_buffer() const { + T *buffer = malloc_array(size_); std::copy(data_, data_ + size_, buffer); return buffer; } template -T* matrix::move_to_buffer() { - T* buffer = data_; +T *matrix::move_to_buffer() { + T *buffer = data_; data_ = nullptr; size_ = 0; rows_ = 0; @@ -380,7 +379,7 @@ T* matrix::move_to_buffer() { //----------------------------------------------------------------------- template -T& matrix::operator[](size_t p) { +T &matrix::operator[](size_t p) { #ifdef DEBUG if (p >= size_) { std::cerr @@ -392,7 +391,7 @@ T& matrix::operator[](size_t p) { return data_[p]; } template -const T& matrix::operator[](size_t p) const { +const T &matrix::operator[](size_t p) const { #ifdef DEBUG if (p >= size_) { std::cerr << "Error: matrix class operator [] const: Matrix subscript out " @@ -405,7 +404,7 @@ const T& matrix::operator[](size_t p) const { } template -T& matrix::operator()(size_t i, size_t j) { +T &matrix::operator()(size_t i, size_t j) { #ifdef DEBUG if (i >= rows_ || j >= cols_) { std::cerr @@ -418,7 +417,7 @@ T& matrix::operator()(size_t i, size_t j) { } template -const T& matrix::operator()(size_t i, size_t j) const { +const T &matrix::operator()(size_t i, size_t j) const { #ifdef DEBUG if (i >= rows_ || j >= cols_) { std::cerr << "Error: matrix class operator () const: Matrices subscript " @@ -438,7 +437,8 @@ void matrix::clear() { free(data_); } -template inline void matrix::initialize(size_t rows, size_t cols) { +template +inline void matrix::initialize(size_t rows, size_t cols) { if (rows_ != rows || cols_ != cols) { free(data_); rows_ = rows; @@ -450,7 +450,7 @@ template inline void matrix::initialize(size_t rows, size_t cols) { } template -void matrix::fill(const T& val) { +void matrix::fill(const T &val) { std::fill(data_, data_ + size_, val); } @@ -473,52 +473,58 @@ void matrix::resize(size_t rows, size_t cols) { } // Addressing elements by row or column -template inline std::vector matrix::row_index(size_t row) const { +template +inline std::vector matrix::row_index(size_t row) const { #ifdef DEBUG if (row >= rows_) { - std::cerr << "Error: matrix class operator row_index out of bounds " - << row << " >= " << rows_ << std::endl; + std::cerr << "Error: matrix class operator row_index out of bounds " << row + << " >= " << rows_ << std::endl; exit(1); } #endif std::vector ret; ret.reserve(cols_); - for(size_t i = 0; i < cols_; i++) + for (size_t i = 0; i < cols_; i++) ret.emplace_back(data_[i * rows_ + row]); // Allow for Named Return Value Optimization (NRVO) by not using std::move return ret; } -template inline std::vector matrix::col_index(size_t col) const { +template +inline std::vector matrix::col_index(size_t col) const { #ifdef DEBUG if (col >= cols_) { - std::cerr << "Error: matrix class operator col_index out of bounds " - << col << " >= " << cols_ << std::endl; + std::cerr << "Error: matrix class operator col_index out of bounds " << col + << " >= " << cols_ << std::endl; exit(1); } #endif std::vector ret; ret.reserve(rows_); // we want the elements for all rows i..rows_ and column col - for(size_t i = 0; i < rows_; i++) + for (size_t i = 0; i < rows_; i++) ret.emplace_back(data_[col * rows_ + i]); // Allow for Named Return Value Optimization (NRVO) by not using std::move return ret; } -template inline size_t matrix::GetRows() const { +template +inline size_t matrix::GetRows() const { // returns the rows of the matrix return rows_; } -template inline size_t matrix::GetColumns() const { +template +inline size_t matrix::GetColumns() const { // returns the colums of the matrix return cols_; } -template inline size_t matrix::GetLD() const { +template +inline size_t matrix::GetLD() const { // returns the leading dimension return LD_; } -template inline matrix matrix::operator+(const matrix &A) { +template +inline matrix matrix::operator+(const matrix &A) { // overloads the + for matrix addition, can this be more efficient #ifdef DEBUG if (rows_ != A.rows_ || cols_ != A.cols_) { @@ -534,7 +540,8 @@ template inline matrix matrix::operator+(const matrix &A) { } return temp; } -template inline matrix matrix::operator-(const matrix &A) { +template +inline matrix matrix::operator-(const matrix &A) { // overloads the - for matrix substraction, can this be more efficient #ifdef DEBUG if (rows_ != A.rows_ || cols_ != A.cols_) { @@ -585,7 +592,8 @@ inline matrix matrix::operator-(const matrix &A) const { } return temp; } -template inline matrix &matrix::operator+=(const matrix &A) { +template +inline matrix &matrix::operator+=(const matrix &A) { // overloads the += for matrix addition and assignment, can this be more // efficient #ifdef DEBUG @@ -601,7 +609,8 @@ template inline matrix &matrix::operator+=(const matrix &A) { } return *this; } -template inline matrix &matrix::operator-=(const matrix &A) { +template +inline matrix &matrix::operator-=(const matrix &A) { // overloads the -= for matrix subtraction and assignement, can this be more // efficient #ifdef DEBUG @@ -686,8 +695,8 @@ inline matrix operator*(const matrix &A, // C-> alpha*op(A)*op(B) +beta C matrix C(A.rows_, B.cols_); double alpha = 1.0, beta = 0.0; - dgemm_(&AerBlas::Trans[0], &AerBlas::Trans[0], &A.rows_, &B.cols_, &A.cols_, &alpha, A.data_, - &A.LD_, B.data_, &B.LD_, &beta, C.data_, &C.LD_); + dgemm_(&AerBlas::Trans[0], &AerBlas::Trans[0], &A.rows_, &B.cols_, &A.cols_, + &alpha, A.data_, &A.LD_, B.data_, &B.LD_, &beta, C.data_, &C.LD_); // cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, A.rows_, B.cols_, // A.cols_, 1.0, A.data_, A.LD_, B.data_, B.LD_, 0.0, C.data_, C.LD_); return C; @@ -698,8 +707,8 @@ inline matrix operator*(const matrix &A, const matrix &B) { // C-> alpha*op(A)*op(B) +beta C matrix C(A.rows_, B.cols_); float alpha = 1.0, beta = 0.0; - sgemm_(&AerBlas::Trans[0], &AerBlas::Trans[0], &A.rows_, &B.cols_, &A.cols_, &alpha, A.data_, - &A.LD_, B.data_, &B.LD_, &beta, C.data_, &C.LD_); + sgemm_(&AerBlas::Trans[0], &AerBlas::Trans[0], &A.rows_, &B.cols_, &A.cols_, + &alpha, A.data_, &A.LD_, B.data_, &B.LD_, &beta, C.data_, &C.LD_); // cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, A.rows_, B.cols_, // A.cols_, 1.0, A.data_, A.LD_, B.data_, B.LD_, 0.0, C.data_, C.LD_); return C; @@ -712,8 +721,8 @@ operator*(const matrix> &A, // C-> alpha*op(A)*op(B) +beta C matrix> C(A.rows_, B.cols_); std::complex alpha = 1.0, beta = 0.0; - cgemm_(&AerBlas::Trans[0], &AerBlas::Trans[0], &A.rows_, &B.cols_, &A.cols_, &alpha, A.data_, - &A.LD_, B.data_, &B.LD_, &beta, C.data_, &C.LD_); + cgemm_(&AerBlas::Trans[0], &AerBlas::Trans[0], &A.rows_, &B.cols_, &A.cols_, + &alpha, A.data_, &A.LD_, B.data_, &B.LD_, &beta, C.data_, &C.LD_); // cblas_zgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, A.rows_, B.cols_, // A.cols_, &alpha, A.data_, A.LD_, B.data_, B.LD_, &beta, C.data_, C.LD_); return C; @@ -726,8 +735,8 @@ operator*(const matrix> &A, // C-> alpha*op(A)*op(B) +beta C matrix> C(A.rows_, B.cols_); std::complex alpha = 1.0, beta = 0.0; - zgemm_(&AerBlas::Trans[0], &AerBlas::Trans[0], &A.rows_, &B.cols_, &A.cols_, &alpha, A.data_, - &A.LD_, B.data_, &B.LD_, &beta, C.data_, &C.LD_); + zgemm_(&AerBlas::Trans[0], &AerBlas::Trans[0], &A.rows_, &B.cols_, &A.cols_, + &alpha, A.data_, &A.LD_, B.data_, &B.LD_, &beta, C.data_, &C.LD_); // cblas_zgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, A.rows_, B.cols_, // A.cols_, &alpha, A.data_, A.LD_, B.data_, B.LD_, &beta, C.data_, C.LD_); return C; @@ -740,8 +749,8 @@ operator*(const matrix &A, const matrix> &B) { matrix> C(A.rows_, B.cols_), Ac(A.rows_, A.cols_); Ac = A; std::complex alpha = 1.0, beta = 0.0; - cgemm_(&AerBlas::Trans[0], &AerBlas::Trans[0], &Ac.rows_, &B.cols_, &Ac.cols_, &alpha, Ac.data_, - &Ac.LD_, B.data_, &B.LD_, &beta, C.data_, &C.LD_); + cgemm_(&AerBlas::Trans[0], &AerBlas::Trans[0], &Ac.rows_, &B.cols_, &Ac.cols_, + &alpha, Ac.data_, &Ac.LD_, B.data_, &B.LD_, &beta, C.data_, &C.LD_); // cblas_zgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, Ac.rows_, B.cols_, // Ac.cols_, &alpha, Ac.data_, Ac.LD_, B.data_, B.LD_, &beta, C.data_, C.LD_); return C; @@ -754,8 +763,8 @@ operator*(const matrix &A, const matrix> &B) { matrix> C(A.rows_, B.cols_), Ac(A.rows_, A.cols_); Ac = A; std::complex alpha = 1.0, beta = 0.0; - zgemm_(&AerBlas::Trans[0], &AerBlas::Trans[0], &Ac.rows_, &B.cols_, &Ac.cols_, &alpha, Ac.data_, - &Ac.LD_, B.data_, &B.LD_, &beta, C.data_, &C.LD_); + zgemm_(&AerBlas::Trans[0], &AerBlas::Trans[0], &Ac.rows_, &B.cols_, &Ac.cols_, + &alpha, Ac.data_, &Ac.LD_, B.data_, &B.LD_, &beta, C.data_, &C.LD_); // cblas_zgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, Ac.rows_, B.cols_, // Ac.cols_, &alpha, Ac.data_, Ac.LD_, B.data_, B.LD_, &beta, C.data_, C.LD_); return C; @@ -768,8 +777,8 @@ operator*(const matrix> &A, const matrix &B) { matrix> C(A.rows_, B.cols_), Bc(B.rows_, B.cols_); Bc = B; std::complex alpha = 1.0, beta = 0.0; - cgemm_(&AerBlas::Trans[0], &AerBlas::Trans[0], &A.rows_, &Bc.cols_, &A.cols_, &alpha, A.data_, - &A.LD_, Bc.data_, &Bc.LD_, &beta, C.data_, &C.LD_); + cgemm_(&AerBlas::Trans[0], &AerBlas::Trans[0], &A.rows_, &Bc.cols_, &A.cols_, + &alpha, A.data_, &A.LD_, Bc.data_, &Bc.LD_, &beta, C.data_, &C.LD_); // cblas_zgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, A.rows_, Bc.cols_, // A.cols_, &alpha, A.data_, A.LD_, Bc.data_, Bc.LD_, &beta, C.data_, C.LD_); return C; @@ -782,8 +791,8 @@ operator*(const matrix> &A, const matrix &B) { matrix> C(A.rows_, B.cols_), Bc(B.rows_, B.cols_); Bc = B; std::complex alpha = 1.0, beta = 0.0; - zgemm_(&AerBlas::Trans[0], &AerBlas::Trans[0], &A.rows_, &Bc.cols_, &A.cols_, &alpha, A.data_, - &A.LD_, Bc.data_, &Bc.LD_, &beta, C.data_, &C.LD_); + zgemm_(&AerBlas::Trans[0], &AerBlas::Trans[0], &A.rows_, &Bc.cols_, &A.cols_, + &alpha, A.data_, &A.LD_, Bc.data_, &Bc.LD_, &beta, C.data_, &C.LD_); // cblas_zgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, A.rows_, Bc.cols_, // A.cols_, &alpha, A.data_, A.LD_, Bc.data_, Bc.LD_, &beta, C.data_, C.LD_); return C; @@ -796,8 +805,8 @@ inline std::vector operator*(const matrix &A, std::vector y(A.rows_); float alpha = 1.0, beta = 0.0; const size_t incx = 1, incy = 1; - sgemv_(&AerBlas::Trans[0], &A.rows_, &A.cols_, &alpha, A.data_, &A.LD_, x.data(), &incx, - &beta, y.data(), &incy); + sgemv_(&AerBlas::Trans[0], &A.rows_, &A.cols_, &alpha, A.data_, &A.LD_, + x.data(), &incx, &beta, y.data(), &incy); return y; } // Double-Precision Real @@ -807,8 +816,8 @@ inline std::vector operator*(const matrix &A, std::vector y(A.rows_); double alpha = 1.0, beta = 0.0; const size_t incx = 1, incy = 1; - dgemv_(&AerBlas::Trans[0], &A.rows_, &A.cols_, &alpha, A.data_, &A.LD_, x.data(), &incx, - &beta, y.data(), &incy); + dgemv_(&AerBlas::Trans[0], &A.rows_, &A.cols_, &alpha, A.data_, &A.LD_, + x.data(), &incx, &beta, y.data(), &incy); return y; } // Single-Precision Complex @@ -819,8 +828,8 @@ operator*(const matrix> &A, std::vector> y(A.rows_); std::complex alpha = 1.0, beta = 0.0; const size_t incx = 1, incy = 1; - cgemv_(&AerBlas::Trans[0], &A.rows_, &A.cols_, &alpha, A.data_, &A.LD_, x.data(), &incx, - &beta, y.data(), &incy); + cgemv_(&AerBlas::Trans[0], &A.rows_, &A.cols_, &alpha, A.data_, &A.LD_, + x.data(), &incx, &beta, y.data(), &incy); return y; } // Double-Precision Complex @@ -831,8 +840,8 @@ operator*(const matrix> &A, std::vector> y(A.rows_); std::complex alpha = 1.0, beta = 0.0; const size_t incx = 1, incy = 1; - zgemv_(&AerBlas::Trans[0], &A.rows_, &A.cols_, &alpha, A.data_, &A.LD_, x.data(), &incx, - &beta, y.data(), &incy); + zgemv_(&AerBlas::Trans[0], &A.rows_, &A.cols_, &alpha, A.data_, &A.LD_, + x.data(), &incx, &beta, y.data(), &incy); return y; } diff --git a/src/framework/noise_utils.hpp b/src/framework/noise_utils.hpp index eb3947fbd3..5694bd88ba 100644 --- a/src/framework/noise_utils.hpp +++ b/src/framework/noise_utils.hpp @@ -26,28 +26,30 @@ namespace Utils { // Transform a superoperator matrix to a Choi matrix template -matrix superop2choi(const matrix& superop, size_t dim); +matrix superop2choi(const matrix &superop, size_t dim); // Transform a superoperator matrix to a set of Kraus matrices template -std::vector> superop2kraus(const matrix& superop, size_t dim, double threshold = 1e-10); +std::vector> superop2kraus(const matrix &superop, size_t dim, + double threshold = 1e-10); // Transform a Choi matrix to a superoperator matrix template -matrix choi2superop(const matrix& choi, size_t dim); +matrix choi2superop(const matrix &choi, size_t dim); // Transform a Choi matrix to a set of Kraus matrices template std::vector>> -choi2kraus(const matrix>& choi, size_t dim, double threshold = 1e-10); +choi2kraus(const matrix> &choi, size_t dim, + double threshold = 1e-10); // Transform a set of Kraus matrices to a Choi matrix template -matrix kraus2choi(const std::vector>& kraus, size_t dim); +matrix kraus2choi(const std::vector> &kraus, size_t dim); // Transform a set of Kraus matrices to a superoperator matrix template -matrix kraus2superop(const std::vector>& kraus, size_t dim); +matrix kraus2superop(const std::vector> &kraus, size_t dim); // Reshuffle transformation // Transforms a matrix with dimension (d0 * d1, d2 * d3) @@ -55,15 +57,15 @@ matrix kraus2superop(const std::vector>& kraus, size_t dim); // by transposition of bipartite indices // M[(i, j), (k, l)] -> M[(i, j), (k, i)] template -matrix reshuffle(const matrix &mat, size_t d0, size_t d1, size_t d2, size_t d3); - +matrix reshuffle(const matrix &mat, size_t d0, size_t d1, size_t d2, + size_t d3); //========================================================================= // Implementations //========================================================================= template -matrix kraus2superop(const std::vector>& kraus, size_t dim) { +matrix kraus2superop(const std::vector> &kraus, size_t dim) { matrix superop(dim * dim, dim * dim); for (const auto mat : kraus) { superop += Utils::tensor_product(Utils::conjugate(mat), mat); @@ -72,28 +74,29 @@ matrix kraus2superop(const std::vector>& kraus, size_t dim) { } template -matrix kraus2choi(const std::vector>& kraus, size_t dim) { +matrix kraus2choi(const std::vector> &kraus, size_t dim) { return superop2choi(kraus2superop(kraus, dim), dim); } template -matrix superop2choi(const matrix& superop, size_t dim) { +matrix superop2choi(const matrix &superop, size_t dim) { return reshuffle(superop, dim, dim, dim, dim); } template -std::vector> superop2kraus(const matrix& superop, size_t dim, double threshold) { +std::vector> superop2kraus(const matrix &superop, size_t dim, + double threshold) { return choi2kraus(superop2choi(superop, dim), dim, threshold); } template -matrix choi2superop(const matrix& choi, size_t dim) { +matrix choi2superop(const matrix &choi, size_t dim) { return reshuffle(choi, dim, dim, dim, dim); } template std::vector>> -choi2kraus(const matrix>& choi, size_t dim, double threshold) { +choi2kraus(const matrix> &choi, size_t dim, double threshold) { size_t dim2 = dim * dim; std::vector evals; @@ -108,7 +111,7 @@ choi2kraus(const matrix>& choi, size_t dim, double threshold) { const size_t idx = dim2 - 1 - i; const T eval = evals[idx]; if (eval > 0.0 && !Linalg::almost_equal(eval, 0.0, threshold)) { - std::complex coeff(std::sqrt(eval), 0.0); + std::complex coeff(std::sqrt(eval), 0.0); matrix> kmat(dim, dim); for (size_t col = 0; col < dim; col++) for (size_t row = 0; row < dim; row++) { @@ -121,19 +124,20 @@ choi2kraus(const matrix>& choi, size_t dim, double threshold) { } template -matrix reshuffle(const matrix &mat, size_t d0, size_t d1, size_t d2, size_t d3) { +matrix reshuffle(const matrix &mat, size_t d0, size_t d1, size_t d2, + size_t d3) { matrix ret(d1 * d3, d0 * d2); for (size_t i0 = 0; i0 < d0; ++i0) for (size_t i1 = 0; i1 < d1; ++i1) for (size_t i2 = 0; i2 < d2; ++i2) for (size_t i3 = 0; i3 < d3; ++i3) { - ret(d1 * i3 + i1, d0 * i2 + i0) = mat(d1 * i0 + i1, d3 * i2 + i3); + ret(d1 * i3 + i1, d0 * i2 + i0) = mat(d1 * i0 + i1, d3 * i2 + i3); } return ret; } //------------------------------------------------------------------------- -} // end namespace Noise +} // namespace Utils //------------------------------------------------------------------------- } // end namespace AER //------------------------------------------------------------------------- diff --git a/src/framework/operations.hpp b/src/framework/operations.hpp old mode 100755 new mode 100644 index c1eb65c2fe..3e52f2bbea --- a/src/framework/operations.hpp +++ b/src/framework/operations.hpp @@ -16,15 +16,15 @@ #define _aer_framework_operations_hpp_ #include -#include #include #include +#include #include -#include "framework/types.hpp" #include "framework/json_parser.hpp" -#include "framework/utils.hpp" #include "framework/linalg/almost_equal.hpp" +#include "framework/types.hpp" +#include "framework/utils.hpp" #include "simulators/stabilizer/clifford.hpp" namespace AER { @@ -33,39 +33,81 @@ namespace Operations { // 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, LessEqual, Greater, GreaterEqual}; +enum class RegComparison { + Equal, + NotEqual, + Less, + LessEqual, + Greater, + GreaterEqual +}; // Enum class for operation types enum class OpType { - gate, measure, reset, bfunc, barrier, qerror_loc, - matrix, diagonal_matrix, multiplexer, initialize, sim_op, nop, + gate, + measure, + reset, + bfunc, + barrier, + qerror_loc, + matrix, + diagonal_matrix, + multiplexer, + initialize, + sim_op, + nop, // Noise instructions - kraus, superop, roerror, noise_switch, + kraus, + superop, + roerror, + noise_switch, // Save instructions - save_state, save_expval, save_expval_var, save_statevec, save_statevec_dict, - save_densmat, save_probs, save_probs_ket, save_amps, save_amps_sq, - save_stabilizer, save_clifford, save_unitary, save_mps, save_superop, + save_state, + save_expval, + save_expval_var, + save_statevec, + save_statevec_dict, + save_densmat, + save_probs, + save_probs_ket, + save_amps, + save_amps_sq, + save_stabilizer, + save_clifford, + save_unitary, + save_mps, + save_superop, // Set instructions - set_statevec, set_densmat, set_unitary, set_superop, - set_stabilizer, set_mps, + set_statevec, + set_densmat, + set_unitary, + set_superop, + set_stabilizer, + set_mps, // Control Flow - jump, mark + jump, + mark }; enum class DataSubType { - single, c_single, list, c_list, accum, c_accum, average, c_average + single, + c_single, + list, + c_list, + accum, + c_accum, + average, + c_average }; static const std::unordered_set SAVE_TYPES = { - OpType::save_state, OpType::save_expval, OpType::save_expval_var, - OpType::save_statevec, OpType::save_statevec_dict, - OpType::save_densmat, OpType::save_probs, OpType::save_probs_ket, - OpType::save_amps, OpType::save_amps_sq, OpType::save_stabilizer, - OpType::save_clifford, - OpType::save_unitary, OpType::save_mps, OpType::save_superop -}; + OpType::save_state, OpType::save_expval, OpType::save_expval_var, + OpType::save_statevec, OpType::save_statevec_dict, OpType::save_densmat, + OpType::save_probs, OpType::save_probs_ket, OpType::save_amps, + OpType::save_amps_sq, OpType::save_stabilizer, OpType::save_clifford, + OpType::save_unitary, OpType::save_mps, OpType::save_superop}; -inline std::ostream& operator<<(std::ostream& stream, const OpType& type) { +inline std::ostream &operator<<(std::ostream &stream, const OpType &type) { switch (type) { case OpType::gate: stream << "gate"; @@ -189,40 +231,39 @@ inline std::ostream& operator<<(std::ostream& stream, const OpType& type) { return stream; } - -inline std::ostream& operator<<(std::ostream& stream, const DataSubType& subtype) { +inline std::ostream &operator<<(std::ostream &stream, + const DataSubType &subtype) { switch (subtype) { - case DataSubType::single: - stream << "single"; - break; - case DataSubType::c_single: - stream << "c_single"; - break; - case DataSubType::list: - stream << "list"; - break; - case DataSubType::c_list: - stream << "c_list"; - break; - case DataSubType::accum: - stream << "accum"; - break; - case DataSubType::c_accum: - stream << "c_accum"; - break; - case DataSubType::average: - stream << "average"; - break; - case DataSubType::c_average: - stream << "c_average"; - break; - default: - stream << "unknown"; + case DataSubType::single: + stream << "single"; + break; + case DataSubType::c_single: + stream << "c_single"; + break; + case DataSubType::list: + stream << "list"; + break; + case DataSubType::c_list: + stream << "c_list"; + break; + case DataSubType::accum: + stream << "accum"; + break; + case DataSubType::c_accum: + stream << "c_accum"; + break; + case DataSubType::average: + stream << "average"; + break; + case DataSubType::c_average: + stream << "c_average"; + break; + default: + stream << "unknown"; } return stream; } - //------------------------------------------------------------------------------ // Op Class //------------------------------------------------------------------------------ @@ -234,17 +275,19 @@ struct Op { reg_t qubits; // qubits operation acts on std::vector regs; // list of qubits for matrixes std::vector params; // real or complex params for gates - std::vector int_params; // integer parameters - std::vector string_params; // used for label, control-flow, and boolean functions + std::vector int_params; // integer parameters + std::vector + string_params; // used for label, control-flow, and boolean functions // Conditional Operations bool conditional = false; // is gate conditional gate - uint_t conditional_reg; // (opt) the (single) register location to look up for conditional - RegComparison bfunc; // (opt) boolean function relation + uint_t conditional_reg; // (opt) the (single) register location to look up for + // conditional + RegComparison bfunc; // (opt) boolean function relation // Measurement - reg_t memory; // (opt) register operation it acts on (measure) - reg_t registers; // (opt) register locations it acts on (measure, conditional) + reg_t memory; // (opt) register operation it acts on (measure) + reg_t registers; // (opt) register locations it acts on (measure, conditional) // Mat and Kraus std::vector mats; @@ -263,22 +306,25 @@ struct Op { DataSubType save_type = DataSubType::single; }; -inline std::ostream& operator<<(std::ostream& s, const Op& op) { +inline std::ostream &operator<<(std::ostream &s, const Op &op) { s << op.name << "["; bool first = true; - for (size_t qubit: op.qubits) { - if (!first) s << ","; + for (size_t qubit : op.qubits) { + if (!first) + s << ","; s << qubit; first = false; } s << "],["; first = true; - for (reg_t reg: op.regs) { - if (!first) s << ","; + for (reg_t reg : op.regs) { + if (!first) + s << ","; s << "["; bool first0 = true; - for (size_t qubit: reg) { - if (!first0) s << ","; + for (size_t qubit : reg) { + if (!first0) + s << ","; s << qubit; first0 = false; } @@ -296,7 +342,8 @@ inline std::ostream& operator<<(std::ostream& s, const Op& op) { // Raise an exception if name string is empty inline void check_empty_name(const Op &op) { if (op.name.empty()) - throw std::invalid_argument(R"(Invalid qobj instruction ("name" is empty).)"); + throw std::invalid_argument( + R"(Invalid qobj instruction ("name" is empty).)"); } // Raise an exception if qubits list is empty @@ -316,8 +363,9 @@ inline void check_empty_params(const Op &op) { // Raise an exception if params is empty inline void check_length_params(const Op &op, const size_t size) { if (op.params.size() != size) - throw std::invalid_argument(R"(Invalid qobj ")" + op.name + - R"(" instruction ("params" is incorrect length).)"); + throw std::invalid_argument( + R"(Invalid qobj ")" + op.name + + R"(" instruction ("params" is incorrect length).)"); } // Raise an exception if qubits list contains duplications @@ -333,7 +381,8 @@ inline void check_duplicate_qubits(const Op &op) { // Generator functions //------------------------------------------------------------------------------ -inline Op make_initialize(const reg_t &qubits, const std::vector &init_data) { +inline Op make_initialize(const reg_t &qubits, + const std::vector &init_data) { Op op; op.type = OpType::initialize; op.name = "initialize"; @@ -342,7 +391,8 @@ inline Op make_initialize(const reg_t &qubits, const std::vector &ini return op; } -inline Op make_unitary(const reg_t &qubits, const cmatrix_t &mat, const int_t conditional = -1, std::string label = "") { +inline Op make_unitary(const reg_t &qubits, const cmatrix_t &mat, + const int_t conditional = -1, std::string label = "") { Op op; op.type = OpType::matrix; op.name = "unitary"; @@ -357,7 +407,8 @@ inline Op make_unitary(const reg_t &qubits, const cmatrix_t &mat, const int_t co return op; } -inline Op make_unitary(const reg_t &qubits, cmatrix_t &&mat, std::string label = "") { +inline Op make_unitary(const reg_t &qubits, cmatrix_t &&mat, + std::string label = "") { Op op; op.type = OpType::matrix; op.name = "unitary"; @@ -369,7 +420,8 @@ inline Op make_unitary(const reg_t &qubits, cmatrix_t &&mat, std::string label = return op; } -inline Op make_diagonal(const reg_t &qubits, const cvector_t &vec, const std::string label = "") { +inline Op make_diagonal(const reg_t &qubits, const cvector_t &vec, + const std::string label = "") { Op op; op.type = OpType::diagonal_matrix; op.name = "diagonal"; @@ -382,7 +434,8 @@ inline Op make_diagonal(const reg_t &qubits, const cvector_t &vec, const std::st return op; } -inline Op make_diagonal(const reg_t &qubits, cvector_t &&vec, const std::string label = "") { +inline Op make_diagonal(const reg_t &qubits, cvector_t &&vec, + const std::string label = "") { Op op; op.type = OpType::diagonal_matrix; op.name = "diagonal"; @@ -395,7 +448,8 @@ inline Op make_diagonal(const reg_t &qubits, cvector_t &&vec, const std::string return op; } -inline Op make_superop(const reg_t &qubits, const cmatrix_t &mat, const int_t conditional = -1) { +inline Op make_superop(const reg_t &qubits, const cmatrix_t &mat, + const int_t conditional = -1) { Op op; op.type = OpType::superop; op.name = "superop"; @@ -418,7 +472,8 @@ inline Op make_superop(const reg_t &qubits, cmatrix_t &&mat) { return op; } -inline Op make_kraus(const reg_t &qubits, const std::vector &mats, const int_t conditional = -1) { +inline Op make_kraus(const reg_t &qubits, const std::vector &mats, + const int_t conditional = -1) { Op op; op.type = OpType::kraus; op.name = "kraus"; @@ -440,7 +495,8 @@ inline Op make_kraus(const reg_t &qubits, std::vector &&mats) { return op; } -inline Op make_roerror(const reg_t &memory, const std::vector &probs) { +inline Op make_roerror(const reg_t &memory, + const std::vector &probs) { Op op; op.type = OpType::roerror; op.name = "roerror"; @@ -458,7 +514,8 @@ inline Op make_roerror(const reg_t &memory, std::vector &&probs) { return op; } -inline Op make_bfunc(const std::string &mask, const std::string &val, const std::string &relation, const uint_t regidx) { +inline Op make_bfunc(const std::string &mask, const std::string &val, + const std::string &relation, const uint_t regidx) { Op op; op.type = OpType::bfunc; op.name = "bfunc"; @@ -469,39 +526,37 @@ inline Op make_bfunc(const std::string &mask, const std::string &val, const std: // Load single register op.registers.push_back(regidx); - + // Format hex strings Utils::format_hex_inplace(op.string_params[0]); Utils::format_hex_inplace(op.string_params[1]); const stringmap_t comp_table({ - {"==", RegComparison::Equal}, - {"!=", RegComparison::NotEqual}, - {"<", RegComparison::Less}, - {"<=", RegComparison::LessEqual}, - {">", RegComparison::Greater}, - {">=", RegComparison::GreaterEqual}, + {"==", RegComparison::Equal}, + {"!=", RegComparison::NotEqual}, + {"<", RegComparison::Less}, + {"<=", RegComparison::LessEqual}, + {">", RegComparison::Greater}, + {">=", RegComparison::GreaterEqual}, }); auto it = comp_table.find(relation); if (it == comp_table.end()) { std::stringstream msg; - msg << "Invalid bfunc relation string :\"" << it->first << "\"." << std::endl; + msg << "Invalid bfunc relation string :\"" << it->first << "\"." + << std::endl; throw std::invalid_argument(msg.str()); } else { op.bfunc = it->second; } return op; - } -Op make_gate(const std::string &name, - const reg_t &qubits, +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::string &label) { + const int_t conditional, const std::string &label) { Op op; op.type = OpType::gate; op.name = name; @@ -510,7 +565,7 @@ Op make_gate(const std::string &name, if (string_params.size() > 0) op.string_params = string_params; - else if (label != "") + else if (label != "") op.string_params = {label}; else op.string_params = {op.name}; @@ -556,7 +611,7 @@ inline Op make_u3(uint_t qubit, T theta, T phi, T lam) { return op; } -inline Op make_reset(const reg_t & qubits, uint_t state = 0) { +inline Op make_reset(const reg_t &qubits, uint_t state = 0) { Op op; op.type = OpType::reset; op.name = "reset"; @@ -623,31 +678,29 @@ inline Op make_multiplexer(const reg_t &qubits, return op; } -inline Op make_save_state(const reg_t &qubits, - const std::string &name, +inline Op make_save_state(const reg_t &qubits, const std::string &name, const std::string &snapshot_type, const std::string &label) { Op op; op.name = name; // Get subtype - static const std::unordered_map types { - {"save_state", OpType::save_state}, - {"save_statevector", OpType::save_statevec}, - {"save_statevector_dict", OpType::save_statevec_dict}, - {"save_amplitudes", OpType::save_amps}, - {"save_amplitudes_sq", OpType::save_amps_sq}, - {"save_clifford", OpType::save_clifford}, - {"save_probabilities", OpType::save_probs}, - {"save_probabilities_dict", OpType::save_probs_ket}, - {"save_matrix_product_state", OpType::save_mps}, - {"save_unitary", OpType::save_unitary}, - {"save_superop", OpType::save_superop}, - {"save_density_matrix", OpType::save_densmat}, - {"save_stabilizer", OpType::save_stabilizer}, - {"save_expval", OpType::save_expval}, - {"save_expval_var", OpType::save_expval_var} - }; + static const std::unordered_map types{ + {"save_state", OpType::save_state}, + {"save_statevector", OpType::save_statevec}, + {"save_statevector_dict", OpType::save_statevec_dict}, + {"save_amplitudes", OpType::save_amps}, + {"save_amplitudes_sq", OpType::save_amps_sq}, + {"save_clifford", OpType::save_clifford}, + {"save_probabilities", OpType::save_probs}, + {"save_probabilities_dict", OpType::save_probs_ket}, + {"save_matrix_product_state", OpType::save_mps}, + {"save_unitary", OpType::save_unitary}, + {"save_superop", OpType::save_superop}, + {"save_density_matrix", OpType::save_densmat}, + {"save_stabilizer", OpType::save_stabilizer}, + {"save_expval", OpType::save_expval}, + {"save_expval_var", OpType::save_expval_var}}; auto type_it = types.find(name); if (type_it == types.end()) { @@ -657,15 +710,11 @@ inline Op make_save_state(const reg_t &qubits, op.type = type_it->second; // Get subtype - static const std::unordered_map subtypes { - {"single", DataSubType::single}, - {"c_single", DataSubType::c_single}, - {"average", DataSubType::average}, - {"c_average", DataSubType::c_average}, - {"list", DataSubType::list}, - {"c_list", DataSubType::c_list}, - {"accum", DataSubType::accum}, - {"c_accum", DataSubType::c_accum}, + static const std::unordered_map subtypes{ + {"single", DataSubType::single}, {"c_single", DataSubType::c_single}, + {"average", DataSubType::average}, {"c_average", DataSubType::c_average}, + {"list", DataSubType::list}, {"c_list", DataSubType::c_list}, + {"accum", DataSubType::accum}, {"c_accum", DataSubType::c_accum}, }; auto subtype_it = subtypes.find(snapshot_type); @@ -674,7 +723,7 @@ inline Op make_save_state(const reg_t &qubits, "\" in save data instruction."); } op.save_type = subtype_it->second; - + op.string_params.emplace_back(label); op.qubits = qubits; @@ -682,8 +731,7 @@ inline Op make_save_state(const reg_t &qubits, return op; } -inline Op make_save_amplitudes(const reg_t &qubits, - const std::string &name, +inline Op make_save_amplitudes(const reg_t &qubits, const std::string &name, const std::vector &base_type, const std::string &snapshot_type, const std::string &label) { @@ -692,8 +740,7 @@ inline Op make_save_amplitudes(const reg_t &qubits, return op; } -inline Op make_save_expval(const reg_t &qubits, - const std::string &name, +inline Op make_save_expval(const reg_t &qubits, const std::string &name, const std::vector pauli_strings, const std::vector coeff_reals, const std::vector coeff_imags, @@ -706,7 +753,8 @@ inline Op make_save_expval(const reg_t &qubits, auto op = make_save_state(qubits, name, snapshot_type, label); for (uint_t i = 0; i < pauli_strings.size(); ++i) - op.expval_params.emplace_back(pauli_strings[i], coeff_reals[i], coeff_imags[i]); + op.expval_params.emplace_back(pauli_strings[i], coeff_reals[i], + coeff_imags[i]); if (op.expval_params.empty()) { std::string pauli(op.qubits.size(), 'I'); @@ -715,12 +763,13 @@ inline Op make_save_expval(const reg_t &qubits, return op; } -template -inline Op make_set_vector(const reg_t &qubits, const std::string &name, const inputdata_t ¶ms) { +template +inline Op make_set_vector(const reg_t &qubits, const std::string &name, + const inputdata_t ¶ms) { Op op; // Get type - static const std::unordered_map types { - {"set_statevector", OpType::set_statevec}, + static const std::unordered_map types{ + {"set_statevector", OpType::set_statevec}, }; auto type_it = types.find(name); if (type_it == types.end()) { @@ -730,19 +779,21 @@ inline Op make_set_vector(const reg_t &qubits, const std::string &name, const in op.type = type_it->second; op.name = name; op.qubits = qubits; - op.params = Parser::template get_list_elem>(params, 0); + op.params = + Parser::template get_list_elem>( + params, 0); return op; } -template -inline Op make_set_matrix(const reg_t &qubits, const std::string &name, const inputdata_t ¶ms) { +template +inline Op make_set_matrix(const reg_t &qubits, const std::string &name, + const inputdata_t ¶ms) { Op op; // Get type - static const std::unordered_map types { - {"set_density_matrix", OpType::set_densmat}, - {"set_unitary", OpType::set_unitary}, - {"set_superop", OpType::set_superop} - }; + static const std::unordered_map types{ + {"set_density_matrix", OpType::set_densmat}, + {"set_unitary", OpType::set_unitary}, + {"set_superop", OpType::set_superop}}; auto type_it = types.find(name); if (type_it == types.end()) { throw std::runtime_error("Invalid data type \"" + name + @@ -751,38 +802,45 @@ inline Op make_set_matrix(const reg_t &qubits, const std::string &name, const in op.type = type_it->second; op.name = name; op.qubits = qubits; - op.mats.push_back(Parser::template get_list_elem(params, 0)); + op.mats.push_back( + Parser::template get_list_elem(params, 0)); return op; } -template -inline Op make_set_mps(const reg_t &qubits, const std::string &name, const inputdata_t ¶ms) { +template +inline Op make_set_mps(const reg_t &qubits, const std::string &name, + const inputdata_t ¶ms) { Op op; op.type = OpType::set_mps; op.name = name; op.qubits = qubits; - op.mps = Parser::template get_list_elem(params, 0); + op.mps = + Parser::template get_list_elem(params, 0); return op; } -template -inline Op make_set_clifford(const reg_t &qubits, const std::string &name, const inputdata_t ¶ms) { +template +inline Op make_set_clifford(const reg_t &qubits, const std::string &name, + const inputdata_t ¶ms) { Op op; op.type = OpType::set_stabilizer; op.name = name; op.qubits = qubits; - op.clifford = Parser::template get_list_elem(params, 0); + op.clifford = Parser::template get_list_elem( + params, 0); return op; } -inline Op make_jump(const reg_t &qubits, const std::vector ¶ms, const int_t conditional) { +inline Op make_jump(const reg_t &qubits, const std::vector ¶ms, + const int_t conditional) { Op op; op.type = OpType::jump; op.name = "jump"; op.qubits = qubits; op.string_params = params; if (op.string_params.empty()) - throw std::invalid_argument(std::string("Invalid jump (\"params\" field missing).")); + throw std::invalid_argument( + std::string("Invalid jump (\"params\" field missing).")); if (conditional >= 0) { op.conditional = true; @@ -792,19 +850,22 @@ inline Op make_jump(const reg_t &qubits, const std::vector ¶ms, return op; } -inline Op make_mark(const reg_t &qubits, const std::vector ¶ms) { +inline Op make_mark(const reg_t &qubits, + const std::vector ¶ms) { Op op; op.type = OpType::mark; op.name = "mark"; op.qubits = qubits; op.string_params = params; if (op.string_params.empty()) - throw std::invalid_argument(std::string("Invalid mark (\"params\" field missing).")); + throw std::invalid_argument( + std::string("Invalid mark (\"params\" field missing).")); return op; } -inline Op make_measure(const reg_t &qubits, const reg_t &memory, const reg_t ®isters) { +inline Op make_measure(const reg_t &qubits, const reg_t &memory, + const reg_t ®isters) { Op op; op.type = OpType::measure; op.name = "measure"; @@ -814,7 +875,8 @@ inline Op make_measure(const reg_t &qubits, const reg_t &memory, const reg_t &re return op; } -inline Op make_qerror_loc(const reg_t &qubits, const std::string &label, const int_t conditional = -1) { +inline Op make_qerror_loc(const reg_t &qubits, const std::string &label, + const int_t conditional = -1) { Op op; op.type = OpType::qerror_loc; op.name = label; @@ -826,99 +888,97 @@ inline Op make_qerror_loc(const reg_t &qubits, const std::string &label, const i return op; } - //------------------------------------------------------------------------------ // JSON conversion //------------------------------------------------------------------------------ // Main deserialization functions -template -Op input_to_op(const inputdata_t& input); // Partial TODO -json_t op_to_json(const Op &op); // Partial TODO +template +Op input_to_op(const inputdata_t &input); // Partial TODO +json_t op_to_json(const Op &op); // Partial TODO -inline void from_json(const json_t &js, Op &op) {op = input_to_op(js);} +inline void from_json(const json_t &js, Op &op) { op = input_to_op(js); } -inline void to_json(json_t &js, const Op &op) { js = op_to_json(op);} +inline void to_json(json_t &js, const Op &op) { js = op_to_json(op); } -void to_json(json_t &js, const DataSubType& type); +void to_json(json_t &js, const DataSubType &type); // Standard operations -template -Op input_to_op_gate(const inputdata_t& input); -template -Op input_to_op_barrier(const inputdata_t& input); -template -Op input_to_op_measure(const inputdata_t& input); -template -Op input_to_op_reset(const inputdata_t& input); -template -Op input_to_op_bfunc(const inputdata_t& input); -template -Op input_to_op_initialize(const inputdata_t& input); -template -Op input_to_op_pauli(const inputdata_t& input); +template +Op input_to_op_gate(const inputdata_t &input); +template +Op input_to_op_barrier(const inputdata_t &input); +template +Op input_to_op_measure(const inputdata_t &input); +template +Op input_to_op_reset(const inputdata_t &input); +template +Op input_to_op_bfunc(const inputdata_t &input); +template +Op input_to_op_initialize(const inputdata_t &input); +template +Op input_to_op_pauli(const inputdata_t &input); // Set state -template -Op input_to_op_set_vector(const inputdata_t& input, OpType op_type); +template +Op input_to_op_set_vector(const inputdata_t &input, OpType op_type); -template -Op input_to_op_set_matrix(const inputdata_t& input, OpType op_type); +template +Op input_to_op_set_matrix(const inputdata_t &input, OpType op_type); -template -Op input_to_op_set_clifford(const inputdata_t& input, OpType op_type); +template +Op input_to_op_set_clifford(const inputdata_t &input, OpType op_type); -template -Op input_to_op_set_mps(const inputdata_t& input, OpType op_type); +template +Op input_to_op_set_mps(const inputdata_t &input, OpType op_type); // Save data -template -Op input_to_op_save_default(const inputdata_t& input, OpType op_type); -template -Op input_to_op_save_expval(const inputdata_t& input, bool variance); -template -Op input_to_op_save_amps(const inputdata_t& input, bool squared); +template +Op input_to_op_save_default(const inputdata_t &input, OpType op_type); +template +Op input_to_op_save_expval(const inputdata_t &input, bool variance); +template +Op input_to_op_save_amps(const inputdata_t &input, bool squared); // Control-Flow -template -Op input_to_op_jump(const inputdata_t& input); -template -Op input_to_op_mark(const inputdata_t& input); +template +Op input_to_op_jump(const inputdata_t &input); +template +Op input_to_op_mark(const inputdata_t &input); // Matrices -template -Op input_to_op_unitary(const inputdata_t& input); -template -Op input_to_op_diagonal(const inputdata_t& input); -template -Op input_to_op_superop(const inputdata_t& input); -template -Op input_to_op_multiplexer(const inputdata_t& input); -template -Op input_to_op_kraus(const inputdata_t& input); -template -Op input_to_op_noise_switch(const inputdata_t& input); -template -Op input_to_op_qerror_loc(const inputdata_t& input); +template +Op input_to_op_unitary(const inputdata_t &input); +template +Op input_to_op_diagonal(const inputdata_t &input); +template +Op input_to_op_superop(const inputdata_t &input); +template +Op input_to_op_multiplexer(const inputdata_t &input); +template +Op input_to_op_kraus(const inputdata_t &input); +template +Op input_to_op_noise_switch(const inputdata_t &input); +template +Op input_to_op_qerror_loc(const inputdata_t &input); // Classical bits -template -Op input_to_op_roerror(const inputdata_t& input); +template +Op input_to_op_roerror(const inputdata_t &input); // Optional instruction parameters -enum class Allowed {Yes, No}; - -template -void add_conditional(const Allowed val, Op& op, const inputdata_t& input); +enum class Allowed { Yes, No }; +template +void add_conditional(const Allowed val, Op &op, const inputdata_t &input); //------------------------------------------------------------------------------ // Implementation: JSON deserialization //------------------------------------------------------------------------------ // TODO: convert if-else to switch -template -Op input_to_op(const inputdata_t& input) { +template +Op input_to_op(const inputdata_t &input) { // load operation identifier std::string name; Parser::get_value(name, "name", input); @@ -1001,7 +1061,7 @@ Op input_to_op(const inputdata_t& input) { if (name == "pauli") return input_to_op_pauli(input); - //Control-flow + // Control-flow if (name == "jump") return input_to_op_jump(input); if (name == "mark") @@ -1032,32 +1092,30 @@ 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; js = ss.str(); } - -void to_json(json_t &js, const DataSubType& subtype) { +void to_json(json_t &js, const DataSubType &subtype) { std::stringstream ss; ss << subtype; js = ss.str(); } - //------------------------------------------------------------------------------ // Implementation: Gates, measure, reset deserialization //------------------------------------------------------------------------------ -template -void add_conditional(const Allowed allowed, Op& op, const inputdata_t& input) { +template +void add_conditional(const Allowed allowed, Op &op, const inputdata_t &input) { // Check conditional if (Parser::check_key("conditional", input)) { // If instruction isn't allow to be conditional throw an exception if (allowed == Allowed::No) { - throw std::invalid_argument("Invalid instruction: \"" + op.name + "\" cannot be conditional."); + throw std::invalid_argument("Invalid instruction: \"" + op.name + + "\" cannot be conditional."); } // If instruction is allowed to be conditional add parameters Parser::get_value(op.conditional_reg, "conditional", input); @@ -1065,8 +1123,8 @@ void add_conditional(const Allowed allowed, Op& op, const inputdata_t& input) { } } -template -Op input_to_op_gate(const inputdata_t& input) { +template +Op input_to_op_gate(const inputdata_t &input) { Op op; op.type = OpType::gate; Parser::get_value(op.name, "name", input); @@ -1077,7 +1135,7 @@ Op input_to_op_gate(const inputdata_t& input) { // If label is not specified record the gate name as the label std::string label; Parser::get_value(label, "label", input); - if (label != "") + if (label != "") op.string_params = {label}; else op.string_params = {op.name}; @@ -1098,8 +1156,8 @@ Op input_to_op_gate(const inputdata_t& input) { return op; } -template -Op input_to_op_qerror_loc(const inputdata_t& input) { +template +Op input_to_op_qerror_loc(const inputdata_t &input) { Op op; op.type = OpType::qerror_loc; Parser::get_value(op.name, "label", input); @@ -1108,7 +1166,7 @@ Op input_to_op_qerror_loc(const inputdata_t& input) { return op; } -template +template Op input_to_op_barrier(const inputdata_t &input) { Op op; op.type = OpType::barrier; @@ -1119,8 +1177,8 @@ Op input_to_op_barrier(const inputdata_t &input) { return op; } -template -Op input_to_op_measure(const inputdata_t& input) { +template +Op input_to_op_measure(const inputdata_t &input) { Op op; op.type = OpType::measure; op.name = "measure"; @@ -1135,16 +1193,19 @@ Op input_to_op_measure(const inputdata_t& input) { check_empty_qubits(op); check_duplicate_qubits(op); if (op.memory.empty() == false && op.memory.size() != op.qubits.size()) { - throw std::invalid_argument(R"(Invalid measure operation: "memory" and "qubits" are different lengths.)"); + throw std::invalid_argument( + R"(Invalid measure operation: "memory" and "qubits" are different lengths.)"); } - if (op.registers.empty() == false && op.registers.size() != op.qubits.size()) { - throw std::invalid_argument(R"(Invalid measure operation: "register" and "qubits" are different lengths.)"); + if (op.registers.empty() == false && + op.registers.size() != op.qubits.size()) { + throw std::invalid_argument( + R"(Invalid measure operation: "register" and "qubits" are different lengths.)"); } return op; } -template -Op input_to_op_reset(const inputdata_t& input) { +template +Op input_to_op_reset(const inputdata_t &input) { Op op; op.type = OpType::reset; op.name = "reset"; @@ -1159,8 +1220,8 @@ Op input_to_op_reset(const inputdata_t& input) { return op; } -template -Op input_to_op_initialize(const inputdata_t& input) { +template +Op input_to_op_initialize(const inputdata_t &input) { Op op; op.type = OpType::initialize; op.name = "initialize"; @@ -1176,8 +1237,8 @@ Op input_to_op_initialize(const inputdata_t& input) { check_length_params(op, 1ULL << op.qubits.size()); return op; } -template -Op input_to_op_pauli(const inputdata_t& input){ +template +Op input_to_op_pauli(const inputdata_t &input) { Op op; op.type = OpType::gate; op.name = "pauli"; @@ -1188,7 +1249,7 @@ Op input_to_op_pauli(const inputdata_t& input){ // If label is not specified record the gate name as the label std::string label; Parser::get_value(label, "label", input); - if (label != "") + if (label != "") op.string_params.push_back(label); else op.string_params.push_back(op.name); @@ -1206,16 +1267,19 @@ Op input_to_op_pauli(const inputdata_t& input){ //------------------------------------------------------------------------------ // Implementation: Boolean Functions //------------------------------------------------------------------------------ -template -Op input_to_op_bfunc(const inputdata_t& input) { +template +Op input_to_op_bfunc(const inputdata_t &input) { Op op; op.type = OpType::bfunc; op.name = "bfunc"; op.string_params.resize(2); std::string relation; - Parser::get_value(op.string_params[0], "mask", input); // mask hexadecimal string - Parser::get_value(op.string_params[1], "val", input); // value hexadecimal string - Parser::get_value(relation, "relation", input); // relation string + Parser::get_value(op.string_params[0], "mask", + input); // mask hexadecimal string + Parser::get_value(op.string_params[1], "val", + input); // value hexadecimal string + Parser::get_value(relation, "relation", + input); // relation string // Load single register / memory bit for storing result uint_t tmp; if (Parser::get_value(tmp, "register", input)) { @@ -1224,24 +1288,25 @@ Op input_to_op_bfunc(const inputdata_t& input) { if (Parser::get_value(tmp, "memory", input)) { op.memory.push_back(tmp); } - + // Format hex strings Utils::format_hex_inplace(op.string_params[0]); Utils::format_hex_inplace(op.string_params[1]); const stringmap_t comp_table({ - {"==", RegComparison::Equal}, - {"!=", RegComparison::NotEqual}, - {"<", RegComparison::Less}, - {"<=", RegComparison::LessEqual}, - {">", RegComparison::Greater}, - {">=", RegComparison::GreaterEqual}, + {"==", RegComparison::Equal}, + {"!=", RegComparison::NotEqual}, + {"<", RegComparison::Less}, + {"<=", RegComparison::LessEqual}, + {">", RegComparison::Greater}, + {">=", RegComparison::GreaterEqual}, }); auto it = comp_table.find(relation); if (it == comp_table.end()) { std::stringstream msg; - msg << "Invalid bfunc relation string :\"" << it->first << "\"." << std::endl; + msg << "Invalid bfunc relation string :\"" << it->first << "\"." + << std::endl; throw std::invalid_argument(msg.str()); } else { op.bfunc = it->second; @@ -1252,13 +1317,14 @@ Op input_to_op_bfunc(const inputdata_t& input) { // Validation if (op.registers.empty()) { - throw std::invalid_argument("Invalid measure operation: \"register\" is empty."); + throw std::invalid_argument( + "Invalid measure operation: \"register\" is empty."); } return op; } -template -Op input_to_op_roerror(const inputdata_t& input) { +template +Op input_to_op_roerror(const inputdata_t &input) { Op op; op.type = OpType::roerror; op.name = "roerror"; @@ -1273,8 +1339,8 @@ Op input_to_op_roerror(const inputdata_t& input) { //------------------------------------------------------------------------------ // Implementation: Matrix and Kraus deserialization //------------------------------------------------------------------------------ -template -Op input_to_op_unitary(const inputdata_t& input) { +template +Op input_to_op_unitary(const inputdata_t &input) { Op op; op.type = OpType::matrix; op.name = "unitary"; @@ -1300,8 +1366,8 @@ Op input_to_op_unitary(const inputdata_t& input) { add_conditional(Allowed::Yes, op, input); return op; } -template -Op input_to_op_diagonal(const inputdata_t& input) { +template +Op input_to_op_diagonal(const inputdata_t &input) { Op op; op.type = OpType::diagonal_matrix; op.name = "diagonal"; @@ -1329,8 +1395,8 @@ Op input_to_op_diagonal(const inputdata_t& input) { add_conditional(Allowed::Yes, op, input); return op; } -template -Op input_to_op_superop(const inputdata_t& input) { +template +Op input_to_op_superop(const inputdata_t &input) { // Warning: we don't check superoperator is valid! Op op; op.type = OpType::superop; @@ -1347,8 +1413,8 @@ Op input_to_op_superop(const inputdata_t& input) { } return op; } -template -Op input_to_op_multiplexer(const inputdata_t& input) { +template +Op input_to_op_multiplexer(const inputdata_t &input) { // Parse parameters reg_t qubits; std::vector mats; @@ -1362,8 +1428,8 @@ Op input_to_op_multiplexer(const inputdata_t& input) { add_conditional(Allowed::Yes, op, input); return op; } -template -Op input_to_op_kraus(const inputdata_t& input) { +template +Op input_to_op_kraus(const inputdata_t &input) { Op op; op.type = OpType::kraus; op.name = "kraus"; @@ -1378,8 +1444,8 @@ Op input_to_op_kraus(const inputdata_t& input) { return op; } -template -Op input_to_op_noise_switch(const inputdata_t& input) { +template +Op input_to_op_noise_switch(const inputdata_t &input) { Op op; op.type = OpType::noise_switch; op.name = "noise_switch"; @@ -1392,48 +1458,53 @@ Op input_to_op_noise_switch(const inputdata_t& input) { //------------------------------------------------------------------------------ // Implementation: Set state //------------------------------------------------------------------------------ -template +template Op input_to_op_set_vector(const inputdata_t &input, OpType op_type) { Op op; op.type = op_type; - const inputdata_t& params = Parser::get_value("params", input); - op.params = Parser::template get_list_elem>(params, 0); + const inputdata_t ¶ms = Parser::get_value("params", input); + op.params = + Parser::template get_list_elem>( + params, 0); Parser::get_value(op.name, "name", input); Parser::get_value(op.qubits, "qubits", input); add_conditional(Allowed::No, op, input); return op; } -template +template Op input_to_op_set_matrix(const inputdata_t &input, OpType op_type) { Op op; op.type = op_type; - const inputdata_t& params = Parser::get_value("params", input); - op.mats.push_back(Parser::template get_list_elem(params, 0)); + const inputdata_t ¶ms = Parser::get_value("params", input); + op.mats.push_back( + Parser::template get_list_elem(params, 0)); Parser::get_value(op.name, "name", input); Parser::get_value(op.qubits, "qubits", input); add_conditional(Allowed::No, op, input); return op; } -template +template Op input_to_op_set_clifford(const inputdata_t &input, OpType op_type) { Op op; op.type = op_type; - const inputdata_t& params = Parser::get_value("params", input); - op.clifford = Parser::template get_list_elem(params, 0); + const inputdata_t ¶ms = Parser::get_value("params", input); + op.clifford = Parser::template get_list_elem( + params, 0); Parser::get_value(op.name, "name", input); Parser::get_value(op.qubits, "qubits", input); add_conditional(Allowed::No, op, input); return op; } -template +template Op input_to_op_set_mps(const inputdata_t &input, OpType op_type) { Op op; op.type = op_type; - const inputdata_t& params = Parser::get_value("params", input); - op.mps = Parser::template get_list_elem(params, 0); + const inputdata_t ¶ms = Parser::get_value("params", input); + op.mps = + Parser::template get_list_elem(params, 0); Parser::get_value(op.name, "name", input); Parser::get_value(op.qubits, "qubits", input); @@ -1444,22 +1515,18 @@ Op input_to_op_set_mps(const inputdata_t &input, OpType op_type) { //------------------------------------------------------------------------------ // Implementation: Save data deserialization //------------------------------------------------------------------------------ -template -Op input_to_op_save_default(const inputdata_t& input, OpType op_type) { +template +Op input_to_op_save_default(const inputdata_t &input, OpType op_type) { Op op; op.type = op_type; Parser::get_value(op.name, "name", input); // Get subtype - static const std::unordered_map subtypes { - {"single", DataSubType::single}, - {"c_single", DataSubType::c_single}, - {"average", DataSubType::average}, - {"c_average", DataSubType::c_average}, - {"list", DataSubType::list}, - {"c_list", DataSubType::c_list}, - {"accum", DataSubType::accum}, - {"c_accum", DataSubType::c_accum}, + static const std::unordered_map subtypes{ + {"single", DataSubType::single}, {"c_single", DataSubType::c_single}, + {"average", DataSubType::average}, {"c_average", DataSubType::c_average}, + {"list", DataSubType::list}, {"c_list", DataSubType::c_list}, + {"accum", DataSubType::accum}, {"c_accum", DataSubType::c_accum}, }; std::string subtype; Parser::get_value(subtype, "snapshot_type", input); @@ -1469,7 +1536,7 @@ Op input_to_op_save_default(const inputdata_t& input, OpType op_type) { "\" in save data instruction."); } op.save_type = subtype_it->second; - + // Get data key op.string_params.emplace_back(""); Parser::get_value(op.string_params[0], "label", input); @@ -1478,26 +1545,30 @@ Op input_to_op_save_default(const inputdata_t& input, OpType op_type) { Parser::get_value(op.qubits, "qubits", input); return op; } -template -Op input_to_op_save_expval(const inputdata_t& input, bool variance) { +template +Op input_to_op_save_expval(const inputdata_t &input, bool variance) { // Initialized default save instruction params - auto op_type = (variance) ? OpType::save_expval_var - : OpType::save_expval; + auto op_type = (variance) ? OpType::save_expval_var : OpType::save_expval; Op op = input_to_op_save_default(input, op_type); // Parse Pauli operator components const auto threshold = 1e-12; // drop small components // Get components - if (Parser::check_key("params", input) && Parser::is_array("params", input)) { + if (Parser::check_key("params", input) && + Parser::is_array("params", input)) { for (const auto &comp_ : Parser::get_value("params", input)) { - const auto& comp = Parser::get_as_list(comp_); + const auto &comp = Parser::get_as_list(comp_); // Get complex coefficient - std::vector coeffs = Parser::template get_list_elem>(comp, 1); + std::vector coeffs = + Parser::template get_list_elem>(comp, + 1); if (std::abs(coeffs[0]) > threshold || std::abs(coeffs[1]) > threshold) { - std::string pauli = Parser::template get_list_elem(comp, 0); + std::string pauli = + Parser::template get_list_elem(comp, 0); if (pauli.size() != op.qubits.size()) { - throw std::invalid_argument(std::string("Invalid expectation value save instruction ") + - "(Pauli label does not match qubit number.)."); + throw std::invalid_argument( + std::string("Invalid expectation value save instruction ") + + "(Pauli label does not match qubit number.)."); } op.expval_params.emplace_back(pauli, coeffs[0], coeffs[1]); } @@ -1516,17 +1587,16 @@ Op input_to_op_save_expval(const inputdata_t& input, bool variance) { return op; } -template -Op input_to_op_save_amps(const inputdata_t& input, bool squared) { +template +Op input_to_op_save_amps(const inputdata_t &input, bool squared) { // Initialized default save instruction params - auto op_type = (squared) ? OpType::save_amps_sq - : OpType::save_amps; + auto op_type = (squared) ? OpType::save_amps_sq : OpType::save_amps; Op op = input_to_op_save_default(input, op_type); Parser::get_value(op.int_params, "params", input); return op; } -template +template Op input_to_op_jump(const inputdata_t &input) { Op op; op.type = OpType::jump; @@ -1534,7 +1604,8 @@ Op input_to_op_jump(const inputdata_t &input) { Parser::get_value(op.qubits, "qubits", input); Parser::get_value(op.string_params, "params", input); if (op.string_params.empty()) - throw std::invalid_argument(std::string("Invalid jump (\"params\" field missing).")); + throw std::invalid_argument( + std::string("Invalid jump (\"params\" field missing).")); // Conditional add_conditional(Allowed::Yes, op, input); @@ -1542,7 +1613,7 @@ Op input_to_op_jump(const inputdata_t &input) { return op; } -template +template Op input_to_op_mark(const inputdata_t &input) { Op op; op.type = OpType::mark; @@ -1550,7 +1621,8 @@ Op input_to_op_mark(const inputdata_t &input) { Parser::get_value(op.qubits, "qubits", input); Parser::get_value(op.string_params, "params", input); if (op.string_params.empty()) - throw std::invalid_argument(std::string("Invalid mark (\"params\" field missing).")); + throw std::invalid_argument( + std::string("Invalid mark (\"params\" field missing).")); // Conditional add_conditional(Allowed::No, op, input); @@ -1558,7 +1630,6 @@ Op input_to_op_mark(const inputdata_t &input) { return op; } - //------------------------------------------------------------------------------ } // end namespace Operations //------------------------------------------------------------------------------ diff --git a/src/framework/opset.hpp b/src/framework/opset.hpp old mode 100755 new mode 100644 index 4516c1c0e5..92cc3e2b15 --- a/src/framework/opset.hpp +++ b/src/framework/opset.hpp @@ -15,8 +15,8 @@ #ifndef _aer_framework_opset_hpp_ #define _aer_framework_opset_hpp_ -#include #include "framework/operations.hpp" +#include namespace AER { namespace Operations { @@ -31,7 +31,8 @@ class OpSet { // Hash function so that we can use an enum class as a std::unordered_set // key on older C++11 compilers like GCC 5. struct EnumClassHash { - template size_t operator()(T t) const { + template + size_t operator()(T t) const { return static_cast(t); } }; @@ -41,8 +42,8 @@ class OpSet { using optypeset_t = std::unordered_set; // Public data members - optypeset_t optypes; // A set of op types - stringset_t gates; // A set of names for OpType::gates + optypeset_t optypes; // A set of op types + stringset_t gates; // A set of names for OpType::gates OpSet() = default; diff --git a/src/framework/pybind_basics.hpp b/src/framework/pybind_basics.hpp old mode 100755 new mode 100644 index e32f214482..cfcb1f2fe5 --- a/src/framework/pybind_basics.hpp +++ b/src/framework/pybind_basics.hpp @@ -33,36 +33,48 @@ namespace AerToPy { // Template specialization is used with this function for adding custom // conversion for other types // NOTE: Can this function be replaced by overload py::cast for custom types? -template py::object to_python(T &&obj); +template +py::object to_python(T &&obj); // Move a matrix to Python via conversion to Numpy array -template py::object to_python(matrix &&obj); +template +py::object to_python(matrix &&obj); // Move a Vector to Python via conversion to Numpy array -template py::object to_python(AER::Vector &&obj); +template +py::object to_python(AER::Vector &&obj); // Move a Vector to Python via recusivly calling to_python on elements -template py::object to_python(std::vector &&obj); +template +py::object to_python(std::vector &&obj); -// Move an Unordered string map to Python object by calling to_python on elements -template py::object to_python(std::unordered_map &&obj); +// Move an Unordered string map to Python object by calling to_python on +// elements +template +py::object to_python(std::unordered_map &&obj); // Move an Unordered string map into an existing Python dict template void add_to_python(py::dict &pydata, std::unordered_map &&obj); - // Template specialization for moving numeric std::vectors to Numpy arrays -template <> py::object to_python(std::vector &&obj); -template <> py::object to_python(std::vector &&obj); -template <> py::object to_python(std::vector &&obj); -template <> py::object to_python(std::vector &&obj); -template <> py::object to_python(std::vector> &&obj); -template <> py::object to_python(std::vector> &&obj); +template <> +py::object to_python(std::vector &&obj); +template <> +py::object to_python(std::vector &&obj); +template <> +py::object to_python(std::vector &&obj); +template <> +py::object to_python(std::vector &&obj); +template <> +py::object to_python(std::vector> &&obj); +template <> +py::object to_python(std::vector> &&obj); // Template specialization for JSON // NOTE: this copies rather than moves -template <> py::object to_python(json_t &&obj); +template <> +py::object to_python(json_t &&obj); //------------------------------------------------------------------------------ // Convert To Numpy Arrays @@ -109,7 +121,7 @@ py::object to_python(std::unordered_map &&obj) { template void add_to_python(py::dict &pydata, std::unordered_map &&obj) { - for(auto& elt : obj) { + for (auto &elt : obj) { pydata[elt.first.data()] = to_python(std::move(elt.second)); } } @@ -117,7 +129,7 @@ void add_to_python(py::dict &pydata, std::unordered_map &&obj) { template py::object to_python(std::vector &&obj) { py::list pydata; - for(auto& elt : obj) { + for (auto &elt : obj) { pydata.append(to_python(std::move(elt))); } return std::move(pydata); @@ -169,39 +181,39 @@ py::object to_python(std::vector> &&obj) { template py::array_t to_numpy(matrix &&src) { - std::array shape {static_cast(src.GetRows()), - static_cast(src.GetColumns())}; - matrix* src_ptr = new matrix(std::move(src)); - auto capsule = py::capsule(src_ptr, [](void* p) { delete reinterpret_cast*>(p); }); + std::array shape{static_cast(src.GetRows()), + static_cast(src.GetColumns())}; + matrix *src_ptr = new matrix(std::move(src)); + auto capsule = py::capsule( + src_ptr, [](void *p) { delete reinterpret_cast *>(p); }); return py::array_t(shape, src_ptr->data(), capsule); } template py::array_t to_numpy(AER::Vector &&src) { - AER::Vector* src_ptr = new AER::Vector(std::move(src)); - auto capsule = py::capsule(src_ptr, [](void* p) { - delete reinterpret_cast*>(p); - }); + AER::Vector *src_ptr = new AER::Vector(std::move(src)); + auto capsule = py::capsule( + src_ptr, [](void *p) { delete reinterpret_cast *>(p); }); return py::array_t( - src_ptr->size(), // shape of array - src_ptr->data(), // c-style contiguous strides for vector - capsule // numpy array references this parent + src_ptr->size(), // shape of array + src_ptr->data(), // c-style contiguous strides for vector + capsule // numpy array references this parent ); } - template py::array_t to_numpy(std::vector &&src) { - std::vector* src_ptr = new std::vector(std::move(src)); - auto capsule = py::capsule(src_ptr, [](void* p) { delete reinterpret_cast*>(p); }); + std::vector *src_ptr = new std::vector(std::move(src)); + auto capsule = py::capsule( + src_ptr, [](void *p) { delete reinterpret_cast *>(p); }); return py::array_t( - src_ptr->size(), // shape of array - src_ptr->data(), // c-style contiguous strides for vector - capsule // numpy array references this parent + src_ptr->size(), // shape of array + src_ptr->data(), // c-style contiguous strides for vector + capsule // numpy array references this parent ); } //------------------------------------------------------------------------------ -} // end namespace AerToPy +} // end namespace AerToPy //------------------------------------------------------------------------------ #endif diff --git a/src/framework/pybind_casts.hpp b/src/framework/pybind_casts.hpp index e74b6d22f6..7e18ee30b4 100644 --- a/src/framework/pybind_casts.hpp +++ b/src/framework/pybind_casts.hpp @@ -16,60 +16,69 @@ #define _aer_framework_pybind_casts_hpp_ #include "../simulators/stabilizer/clifford.hpp" +#include namespace py = pybind11; namespace pybind11 { namespace detail { -template struct type_caster>{ +template +struct type_caster> { using base = type_caster_base>; + public: PYBIND11_TYPE_CASTER(matrix, _("matrix_t")); // Conversion part 1 (Python->C++): - bool load(py::handle src, bool convert){ - // TODO: Check if make sense have to flavors of matrix: F-style and C-style - auto py_matrix = py::cast>(src); - auto c_order = py_matrix.attr("flags").attr("carray").template cast(); - if(py_matrix.ndim() != 2){ - throw std::invalid_argument(std::string("Python: invalid matrix (empty array).")); - } - size_t nrows = py_matrix.shape(0); - size_t ncols = py_matrix.shape(1); - // Matrix looks ok, now we parse it - auto raw_mat = py_matrix.template unchecked<2>(); - if(c_order){ - value = matrix(nrows, ncols, false); - for (size_t r = 0; r < nrows; r++) { - for (size_t c = 0; c < ncols; c++) { - value(r, c) = raw_mat(r, c); - } - } - } else { - value = matrix::copy_from_buffer(nrows, ncols, static_cast(py_matrix.request().ptr)); + bool load(py::handle src, bool convert) { + // TODO: Check if make sense have to flavors of matrix: F-style and C-style + auto py_matrix = py::cast>(src); + auto c_order = py_matrix.attr("flags").attr("carray").template cast(); + if (py_matrix.ndim() != 2) { + throw std::invalid_argument( + std::string("Python: invalid matrix (empty array).")); + } + size_t nrows = py_matrix.shape(0); + size_t ncols = py_matrix.shape(1); + // Matrix looks ok, now we parse it + auto raw_mat = py_matrix.template unchecked<2>(); + if (c_order) { + value = matrix(nrows, ncols, false); + for (size_t r = 0; r < nrows; r++) { + for (size_t c = 0; c < ncols; c++) { + value(r, c) = raw_mat(r, c); + } } - return true; + } else { + value = matrix::copy_from_buffer( + nrows, ncols, static_cast(py_matrix.request().ptr)); + } + return true; } // Conversion part 2 (C++ -> Python): - static py::handle cast(matrix, py::return_value_policy policy, py::handle parent){ - throw std::runtime_error("Casting from matrix to python not supported."); + static py::handle cast(matrix, py::return_value_policy policy, + py::handle parent) { + throw std::runtime_error("Casting from matrix to python not supported."); } }; -template <> struct type_caster{ - using base = type_caster_base; +template <> +struct type_caster { + using base = type_caster_base; + public: - PYBIND11_TYPE_CASTER(AER::Clifford::Clifford, _("clifford")); - // Conversion part 1 (Python->C++): - bool load(py::handle src, bool convert){ - AER::Clifford::build_from(src, value); - return true; - } - // Conversion part 2 (C++ -> Python): - static py::handle cast(AER::Clifford::Clifford, py::return_value_policy policy, py::handle parent){ - throw std::runtime_error("Casting from Clifford to python not supported."); - } + PYBIND11_TYPE_CASTER(AER::Clifford::Clifford, _("clifford")); + // Conversion part 1 (Python->C++): + bool load(py::handle src, bool convert) { + AER::Clifford::build_from(src, value); + return true; + } + // Conversion part 2 (C++ -> Python): + static py::handle cast(AER::Clifford::Clifford, + py::return_value_policy policy, py::handle parent) { + throw std::runtime_error("Casting from Clifford to python not supported."); + } }; -} -} +} // namespace detail +} // namespace pybind11 #endif // _aer_framework_pybind_casts_hpp_ \ No newline at end of file diff --git a/src/framework/pybind_json.hpp b/src/framework/pybind_json.hpp old mode 100755 new mode 100644 index 6aa9dc89da..7ac889c3c2 --- a/src/framework/pybind_json.hpp +++ b/src/framework/pybind_json.hpp @@ -26,18 +26,17 @@ #include #include #include -#include #include -#include #include +#include #include "misc/warnings.hpp" DISABLE_WARNING_PUSH -#include #include -#include #include #include +#include +#include #include DISABLE_WARNING_POP @@ -109,9 +108,9 @@ json_t numpy_to_json_2d(py::array_t arr); template json_t numpy_to_json_3d(py::array_t arr); -json_t iterable_to_json_list(const py::handle& obj); +json_t iterable_to_json_list(const py::handle &obj); -} //end namespace JSON +} // end namespace JSON /******************************************************************************* * @@ -125,190 +124,195 @@ json_t iterable_to_json_list(const py::handle& obj); template json_t JSON::numpy_to_json_1d(py::array_t arr) { - py::buffer_info buf = arr.request(); - if (buf.ndim != 1) { - throw std::runtime_error("Number of dims must be 1"); - } + py::buffer_info buf = arr.request(); + if (buf.ndim != 1) { + throw std::runtime_error("Number of dims must be 1"); + } - T *ptr = (T *) buf.ptr; - size_t D0 = buf.shape[0]; + T *ptr = (T *)buf.ptr; + size_t D0 = buf.shape[0]; - std::vector tbr; // to be returned - for (size_t n0 = 0; n0 < D0; n0++) - tbr.push_back(ptr[n0]); + std::vector tbr; // to be returned + for (size_t n0 = 0; n0 < D0; n0++) + tbr.push_back(ptr[n0]); - return std::move(tbr); + return std::move(tbr); } template json_t JSON::numpy_to_json_2d(py::array_t arr) { - py::buffer_info buf = arr.request(); - if (buf.ndim != 2) { - throw std::runtime_error("Number of dims must be 2"); - } - - T *ptr = (T *) buf.ptr; - size_t D0 = buf.shape[0]; - size_t D1 = buf.shape[1]; - - std::vector > tbr; // to be returned - for (size_t n0 = 0; n0 < D0; n0++) { - std::vector tbr1; - for (size_t n1 = 0; n1 < D1; n1++) { - tbr1.push_back(ptr[n1 + D1*n0]); - } - tbr.push_back(tbr1); + py::buffer_info buf = arr.request(); + if (buf.ndim != 2) { + throw std::runtime_error("Number of dims must be 2"); + } + + T *ptr = (T *)buf.ptr; + size_t D0 = buf.shape[0]; + size_t D1 = buf.shape[1]; + + std::vector> tbr; // to be returned + for (size_t n0 = 0; n0 < D0; n0++) { + std::vector tbr1; + for (size_t n1 = 0; n1 < D1; n1++) { + tbr1.push_back(ptr[n1 + D1 * n0]); } + tbr.push_back(tbr1); + } - return std::move(tbr); - + return std::move(tbr); } template json_t JSON::numpy_to_json_3d(py::array_t arr) { - py::buffer_info buf = arr.request(); - if (buf.ndim != 3) { - throw std::runtime_error("Number of dims must be 3"); - } - T *ptr = (T *) buf.ptr; - size_t D0 = buf.shape[0]; - size_t D1 = buf.shape[1]; - size_t D2 = buf.shape[2]; - - // to be returned - std::vector > > tbr; - for (size_t n0 = 0; n0 < D0; n0++) { - std::vector > tbr1; - for (size_t n1 = 0; n1 < D1; n1++) { - std::vector tbr2; - for (size_t n2 = 0; n2 < D2; n2++) { - tbr2.push_back(ptr[n2 + D2*(n1 + D1*n0)]); - } - tbr1.push_back(tbr2); - } - tbr.push_back(tbr1); + py::buffer_info buf = arr.request(); + if (buf.ndim != 3) { + throw std::runtime_error("Number of dims must be 3"); + } + T *ptr = (T *)buf.ptr; + size_t D0 = buf.shape[0]; + size_t D1 = buf.shape[1]; + size_t D2 = buf.shape[2]; + + // to be returned + std::vector>> tbr; + for (size_t n0 = 0; n0 < D0; n0++) { + std::vector> tbr1; + for (size_t n1 = 0; n1 < D1; n1++) { + std::vector tbr2; + for (size_t n2 = 0; n2 < D2; n2++) { + tbr2.push_back(ptr[n2 + D2 * (n1 + D1 * n0)]); + } + tbr1.push_back(tbr2); } + tbr.push_back(tbr1); + } - return std::move(tbr); - + return std::move(tbr); } template json_t JSON::numpy_to_json(py::array_t arr) { - py::buffer_info buf = arr.request(); - - if (buf.ndim == 1) { - return JSON::numpy_to_json_1d(arr); - } else if (buf.ndim == 2) { - return JSON::numpy_to_json_2d(arr); - } else if (buf.ndim == 3) { - return JSON::numpy_to_json_3d(arr); - } else { - throw std::runtime_error("Invalid number of dimensions!"); - } - json_t tbr; - return tbr; + py::buffer_info buf = arr.request(); + + if (buf.ndim == 1) { + return JSON::numpy_to_json_1d(arr); + } else if (buf.ndim == 2) { + return JSON::numpy_to_json_2d(arr); + } else if (buf.ndim == 3) { + return JSON::numpy_to_json_3d(arr); + } else { + throw std::runtime_error("Invalid number of dimensions!"); + } + json_t tbr; + return tbr; } -json_t JSON::iterable_to_json_list(const py::handle& obj){ - json_t js = nl::json::array(); - for (py::handle value: obj) { - js.push_back(value); - } - return js; +json_t JSON::iterable_to_json_list(const py::handle &obj) { + json_t js = nl::json::array(); + for (py::handle value : obj) { + js.push_back(value); + } + return js; } void std::to_json(json_t &js, const py::handle &obj) { - static py::object PyNoiseModel = py::module::import("qiskit_aer.noise.noise_model").attr("NoiseModel"); - static py::object PyQasmQobj = py::module::import("qiskit.qobj.qasm_qobj").attr("QasmQobj"); - static py::object PyQasmQobjHeader = py::module::import("qiskit.qobj.common").attr("QobjExperimentHeader"); - if (py::isinstance(obj)) { - js = obj.cast(); - } else if (py::isinstance(obj)) { - js = obj.cast(); - } else if (py::isinstance(obj)) { - js = obj.cast(); - } else if (py::isinstance(obj)) { - js = obj.cast(); - } else if (py::isinstance(obj) || py::isinstance(obj)) { - js = JSON::iterable_to_json_list(obj); - } else if (py::isinstance(obj)) { - for (auto item : py::cast(obj)) { - js[item.first.cast()] = item.second; - } - } else if (py::isinstance >(obj)) { - js = JSON::numpy_to_json(obj.cast >()); - } else if (py::isinstance > >(obj)) { - js = JSON::numpy_to_json(obj.cast, py::array::c_style> >()); - } else if (obj.is_none()) { - return; - } else if (py::isinstance(obj, PyNoiseModel)){ - std::to_json(js, obj.attr("to_dict")()); - } else if (py::isinstance(obj, PyQasmQobj)){ - std::to_json(js, obj.attr("to_dict")()); - } else if (py::isinstance(obj, PyQasmQobjHeader)){ - std::to_json(js, obj.attr("to_dict")()); + static py::object PyNoiseModel = + py::module::import("qiskit_aer.noise.noise_model").attr("NoiseModel"); + static py::object PyQasmQobj = + py::module::import("qiskit.qobj.qasm_qobj").attr("QasmQobj"); + static py::object PyQasmQobjHeader = + py::module::import("qiskit.qobj.common").attr("QobjExperimentHeader"); + if (py::isinstance(obj)) { + js = obj.cast(); + } else if (py::isinstance(obj)) { + js = obj.cast(); + } else if (py::isinstance(obj)) { + js = obj.cast(); + } else if (py::isinstance(obj)) { + js = obj.cast(); + } else if (py::isinstance(obj) || py::isinstance(obj)) { + js = JSON::iterable_to_json_list(obj); + } else if (py::isinstance(obj)) { + for (auto item : py::cast(obj)) { + js[item.first.cast()] = item.second; + } + } else if (py::isinstance>(obj)) { + js = JSON::numpy_to_json( + obj.cast>()); + } else if (py::isinstance>>(obj)) { + js = JSON::numpy_to_json( + obj.cast, py::array::c_style>>()); + } else if (obj.is_none()) { + return; + } else if (py::isinstance(obj, PyNoiseModel)) { + std::to_json(js, obj.attr("to_dict")()); + } else if (py::isinstance(obj, PyQasmQobj)) { + std::to_json(js, obj.attr("to_dict")()); + } else if (py::isinstance(obj, PyQasmQobjHeader)) { + std::to_json(js, obj.attr("to_dict")()); + } else { + auto type_str = std::string(py::str(obj.get_type())); + if (type_str == "" || + type_str == "" || + type_str == "" || + type_str == "") { + auto tmp = obj.cast>(); + js.push_back(tmp.real()); + js.push_back(tmp.imag()); + } else if (type_str == "" || + type_str == "" || + type_str == "" || + type_str == "") { + js = obj.cast(); + } else if (type_str == "" || + type_str == "") { + js = obj.cast(); + } else if (py::isinstance( + obj)) { // last one to avoid intercepting numpy arrays, etc + js = JSON::iterable_to_json_list(obj); } else { - auto type_str = std::string(py::str(obj.get_type())); - if ( type_str == "" - || type_str == "" - || type_str == "" - || type_str == "" ) { - auto tmp = obj.cast>(); - js.push_back(tmp.real()); - js.push_back(tmp.imag()); - } else if ( type_str == "" - || type_str == "" - || type_str == "" - || type_str == "" ) { - js = obj.cast(); - } else if ( type_str == "" - || type_str == "" ) { - js = obj.cast(); - } else if ( py::isinstance(obj) ){ // last one to avoid intercepting numpy arrays, etc - js = JSON::iterable_to_json_list(obj); - } else { - throw std::runtime_error("to_json not implemented for this type of object: " + std::string(py::str(obj.get_type()))); - } + throw std::runtime_error( + "to_json not implemented for this type of object: " + + std::string(py::str(obj.get_type()))); } + } } void std::from_json(const json_t &js, py::object &o) { - if (js.is_boolean()) { - o = py::bool_(js.get()); - } else if (js.is_number()) { - if (js.is_number_float()) { - o = py::float_(js.get()); - } else if (js.is_number_unsigned()) { - o = py::int_(js.get()); - } else { - o = py::int_(js.get()); - } - } else if (js.is_string()) { - o = py::str(js.get()); - } else if (js.is_array()) { - std::vector obj(js.size()); - for (auto i = 0; i < js.size(); i++) - { - py::object tmp; - from_json(js[i], tmp); - obj[i] = tmp; - } - o = py::cast(obj); - } else if (js.is_object()) { - py::dict obj; - for (json_t::const_iterator it = js.cbegin(); it != js.cend(); ++it) - { - py::object tmp; - from_json(it.value(), tmp); - obj[py::str(it.key())] = tmp; - } - o = std::move(obj); - } else if (js.is_null()) { - o = py::none(); + if (js.is_boolean()) { + o = py::bool_(js.get()); + } else if (js.is_number()) { + if (js.is_number_float()) { + o = py::float_(js.get()); + } else if (js.is_number_unsigned()) { + o = py::int_(js.get()); } else { - throw std::runtime_error("from_json not implemented for this json::type: " + js.dump()); + o = py::int_(js.get()); + } + } else if (js.is_string()) { + o = py::str(js.get()); + } else if (js.is_array()) { + std::vector obj(js.size()); + for (auto i = 0; i < js.size(); i++) { + py::object tmp; + from_json(js[i], tmp); + obj[i] = tmp; + } + o = py::cast(obj); + } else if (js.is_object()) { + py::dict obj; + for (json_t::const_iterator it = js.cbegin(); it != js.cend(); ++it) { + py::object tmp; + from_json(it.value(), tmp); + obj[py::str(it.key())] = tmp; } + o = std::move(obj); + } else if (js.is_null()) { + o = py::none(); + } else { + throw std::runtime_error("from_json not implemented for this json::type: " + + js.dump()); + } } //------------------------------------------------------------------------------ diff --git a/src/framework/python_parser.hpp b/src/framework/python_parser.hpp index e2867a8a0c..1e089cd349 100644 --- a/src/framework/python_parser.hpp +++ b/src/framework/python_parser.hpp @@ -19,136 +19,139 @@ #include "json_parser.hpp" #include "pybind_json.hpp" -namespace AER{ +namespace AER { template <> struct Parser { - Parser() = delete; - - static bool check_key(const std::string& key, const py::handle& po){ - if(py::isinstance(po)){ - return !py::cast(po)[key.c_str()].is_none(); - } - return py::hasattr(po, key.c_str()); - } - - static bool check_keys(const std::vector& keys, const py::handle& po) { - bool pass = true; - for (const auto &s : keys){ - pass &= check_key(s, po); - } - return pass; - } - - static py::object get_py_value(const std::string& key, const py::handle& po){ - if(py::isinstance(po)){ - return py::cast(po)[key.c_str()]; - } - return po.attr(key.c_str()); - } - - static bool get_value(py::object& var, const std::string& key, const py::handle& po) { - if(check_key(key, po)) { - var = get_py_value(key, po); - return true; - } else { - return false; - } - } - - template - static bool get_value(T &var, const std::string& key, const py::handle& po){ - if(check_key(key, po)) { - var = get_py_value(key, po).cast(); - return true; - } else { - return false; - } - } - - static void convert_to_json(json_t &var, const py::handle& po){ - if(py::hasattr(po, "to_dict")){ - std::to_json(var, po.attr("to_dict")()); - }else if(py::isinstance(po)){ - var = nl::json::array(); - for(auto item: po){ - json_t item_js; - convert_to_json(item_js, item); - var.push_back(item_js); - } - }else{ - std::to_json(var, po); - } - } - - static py::object get_value(const std::string& key, const py::handle& po){ - return get_py_value(key, po); - } - - static bool is_array(const py::handle& po){ - return py::isinstance(po) || py::isinstance(po); - } - - static bool is_array(const std::string& key, const py::handle& po) { - py::object the_list = get_py_value(key, po); - return is_array(the_list); - } - - static bool is_list_like(const py::handle& po){ - return is_array(po) || py::isinstance(po); - } - - static py::list get_as_list(const py::handle& po){ - if(!is_list_like(po)){ - throw std::runtime_error("Object is not list like!"); - } - return py::cast(po); - } - - static py::list get_list(const std::string& key, const py::handle& po){ - py::object the_list = get_py_value(key, po); - if(!is_array(the_list)){ - throw std::runtime_error("Object " + key + "is not a list!"); - } - return py::cast(the_list); - } - - static bool is_number(const py::handle& po){ - return py::isinstance(po) || py::isinstance(po); - } - - static bool is_number(const std::string& key, const py::handle& po) { - py::object key_po = get_py_value(key, po); - return is_number(key_po); - } - - template - static T get_list_elem(const py::list& po, unsigned int i){ - return py::cast(po[i]).cast(); - } - - template - static T get_list_elem(const py::handle& po, unsigned int i){ - auto py_list = get_as_list(po); - return get_list_elem(py_list, i); - } - - static std::string dump(const py::handle& po){ - json_t js; - convert_to_json(js, po); - return js.dump(); - } + Parser() = delete; + + static bool check_key(const std::string &key, const py::handle &po) { + if (py::isinstance(po)) { + return !py::cast(po)[key.c_str()].is_none(); + } + return py::hasattr(po, key.c_str()); + } + + static bool check_keys(const std::vector &keys, + const py::handle &po) { + bool pass = true; + for (const auto &s : keys) { + pass &= check_key(s, po); + } + return pass; + } + + static py::object get_py_value(const std::string &key, const py::handle &po) { + if (py::isinstance(po)) { + return py::cast(po)[key.c_str()]; + } + return po.attr(key.c_str()); + } + + static bool get_value(py::object &var, const std::string &key, + const py::handle &po) { + if (check_key(key, po)) { + var = get_py_value(key, po); + return true; + } else { + return false; + } + } + + template + static bool get_value(T &var, const std::string &key, const py::handle &po) { + if (check_key(key, po)) { + var = get_py_value(key, po).cast(); + return true; + } else { + return false; + } + } + + static void convert_to_json(json_t &var, const py::handle &po) { + if (py::hasattr(po, "to_dict")) { + std::to_json(var, po.attr("to_dict")()); + } else if (py::isinstance(po)) { + var = nl::json::array(); + for (auto item : po) { + json_t item_js; + convert_to_json(item_js, item); + var.push_back(item_js); + } + } else { + std::to_json(var, po); + } + } + + static py::object get_value(const std::string &key, const py::handle &po) { + return get_py_value(key, po); + } + + static bool is_array(const py::handle &po) { + return py::isinstance(po) || py::isinstance(po); + } + + static bool is_array(const std::string &key, const py::handle &po) { + py::object the_list = get_py_value(key, po); + return is_array(the_list); + } + + static bool is_list_like(const py::handle &po) { + return is_array(po) || py::isinstance(po); + } + + static py::list get_as_list(const py::handle &po) { + if (!is_list_like(po)) { + throw std::runtime_error("Object is not list like!"); + } + return py::cast(po); + } + + static py::list get_list(const std::string &key, const py::handle &po) { + py::object the_list = get_py_value(key, po); + if (!is_array(the_list)) { + throw std::runtime_error("Object " + key + "is not a list!"); + } + return py::cast(the_list); + } + + static bool is_number(const py::handle &po) { + return py::isinstance(po) || py::isinstance(po); + } + + static bool is_number(const std::string &key, const py::handle &po) { + py::object key_po = get_py_value(key, po); + return is_number(key_po); + } + + template + static T get_list_elem(const py::list &po, unsigned int i) { + return py::cast(po[i]).cast(); + } + + template + static T get_list_elem(const py::handle &po, unsigned int i) { + auto py_list = get_as_list(po); + return get_list_elem(py_list, i); + } + + static std::string dump(const py::handle &po) { + json_t js; + convert_to_json(js, po); + return js.dump(); + } }; template <> -bool Parser::get_value(json_t &var, const std::string& key, const py::handle& po){ - py::object ret_po; - auto success = get_value(ret_po, key, po); - if(success){ - convert_to_json(var, ret_po); - } - return success; -} +bool Parser::get_value(json_t &var, const std::string &key, + const py::handle &po) { + py::object ret_po; + auto success = get_value(ret_po, key, po); + if (success) { + convert_to_json(var, ret_po); + } + return success; } +} // namespace AER #endif // _aer_framework_python_parser_hpp_ diff --git a/src/framework/qobj.hpp b/src/framework/qobj.hpp old mode 100755 new mode 100644 index 7eb7313a1b..0e502b978c --- a/src/framework/qobj.hpp +++ b/src/framework/qobj.hpp @@ -30,7 +30,7 @@ namespace AER { //============================================================================ class Qobj { - public: +public: //---------------------------------------------------------------- // Constructors //---------------------------------------------------------------- @@ -46,12 +46,12 @@ class Qobj { //---------------------------------------------------------------- // Data //---------------------------------------------------------------- - std::string id; // qobj identifier passed to result - std::string type = "QASM"; // currently we only support QASM - std::vector circuits; // List of circuits - json_t header; // (optional) passed through to result - json_t config; // (optional) qobj level config data - Noise::NoiseModel noise_model; // (optional) noise model + std::string id; // qobj identifier passed to result + std::string type = "QASM"; // currently we only support QASM + std::vector circuits; // List of circuits + json_t header; // (optional) passed through to result + json_t config; // (optional) qobj level config data + Noise::NoiseModel noise_model; // (optional) noise model }; //============================================================================ @@ -67,7 +67,7 @@ Qobj::Qobj(const inputdata_t &input) { if (Parser::get_value(id, "qobj_id", input) == false) { throw std::invalid_argument(R"(Invalid qobj: no "qobj_id" field)"); }; - Parser::get_value(type, "type", input); + Parser::get_value(type, "type", input); if (type != "QASM") { throw std::invalid_argument(R"(Invalid qobj: "type" != "QASM".)"); }; @@ -100,12 +100,13 @@ Qobj::Qobj(const inputdata_t &input) { } // Check for fixed simulator seed - // If simulator seed is set, each experiment will be set to a fixed (but different) seed - // Otherwise a random seed will be chosen for each experiment + // If simulator seed is set, each experiment will be set to a fixed (but + // different) seed Otherwise a random seed will be chosen for each experiment int_t seed = -1; uint_t seed_shift = 0; - bool has_simulator_seed = Parser::get_value(seed, "seed_simulator", config); // config always json - const auto& circs = Parser::get_list("experiments", input); + bool has_simulator_seed = Parser::get_value( + seed, "seed_simulator", config); // config always json + const auto &circs = Parser::get_list("experiments", input); const size_t num_circs = circs.size(); // Check if parameterized qobj @@ -128,7 +129,7 @@ Qobj::Qobj(const inputdata_t &input) { } // Load circuits - for (size_t i=0; i(circs[i]), config, truncation); @@ -141,7 +142,7 @@ Qobj::Qobj(const inputdata_t &input) { const auto circ_params = param_table[i]; const size_t num_params = circ_params[0].second.size(); const size_t num_instr = circuit.ops.size(); - for (size_t j=0; j= num_instr) { - throw std::invalid_argument(R"(Invalid parameterized qobj: instruction position out of range)"); + throw std::invalid_argument( + R"(Invalid parameterized qobj: instruction position out of range)"); } auto &op = param_circuit.ops[instr_pos]; if (param_pos >= op.params.size()) { - throw std::invalid_argument(R"(Invalid parameterized qobj: instruction param position out of range)"); + throw std::invalid_argument( + R"(Invalid parameterized qobj: instruction param position out of range)"); } if (j >= params.second.size()) { - throw std::invalid_argument(R"(Invalid parameterized qobj: parameterization value out of range)"); + throw std::invalid_argument( + R"(Invalid parameterized qobj: 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. + // 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 (truncation) param_circuit.set_params(true); circuits.push_back(std::move(param_circuit)); @@ -177,13 +182,13 @@ Qobj::Qobj(const inputdata_t &input) { if (!has_simulator_seed) { seed = circuits[0].seed; } - for (auto& circuit : circuits) { + for (auto &circuit : circuits) { circuit.seed = seed + seed_shift; - seed_shift += 2113; // Shift the seed + seed_shift += 2113; // Shift the seed } } //------------------------------------------------------------------------------ -} // namespace AER +} // namespace AER //------------------------------------------------------------------------------ #endif diff --git a/src/framework/results/data/data.hpp b/src/framework/results/data/data.hpp index 878c117af0..82ccdd8650 100644 --- a/src/framework/results/data/data.hpp +++ b/src/framework/results/data/data.hpp @@ -16,22 +16,22 @@ #define _aer_framework_results_data_hpp_ // Data primatives -#include "framework/results/data/subtypes/data_map.hpp" #include "framework/results/data/subtypes/accum_data.hpp" #include "framework/results/data/subtypes/average_data.hpp" +#include "framework/results/data/subtypes/data_map.hpp" #include "framework/results/data/subtypes/list_data.hpp" #include "framework/results/data/subtypes/single_data.hpp" // Data Containers -#include "framework/results/data/mixins/data_creg.hpp" -#include "framework/results/data/mixins/data_rvalue.hpp" -#include "framework/results/data/mixins/data_rvector.hpp" -#include "framework/results/data/mixins/data_rdict.hpp" +#include "framework/results/data/mixins/data_cdict.hpp" #include "framework/results/data/mixins/data_cmatrix.hpp" +#include "framework/results/data/mixins/data_creg.hpp" #include "framework/results/data/mixins/data_cvector.hpp" -#include "framework/results/data/mixins/data_cdict.hpp" #include "framework/results/data/mixins/data_json.hpp" #include "framework/results/data/mixins/data_mps.hpp" +#include "framework/results/data/mixins/data_rdict.hpp" +#include "framework/results/data/mixins/data_rvalue.hpp" +#include "framework/results/data/mixins/data_rvector.hpp" namespace AER { @@ -65,60 +65,60 @@ struct Data : public DataCreg, //---------------------------------------------------------------- template void add_single(const T &data, const std::string &outer_key, - const Args &... inner_keys); + const Args &...inner_keys); template void add_single(T &data, const std::string &outer_key, - const Args &... inner_keys); + const Args &...inner_keys); template void add_single(T &&data, const std::string &outer_key, - const Args &... inner_keys); + const Args &...inner_keys); //---------------------------------------------------------------- // Add list data //---------------------------------------------------------------- template void add_list(const T &data, const std::string &outer_key, - const Args &... inner_keys); + const Args &...inner_keys); template void add_list(T &data, const std::string &outer_key, - const Args &... inner_keys); + const Args &...inner_keys); template void add_list(T &&data, const std::string &outer_key, - const Args &... inner_keys); + const Args &...inner_keys); //---------------------------------------------------------------- // Add accum data //---------------------------------------------------------------- template void add_accum(const T &data, const std::string &outer_key, - const Args &... inner_keys); + const Args &...inner_keys); template void add_accum(T &data, const std::string &outer_key, - const Args &... inner_keys); + const Args &...inner_keys); template void add_accum(T &&data, const std::string &outer_key, - const Args &... inner_keys); + const Args &...inner_keys); //---------------------------------------------------------------- // Add average data //---------------------------------------------------------------- template void add_average(const T &data, const std::string &outer_key, - const Args &... inner_keys); + const Args &...inner_keys); template void add_average(T &data, const std::string &outer_key, - const Args &... inner_keys); + const Args &...inner_keys); template void add_average(T &&data, const std::string &outer_key, - const Args &... inner_keys); + const Args &...inner_keys); //---------------------------------------------------------------- // Utility and config @@ -162,87 +162,86 @@ json_t Data::to_json() { return result; } - template void Data::add_single(const T &data, const std::string &outer_key, - const Args &... inner_keys) { + const Args &...inner_keys) { DataMap::add(data, outer_key, inner_keys...); } template void Data::add_single(T &data, const std::string &outer_key, - const Args &... inner_keys) { + const Args &...inner_keys) { DataMap::add(data, outer_key, inner_keys...); } template void Data::add_single(T &&data, const std::string &outer_key, - const Args &... inner_keys) { + const Args &...inner_keys) { DataMap::add(std::move(data), outer_key, inner_keys...); } template void Data::add_list(const T &data, const std::string &outer_key, - const Args &... inner_keys) { + const Args &...inner_keys) { DataMap::add(data, outer_key, inner_keys...); } template void Data::add_list(T &data, const std::string &outer_key, - const Args &... inner_keys) { + const Args &...inner_keys) { DataMap::add(data, outer_key, inner_keys...); } template void Data::add_list(T &&data, const std::string &outer_key, - const Args &... inner_keys) { + const Args &...inner_keys) { DataMap::add(std::move(data), outer_key, inner_keys...); } template void Data::add_accum(const T &data, const std::string &outer_key, - const Args &... inner_keys) { + const Args &...inner_keys) { DataMap::add(data, outer_key, inner_keys...); } template void Data::add_accum(T &data, const std::string &outer_key, - const Args &... inner_keys) { + const Args &...inner_keys) { DataMap::add(data, outer_key, inner_keys...); } template void Data::add_accum(T &&data, const std::string &outer_key, - const Args &... inner_keys) { + const Args &...inner_keys) { DataMap::add(std::move(data), outer_key, inner_keys...); } template void Data::add_average(const T &data, const std::string &outer_key, - const Args &... inner_keys) { + const Args &...inner_keys) { DataMap::add(data, outer_key, inner_keys...); } template void Data::add_average(T &data, const std::string &outer_key, - const Args &... inner_keys) { + const Args &...inner_keys) { DataMap::add(data, outer_key, inner_keys...); } template void Data::add_average(T &&data, const std::string &outer_key, - const Args &... inner_keys) { + const Args &...inner_keys) { DataMap::add(std::move(data), outer_key, inner_keys...); } diff --git a/src/framework/results/data/metadata.hpp b/src/framework/results/data/metadata.hpp index 969179ca3a..cf7cb39bb1 100644 --- a/src/framework/results/data/metadata.hpp +++ b/src/framework/results/data/metadata.hpp @@ -33,15 +33,15 @@ struct Metadata : public DataMap, //---------------------------------------------------------------- template void add(const json_t &data, const std::string &outer_key, - const Args &... inner_keys); + const Args &...inner_keys); template void add(json_t &data, const std::string &outer_key, - const Args &... inner_keys); + const Args &...inner_keys); template void add(json_t &&data, const std::string &outer_key, - const Args &... inner_keys); + const Args &...inner_keys); //---------------------------------------------------------------- // Add general metadata @@ -51,13 +51,13 @@ struct Metadata : public DataMap, //---------------------------------------------------------------- template void add(const T &data, const std::string &outer_key, - const Args &... inner_keys); + const Args &...inner_keys); template - void add(T &data, const std::string &outer_key, const Args &... inner_keys); + void add(T &data, const std::string &outer_key, const Args &...inner_keys); template - void add(T &&data, const std::string &outer_key, const Args &... inner_keys); + void add(T &&data, const std::string &outer_key, const Args &...inner_keys); // Serialize engine data to JSON json_t to_json(); @@ -87,7 +87,7 @@ json_t Metadata::to_json() { template void Metadata::add(const T &data, const std::string &outer_key, - const Args &... inner_keys) { + const Args &...inner_keys) { json_t tmp = data; DataMap::add( std::move(tmp), outer_key, inner_keys...); @@ -95,7 +95,7 @@ void Metadata::add(const T &data, const std::string &outer_key, template void Metadata::add(T &data, const std::string &outer_key, - const Args &... inner_keys) { + const Args &...inner_keys) { json_t tmp = data; DataMap::add( std::move(tmp), outer_key, inner_keys...); @@ -103,7 +103,7 @@ void Metadata::add(T &data, const std::string &outer_key, template void Metadata::add(T &&data, const std::string &outer_key, - const Args &... inner_keys) { + const Args &...inner_keys) { json_t tmp = data; DataMap::add( std::move(tmp), outer_key, inner_keys...); @@ -111,21 +111,21 @@ void Metadata::add(T &&data, const std::string &outer_key, template void Metadata::add(const json_t &data, const std::string &outer_key, - const Args &... inner_keys) { + const Args &...inner_keys) { DataMap::add(data, outer_key, inner_keys...); } template void Metadata::add(json_t &data, const std::string &outer_key, - const Args &... inner_keys) { + const Args &...inner_keys) { DataMap::add(data, outer_key, inner_keys...); } template void Metadata::add(json_t &&data, const std::string &outer_key, - const Args &... inner_keys) { + const Args &...inner_keys) { DataMap::add( std::move(data), outer_key, inner_keys...); } diff --git a/src/framework/results/data/mixins/data_cdict.hpp b/src/framework/results/data/mixins/data_cdict.hpp index 16d1e3b8d7..69b4670c3b 100644 --- a/src/framework/results/data/mixins/data_cdict.hpp +++ b/src/framework/results/data/mixins/data_cdict.hpp @@ -29,10 +29,11 @@ namespace AER { // Result container for Qiskit-Aer //============================================================================ -struct DataCDict : public DataMap, 1>, - public DataMap, 2>, - public DataMap, 1>, - public DataMap, 2> { +struct DataCDict + : public DataMap, 1>, + public DataMap, 2>, + public DataMap, 1>, + public DataMap, 2> { // Serialize engine data to JSON void add_to_json(json_t &result); @@ -46,10 +47,14 @@ struct DataCDict : public DataMap, //------------------------------------------------------------------------------ DataCDict &DataCDict::combine(DataCDict &&other) { - DataMap, 1>::combine(std::move(other)); - DataMap, 2>::combine(std::move(other)); - DataMap, 1>::combine(std::move(other)); - DataMap, 2>::combine(std::move(other)); + DataMap, 1>::combine( + std::move(other)); + DataMap, 2>::combine( + std::move(other)); + DataMap, 1>::combine( + std::move(other)); + DataMap, 2>::combine( + std::move(other)); return *this; } diff --git a/src/framework/results/data/mixins/data_cmatrix.hpp b/src/framework/results/data/mixins/data_cmatrix.hpp index 0aa1920603..f1e23b6707 100644 --- a/src/framework/results/data/mixins/data_cmatrix.hpp +++ b/src/framework/results/data/mixins/data_cmatrix.hpp @@ -15,9 +15,9 @@ #ifndef _aer_framework_results_data_cmatrix_hpp_ #define _aer_framework_results_data_cmatrix_hpp_ -#include "framework/results/data/subtypes/data_map.hpp" #include "framework/results/data/subtypes/accum_data.hpp" #include "framework/results/data/subtypes/average_data.hpp" +#include "framework/results/data/subtypes/data_map.hpp" #include "framework/results/data/subtypes/list_data.hpp" #include "framework/results/data/subtypes/single_data.hpp" #include "framework/types.hpp" @@ -28,23 +28,22 @@ namespace AER { // Result container for Qiskit-Aer //============================================================================ -struct DataCMatrix : - public DataMap, 1>, - public DataMap, 1>, - public DataMap, 2>, - public DataMap, 2>, - public DataMap, 1>, - public DataMap, 1>, - public DataMap, 2>, - public DataMap, 2>, - public DataMap, 1>, - public DataMap, 1>, - public DataMap, 2>, - public DataMap, 2>, - public DataMap, 1>, - public DataMap, 1>, - public DataMap, 2>, - public DataMap, 2> { +struct DataCMatrix : public DataMap, 1>, + public DataMap, 1>, + public DataMap, 2>, + public DataMap, 2>, + public DataMap, 1>, + public DataMap, 1>, + public DataMap, 2>, + public DataMap, 2>, + public DataMap, 1>, + public DataMap, 1>, + public DataMap, 2>, + public DataMap, 2>, + public DataMap, 1>, + public DataMap, 1>, + public DataMap, 2>, + public DataMap, 2> { // Serialize engine data to JSON void add_to_json(json_t &result); diff --git a/src/framework/results/data/mixins/data_creg.hpp b/src/framework/results/data/mixins/data_creg.hpp index 73a68acb11..f97b769ce6 100644 --- a/src/framework/results/data/mixins/data_creg.hpp +++ b/src/framework/results/data/mixins/data_creg.hpp @@ -26,8 +26,8 @@ namespace AER { // Result container for Qiskit-Aer //============================================================================ -struct DataCreg : public DataMap, // Counts - public DataMap // Memory +struct DataCreg : public DataMap, // Counts + public DataMap // Memory { // Serialize engine data to JSON void add_to_json(json_t &result); diff --git a/src/framework/results/data/mixins/data_mps.hpp b/src/framework/results/data/mixins/data_mps.hpp index 21e20619c6..281a91bf70 100644 --- a/src/framework/results/data/mixins/data_mps.hpp +++ b/src/framework/results/data/mixins/data_mps.hpp @@ -25,7 +25,7 @@ namespace AER { //============================================================================ // Result container for Qiskit-Aer //============================================================================ -//using cmat = std::vector>; +// using cmat = std::vector>; struct DataMPS : public DataMap, public DataMap, public DataMap, diff --git a/src/framework/results/data/mixins/data_rdict.hpp b/src/framework/results/data/mixins/data_rdict.hpp index 8f9e0f55a2..9e470267b4 100644 --- a/src/framework/results/data/mixins/data_rdict.hpp +++ b/src/framework/results/data/mixins/data_rdict.hpp @@ -15,12 +15,12 @@ #ifndef _aer_framework_results_data_rdict_hpp_ #define _aer_framework_results_data_rdict_hpp_ -#include -#include "framework/results/data/subtypes/data_map.hpp" -#include "framework/results/data/subtypes/list_data.hpp" #include "framework/results/data/subtypes/accum_data.hpp" #include "framework/results/data/subtypes/average_data.hpp" +#include "framework/results/data/subtypes/data_map.hpp" +#include "framework/results/data/subtypes/list_data.hpp" #include "framework/types.hpp" +#include namespace AER { @@ -28,12 +28,13 @@ namespace AER { // Result container for Qiskit-Aer //============================================================================ -struct DataRDict : public DataMap, 1>, - public DataMap, 2>, - public DataMap, 1>, - public DataMap, 2>, - public DataMap, 1>, - public DataMap, 2> { +struct DataRDict + : public DataMap, 1>, + public DataMap, 2>, + public DataMap, 1>, + public DataMap, 2>, + public DataMap, 1>, + public DataMap, 2> { // Serialize engine data to JSON void add_to_json(json_t &result); @@ -47,12 +48,18 @@ struct DataRDict : public DataMap, 1>, //------------------------------------------------------------------------------ DataRDict &DataRDict::combine(DataRDict &&other) { - DataMap, 1>::combine(std::move(other)); - DataMap, 2>::combine(std::move(other)); - DataMap, 1>::combine(std::move(other)); - DataMap, 2>::combine(std::move(other)); - DataMap, 1>::combine(std::move(other)); - DataMap, 2>::combine(std::move(other)); + DataMap, 1>::combine( + std::move(other)); + DataMap, 2>::combine( + std::move(other)); + DataMap, 1>::combine( + std::move(other)); + DataMap, 2>::combine( + std::move(other)); + DataMap, 1>::combine( + std::move(other)); + DataMap, 2>::combine( + std::move(other)); return *this; } diff --git a/src/framework/results/data/mixins/data_rvalue.hpp b/src/framework/results/data/mixins/data_rvalue.hpp index 901c84eb30..8f89412ea4 100644 --- a/src/framework/results/data/mixins/data_rvalue.hpp +++ b/src/framework/results/data/mixins/data_rvalue.hpp @@ -15,9 +15,9 @@ #ifndef _aer_framework_results_data_rvalue_hpp_ #define _aer_framework_results_data_rvalue_hpp_ -#include "framework/results/data/subtypes/data_map.hpp" #include "framework/results/data/subtypes/accum_data.hpp" #include "framework/results/data/subtypes/average_data.hpp" +#include "framework/results/data/subtypes/data_map.hpp" #include "framework/results/data/subtypes/list_data.hpp" #include "framework/results/data/subtypes/single_data.hpp" #include "framework/types.hpp" @@ -28,13 +28,12 @@ namespace AER { // Result container for Qiskit-Aer //============================================================================ -struct DataRValue : - public DataMap, - public DataMap, - public DataMap, - public DataMap, - public DataMap, - public DataMap { +struct DataRValue : public DataMap, + public DataMap, + public DataMap, + public DataMap, + public DataMap, + public DataMap { // Serialize engine data to JSON void add_to_json(json_t &result); diff --git a/src/framework/results/data/mixins/data_rvector.hpp b/src/framework/results/data/mixins/data_rvector.hpp index ab283f7ac1..6688b80db1 100644 --- a/src/framework/results/data/mixins/data_rvector.hpp +++ b/src/framework/results/data/mixins/data_rvector.hpp @@ -15,11 +15,11 @@ #ifndef _aer_framework_results_data_rvector_hpp_ #define _aer_framework_results_data_rvector_hpp_ +#include "framework/results/data/subtypes/accum_data.hpp" +#include "framework/results/data/subtypes/average_data.hpp" #include "framework/results/data/subtypes/data_map.hpp" #include "framework/results/data/subtypes/list_data.hpp" #include "framework/results/data/subtypes/single_data.hpp" -#include "framework/results/data/subtypes/accum_data.hpp" -#include "framework/results/data/subtypes/average_data.hpp" #include "framework/types.hpp" namespace AER { diff --git a/src/framework/results/data/mixins/pybind_data_cdict.hpp b/src/framework/results/data/mixins/pybind_data_cdict.hpp old mode 100755 new mode 100644 index 7bcddf3cdc..9f025e39b2 --- a/src/framework/results/data/mixins/pybind_data_cdict.hpp +++ b/src/framework/results/data/mixins/pybind_data_cdict.hpp @@ -30,8 +30,7 @@ py::object to_python(AER::DataCDict &&data); // Move an DataCDict container object to an existing new Python dict void add_to_python(py::dict &pydata, AER::DataCDict &&data); -} //end namespace AerToPy - +} // end namespace AerToPy //============================================================================ // Implementations @@ -44,10 +43,26 @@ py::object AerToPy::to_python(AER::DataCDict &&data) { } void AerToPy::add_to_python(py::dict &pydata, AER::DataCDict &&data) { - AerToPy::add_to_python(pydata, static_cast, 1>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 2>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 1>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 2>&&>(data)); + AerToPy::add_to_python( + pydata, + static_cast, 1> &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast, 2> &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast, 1> &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast, 2> &&>( + data)); } #endif diff --git a/src/framework/results/data/mixins/pybind_data_cmatrix.hpp b/src/framework/results/data/mixins/pybind_data_cmatrix.hpp old mode 100755 new mode 100644 index 4b53de3c8a..994adc2e8b --- a/src/framework/results/data/mixins/pybind_data_cmatrix.hpp +++ b/src/framework/results/data/mixins/pybind_data_cmatrix.hpp @@ -30,8 +30,7 @@ py::object to_python(AER::DataCMatrix &&data); // Move an DataCMatrix container object to an existing new Python dict void add_to_python(py::dict &pydata, AER::DataCMatrix &&data); -} //end namespace AerToPy - +} // end namespace AerToPy //============================================================================ // Implementations @@ -44,22 +43,70 @@ py::object AerToPy::to_python(AER::DataCMatrix &&data) { } void AerToPy::add_to_python(py::dict &pydata, AER::DataCMatrix &&data) { - AerToPy::add_to_python(pydata, static_cast, 1>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 1>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 2>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 2>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 1>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 1>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 2>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 2>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 1>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 1>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 2>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 2>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 1>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 1>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 2>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 2>&&>(data)); + AerToPy::add_to_python( + pydata, + static_cast, 1> &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast, 1> &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast, 2> &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast, 2> &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast, 1> &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast, 1> &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast, 2> &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast, 2> &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast, 1> &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast, 1> &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast, 2> &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast, 2> &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast, 1> &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast< + AER::DataMap, 1> &&>(data)); + AerToPy::add_to_python( + pydata, + static_cast, 2> &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast< + AER::DataMap, 2> &&>(data)); } #endif diff --git a/src/framework/results/data/mixins/pybind_data_creg.hpp b/src/framework/results/data/mixins/pybind_data_creg.hpp old mode 100755 new mode 100644 index 9585154c42..2156dd1d9b --- a/src/framework/results/data/mixins/pybind_data_creg.hpp +++ b/src/framework/results/data/mixins/pybind_data_creg.hpp @@ -30,8 +30,7 @@ py::object to_python(AER::DataCreg &&data); // Move an DataCreg container object to an existing new Python dict void add_to_python(py::dict &pydata, AER::DataCreg &&data); -} //end namespace AerToPy - +} // end namespace AerToPy //============================================================================ // Implementations @@ -44,8 +43,12 @@ py::object AerToPy::to_python(AER::DataCreg &&data) { } void AerToPy::add_to_python(py::dict &pydata, AER::DataCreg &&data) { - AerToPy::add_to_python(pydata, static_cast&&>(data)); - AerToPy::add_to_python(pydata, static_cast&&>(data)); + AerToPy::add_to_python( + pydata, + static_cast &&>(data)); + AerToPy::add_to_python( + pydata, + static_cast &&>(data)); } #endif diff --git a/src/framework/results/data/mixins/pybind_data_cvector.hpp b/src/framework/results/data/mixins/pybind_data_cvector.hpp old mode 100755 new mode 100644 index 3115cc8b09..15c7991780 --- a/src/framework/results/data/mixins/pybind_data_cvector.hpp +++ b/src/framework/results/data/mixins/pybind_data_cvector.hpp @@ -30,8 +30,7 @@ py::object to_python(AER::DataCVector &&data); // Move an DataCVector container object to an existing new Python dict void add_to_python(py::dict &pydata, AER::DataCVector &&data); -} //end namespace AerToPy - +} // end namespace AerToPy //============================================================================ // Implementations @@ -44,14 +43,38 @@ py::object AerToPy::to_python(AER::DataCVector &&data) { } void AerToPy::add_to_python(py::dict &pydata, AER::DataCVector &&data) { - AerToPy::add_to_python(pydata, static_cast, 1>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 1>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 2>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 2>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 1>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 1>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 2>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 2>&&>(data)); + AerToPy::add_to_python( + pydata, + static_cast, 1> + &&>(data)); + AerToPy::add_to_python( + pydata, + static_cast, 1> + &&>(data)); + AerToPy::add_to_python( + pydata, + static_cast, 2> + &&>(data)); + AerToPy::add_to_python( + pydata, + static_cast, 2> + &&>(data)); + AerToPy::add_to_python( + pydata, + static_cast, 1> + &&>(data)); + AerToPy::add_to_python( + pydata, + static_cast, 1> + &&>(data)); + AerToPy::add_to_python( + pydata, + static_cast, 2> + &&>(data)); + AerToPy::add_to_python( + pydata, + static_cast, 2> + &&>(data)); } #endif diff --git a/src/framework/results/data/mixins/pybind_data_json.hpp b/src/framework/results/data/mixins/pybind_data_json.hpp old mode 100755 new mode 100644 index 89759ed3ce..51bebb049b --- a/src/framework/results/data/mixins/pybind_data_json.hpp +++ b/src/framework/results/data/mixins/pybind_data_json.hpp @@ -30,8 +30,7 @@ py::object to_python(AER::DataJSON &&data); // Move an DataJSON container object to an existing new Python dict void add_to_python(py::dict &pydata, AER::DataJSON &&data); -} //end namespace AerToPy - +} // end namespace AerToPy //============================================================================ // Implementations @@ -44,10 +43,14 @@ py::object AerToPy::to_python(AER::DataJSON &&data) { } void AerToPy::add_to_python(py::dict &pydata, AER::DataJSON &&data) { - AerToPy::add_to_python(pydata, static_cast&&>(data)); - AerToPy::add_to_python(pydata, static_cast&&>(data)); - AerToPy::add_to_python(pydata, static_cast&&>(data)); - AerToPy::add_to_python(pydata, static_cast&&>(data)); + AerToPy::add_to_python( + pydata, static_cast &&>(data)); + AerToPy::add_to_python( + pydata, static_cast &&>(data)); + AerToPy::add_to_python( + pydata, static_cast &&>(data)); + AerToPy::add_to_python( + pydata, static_cast &&>(data)); } #endif diff --git a/src/framework/results/data/mixins/pybind_data_mps.hpp b/src/framework/results/data/mixins/pybind_data_mps.hpp old mode 100755 new mode 100644 index 7196d884a4..b7be3fcc00 --- a/src/framework/results/data/mixins/pybind_data_mps.hpp +++ b/src/framework/results/data/mixins/pybind_data_mps.hpp @@ -25,7 +25,8 @@ namespace AerToPy { // Move mps_container_t to python object -template <> py::object to_python(AER::mps_container_t &&mps); +template <> +py::object to_python(AER::mps_container_t &&mps); // Move an DataMPS container object to a new Python dict py::object to_python(AER::DataMPS &&data); @@ -33,21 +34,21 @@ py::object to_python(AER::DataMPS &&data); // Move an DataMPS container object to an existing new Python dict void add_to_python(py::dict &pydata, AER::DataMPS &&data); -} //end namespace AerToPy - +} // end namespace AerToPy //============================================================================ // Implementations //============================================================================ -template <> py::object AerToPy::to_python(AER::mps_container_t &&data) { +template <> +py::object AerToPy::to_python(AER::mps_container_t &&data) { py::list mats; - for (auto& pair: data.first) { + for (auto &pair : data.first) { mats.append(py::make_tuple(AerToPy::to_python(std::move(pair.first)), AerToPy::to_python(std::move(pair.second)))); } py::list vecs; - for (auto&& vec: data.second) { + for (auto &&vec : data.second) { vecs.append(AerToPy::to_python(std::move(vec))); } return py::make_tuple(std::move(mats), std::move(vecs)); @@ -60,10 +61,22 @@ py::object AerToPy::to_python(AER::DataMPS &&data) { } void AerToPy::add_to_python(py::dict &pydata, AER::DataMPS &&data) { - AerToPy::add_to_python(pydata, static_cast&&>(data)); - AerToPy::add_to_python(pydata, static_cast&&>(data)); - AerToPy::add_to_python(pydata, static_cast&&>(data)); - AerToPy::add_to_python(pydata, static_cast&&>(data)); + AerToPy::add_to_python( + pydata, + static_cast &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast &&>( + data)); } #endif diff --git a/src/framework/results/data/mixins/pybind_data_rdict.hpp b/src/framework/results/data/mixins/pybind_data_rdict.hpp old mode 100755 new mode 100644 index 03e2a0a30c..1a92571c63 --- a/src/framework/results/data/mixins/pybind_data_rdict.hpp +++ b/src/framework/results/data/mixins/pybind_data_rdict.hpp @@ -30,8 +30,7 @@ py::object to_python(AER::DataRDict &&data); // Move an DataRDict container object to an existing new Python dict void add_to_python(py::dict &pydata, AER::DataRDict &&data); -} //end namespace AerToPy - +} // end namespace AerToPy //============================================================================ // Implementations @@ -44,12 +43,32 @@ py::object AerToPy::to_python(AER::DataRDict &&data) { } void AerToPy::add_to_python(py::dict &pydata, AER::DataRDict &&data) { - AerToPy::add_to_python(pydata, static_cast, 1>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 2>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 1>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 2>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 1>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 2>&&>(data)); + AerToPy::add_to_python( + pydata, + static_cast, 1> + &&>(data)); + AerToPy::add_to_python( + pydata, + static_cast, 2> + &&>(data)); + AerToPy::add_to_python( + pydata, + static_cast, 1> + &&>(data)); + AerToPy::add_to_python( + pydata, + static_cast, 2> + &&>(data)); + AerToPy::add_to_python( + pydata, + static_cast< + AER::DataMap, 1> &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast< + AER::DataMap, 2> &&>( + data)); } #endif diff --git a/src/framework/results/data/mixins/pybind_data_rvalue.hpp b/src/framework/results/data/mixins/pybind_data_rvalue.hpp old mode 100755 new mode 100644 index 15d9f18469..dfed06ea4c --- a/src/framework/results/data/mixins/pybind_data_rvalue.hpp +++ b/src/framework/results/data/mixins/pybind_data_rvalue.hpp @@ -30,8 +30,7 @@ py::object to_python(AER::DataRValue &&data); // Move an DataRValue container object to an existing new Python dict void add_to_python(py::dict &pydata, AER::DataRValue &&data); -} //end namespace AerToPy - +} // end namespace AerToPy //============================================================================ // Implementations @@ -44,12 +43,18 @@ py::object AerToPy::to_python(AER::DataRValue &&data) { } void AerToPy::add_to_python(py::dict &pydata, AER::DataRValue &&data) { - AerToPy::add_to_python(pydata, static_cast&&>(data)); - AerToPy::add_to_python(pydata, static_cast&&>(data)); - AerToPy::add_to_python(pydata, static_cast&&>(data)); - AerToPy::add_to_python(pydata, static_cast&&>(data)); - AerToPy::add_to_python(pydata, static_cast&&>(data)); - AerToPy::add_to_python(pydata, static_cast&&>(data)); + AerToPy::add_to_python( + pydata, static_cast &&>(data)); + AerToPy::add_to_python( + pydata, static_cast &&>(data)); + AerToPy::add_to_python( + pydata, static_cast &&>(data)); + AerToPy::add_to_python( + pydata, static_cast &&>(data)); + AerToPy::add_to_python( + pydata, static_cast &&>(data)); + AerToPy::add_to_python( + pydata, static_cast &&>(data)); } #endif diff --git a/src/framework/results/data/mixins/pybind_data_rvector.hpp b/src/framework/results/data/mixins/pybind_data_rvector.hpp old mode 100755 new mode 100644 index 58ca61ec9d..212bef99bb --- a/src/framework/results/data/mixins/pybind_data_rvector.hpp +++ b/src/framework/results/data/mixins/pybind_data_rvector.hpp @@ -30,8 +30,7 @@ py::object to_python(AER::DataRVector &&data); // Move an DataRVector container object to an existing new Python dict void add_to_python(py::dict &pydata, AER::DataRVector &&data); -} //end namespace AerToPy - +} // end namespace AerToPy //============================================================================ // Implementations @@ -44,12 +43,30 @@ py::object AerToPy::to_python(AER::DataRVector &&data) { } void AerToPy::add_to_python(py::dict &pydata, AER::DataRVector &&data) { - AerToPy::add_to_python(pydata, static_cast, 1>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 2>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 1>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 2>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 1>&&>(data)); - AerToPy::add_to_python(pydata, static_cast, 2>&&>(data)); + AerToPy::add_to_python( + pydata, + static_cast, 1> &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast, 2> &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast, 1> &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast, 2> &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast, 1> &&>( + data)); + AerToPy::add_to_python( + pydata, + static_cast, 2> &&>( + data)); } #endif diff --git a/src/framework/results/data/pybind_data.hpp b/src/framework/results/data/pybind_data.hpp old mode 100755 new mode 100644 index dcd25fb17f..53b338c372 --- a/src/framework/results/data/pybind_data.hpp +++ b/src/framework/results/data/pybind_data.hpp @@ -16,23 +16,23 @@ #define _aer_framework_result_data_pybind_data_hpp_ #include "framework/results/data/data.hpp" -#include "framework/results/data/mixins/pybind_data_creg.hpp" -#include "framework/results/data/mixins/pybind_data_rdict.hpp" -#include "framework/results/data/mixins/pybind_data_rvalue.hpp" -#include "framework/results/data/mixins/pybind_data_rvector.hpp" +#include "framework/results/data/mixins/pybind_data_cdict.hpp" #include "framework/results/data/mixins/pybind_data_cmatrix.hpp" +#include "framework/results/data/mixins/pybind_data_creg.hpp" #include "framework/results/data/mixins/pybind_data_cvector.hpp" -#include "framework/results/data/mixins/pybind_data_cdict.hpp" #include "framework/results/data/mixins/pybind_data_json.hpp" #include "framework/results/data/mixins/pybind_data_mps.hpp" +#include "framework/results/data/mixins/pybind_data_rdict.hpp" +#include "framework/results/data/mixins/pybind_data_rvalue.hpp" +#include "framework/results/data/mixins/pybind_data_rvector.hpp" namespace AerToPy { // Move an ExperimentResult data object to a Python dict -template <> py::object to_python(AER::Data &&data); - -} //end namespace AerToPy +template <> +py::object to_python(AER::Data &&data); +} // end namespace AerToPy //============================================================================ // Implementations @@ -41,15 +41,15 @@ template <> py::object to_python(AER::Data &&data); template <> py::object AerToPy::to_python(AER::Data &&data) { py::dict pydata; - AerToPy::add_to_python(pydata, static_cast(data)); - AerToPy::add_to_python(pydata, static_cast(data)); - AerToPy::add_to_python(pydata, static_cast(data)); - AerToPy::add_to_python(pydata, static_cast(data)); - AerToPy::add_to_python(pydata, static_cast(data)); - AerToPy::add_to_python(pydata, static_cast(data)); - AerToPy::add_to_python(pydata, static_cast(data)); - AerToPy::add_to_python(pydata, static_cast(data)); - AerToPy::add_to_python(pydata, static_cast(data)); + AerToPy::add_to_python(pydata, static_cast(data)); + AerToPy::add_to_python(pydata, static_cast(data)); + AerToPy::add_to_python(pydata, static_cast(data)); + AerToPy::add_to_python(pydata, static_cast(data)); + AerToPy::add_to_python(pydata, static_cast(data)); + AerToPy::add_to_python(pydata, static_cast(data)); + AerToPy::add_to_python(pydata, static_cast(data)); + AerToPy::add_to_python(pydata, static_cast(data)); + AerToPy::add_to_python(pydata, static_cast(data)); return std::move(pydata); } diff --git a/src/framework/results/data/pybind_metadata.hpp b/src/framework/results/data/pybind_metadata.hpp old mode 100755 new mode 100644 index 244083d931..ca2f8a58bb --- a/src/framework/results/data/pybind_metadata.hpp +++ b/src/framework/results/data/pybind_metadata.hpp @@ -21,10 +21,10 @@ namespace AerToPy { // Move an ExperimentResult metdata object to a Python dict -template <> py::object to_python(AER::Metadata &&metadata); - -} //end namespace AerToPy +template <> +py::object to_python(AER::Metadata &&metadata); +} // end namespace AerToPy //============================================================================ // Implementations @@ -33,9 +33,15 @@ template <> py::object to_python(AER::Metadata &&metadata); template <> py::object AerToPy::to_python(AER::Metadata &&metadata) { py::dict pydata; - add_to_python(pydata, static_cast&&>(metadata)); - add_to_python(pydata, static_cast&&>(metadata)); - add_to_python(pydata, static_cast&&>(metadata)); + add_to_python( + pydata, + static_cast &&>(metadata)); + add_to_python( + pydata, + static_cast &&>(metadata)); + add_to_python( + pydata, + static_cast &&>(metadata)); return std::move(pydata); } diff --git a/src/framework/results/data/subtypes/accum_data.hpp b/src/framework/results/data/subtypes/accum_data.hpp old mode 100755 new mode 100644 index a424f8a107..3e34f24caf --- a/src/framework/results/data/subtypes/accum_data.hpp +++ b/src/framework/results/data/subtypes/accum_data.hpp @@ -22,16 +22,17 @@ namespace AER { template class AccumData : public SingleData { -using Base = SingleData; + using Base = SingleData; + public: // Add data (copy) - void add(const T& data); + void add(const T &data); // Add data (move) - void add(T&& data); + void add(T &&data); // Combine data (move) - void combine(AccumData&& other); + void combine(AccumData &&other); // Clear all stored data void clear(); @@ -45,7 +46,7 @@ using Base = SingleData; //------------------------------------------------------------------------------ template -void AccumData::add(const T& data) { +void AccumData::add(const T &data) { if (empty_) { Base::data_ = data; empty_ = false; @@ -55,7 +56,7 @@ void AccumData::add(const T& data) { } template -void AccumData::add(T&& data) { +void AccumData::add(T &&data) { if (empty_) { Base::data_ = std::move(data); empty_ = false; @@ -65,7 +66,7 @@ void AccumData::add(T&& data) { } template -void AccumData::combine(AccumData&& other) { +void AccumData::combine(AccumData &&other) { add(std::move(other.data_)); } @@ -76,6 +77,6 @@ void AccumData::clear() { } //------------------------------------------------------------------------------ -} // end namespace AER +} // end namespace AER //------------------------------------------------------------------------------ #endif diff --git a/src/framework/results/data/subtypes/average_data.hpp b/src/framework/results/data/subtypes/average_data.hpp old mode 100755 new mode 100644 index fea9a7c858..25db5a8cd3 --- a/src/framework/results/data/subtypes/average_data.hpp +++ b/src/framework/results/data/subtypes/average_data.hpp @@ -21,19 +21,20 @@ namespace AER { template class AverageData : public AccumData { -using Base = AccumData; + using Base = AccumData; + public: // Access data - T& value(); + T &value(); // Add data (copy) - void add(const T& data); + void add(const T &data); // Add data (move) - void add(T&& data); + void add(T &&data); // Add data - void combine(AverageData&& other); + void combine(AverageData &&other); // Clear all stored data void clear(); @@ -58,21 +59,21 @@ using Base = AccumData; //------------------------------------------------------------------------------ template -void AverageData::add(const T& data) { +void AverageData::add(const T &data) { denormalize(); Base::add(data); count_ += 1; } template -void AverageData::add(T&& data) { +void AverageData::add(T &&data) { denormalize(); Base::add(std::move(data)); count_ += 1; } template -void AverageData::combine(AverageData&& other) { +void AverageData::combine(AverageData &&other) { denormalize(); other.denormalize(); Base::combine(std::move(other)); @@ -103,12 +104,12 @@ void AverageData::denormalize() { } template -T& AverageData::value() { +T &AverageData::value() { normalize(); return Base::data_; } //------------------------------------------------------------------------------ -} // end namespace AER +} // end namespace AER //------------------------------------------------------------------------------ #endif diff --git a/src/framework/results/data/subtypes/data_map.hpp b/src/framework/results/data/subtypes/data_map.hpp old mode 100755 new mode 100644 index 7f0d4fb0a6..8c942ae0ac --- a/src/framework/results/data/subtypes/data_map.hpp +++ b/src/framework/results/data/subtypes/data_map.hpp @@ -25,23 +25,23 @@ template