diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 000000000..26833e234 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,207 @@ +FormatStyle: file +# WarningsAsErrors: "*" +Checks: "-*, + abseil-*,\ + -abseil-string-find-startswith,\ + -abseil-string-find-str-contains,\ + bugprone-*,\ + -bugprone-argument-comment,\ + -bugprone-assert-side-effect,\ + -bugprone-bad-signal-to-kill-thread,\ + -bugprone-bool-pointer-implicit-conversion,\ + -bugprone-branch-clone,\ + -bugprone-copy-constructor-init,\ + -bugprone-dangling-handle,\ + -bugprone-dynamic-static-initializers,\ + -bugprone-easily-swappable-parameters,\ + -bugprone-exception-escape,\ + -bugprone-fold-init-type,\ + -bugprone-forward-declaration-namespace,\ + -bugprone-forwarding-reference-overload,\ + -bugprone-implicit-widening-of-multiplication-result,\ + -bugprone-inaccurate-erase,\ + -bugprone-incorrect-roundings,\ + -bugprone-infinite-loop,\ + -bugprone-integer-division,\ + -bugprone-lambda-function-name,\ + -bugprone-macro-parentheses,\ + -bugprone-macro-repeated-side-effects,\ + -bugprone-misplaced-operator-in-strlen-in-alloc,\ + -bugprone-misplaced-widening-cast,\ + -bugprone-move-forwarding-reference,\ + -bugprone-multiple-statement-macro,\ + -bugprone-narrowing-conversions,\ + -bugprone-no-escape,\ + -bugprone-not-null-terminated-result,\ + -bugprone-parent-virtual-call,\ + -bugprone-posix-return,\ + -bugprone-redundant-branch-condition,\ + -bugprone-reserved-identifier,\ + -bugprone-signal-handler,\ + -bugprone-signed-char-misuse,\ + -bugprone-sizeof-container,\ + -bugprone-sizeof-expression,\ + -bugprone-spuriously-wake-up-functions,\ + -bugprone-string-constructor,\ + -bugprone-string-integer-assignment,\ + -bugprone-string-literal-with-embedded-nul,\ + -bugprone-stringview-nullptr,\ + -bugprone-suspicious-enum-usage,\ + -bugprone-suspicious-include,\ + -bugprone-suspicious-memory-comparison,\ + -bugprone-suspicious-memset-usage,\ + -bugprone-suspicious-missing-comma,\ + -bugprone-suspicious-semicolon,\ + -bugprone-suspicious-string-compare,\ + -bugprone-swapped-arguments,\ + -bugprone-terminating-continue,\ + -bugprone-throw-keyword-missing,\ + -bugprone-too-small-loop-variable,\ + -bugprone-undefined-memory-manipulation,\ + -bugprone-undelegated-constructor,\ + -bugprone-unhandled-exception-at-new,\ + -bugprone-unhandled-self-assignment,\ + -bugprone-unused-raii,\ + -bugprone-unused-return-value,\ + -bugprone-use-after-move,\ + -bugprone-virtual-near-miss,\ + cert-*,\ + -cert-dcl16-c,\ + -cert-dcl21-cpp,\ + -cert-dcl37-c,\ + -cert-dcl50-cpp,\ + -cert-dcl51-cpp,\ + -cert-dcl54-cpp,\ + -cert-dcl58-cpp,\ + -cert-err33-c,\ + -cert-msc30-c,\ + -cert-msc32-c,\ + -cert-msc50-cpp,\ + -cert-msc51-cpp,\ + -cert-oop54-cpp,\ + -cert-str34-c,\ + -cert-str34-c,\ + -cert-str34-c,\ + -cert-str34-c,\ + -clang-analyzer-*,\ + concurrency-*,\ + -concurrency-mt-unsafe,\ + cppcoreguidelines-*,\ + -concurrency-mt-unsafe,\ + -cppcoreguidelines-avoid-c-arrays,\ + -cppcoreguidelines-avoid-const-or-ref-data-members,\ + -cppcoreguidelines-avoid-do-while,\ + -cppcoreguidelines-avoid-goto,\ + -cppcoreguidelines-avoid-magic-numbers,\ + -cppcoreguidelines-avoid-non-const-global-variables,\ + -cppcoreguidelines-c-copy-assignment-signature,\ + -cppcoreguidelines-explicit-virtual-functions,\ + -cppcoreguidelines-init-variables,\ + -cppcoreguidelines-interfaces-global-init,\ + -cppcoreguidelines-macro-usage,\ + -cppcoreguidelines-narrowing-conversions,\ + -cppcoreguidelines-no-malloc,\ + -cppcoreguidelines-non-private-member-variables-in-classes,\ + -cppcoreguidelines-owning-memory,\ + -cppcoreguidelines-prefer-member-initializer,\ + -cppcoreguidelines-pro-bounds-array-to-pointer-decay,\ + -cppcoreguidelines-pro-bounds-constant-array-index,\ + -cppcoreguidelines-pro-bounds-pointer-arithmetic,\ + -cppcoreguidelines-pro-type-const-cast,\ + -cppcoreguidelines-pro-type-member-init,\ + -cppcoreguidelines-pro-type-reinterpret-cast,\ + -cppcoreguidelines-pro-type-static-cast-downcast,\ + -cppcoreguidelines-pro-type-union-access,\ + -cppcoreguidelines-pro-type-vararg,\ + -cppcoreguidelines-slicing,\ + -cppcoreguidelines-special-member-functions,\ + -cppcoreguidelines-virtual-class-destructor,\ + google-*,\ + -google-default-arguments,\ + -google-explicit-constructor,\ + -google-readability-avoid-underscore-in-googletest-name,\ + -google-readability-braces-around-statements,\ + -google-readability-casting,\ + -google-readability-namespace-comments,\ + -google-readability-todo,\ + -google-runtime-int,\ + -google-upgrade-googletest-case,\ + misc-*,\ + -misc-misplaced-const,\ + -misc-new-delete-overloads,\ + -misc-non-private-member-variables-in-classes,\ + -misc-no-recursion,\ + -misc-redundant-expression,\ + -misc-uniqueptr-reset-release,\ + -misc-unconventional-assign-operator,\ + -misc-unused-parameters,\ + -misc-unused-using-decls,\ + modernize-*,\ + -modernize-avoid-c-arrays,\ + -modernize-concat-nested-namespaces,\ + -modernize-deprecated-headers,\ + -modernize-loop-convert,\ + -modernize-macro-to-enum,\ + -modernize-make-unique,\ + -modernize-pass-by-value,\ + -modernize-raw-string-literal,\ + -modernize-redundant-void-arg,\ + -modernize-return-braced-init-list,\ + -modernize-unary-static-assert,\ + -modernize-use-auto,\ + -modernize-use-bool-literals,\ + -modernize-use-default-member-init,\ + -modernize-use-emplace,\ + -modernize-use-equals-default,\ + -modernize-use-equals-delete,\ + -modernize-use-nodiscard,\ + -modernize-use-override,\ + -modernize-use-trailing-return-type,\ + -modernize-use-transparent-functors,\ + -modernize-use-using,\ + performance-*,\ + -performance-faster-string-find,\ + -performance-for-range-copy,\ + -performance-inefficient-algorithm,\ + -performance-inefficient-string-concatenation,\ + -performance-inefficient-vector-operation,\ + -performance-move-const-arg,\ + -performance-no-automatic-move,\ + -performance-noexcept-move-constructor,\ + -performance-no-int-to-ptr,\ + -performance-trivially-destructible,\ + -performance-unnecessary-copy-initialization,\ + -performance-unnecessary-value-param,\ + portability-*,\ + readability-*,\ + -readability-avoid-const-params-in-decls,\ + -readability-braces-around-statements,\ + -readability-const-return-type,\ + -readability-container-data-pointer,\ + -readability-container-size-empty,\ + -readability-convert-member-functions-to-static,\ + -readability-else-after-return,\ + -readability-function-cognitive-complexity,\ + -readability-identifier-length,\ + -readability-implicit-bool-conversion,\ + -readability-inconsistent-declaration-parameter-name,\ + -readability-isolate-declaration,\ + -readability-magic-numbers,\ + -readability-make-member-function-const,\ + -readability-named-parameter,\ + -readability-non-const-parameter,\ + -readability-qualified-auto,\ + -readability-redundant-access-specifiers,\ + -readability-redundant-control-flow,\ + -readability-redundant-declaration,\ + -readability-redundant-member-init,\ + -readability-redundant-smartptr-get,\ + -readability-redundant-string-cstr,\ + -readability-redundant-string-init,\ + -readability-simplify-boolean-expr,\ + -readability-static-accessed-through-instance,\ + -readability-static-definition-in-anonymous-namespace,\ + -readability-suspicious-call-argument,\ + -readability-uppercase-literal-suffix,\ + -readability-use-anyofallof + " diff --git a/CHANGES.md b/CHANGES.md index 1054de1e0..2a1904271 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,8 +11,14 @@ - Refactored qpp::internal::QEngineState and qpp::internal::QEngineStatistics in separate files, ["qpp/internal/classes/qengine_state.hpp"] and ["qpp/internal/classes/qengine_statistics.hpp"], respectively -- Significant code refactoring -- Introduced post-selection +- API changes in ["qpp/classes/qengine.hpp"] + - `qpp::QEngine::get_measured()` -> + `qpp::QEngine::get_measured_destructively()` + - `qpp::QEngine::get_non_measured()` -> + `qpp::QEngine::get_non_measured_destructively()` + - `qpp::QEngine::was_measured()` -> + `qpp::QEngine::was_measured_destructively()` +- Introduced post-selection in ["qpp/classes/qengine.hpp"] # Version 5.1 - 1 March 2024 @@ -42,10 +48,10 @@ - API changes in ["qpp/classes/qengine.hpp"] and ["qpp/classes/qnoisy_engine.hpp"] - Enabled mixed-state engines by refactoring - `qpp::QEngine` -> `template qpp::QEngineT` - `qpp::QNoisyEngine` -> `template qpp::QNoisyEngineT` - The template argument T is restricted to `qpp::ket` (pure state - engines) and `qpp::cmat` (mixed states engines) + - `qpp::QEngine` -> `template qpp::QEngineT` + - `qpp::QNoisyEngine` -> `template qpp::QNoisyEngineT` + The template argument T is restricted to `qpp::ket` (pure state + engines) and `qpp::cmat` (mixed states engines) - The following additional engines are now available - `qpp::QEngine` - pure state ideal engine, backwards compatibility diff --git a/include/qpp/MATLAB/matlab.hpp b/include/qpp/MATLAB/matlab.hpp index 100a7b674..30fcb8da4 100644 --- a/include/qpp/MATLAB/matlab.hpp +++ b/include/qpp/MATLAB/matlab.hpp @@ -72,7 +72,6 @@ load_MATLAB(const std::string& mat_file, const std::string& var_name) { MATFile* pmat = matOpen(mat_file.c_str(), "r"); // EXCEPTION CHECKS - if (!pmat) { throw std::runtime_error( "qpp::load_MATLAB(): Can not open MATLAB file " + mat_file + "!"); @@ -156,7 +155,6 @@ load_MATLAB(const std::string& mat_file, const std::string& var_name) { MATFile* pmat = matOpen(mat_file.c_str(), "r"); // EXCEPTION CHECKS - if (!pmat) { throw std::runtime_error( "qpp::load_MATLAB(): Can not open MATLAB file " + mat_file + "!"); @@ -218,7 +216,6 @@ save_MATLAB(const Eigen::MatrixBase& A, const std::string& mat_file, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::save_MATLAB()", "A"); @@ -287,7 +284,6 @@ save_MATLAB(const Eigen::MatrixBase& A, const std::string& mat_file, const dyn_mat& rA = A.template cast(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::save_MATLAB()", "A"); diff --git a/include/qpp/classes/gates.hpp b/include/qpp/classes/gates.hpp index 01c93d5fd..0f6684cef 100644 --- a/include/qpp/classes/gates.hpp +++ b/include/qpp/classes/gates.hpp @@ -148,7 +148,6 @@ class Gates final : public internal::Singleton // const Singleton */ cmat RX(realT theta) const { // EXCEPTION CHECKS - // END EXCEPTION CHECKS return Rn(theta, {1, 0, 0}); @@ -162,7 +161,6 @@ class Gates final : public internal::Singleton // const Singleton */ cmat RY(realT theta) const { // EXCEPTION CHECKS - // END EXCEPTION CHECKS return Rn(theta, {0, 1, 0}); @@ -176,7 +174,6 @@ class Gates final : public internal::Singleton // const Singleton */ cmat RZ(realT theta) const { // EXCEPTION CHECKS - // END EXCEPTION CHECKS return Rn(theta, {0, 0, 1}); @@ -195,7 +192,6 @@ class Gates final : public internal::Singleton // const Singleton */ cmat Zd(idx D = 2) const { // EXCEPTION CHECKS - // check valid dimension if (D == 0) { throw exception::DimsInvalid("qpp::Gates::Zd()", "D"); @@ -222,7 +218,6 @@ class Gates final : public internal::Singleton // const Singleton */ [[qpp::parallel]] cmat SWAPd(idx D = 2) const { // EXCEPTION CHECKS - // check valid dimension if (D == 0) { throw exception::DimsInvalid("qpp::Gates::SWAPd()", "D"); @@ -261,7 +256,6 @@ class Gates final : public internal::Singleton // const Singleton */ [[qpp::parallel]] cmat Fd(idx D = 2) const { // EXCEPTION CHECKS - // check valid dimension if (D == 0) { throw exception::DimsInvalid("qpp::Gates::Fd()", "D"); @@ -308,7 +302,6 @@ class Gates final : public internal::Singleton // const Singleton // check co-primality (unitarity) only in DEBUG version assert(gcd(a, N) == 1); // EXCEPTION CHECKS - // check valid arguments if (N < 3 || a >= N) { throw exception::OutOfRange("qpp::Gates::MODMUL()", "a/N"); @@ -363,7 +356,6 @@ class Gates final : public internal::Singleton // const Singleton */ cmat Xd(idx D = 2) const { // EXCEPTION CHECKS - // check valid dimension if (D == 0) { throw exception::DimsInvalid("qpp::Gates::Xd()", "D"); @@ -389,7 +381,6 @@ class Gates final : public internal::Singleton // const Singleton template Derived Id(idx D = 2) const { // EXCEPTION CHECKS - // check valid dimension if (D == 0) { throw exception::DimsInvalid("qpp::Gates::Id()", "D"); @@ -418,7 +409,6 @@ class Gates final : public internal::Singleton // const Singleton const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check matrix zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::Gates::GATE()", "A"); @@ -457,7 +447,6 @@ class Gates final : public internal::Singleton // const Singleton throw exception::MatrixMismatchSubsys("qpp::Gates::GATE()", "A/dims/target"); } - // END EXCEPTION CHECKS // Use static allocation for speed! @@ -568,7 +557,6 @@ class Gates final : public internal::Singleton // const Singleton const std::vector& target, idx n, idx d = 2) const { // EXCEPTION CHECKS - // check valid local dimension if (d == 0) { throw exception::DimsInvalid("qpp::Gates::GATE()", "d"); @@ -604,7 +592,6 @@ class Gates final : public internal::Singleton // const Singleton const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check matrix zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::Gates::CTRL()", "A"); @@ -758,7 +745,6 @@ class Gates final : public internal::Singleton // const Singleton const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::Gates::expandout()", "A"); @@ -838,7 +824,6 @@ class Gates final : public internal::Singleton // const Singleton expandout(const Eigen::MatrixBase& A, idx pos, idx n, idx d = 2) const { // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(A)) { throw exception::ZeroSize("qpp::Gates::expandout()", "A"); @@ -866,7 +851,6 @@ class Gates final : public internal::Singleton // const Singleton */ std::optional get_name(const cmat& U) const { // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(U)) { throw exception::ZeroSize("qpp::Gates::get_name()", "U"); @@ -876,7 +860,6 @@ class Gates final : public internal::Singleton // const Singleton if (!internal::check_square_mat(U)) { return {}; } - // END EXCEPTION CHECKS const idx D = static_cast(U.rows()); diff --git a/include/qpp/classes/layouts.hpp b/include/qpp/classes/layouts.hpp index b521d3c5d..167853549 100644 --- a/include/qpp/classes/layouts.hpp +++ b/include/qpp/classes/layouts.hpp @@ -99,7 +99,6 @@ class Lattice : public ILayout { */ explicit Lattice(const std::vector& dims) : dims_{dims} { // EXCEPTION CHECKS - if (dims.empty()) { throw exception::ZeroSize("qpp::Lattice::Lattice()", "dims"); } @@ -126,7 +125,6 @@ class Lattice : public ILayout { */ idx operator()(const std::vector& xs) const override { // EXCEPTION CHECKS - if (xs.size() != dims_.size()) { throw exception::SizeMismatch("qpp::Lattice::operator()", "xs"); } @@ -162,7 +160,6 @@ class Lattice : public ILayout { */ std::vector to_coordinates(idx i) const override { // EXCEPTION CHECKS - if (i >= prod(dims_)) { throw exception::OutOfRange("qpp::Lattice::to_coordinates()", "i"); } @@ -203,7 +200,6 @@ class PeriodicBoundaryLattice : public Lattice { */ idx operator()(const std::vector& xs) const override { // EXCEPTION CHECKS - if (xs.size() != dims_.size()) { throw exception::SizeMismatch("qpp::Lattice::operator()", "xs"); } diff --git a/include/qpp/classes/noise.hpp b/include/qpp/classes/noise.hpp index 62c89ac5e..d867643b0 100644 --- a/include/qpp/classes/noise.hpp +++ b/include/qpp/classes/noise.hpp @@ -174,7 +174,6 @@ class NoiseBase { std::is_same_v>* = nullptr) : Ks_{Ks}, probs_(Ks.size()) { // EXCEPTION CHECKS - if (Ks.empty()) { throw exception::ZeroSize("qpp::NoiseBase::NoiseBase()", "Ks"); } @@ -211,7 +210,6 @@ class NoiseBase { std::is_same_v>* = nullptr) : Ks_{Ks}, probs_(probs) { // EXCEPTION CHECKS - if (Ks.empty()) { throw exception::ZeroSize("qpp::NoiseBase::NoiseBase()", "Ks"); } @@ -401,7 +399,6 @@ class QubitDepolarizingNoise : public NoiseBase { Gates::get_no_thread_local_instance().Z}, {1 - p, p / 3, p / 3, p / 3}) { // EXCEPTION CHECKS - if (p < 0 || p > 1) { throw exception::OutOfRange( "qpp::QubitDepolarizingNoise::QubitDepolarizingNoise()", "p"); @@ -426,7 +423,6 @@ class QubitPhaseFlipNoise : public NoiseBase { Gates::get_no_thread_local_instance().Z}, {1 - p, p}) { // EXCEPTION CHECKS - if (p < 0 || p > 1) { throw exception::OutOfRange( "qpp::QubitPhaseFlipNoise::QubitPhaseFlipNoise()", "p"); @@ -451,7 +447,6 @@ class QubitBitFlipNoise : public NoiseBase { Gates::get_no_thread_local_instance().X}, {1 - p, p}) { // EXCEPTION CHECKS - if (p < 0 || p > 1) { throw exception::OutOfRange( "qpp::QubitBitFlipNoise::QubitBitFlipNoise()", "p"); @@ -476,7 +471,6 @@ class QubitBitPhaseFlipNoise : public NoiseBase { Gates::get_no_thread_local_instance().Y}, {1 - p, p}) { // EXCEPTION CHECKS - if (p < 0 || p > 1) { throw exception::OutOfRange( "qpp::QubitBitPhaseFlipNoise::QubitBitPhaseFlipNoise()", "p"); @@ -501,7 +495,6 @@ class QubitAmplitudeDampingNoise : public NoiseBase { ((cmat(2, 2)) << 1, 0, 0, std::sqrt(gamma)).finished(), ((cmat(2, 2)) << 0, std::sqrt(1 - gamma), 0, 0).finished()}) { // EXCEPTION CHECKS - if (gamma < 0 || gamma > 1) { throw exception::OutOfRange( "qpp::QubitAmplitudeDampingNoise::QubitAmplitudeDampingNoise()", @@ -527,7 +520,6 @@ class QubitPhaseDampingNoise : public NoiseBase { ((cmat(2, 2)) << 1, 0, 0, std::sqrt(1 - lambda)).finished(), ((cmat(2, 2)) << 0, 0, 0, std::sqrt(lambda)).finished()}) { // EXCEPTION CHECKS - if (lambda < 0 || lambda > 1) { throw exception::OutOfRange( "qpp::QubitPhaseDampingNoise::QubitPhaseDampingNoise()", @@ -592,7 +584,6 @@ class QuditDepolarizingNoise : public NoiseBase { explicit QuditDepolarizingNoise(realT p, idx D) : NoiseBase(fill_Ks_(D), fill_probs_(p, D)) { // EXCEPTION CHECKS - if (D < 2) { throw exception::OutOfRange( "qpp::QuditDepolarizingNoise::QuditDepolarizingNoise()", "D"); diff --git a/include/qpp/classes/qcircuit.hpp b/include/qpp/classes/qcircuit.hpp index 7ce7e58d7..40488573a 100644 --- a/include/qpp/classes/qcircuit.hpp +++ b/include/qpp/classes/qcircuit.hpp @@ -107,7 +107,6 @@ class QCircuit : public IDisplay, public IJSON { */ void add_hash_(std::size_t hashU, const cmat& U) { // EXCEPTION CHECKS - auto search = cmat_hash_tbl_.find(hashU); static internal::EqualEigen equal_eigen; if (search != cmat_hash_tbl_.end()) { // found the hash in the table @@ -230,7 +229,6 @@ class QCircuit : public IDisplay, public IJSON { measured_nd_(nq, false), clean_qudits_(nq_, true), clean_dits_(nc_, true), measurement_dits_(nc_, false), circuit_{} { // EXCEPTION CHECKS - // if (nq == 0) // throw exception::ZeroSize("qpp::QCircuit::QCircuit()", "nq"); if (d < 2) { @@ -324,7 +322,6 @@ class QCircuit : public IDisplay, public IJSON { */ bool was_measured(idx i) const { // EXCEPTION CHECKS - if (i >= nq_) { throw exception::OutOfRange("qpp::QCircuit::was_measured()", "i"); } @@ -358,7 +355,6 @@ class QCircuit : public IDisplay, public IJSON { */ bool was_measured_nd(idx i) const { // EXCEPTION CHECKS - if (i >= nq_) { throw exception::OutOfRange("qpp::QCircuit::was_measured_nd()", "i"); @@ -426,7 +422,6 @@ class QCircuit : public IDisplay, public IJSON { */ idx get_gate_count(std::optional U = std::nullopt) const { // EXCEPTION CHECKS - // square matrix if (U.has_value()) { if (!internal::check_square_mat(U.value())) { @@ -464,7 +459,6 @@ class QCircuit : public IDisplay, public IJSON { */ idx get_gate_depth(std::optional U = std::nullopt) const { // EXCEPTION CHECKS - // square matrix if (U.has_value() && !internal::check_square_mat(U.value())) { throw exception::MatrixNotSquare("qpp::get_gate_depth()", "U"); @@ -678,7 +672,6 @@ class QCircuit : public IDisplay, public IJSON { */ idx get_measurement_count(std::optional V = std::nullopt) const { // EXCEPTION CHECKS - if (V.has_value()) { idx result = 0; std::size_t hashV = hash_eigen(V.value()); @@ -766,7 +759,6 @@ class QCircuit : public IDisplay, public IJSON { */ QCircuit& add_qudit(idx n, idx pos) { // EXCEPTION CHECKS - if (pos > nq_) { throw exception::OutOfRange("qpp::QCircuit::add_qudit()", "pos"); } @@ -843,7 +835,6 @@ class QCircuit : public IDisplay, public IJSON { */ QCircuit& add_dit(idx n, idx pos) { // EXCEPTION CHECKS - if (pos > nc_) { throw exception::OutOfRange("qpp::QCircuit::add_dit()", "pos"); } @@ -905,7 +896,6 @@ class QCircuit : public IDisplay, public IJSON { QCircuit& gate(const cmat& U, idx i, std::optional name = std::nullopt) { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // check valid target @@ -960,7 +950,6 @@ class QCircuit : public IDisplay, public IJSON { QCircuit& gate(const cmat& U, idx i, idx j, std::optional name = std::nullopt) { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // check valid target @@ -1016,7 +1005,6 @@ class QCircuit : public IDisplay, public IJSON { QCircuit& gate(const cmat& U, idx i, idx j, idx k, std::optional name = std::nullopt) { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // check valid target @@ -1072,7 +1060,6 @@ class QCircuit : public IDisplay, public IJSON { QCircuit& gate_fan(const cmat& U, const std::vector& target, std::optional name = std::nullopt) { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // check valid target @@ -1157,7 +1144,6 @@ class QCircuit : public IDisplay, public IJSON { QCircuit& gate_fan(const cmat& U, std::optional name = std::nullopt) { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // check non-empty target @@ -1188,7 +1174,6 @@ class QCircuit : public IDisplay, public IJSON { QCircuit& gate(const cmat& U, const std::vector& target, std::optional name = std::nullopt) { // EXCEPTION CHECKS - idx n = static_cast(target.size()); idx D = internal::safe_pow(d_, n); @@ -1258,7 +1243,6 @@ class QCircuit : public IDisplay, public IJSON { */ QCircuit& QFT(const std::vector& target, bool swap = true) { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // check valid target @@ -1374,7 +1358,6 @@ class QCircuit : public IDisplay, public IJSON { QCircuit& TFQ(const std::vector& target, [[maybe_unused]] bool swap = true) { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // check valid target @@ -1497,7 +1480,6 @@ class QCircuit : public IDisplay, public IJSON { std::optional shift = std::nullopt, std::optional name = std::nullopt) { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // check valid ctrl @@ -1607,7 +1589,6 @@ class QCircuit : public IDisplay, public IJSON { std::optional> shift = std::nullopt, std::optional name = std::nullopt) { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // check valid ctrl @@ -1736,7 +1717,6 @@ class QCircuit : public IDisplay, public IJSON { std::optional> shift = std::nullopt, std::optional name = std::nullopt) { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; idx D_target = internal::safe_pow(d_, target.size()); @@ -1859,7 +1839,6 @@ class QCircuit : public IDisplay, public IJSON { std::optional> shift = std::nullopt, std::optional name = std::nullopt) { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // check valid ctrl @@ -1969,7 +1948,6 @@ class QCircuit : public IDisplay, public IJSON { std::optional shift = std::nullopt, std::optional name = std::nullopt) { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; idx D_target = internal::safe_pow(d_, target.size()); @@ -2075,7 +2053,6 @@ class QCircuit : public IDisplay, public IJSON { std::optional shift = std::nullopt, std::optional name = std::nullopt) { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // check valid ctrl and target @@ -2150,7 +2127,6 @@ class QCircuit : public IDisplay, public IJSON { std::optional shift = std::nullopt, std::optional name = std::nullopt) { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // check valid ctrl_dit @@ -2247,7 +2223,6 @@ class QCircuit : public IDisplay, public IJSON { std::optional> shift = std::nullopt, std::optional name = std::nullopt) { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // check valid ctrl_dits @@ -2361,7 +2336,6 @@ class QCircuit : public IDisplay, public IJSON { std::optional> shift = std::nullopt, std::optional name = std::nullopt) { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; idx D_target = internal::safe_pow(d_, target.size()); @@ -2476,7 +2450,6 @@ class QCircuit : public IDisplay, public IJSON { std::optional> shift = std::nullopt, std::optional name = std::nullopt) { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // check valid ctrl_dits @@ -2575,7 +2548,6 @@ class QCircuit : public IDisplay, public IJSON { std::optional shift = std::nullopt, std::optional name = std::nullopt) { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; idx D_target = internal::safe_pow(d_, target.size()); @@ -2670,7 +2642,6 @@ class QCircuit : public IDisplay, public IJSON { std::optional shift = std::nullopt, std::optional name = std::nullopt) { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // check valid ctrl_dit and target @@ -2742,7 +2713,6 @@ class QCircuit : public IDisplay, public IJSON { QCircuit& measure(idx target, idx c_reg, bool destructive = true, std::optional name = "mZ") { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // measuring non-existing qudit @@ -2807,7 +2777,6 @@ class QCircuit : public IDisplay, public IJSON { bool destructive = true, std::optional name = "mZ") { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // check valid target @@ -2887,7 +2856,6 @@ class QCircuit : public IDisplay, public IJSON { QCircuit& measure_all(idx c_reg = 0, bool destructive = true, std::optional name = "mZ") { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; std::vector non_measured = get_non_measured(); @@ -2925,7 +2893,6 @@ class QCircuit : public IDisplay, public IJSON { bool destructive = true, std::optional name = std::nullopt) { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // measuring non-existing qudit @@ -3007,7 +2974,6 @@ class QCircuit : public IDisplay, public IJSON { bool destructive = true, std::optional name = std::nullopt) { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // check valid target @@ -3109,7 +3075,6 @@ class QCircuit : public IDisplay, public IJSON { bool destructive = true, std::optional name = "pZ") { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // post-selecting non-existing qudit @@ -3180,7 +3145,6 @@ class QCircuit : public IDisplay, public IJSON { bool destructive = true, std::optional name = "pZ") { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // check valid target @@ -3274,7 +3238,6 @@ class QCircuit : public IDisplay, public IJSON { bool destructive = true, std::optional name = std::nullopt) { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // measuring non-existing qudit @@ -3363,7 +3326,6 @@ class QCircuit : public IDisplay, public IJSON { bool destructive = true, std::optional name = std::nullopt) { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // check valid target @@ -3470,7 +3432,6 @@ class QCircuit : public IDisplay, public IJSON { */ QCircuit& discard(idx target, std::optional name = "discard") { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // discarding non-existing qudit @@ -3512,7 +3473,6 @@ class QCircuit : public IDisplay, public IJSON { QCircuit& discard(const std::vector& target, std::optional name = "discard") { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // check valid target @@ -3579,7 +3539,6 @@ class QCircuit : public IDisplay, public IJSON { */ QCircuit& reset(idx target, std::optional name = "reset") { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // resetting non-existing qudit @@ -3619,7 +3578,6 @@ class QCircuit : public IDisplay, public IJSON { QCircuit& reset(const std::vector& target, std::optional name = "reset") { // EXCEPTION CHECKS - std::string context{"Step " + std::to_string(get_step_count())}; // check valid target @@ -3662,7 +3620,6 @@ class QCircuit : public IDisplay, public IJSON { */ QCircuit& replicate(idx n) { // EXCEPTION CHECKS - if (n == 0) { throw exception::OutOfRange("qpp::QCircuit::replicate()", "n"); } @@ -3715,7 +3672,6 @@ class QCircuit : public IDisplay, public IJSON { QCircuit& compose_circuit(QCircuit other, bigint pos_qudit, std::optional pos_dit = std::nullopt) { // EXCEPTION CHECKS - // check equal dimensions if (other.d_ != d_) { throw exception::DimsNotEqual("qpp::QCircuit::compose_circuit()", @@ -3901,7 +3857,6 @@ class QCircuit : public IDisplay, public IJSON { const std::vector& target, std::optional pos_dit = std::nullopt) { // EXCEPTION CHECKS - // check equal dimensions if (other.d_ != d_) { throw exception::DimsNotEqual( @@ -4071,7 +4026,6 @@ class QCircuit : public IDisplay, public IJSON { const std::vector& target, std::optional pos_dit = std::nullopt) { // EXCEPTION CHECKS - // check equal dimensions if (other.d_ != d_) { throw exception::DimsNotEqual( @@ -4246,7 +4200,6 @@ class QCircuit : public IDisplay, public IJSON { std::optional> shift = std::nullopt, std::optional pos_dit = std::nullopt) { // EXCEPTION CHECKS - // check non-empty control circuit if (this->get_nq() == 0) { throw exception::ZeroSize("qpp::QCircuit::compose_CTRL_circuit()", @@ -4502,7 +4455,6 @@ class QCircuit : public IDisplay, public IJSON { */ QCircuit& adjoint() { // EXCEPTION CHECKS - if (this->has_measurements()) { throw exception::QuditAlreadyMeasured( "qpp::QCircuit::adjoint()", "Current qpp::QCircuit instance"); @@ -4554,7 +4506,6 @@ class QCircuit : public IDisplay, public IJSON { */ bool is_clean_qudit(idx i) const { // EXCEPTION CHECKS - // check valid target if (i >= nq_) { throw exception::OutOfRange("qpp::QCircuit::is_clean_qudit()", "i"); @@ -4576,7 +4527,6 @@ class QCircuit : public IDisplay, public IJSON { */ bool is_clean_dit(idx i) const { // EXCEPTION CHECKS - // check valid target if (i >= nc_) { throw exception::OutOfRange("qpp::QCircuit::is_clean_dit()", "i"); @@ -4597,7 +4547,6 @@ class QCircuit : public IDisplay, public IJSON { */ bool is_measurement_dit(idx i) const { // EXCEPTION CHECKS - // check valid target if (i >= nc_) { throw exception::OutOfRange("qpp::QCircuit::is_measurement_dit()", @@ -4677,7 +4626,6 @@ class QCircuit : public IDisplay, public IJSON { */ QCircuit& remove_clean_qudit(idx target) { // EXCEPTION CHECKS - // check valid target and clean qudit if (target >= nq_ || !is_clean_qudit(target)) { throw exception::OutOfRange("qpp::QCircuit::remove_clean_qudit()", @@ -4730,7 +4678,6 @@ class QCircuit : public IDisplay, public IJSON { */ QCircuit& remove_clean_dit(idx target) { // EXCEPTION CHECKS - // check valid target and clean dit if (target >= nc_ || !is_clean_dit(target)) { throw exception::OutOfRange("qpp::QCircuit::remove_clean_dit()", @@ -4775,7 +4722,6 @@ class QCircuit : public IDisplay, public IJSON { */ QCircuit& remove_clean_qudits(std::vector target) { // EXCEPTION CHECKS - // check valid target for (idx elem : target) { // removing non-existing or non-clean qudit @@ -4809,7 +4755,6 @@ class QCircuit : public IDisplay, public IJSON { */ QCircuit& remove_clean_dits(std::vector target) { // EXCEPTION CHECKS - // check valid target for (idx elem : target) { // removing non-existing or non-clean dit @@ -5147,7 +5092,6 @@ class QCircuitIterator { */ QCircuitIterator& operator++() { // EXCEPTION CHECKS - // protects against incrementing invalid iterators if (qc_ptr_ == nullptr) { throw exception::InvalidIterator( @@ -5216,7 +5160,6 @@ class QCircuitIterator { */ value_type operator*() const { // EXCEPTION CHECKS - // protects against de-referencing past the last element or // against de-referencing invalid iterators idx num_steps = qc_ptr_->get_step_count(); @@ -5479,7 +5422,6 @@ inline QCircuit compose_circuit(QCircuit qc1, const QCircuit& qc2, std::optional name = std::nullopt, std::optional pos_dit = std::nullopt) { // EXCEPTION CHECKS - // check equal dimensions if (qc1.get_d() != qc2.get_d()) { throw exception::DimsNotEqual("qpp::compose_circuit()", "other"); @@ -5561,7 +5503,6 @@ couple_circuit_left(QCircuit qc1, const QCircuit& qc2, std::optional name = std::nullopt, std::optional pos_dit = std::nullopt) { // EXCEPTION CHECKS - // check equal dimensions if (qc1.get_d() != qc2.get_d()) { throw exception::DimsNotEqual("qpp::couple_circuit_left()", "qc1/qc2"); @@ -5646,7 +5587,6 @@ couple_circuit_right(QCircuit qc1, const QCircuit& qc2, std::optional pos_dit = std::nullopt) { // EXCEPTION CHECKS - // check equal dimensions if (qc1.get_d() != qc2.get_d()) { throw exception::DimsNotEqual("qpp::couple_circuit_right()", "qc1/qc2"); @@ -5735,7 +5675,6 @@ compose_CTRL_circuit(QCircuit qc_ctrl, const std::vector& ctrl, std::optional name = std::nullopt) { // EXCEPTION CHECKS - // check non-empty qc_ctrl and qc_target if (qc_ctrl.get_nq() == 0) { throw exception::ZeroSize("qpp::compose_CTRL_circuit()", "qc_ctrl"); @@ -5850,7 +5789,6 @@ compose_CTRL_circuit(QCircuit qc_ctrl, const std::vector& ctrl, inline QCircuit adjoint(QCircuit qc, std::optional name = nullptr) { // EXCEPTION CHECKS - if (qc.has_measurements()) { throw exception::QuditAlreadyMeasured("qpp::adjoint()", "qc"); } @@ -5898,7 +5836,6 @@ inline QCircuit replicate(QCircuit qc, idx n, } // EXCEPTION CHECKS - if (n == 0) { throw exception::OutOfRange("qpp::replicate()", "n"); } @@ -5941,7 +5878,6 @@ inline QCircuit random_circuit_count( std::optional> two_qudit_gate_names = std::nullopt) { // EXCEPTION CHECKS - // check valid dimension if (d < 2) { throw exception::DimsInvalid("qpp::random_circuit_count()", "d"); @@ -6127,7 +6063,6 @@ inline QCircuit random_circuit_depth( std::optional> two_qudit_gate_names = std::nullopt) { // EXCEPTION CHECKS - // check valid dimension if (d < 2) { throw exception::DimsInvalid("qpp::random_circuit_depth()", "d"); @@ -6304,7 +6239,6 @@ inline QCircuit qpe_circuit(cmat U, qpp::idx n, bool omit_measurements = true, idx d = 2, std::optional name = "qpe") { // EXCEPTION CHECKS - // check square matrix for the gate if (!internal::check_square_mat(U)) { throw exception::MatrixNotSquare("qpp::qpe_circuit()", "U"); diff --git a/include/qpp/classes/qengine.hpp b/include/qpp/classes/qengine.hpp index d74bf6e27..bd8f8bc00 100644 --- a/include/qpp/classes/qengine.hpp +++ b/include/qpp/classes/qengine.hpp @@ -78,6 +78,49 @@ namespace qpp { template class QEngineT : public QBaseEngine { bool can_sample; ///< can sample when executing with multiple repetitions + + /** + * \brief Executes a contiguous series of projective measurement steps + * + * \param engine_state Instance of qpp::internal::QEngineState + * \param steps Vector of qpp::QCircuit::iterator + * \idx pos Index from where the execution starts + * \idx reps Number of repetitions + * \return Reference to the current instance + */ + QEngineT& execute_no_sample_(internal::QEngineState engine_state, + const std::vector& steps, + idx pos, idx reps) { + std::cout << "4" << std::endl; + for (idx rep = 0; rep < reps; ++rep) { + // sets the state of the engine to the entry state + qeng_st_ = engine_state; + bool measured = false; + for (idx i = pos; i < steps.size(); ++i) { + if (internal::is_measurement(steps[i])) { + measured = true; + } + this->execute(steps[i]); + // post-selection failed, stop executing + if (!qeng_st_.post_select_ok_) { + break; + } + } + // post-selection failed, skip this run + if (!qeng_st_.post_select_ok_) { + continue; + } + + // at least one qudit was measured + if (measured) { + std::vector m_res = get_dits(); + ++stats_.data()[m_res]; + } + } + + return *this; + } + protected: internal::QEngineState qeng_st_; ///< current state of the engine internal::QEngineStatistics @@ -86,12 +129,12 @@ class QEngineT : public QBaseEngine { /** * \brief Marks qudit \a i as measured then re-label accordingly the * remaining non-measured qudits + * * \param i Qudit index */ - void set_measured_(idx i) { + void set_measured_destructively_(idx i) { // EXCEPTION CHECKS - - if (was_measured(i)) { + if (was_measured_destructively(i)) { throw exception::QuditAlreadyMeasured( "qpp::QEngineT::set_measured_()", "i"); } @@ -99,14 +142,14 @@ class QEngineT : public QBaseEngine { qeng_st_.subsys_[i] = std::numeric_limits::max(); // set qudit i to measured state for (idx m = i; m < this->qc_ptr_->get_nq(); ++m) { - if (!was_measured(m)) { + if (!was_measured_destructively(m)) { --qeng_st_.subsys_[m]; } } } - // giving a vector of non-measured qudits, get their relative position wrt - // the measured qudits + // giving a vector of non-measured qudits, get their relative position + // w.r.t. the measured qudits /** * \brief Giving a vector \a v of non-measured qudits, gets their relative * position with respect to the measured qudits @@ -118,8 +161,7 @@ class QEngineT : public QBaseEngine { idx vsize = v.size(); for (idx i = 0; i < vsize; ++i) { // EXCEPTION CHECKS - - if (was_measured(v[i])) { + if (was_measured_destructively(v[i])) { throw exception::QuditAlreadyMeasured( "qpp::QEngineT::get_relative_pos_()", "v[i]"); } @@ -131,6 +173,7 @@ class QEngineT : public QBaseEngine { /** * \brief Executes qpp::internal::QCircuitGateStep + * * \param gate_step Instance of qpp::internal::QCircuitGateStep */ virtual void @@ -256,6 +299,7 @@ class QEngineT : public QBaseEngine { /** * \brief Executes qpp::internal::QCircuitMeasurementStep + * * \param measurement_step Instance of * qpp::internal::QCircuitMeasurementStep */ @@ -291,7 +335,7 @@ class QEngineT : public QBaseEngine { qeng_st_.dits_[measurement_step.c_reg_] = results[0]; qeng_st_.probs_[measurement_step.c_reg_] = probs[0]; if (destructive) { - set_measured_(measurement_step.target_[0]); + set_measured_destructively_(measurement_step.target_[0]); } // POST_SELECT(_ND) if (mstep_type_ == MType::POST_SELECT || @@ -318,7 +362,7 @@ class QEngineT : public QBaseEngine { measurement_step.c_reg_)); if (destructive) { for (idx target : measurement_step.target_) { - set_measured_(target); + set_measured_destructively_(target); } } // POST_SELECT_MANY(_ND) @@ -327,7 +371,6 @@ class QEngineT : public QBaseEngine { // post-selection failed if (results != measurement_step.ps_vals_.value()) { qeng_st_.post_select_ok_ = false; - // std::cerr << "POST_SELECT_MANY failed!" << std::endl; } } break; @@ -343,7 +386,7 @@ class QEngineT : public QBaseEngine { qeng_st_.dits_[measurement_step.c_reg_] = mres; qeng_st_.probs_[measurement_step.c_reg_] = probs[mres]; if (destructive) { - set_measured_(measurement_step.target_[0]); + set_measured_destructively_(measurement_step.target_[0]); } // POST_SELECT_V(_ND) if (mstep_type_ == MType::POST_SELECT_V || @@ -351,7 +394,6 @@ class QEngineT : public QBaseEngine { // post-selection failed if (mres != measurement_step.ps_vals_.value()[0]) { qeng_st_.post_select_ok_ = false; - // std::cerr << "POST_SELECT_V failed!" << std::endl; } } break; @@ -368,7 +410,7 @@ class QEngineT : public QBaseEngine { qeng_st_.probs_[measurement_step.c_reg_] = probs[mres]; if (destructive) { for (idx target : measurement_step.target_) { - set_measured_(target); + set_measured_destructively_(target); } } // POST_SELECT_V(_ND) @@ -392,13 +434,13 @@ class QEngineT : public QBaseEngine { case MType::DISCARD: std::tie(std::ignore, std::ignore, qeng_st_.qstate_) = measure_seq(qeng_st_.qstate_, target_rel_pos, d); - set_measured_(measurement_step.target_[0]); + set_measured_destructively_(measurement_step.target_[0]); break; case MType::DISCARD_MANY: std::tie(std::ignore, std::ignore, qeng_st_.qstate_) = measure_seq(qeng_st_.qstate_, target_rel_pos, d); for (idx target : measurement_step.target_) { - set_measured_(target); + set_measured_destructively_(target); } break; } // end switch on measurement type @@ -406,11 +448,138 @@ class QEngineT : public QBaseEngine { /** * \brief Executes qpp::internal::QCircuitNOPStep + * * \param nop_step Instance of qpp::internal::QCircuitNOPStep */ virtual void execute_nop_step_( [[maybe_unused]] const internal::QCircuitNOPStep& nop_step) {} + /** + * \brief Executes a contiguous series of projective measurement steps via + * sampling + * + * \param engine_state Instance of qpp::internal::QEngineState + * \param steps Vector of qpp::QCircuit::iterator + * \idx pos Index from where the execution starts; from this index further, + * all steps are assumed to be a projective measurement (including + * post-selection) + * \idx reps Number of repetitions + * \return Reference to the current instance + */ + QEngineT& execute_sample_(const internal::QEngineState& engine_state, + const std::vector& steps, + idx pos, idx reps) { + std::map>> + c_q; // records the c <- (q, [OPTIONAL ps_val]) map + std::map q_ps_val; // records the q <- ps_val map + std::set q_m; // qubits that were measured (projectively, + // including post-selected) + bool measured = false; + for (idx i = pos; i < steps.size(); ++i) { + // post-selection + if (internal::is_projective_post_selection(steps[i])) { + measured = true; + auto [_, target, ps_vals, c_regs] = + internal::extract_ctrl_target_ps_vals_c_reg(steps[i]); + for (idx q = 0; q < static_cast(target.size()); ++q) { + q_m.emplace(target[q]); + c_q[c_regs[q]] = {target[q], ps_vals[q]}; + // build the q <- ps_val map + // insert if not exists + if (auto it = q_ps_val.find(target[q]); + it == q_ps_val.end()) { + q_ps_val[target[q]] = ps_vals[q]; + } else + // element already exists, make sure that + // post-selection is consistent + { + // post-selection is incompatible + if (auto ps_val = it->second; ps_val != ps_vals[q]) { + qeng_st_.post_select_ok_ = false; + std::cout << "fails here" << std::endl; + std::cout << "sample? " << can_sample << std::endl; + return *this; + } + } + } + std::cout << "1" << std::endl; + } + // projective measurement + else if (internal::is_projective_measurement(steps[i])) { + measured = true; + auto [_, target, ps_vals_, c_regs] = + internal::extract_ctrl_target_ps_vals_c_reg(steps[i]); + for (idx q = 0; q < static_cast(target.size()); ++q) { + q_m.emplace(target[q]); + c_q[c_regs[q]] = {target[q], {}}; + } + std::cout << "2" << std::endl; + } + } + // at least one qudit was measured, add it to stats_ + if (measured) { + std::cout << "----------" << std::endl; + for (auto elem : q_m) { + std::cout << elem << " "; + } + std::cout << "\n-------" << std::endl; + // build the vector of measured qudits that we must sample + // from + std::cout << "3" << std::endl; + std::set sample_from_set; + for (auto [dit, qubit_ps_val] : c_q) { + sample_from_set.emplace(qubit_ps_val.first); + std::cout << "1" << std::endl; + } + // insert the post-selected qubits into the sample_from_set + for (auto [post_selected_qubit, _] : q_ps_val) { + sample_from_set.emplace(post_selected_qubit); + } + std::vector sample_from(sample_from_set.begin(), + sample_from_set.end()); + for (idx rep = 0; rep < reps; ++rep) { + // sample from the quantum state + std::vector sample_result_restricted_support = sample( + engine_state.qstate_, sample_from, this->qc_ptr_->get_d()); + // make sure post-selected qubits agree on their values + bool post_selection_failed = false; + for (idx q = 0; q < sample_from.size(); ++q) { + // qubit sample_from[i] is a post-selected qubit + if (auto it = q_ps_val.find(sample_from[q]); + it != q_ps_val.end()) { + if (sample_result_restricted_support[q] != it->second) { + post_selection_failed = true; + break; + } + } + } + if (post_selection_failed) { + continue; + } + // extend sample_result to full support + std::vector sample_result = this->get_dits(); + idx i = 0; + for (auto [dit, qubit_ps_val] : c_q) { + sample_result[dit] = sample_result_restricted_support[i++]; + } + ++stats_.data()[sample_result]; + } + // compute the final state + auto qstate = engine_state.qstate_; + // build the projector onto the post-selected part + // |...x...y...z...><...x...y...z...| + std::vector prj_ps(qeng_st_.qc_ptr_->get_nq()); + for (auto elem : q_ps_val) { + prj_ps[elem.first] = elem.second; + } + std::cout << "BEGIN prj_ps\n"; + std::cout << disp(prj_ps) << std::endl; + std::cout << "END prj_ps\n"; + } + + return *this; + }; + public: using QBaseEngine::QBaseEngine; using QBaseEngine::execute; @@ -490,7 +659,6 @@ class QEngineT : public QBaseEngine { */ idx get_dit(idx i) const { // EXCEPTION CHECKS - if (i >= this->qc_ptr_->get_nc()) { throw exception::OutOfRange("qpp::QEngineT::get_dit()", "i"); } @@ -528,7 +696,7 @@ class QEngineT : public QBaseEngine { * \param i Qudit index * \return True if qudit \a i was already measured, false otherwise */ - bool was_measured(idx i) const { + bool was_measured_destructively(idx i) const { return qeng_st_.subsys_[i] == std::numeric_limits::max(); } @@ -539,10 +707,10 @@ class QEngineT : public QBaseEngine { * \return Vector of already measured qudit (destructively) indexes at * the current engine state */ - std::vector get_measured() const { + std::vector get_measured_destructively() const { std::vector result; for (idx i = 0; i < this->qc_ptr_->get_nq(); ++i) { - if (was_measured(i)) { + if (was_measured_destructively(i)) { result.emplace_back(i); } } @@ -551,14 +719,14 @@ class QEngineT : public QBaseEngine { } /** - * \brief Vector of non-measured qudit indexes + * \brief Vector of non-measured (destructively) qudit indexes * - * \return Vector of non-measured qudit indexes + * \return Vector of non-measured (destructively) qudit indexes */ - std::vector get_non_measured() const { + std::vector get_non_measured_destructively() const { std::vector result; for (idx i = 0; i < this->qc_ptr_->get_nq(); ++i) { - if (!was_measured(i)) { + if (!was_measured_destructively(i)) { result.emplace_back(i); } } @@ -600,7 +768,6 @@ class QEngineT : public QBaseEngine { */ QEngineT& set_dit(idx i, idx value) { // EXCEPTION CHECKS - if (i >= this->qc_ptr_->get_nc()) { throw exception::OutOfRange("qpp::QEngineT::set_dit()", "i"); } @@ -624,7 +791,6 @@ class QEngineT : public QBaseEngine { */ QEngineT& set_dits(std::vector dits) { // EXCEPTION CHECKS - if (dits.size() != qeng_st_.dits_.size()) { throw exception::SizeMismatch("qpp::QEngineT::set_dits()", "dits"); } @@ -645,8 +811,7 @@ class QEngineT : public QBaseEngine { */ QEngineT& set_state(const T& state) override { // EXCEPTION CHECKS - - idx n = get_non_measured().size(); + idx n = get_non_measured_destructively().size(); idx D = internal::safe_pow(this->qc_ptr_->get_d(), n); if constexpr (std::is_same_v) { if (static_cast(state.rows()) != D) { @@ -713,7 +878,6 @@ class QEngineT : public QBaseEngine { QEngineT& execute( const typename QCircuitTraits::value_type& elem) override { // EXCEPTION CHECKS - // iterator must point to the same quantum circuit description if (elem.get_qc_ptr() != this->qc_ptr_) { throw exception::InvalidIterator( @@ -761,8 +925,6 @@ class QEngineT : public QBaseEngine { return *this; } - idx num_steps = steps.size(); - // in the following, we will partition the circuit as // [0 ... first_measurement_discard_reset_pos ... end) @@ -779,7 +941,7 @@ class QEngineT : public QBaseEngine { // first_measurement_discard_reset_pos must be a projective measurement) this->can_sample = reps > 1; for (idx i = first_measurement_discard_reset_pos; - i < num_steps && this->can_sample; ++i) { + i < steps.size() && this->can_sample; ++i) { if (!(internal::is_projective_measurement(steps[i])) || internal::is_discard(steps[i])) { this->can_sample = false; @@ -794,143 +956,21 @@ class QEngineT : public QBaseEngine { } // save the state just before the first measurement - auto current_engine_state = qeng_st_; + // auto current_engine_state = qeng_st_; // TODO: toggle it to off after debugging! - // this->can_sample = false; + this->can_sample = false; // execute repeatedly everything in the remaining interval // can sample: every step from now on is a projective measurement if (this->can_sample) { - std::map>> - c_q; // records the c <- (q, [OPTIONAL ps_val]) map - std::map q_ps_val; // records the q <- ps_val map - bool measured = false; - for (idx i = first_measurement_discard_reset_pos; i < num_steps; - ++i) { - // post-selection - if (internal::is_projective_post_selection(steps[i])) { - measured = true; - auto [_, target, ps_vals, c_regs] = - internal::extract_ctrl_target_ps_vals_c_reg(steps[i]); - for (idx q = 0; q < static_cast(target.size()); ++q) { - c_q[c_regs[q]] = {target[q], ps_vals[q]}; - // build the q <- ps_val map - // insert if not exists - if (auto it = q_ps_val.find(target[q]); - it == q_ps_val.end()) { - q_ps_val[target[q]] = ps_vals[q]; - } else - // element already exists, make sure that post-selection - // is consistent - { - // post-selection is incompatible - if (auto ps_val = it->second; - ps_val != ps_vals[q]) { - qeng_st_.post_select_ok_ = false; - std::cout << "fails here" << std::endl; - std::cout << "sample? " << can_sample - << std::endl; - return *this; - } - } - } - std::cout << "1" << std::endl; - } - // projective measurement - else if (internal::is_projective_measurement(steps[i])) { - measured = true; - auto [_, target, ps_vals_, c_regs] = - internal::extract_ctrl_target_ps_vals_c_reg(steps[i]); - for (idx q = 0; q < static_cast(target.size()); ++q) { - c_q[c_regs[q]] = {target[q], {}}; - } - std::cout << "2" << std::endl; - } - } - // at least one qudit was measured, add it to stats_ - if (measured) { - // build the vector of measured qudits that we must sample - // from - std::cout << "3" << std::endl; - std::set sample_from_set; - for (auto [dit, qubit_ps_val] : c_q) { - sample_from_set.insert(qubit_ps_val.first); - std::cout << "1" << std::endl; - } - // insert the post-selected qubits into the sample_from_set - for (auto [post_selected_qubit, _] : q_ps_val) { - sample_from_set.insert(post_selected_qubit); - } - std::vector sample_from(sample_from_set.begin(), - sample_from_set.end()); - for (idx rep = 0; rep < reps - 1; ++rep) { - // sample from the quantum state - std::vector sample_result_restricted_support = - sample(current_engine_state.qstate_, sample_from, - this->qc_ptr_->get_d()); - // make sure post-selected qubits agree on their values - bool post_selection_failed = false; - for (idx i = 0; i < sample_from.size(); ++i) { - // qubit sample_from[i] is a post-selected qubit - if (auto it = q_ps_val.find(sample_from[i]); - it != q_ps_val.end()) { - if (sample_result_restricted_support[i] != - it->second) { - post_selection_failed = true; - break; - } - } - } - if (post_selection_failed) { - continue; - } - // extend sample_result to full support - std::vector sample_result = this->get_dits(); - idx i = 0; - for (auto [dit, qubit_ps_val] : c_q) { - sample_result[dit] = - sample_result_restricted_support[i++]; - } - ++stats_.data()[sample_result]; - } - // compute the final state - // execute the last repetition, so we can compute the final - // state - for (idx i = first_measurement_discard_reset_pos; i < num_steps; - ++i) { - this->execute(steps[i]); - } - std::vector m_res = get_dits(); - ++stats_.data()[m_res]; - } + execute_sample_(qeng_st_, steps, + first_measurement_discard_reset_pos, reps); } // cannot sample else { - std::cout << "4" << std::endl; - for (idx rep = 0; rep < reps; ++rep) { - // sets the state of the engine to the entry state - qeng_st_ = current_engine_state; - bool measured = false; - for (idx i = first_measurement_discard_reset_pos; i < num_steps; - ++i) { - if (internal::is_measurement(steps[i])) { - measured = true; - } - this->execute(steps[i]); - if (!qeng_st_.post_select_ok_) { - break; - } - } - // at least one qudit was measured - if (measured) { - if (!qeng_st_.post_select_ok_) { - continue; - } - std::vector m_res = get_dits(); - ++stats_.data()[m_res]; - } - } + execute_no_sample_(qeng_st_, steps, + first_measurement_discard_reset_pos, reps); } return *this; @@ -960,12 +1000,14 @@ class QEngineT : public QBaseEngine { ss << "\"sampling\": " << (this->can_sample ? "true" : "false") << ", "; ss << "\"measured/discarded (destructively)\": "; - ss << disp(get_measured(), IOManipContainerOpts{}.set_sep(", ")); + ss << disp(get_measured_destructively(), + IOManipContainerOpts{}.set_sep(", ")); result += ss.str() + ", "; ss.str(""); ss.clear(); - ss << disp(get_non_measured(), IOManipContainerOpts{}.set_sep(", ")); + ss << disp(get_non_measured_destructively(), + IOManipContainerOpts{}.set_sep(", ")); result += "\"non-measured (destructively)/non-discarded\": " + ss.str(); ss.str(""); diff --git a/include/qpp/classes/qnoisy_engine.hpp b/include/qpp/classes/qnoisy_engine.hpp index 161cee82f..a8201dcec 100644 --- a/include/qpp/classes/qnoisy_engine.hpp +++ b/include/qpp/classes/qnoisy_engine.hpp @@ -72,7 +72,6 @@ class QNoisyEngineT : public QEngineT { explicit QNoisyEngineT(const QCircuit& qc, const NoiseModel& noise) : QEngineT{qc}, noise_{noise}, noise_results_(qc.get_step_count()) { // EXCEPTION CHECKS - // check noise has the correct dimensionality if (qc.get_d() != noise.get_d()) { throw exception::DimsNotEqual("qpp::QNoisyEngineT::QNoisyEngineT()", @@ -133,9 +132,17 @@ class QNoisyEngineT : public QEngineT { for (auto&& elem : *this->qc_ptr_) { (void)execute(elem); + // post-selection failed, stop executing + if (!this->qeng_st_.post_select_ok_) { + break; + } + } + // post-selection failed, skip this run + if (!this->qeng_st_.post_select_ok_) { + continue; } - // we measured at least one qudit + // at least one qudit was measured if (this->qc_ptr_->get_measurement_count() > 0) { std::vector m_res = this->get_dits(); ++this->stats_.data()[m_res]; diff --git a/include/qpp/classes/states.hpp b/include/qpp/classes/states.hpp index cd2f5659b..445b7bbd4 100644 --- a/include/qpp/classes/states.hpp +++ b/include/qpp/classes/states.hpp @@ -106,7 +106,6 @@ class States final : public internal::Singleton // const Singleton */ ket mes(idx d = 2) const { // EXCEPTION CHECKS - // check valid dims if (d == 0) { throw exception::DimsInvalid("qpp::States::mes()", "d"); @@ -131,7 +130,6 @@ class States final : public internal::Singleton // const Singleton */ ket zero(idx n = 1, idx d = 2) const { // EXCEPTION CHECKS - // check out of range if (n == 0) { throw exception::OutOfRange("qpp::States::zero()", "n"); @@ -159,7 +157,6 @@ class States final : public internal::Singleton // const Singleton */ ket one(idx n = 1, idx d = 2) const { // EXCEPTION CHECKS - // check out of range if (n == 0) { throw exception::OutOfRange("qpp::States::one()", "n"); @@ -187,7 +184,6 @@ class States final : public internal::Singleton // const Singleton */ ket jn(idx j, idx n = 1, idx d = 2) const { // EXCEPTION CHECKS - // check out of range if (n == 0) { throw exception::OutOfRange("qpp::States::jn()", "n"); @@ -218,7 +214,6 @@ class States final : public internal::Singleton // const Singleton */ ket j(idx j, idx D = 2) const { // EXCEPTION CHECKS - // check valid subsystem if (j >= D) { throw exception::SubsysMismatchDims("qpp::States::j()", "D/j"); @@ -244,7 +239,6 @@ class States final : public internal::Singleton // const Singleton */ ket plus(idx n = 1) const { // EXCEPTION CHECKS - // check out of range if (n == 0) { throw exception::OutOfRange("qpp::States::plus()", "n"); @@ -266,7 +260,6 @@ class States final : public internal::Singleton // const Singleton */ ket minus(idx n = 1) const { // EXCEPTION CHECKS - // check out of range if (n == 0) { throw exception::OutOfRange("qpp::States::minus()", "n"); diff --git a/include/qpp/entanglement.hpp b/include/qpp/entanglement.hpp index 2402fd346..3f2430538 100644 --- a/include/qpp/entanglement.hpp +++ b/include/qpp/entanglement.hpp @@ -67,7 +67,6 @@ dyn_col_vect schmidtcoeffs(const Eigen::MatrixBase& A, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::schmidtcoeffs()", "A"); @@ -106,7 +105,6 @@ dyn_col_vect schmidtcoeffs(const Eigen::MatrixBase& A, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(A)) { throw exception::ZeroSize("qpp::schmidtcoeffs()", "A"); @@ -138,7 +136,6 @@ cmat schmidtA(const Eigen::MatrixBase& A, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::schmidtA()", "A"); @@ -173,7 +170,6 @@ cmat schmidtA(const Eigen::MatrixBase& A, idx d = 2) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(A)) { throw exception::ZeroSize("qpp::schmidtA()", "A"); @@ -205,7 +201,6 @@ cmat schmidtB(const Eigen::MatrixBase& A, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::schmidtB()", "A"); @@ -242,7 +237,6 @@ cmat schmidtB(const Eigen::MatrixBase& A, idx d = 2) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(A)) { throw exception::ZeroSize("qpp::schmidtB()", "A"); @@ -278,7 +272,6 @@ std::vector schmidtprobs(const Eigen::MatrixBase& A, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::schmidtprobs()", "A"); @@ -324,7 +317,6 @@ std::vector schmidtprobs(const Eigen::MatrixBase& A, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(A)) { throw exception::ZeroSize("qpp::schmidtprobs()", "A"); @@ -366,7 +358,6 @@ schmidt(const Eigen::MatrixBase& A, const std::vector& dims) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::schmidt()", "A"); @@ -413,7 +404,6 @@ template std::tuple, dyn_col_vect> schmidt(const Eigen::MatrixBase& A, idx d = 2) { // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(A)) { throw exception::ZeroSize("qpp::schmidt()", "A"); @@ -448,7 +438,6 @@ realT entanglement(const Eigen::MatrixBase& A, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::entanglement()", "A"); @@ -486,7 +475,6 @@ realT entanglement(const Eigen::MatrixBase& A, idx d = 2) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(A)) { throw exception::ZeroSize("qpp::entanglement()", "A"); @@ -521,7 +509,6 @@ realT gconcurrence(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::gconcurrence()", "A"); @@ -558,7 +545,6 @@ realT negativity(const Eigen::MatrixBase& A, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::negativity()", "A"); @@ -592,7 +578,6 @@ realT negativity(const Eigen::MatrixBase& A, idx d = 2) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(A)) { throw exception::ZeroSize("qpp::negativity()", "A"); @@ -623,7 +608,6 @@ realT lognegativity(const Eigen::MatrixBase& A, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::lognegativity()", "A"); @@ -657,7 +641,6 @@ realT lognegativity(const Eigen::MatrixBase& A, idx d = 2) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(A)) { throw exception::ZeroSize("qpp::lognegativity()", "A"); @@ -686,7 +669,6 @@ realT concurrence(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::concurrence()", "A"); diff --git a/include/qpp/entropies.hpp b/include/qpp/entropies.hpp index 9071a217b..91715c0ad 100644 --- a/include/qpp/entropies.hpp +++ b/include/qpp/entropies.hpp @@ -60,7 +60,6 @@ realT entropy(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::entropy()", "A"); @@ -91,7 +90,6 @@ realT entropy(const Eigen::MatrixBase& A) { */ inline realT entropy(const std::vector& prob) { // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(prob)) { throw exception::ZeroSize("qpp::entropy()", "prob"); @@ -125,7 +123,6 @@ realT renyi(const Eigen::MatrixBase& A, realT alpha) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::renyi()", "A"); @@ -178,7 +175,6 @@ realT renyi(const Eigen::MatrixBase& A, realT alpha) { */ inline realT renyi(const std::vector& prob, realT alpha) { // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(prob)) { throw exception::ZeroSize("qpp::renyi()", "prob"); @@ -234,7 +230,6 @@ realT tsallis(const Eigen::MatrixBase& A, realT q) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::tsallis()", "A"); @@ -278,7 +273,6 @@ realT tsallis(const Eigen::MatrixBase& A, realT q) { */ inline realT tsallis(const std::vector& prob, realT q) { // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(prob)) { throw exception::ZeroSize("qpp::tsallis()", "prob"); @@ -320,7 +314,6 @@ realT qmutualinfo(const Eigen::MatrixBase& A, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::qmutualinfo()", "A"); @@ -396,7 +389,6 @@ realT qmutualinfo(const Eigen::MatrixBase& A, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::qmutualinfo()", "A"); diff --git a/include/qpp/experimental/experimental.hpp b/include/qpp/experimental/experimental.hpp index 6ec4f0cee..3bd34dc66 100644 --- a/include/qpp/experimental/experimental.hpp +++ b/include/qpp/experimental/experimental.hpp @@ -78,7 +78,6 @@ measure_seq(const Eigen::MatrixBase& A, std::vector target, expr_t cA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(cA)) { throw exception::ZeroSize("qpp::measure_seq()", "A"); @@ -283,7 +282,6 @@ measure_seq(const Eigen::MatrixBase& A, const std::vector& target, const typename Eigen::MatrixBase::EvalReturnType& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::measure_seq()", "A"); diff --git a/include/qpp/functions.hpp b/include/qpp/functions.hpp index 638ef4aae..94cc39c8b 100644 --- a/include/qpp/functions.hpp +++ b/include/qpp/functions.hpp @@ -64,7 +64,6 @@ transpose(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::transpose()", "A"); @@ -87,7 +86,6 @@ conjugate(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::conjugate()", "A"); @@ -109,7 +107,6 @@ dyn_mat adjoint(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::adjoint()", "A"); @@ -131,7 +128,6 @@ dyn_mat inverse(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::inverse()", "A"); @@ -157,7 +153,6 @@ typename Derived::Scalar trace(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::trace()", "A"); @@ -184,7 +179,6 @@ typename Derived::Scalar det(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::det()", "A"); @@ -213,7 +207,6 @@ typename Derived::Scalar logdet(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::logdet()", "A"); @@ -249,7 +242,6 @@ typename Derived::Scalar sum(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::sum()", "A"); @@ -271,7 +263,6 @@ typename Derived::Scalar prod(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::prod()", "A"); @@ -292,7 +283,6 @@ realT norm(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::norm()", "A"); @@ -315,7 +305,6 @@ normalize(const Eigen::MatrixBase& A) { const expr_t& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::normalize()", "A"); @@ -357,7 +346,6 @@ eig(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::eig()", "A"); @@ -386,7 +374,6 @@ dyn_col_vect evals(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::evals()", "A"); @@ -413,7 +400,6 @@ cmat evects(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::evects()", "A"); @@ -444,7 +430,6 @@ heig(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::heig()", "A"); @@ -473,7 +458,6 @@ dyn_col_vect hevals(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::hevals()", "A"); @@ -500,7 +484,6 @@ cmat hevects(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::hevects()", "A"); @@ -530,7 +513,6 @@ svd(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::svd()", "A"); @@ -554,7 +536,6 @@ dyn_col_vect svals(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::svals()", "A"); @@ -576,7 +557,6 @@ template const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::svdU()", "A"); @@ -598,7 +578,6 @@ template const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::svdV()", "A"); @@ -625,7 +604,6 @@ template const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::funm()", "A"); @@ -660,7 +638,6 @@ cmat sqrtm(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::sqrtm()", "A"); @@ -686,7 +663,6 @@ cmat absm(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::absm()", "A"); @@ -712,7 +688,6 @@ cmat expm(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::expm()", "A"); @@ -738,7 +713,6 @@ cmat logm(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::logm()", "A"); @@ -764,7 +738,6 @@ cmat sinm(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::sinm()", "A"); @@ -790,7 +763,6 @@ cmat cosm(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::cosm()", "A"); @@ -821,7 +793,6 @@ cmat spectralpowm(const Eigen::MatrixBase& A, const cplx z) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::spectralpowm()", "A"); @@ -866,7 +837,6 @@ template dyn_mat powm(const Eigen::MatrixBase& A, idx n) { // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(A)) { throw exception::ZeroSize("qpp::powm()", "A"); @@ -917,7 +887,6 @@ realT schatten(const Eigen::MatrixBase& A, realT p) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::schatten()", "A"); @@ -957,7 +926,6 @@ cwise(const Eigen::MatrixBase& A, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::cwise()", "A"); @@ -1023,7 +991,6 @@ template [[qpp::critical]] dyn_mat kron(const std::vector& As) { // EXCEPTION CHECKS - if (As.empty()) { throw exception::ZeroSize("qpp::kron()", "As"); } @@ -1075,7 +1042,6 @@ dyn_mat kronpow(const Eigen::MatrixBase& A, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::kronpow()", "A"); @@ -1133,7 +1099,6 @@ dyn_mat dirsum(const T& head, const Args&... tail) { template dyn_mat dirsum(const std::vector& As) { // EXCEPTION CHECKS - if (As.empty()) { throw exception::ZeroSize("qpp::dirsum()", "As"); } @@ -1195,7 +1160,6 @@ dyn_mat dirsumpow(const Eigen::MatrixBase& A, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::dirsumpow()", "A"); @@ -1232,7 +1196,6 @@ dyn_mat reshape(const Eigen::MatrixBase& A, idx Acols = static_cast(rA.cols()); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::reshape()"); @@ -1266,7 +1229,6 @@ dyn_mat comm(const Eigen::MatrixBase& A, const dyn_mat& rB = B.derived(); // EXCEPTION CHECKS - // check types if (!std::is_same_v) { throw exception::TypeMismatch("qpp::comm()", "A/B"); @@ -1317,7 +1279,6 @@ anticomm(const Eigen::MatrixBase& A, const dyn_mat& rB = B.derived(); // EXCEPTION CHECKS - // check types if (!std::is_same_v) { throw exception::TypeMismatch("qpp::anticomm()", "A/B"); @@ -1362,7 +1323,6 @@ dyn_mat prj(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::prj()", "A"); @@ -1392,7 +1352,6 @@ dyn_mat prj(const Eigen::MatrixBase& A) { template dyn_mat grams(const std::vector& As) { // EXCEPTION CHECKS - // check empty list if (!internal::check_nonzero_size(As)) { throw exception::ZeroSize("qpp::grams()", "As"); @@ -1481,7 +1440,6 @@ dyn_mat grams(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::grams()", "A"); } @@ -1623,7 +1581,6 @@ inline ket mket(const std::vector& mask, const std::vector& dims) { std::multiplies<>()); // EXCEPTION CHECKS - // check zero size if (n == 0) { throw exception::ZeroSize("qpp::mket()", "mask"); @@ -1669,7 +1626,6 @@ inline ket mket(const std::vector& mask, idx d = 2) { idx D = internal::safe_pow(d, n); // EXCEPTION CHECKS - // check zero size if (n == 0) { throw exception::ZeroSize("qpp::mket()", "mask"); @@ -1717,7 +1673,6 @@ inline cmat mprj(const std::vector& mask, const std::vector& dims) { std::multiplies<>()); // EXCEPTION CHECKS - // check zero size if (n == 0) { throw exception::ZeroSize("qpp::mprj()", "mask"); @@ -1764,7 +1719,6 @@ inline cmat mprj(const std::vector& mask, idx d = 2) { idx D = internal::safe_pow(d, n); // EXCEPTION CHECKS - // check zero size if (n == 0) { throw exception::ZeroSize("qpp::mprj()", "mask"); @@ -1839,7 +1793,6 @@ std::vector abssq(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::abssq()", "A"); @@ -2000,7 +1953,6 @@ rho2pure(const Eigen::MatrixBase& A) { */ inline std::vector complement(std::vector subsys, idx n) { // EXCEPTION CHECKS - if (n < static_cast(subsys.size())) { throw exception::OutOfRange("qpp::complement()", "n"); } @@ -2037,7 +1989,6 @@ std::vector rho2bloch(const Eigen::MatrixBase& A) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check qubit matrix if (!internal::check_qubit_matrix(rA)) { throw exception::NotQubitMatrix("qpp::rho2bloch()", "A"); @@ -2066,7 +2017,6 @@ std::vector rho2bloch(const Eigen::MatrixBase& A) { */ inline cmat bloch2rho(const std::vector& r) { // EXCEPTION CHECKS - // check 3-dimensional vector if (r.size() != 3) { throw exception::CustomException("qpp::bloch2rho", @@ -2109,7 +2059,6 @@ std::optional> zket2dits(const Eigen::MatrixBase& psi, const dyn_col_vect& rpsi = psi.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rpsi)) { throw exception::ZeroSize("qpp::zket2dits()", "psi"); @@ -2168,7 +2117,6 @@ std::optional> zket2dits(const Eigen::MatrixBase& psi, const dyn_col_vect& rpsi = psi.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(rpsi)) { throw exception::ZeroSize("qpp::zket2dits()", "psi"); @@ -2178,9 +2126,7 @@ std::optional> zket2dits(const Eigen::MatrixBase& psi, if (d < 2) { throw exception::DimsInvalid("qpp::zket2dits()", "d"); } - // END EXCEPTION CHECKS - idx n = internal::get_num_subsys(static_cast(rpsi.rows()), d); std::vector dims(n, d); // local dimensions vector @@ -2205,7 +2151,6 @@ dirac_t dirac(const Eigen::MatrixBase& A, const expr_t& rA = A.derived(); // EXCEPTION CHECKS - if (dims_rows.empty()) { dims_rows.emplace_back(1); } @@ -2313,7 +2258,6 @@ dirac_t dirac(const Eigen::MatrixBase& A, const expr_t& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::dirac()", "A"); @@ -2352,7 +2296,6 @@ ket operator"" _ket() { qpp::ket q = qpp::ket::Zero(internal::safe_pow(2, n)); // EXCEPTION CHECKS - // check valid multi-partite qubit state for (idx i = 0; i < n; ++i) { if (bits[i] != '0' && bits[i] != '1') { @@ -2384,7 +2327,6 @@ bra operator"" _bra() { qpp::bra q = qpp::ket::Zero(internal::safe_pow(2, n)); // EXCEPTION CHECKS - // check valid multi-partite qubit state for (idx i = 0; i < n; ++i) { if (bits[i] != '0' && bits[i] != '1') { @@ -2417,7 +2359,6 @@ cmat operator"" _prj() { constexpr char bits[n + 1] = {Bits..., '\0'}; // EXCEPTION CHECKS - // check valid multi-partite qubit state for (idx i = 0; i < n; ++i) { if (bits[i] != '0' && bits[i] != '1') { @@ -2462,7 +2403,6 @@ std::size_t hash_eigen(const Eigen::MatrixBase& A, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::hash_eigen()", "A"); diff --git a/include/qpp/input_output.hpp b/include/qpp/input_output.hpp index f1206934d..736c14a15 100644 --- a/include/qpp/input_output.hpp +++ b/include/qpp/input_output.hpp @@ -178,7 +178,6 @@ void save(const Eigen::MatrixBase& A, std::ostream& os) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::save()", "A"); @@ -232,7 +231,6 @@ dyn_mat load(std::istream& is, std::enable_if_t>* = nullptr) { // EXCEPTION CHECKS - if (!is.good()) { throw std::runtime_error("qpp::load(): Error opening input stream!"); } @@ -278,7 +276,6 @@ dyn_mat load(std::istream& is, std::enable_if_t>* = nullptr) { // EXCEPTION CHECKS - if (!is.good()) { throw std::runtime_error("qpp::load(): Error opening input stream!"); } @@ -322,7 +319,6 @@ void save(const Eigen::MatrixBase& A, std::ostream& os) { const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::obsolete::save()", "A"); @@ -367,7 +363,6 @@ void save(const Eigen::MatrixBase& A, std::ostream& os) { template dyn_mat load(std::istream& is) { // EXCEPTION CHECKS - if (!is.good()) { throw std::runtime_error( "qpp::obsolete::load(): Error opening input stream!"); diff --git a/include/qpp/instruments.hpp b/include/qpp/instruments.hpp index 48012a2c7..ce9a7e363 100644 --- a/include/qpp/instruments.hpp +++ b/include/qpp/instruments.hpp @@ -68,7 +68,6 @@ ip(const Eigen::MatrixBase& phi, const Eigen::MatrixBase& psi, const dyn_col_vect& rpsi = psi.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rphi)) { throw exception::ZeroSize("qpp::ip()", "phi"); @@ -203,7 +202,6 @@ ip(const Eigen::MatrixBase& phi, const Eigen::MatrixBase& psi, const dyn_col_vect& rpsi = psi.derived(); // EXCEPTION CHECKS - if (!internal::check_nonzero_size(rpsi)) { throw exception::ZeroSize("qpp::ip()", "psi"); } @@ -240,7 +238,6 @@ measure(const Eigen::MatrixBase& A, const std::vector& Ks) { const expr_t& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::measure()", "A"); @@ -340,7 +337,6 @@ measure(const Eigen::MatrixBase& A, const cmat& U) { const expr_t& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::measure()", "A"); @@ -392,7 +388,6 @@ measure(const Eigen::MatrixBase& A, const std::vector& Ks, const typename Eigen::MatrixBase::EvalReturnType& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::measure()", "A"); @@ -542,7 +537,6 @@ measure(const Eigen::MatrixBase& A, const std::vector& Ks, const typename Eigen::MatrixBase::EvalReturnType& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::measure()", "A"); @@ -618,7 +612,6 @@ measure(const Eigen::MatrixBase& A, const cmat& V, const typename Eigen::MatrixBase::EvalReturnType& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::measure()", "A"); @@ -744,7 +737,6 @@ measure(const Eigen::MatrixBase& A, const cmat& V, const typename Eigen::MatrixBase::EvalReturnType& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::measure()", "A"); @@ -790,7 +782,6 @@ measure_seq(const Eigen::MatrixBase& A, std::vector target, expr_t rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::measure_seq()", "A"); @@ -884,7 +875,6 @@ measure_seq(const Eigen::MatrixBase& A, const std::vector& target, const typename Eigen::MatrixBase::EvalReturnType& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::measure_seq()", "A"); @@ -918,7 +908,6 @@ template const typename Eigen::MatrixBase::EvalReturnType& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::sample()", "A"); @@ -992,7 +981,6 @@ std::vector sample(const Eigen::MatrixBase& A, const typename Eigen::MatrixBase::EvalReturnType& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::sample()", "A"); @@ -1029,7 +1017,6 @@ sample(idx num_samples, const Eigen::MatrixBase& A, const typename Eigen::MatrixBase::EvalReturnType& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::sample()", "A"); @@ -1117,7 +1104,6 @@ sample(idx num_samples, const Eigen::MatrixBase& A, const typename Eigen::MatrixBase::EvalReturnType& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::sample()", "A"); @@ -1154,7 +1140,6 @@ reset(const Eigen::MatrixBase& A, const std::vector& target, const typename Eigen::MatrixBase::EvalReturnType& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::reset()", "A"); @@ -1217,7 +1202,6 @@ dyn_mat reset(const Eigen::MatrixBase& A, const typename Eigen::MatrixBase::EvalReturnType& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::reset()", "A"); @@ -1252,7 +1236,6 @@ dyn_mat discard(const Eigen::MatrixBase& A, const typename Eigen::MatrixBase::EvalReturnType& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::discard()", "A"); @@ -1305,7 +1288,6 @@ dyn_mat discard(const Eigen::MatrixBase& A, const typename Eigen::MatrixBase::EvalReturnType& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::discard()", "A"); diff --git a/include/qpp/internal/classes/qengine_state.hpp b/include/qpp/internal/classes/qengine_state.hpp index f358f225a..f764d2c97 100644 --- a/include/qpp/internal/classes/qengine_state.hpp +++ b/include/qpp/internal/classes/qengine_state.hpp @@ -59,7 +59,7 @@ struct QEngineState { std::vector probs_{}; ///< measurement probabilities std::vector dits_{}; ///< classical dits (where measurement ///< results are usually stored) - std::vector subsys_{}; ///< keeps track of the measured + std::vector subsys_{}; ///< keeps track of the destructively measured ///< subsystems, re-label them after ///< measurements bool post_select_ok_ = @@ -73,7 +73,6 @@ struct QEngineState { */ explicit QEngineState(const QCircuit* qc_ptr) : qc_ptr_{qc_ptr} { // EXCEPTION CHECKS - if (qc_ptr->get_nq() == 0) { throw exception::ZeroSize( "qpp::internal::QEngineState::QEngineState()", "nq"); @@ -105,7 +104,6 @@ struct QEngineState { if (qstate.has_value()) { idx D = internal::safe_pow(qc_ptr_->get_d(), qc_ptr_->get_nq()); // EXCEPTION CHECKS - if constexpr (std::is_same_v) { if (static_cast(qstate.value().rows()) != D) { throw exception::DimsNotEqual( diff --git a/include/qpp/internal/util.hpp b/include/qpp/internal/util.hpp index 2c830ea7f..40fade0d3 100644 --- a/include/qpp/internal/util.hpp +++ b/include/qpp/internal/util.hpp @@ -300,7 +300,6 @@ kron2(const Eigen::MatrixBase& A, const dyn_mat& rB = B.derived(); // EXCEPTION CHECKS - // check types if (!std::is_same_v) { throw exception::TypeMismatch("qpp::kron()", "A/B"); @@ -348,7 +347,6 @@ dirsum2(const Eigen::MatrixBase& A, const dyn_mat& rB = B.derived(); // EXCEPTION CHECKS - // check types if (!std::is_same_v) { throw exception::TypeMismatch("qpp::dirsum()", "A/B"); diff --git a/include/qpp/number_theory.hpp b/include/qpp/number_theory.hpp index f27099795..3859cc2ee 100644 --- a/include/qpp/number_theory.hpp +++ b/include/qpp/number_theory.hpp @@ -56,7 +56,6 @@ namespace qpp { */ inline std::vector x2contfrac(realT x, idx N, idx cut = 10000) { // EXCEPTION CHECKS - if (N == 0) { throw exception::OutOfRange("qpp::x2contfrac()", "N"); } @@ -133,7 +132,6 @@ inline realT contfrac2x(const std::vector& cf, */ inline bigint gcd(bigint a, bigint b) { // EXCEPTION CHECKS - if (a == 0 && b == 0) { throw exception::OutOfRange("qpp::gcd()", "a/b"); } @@ -162,7 +160,6 @@ inline bigint gcd(bigint a, bigint b) { */ inline bigint gcd(const std::vector& as) { // EXCEPTION CHECKS - if (as.empty()) { throw exception::ZeroSize("qpp::gcd()", "as"); } @@ -186,7 +183,6 @@ inline bigint gcd(const std::vector& as) { */ inline bigint lcm(bigint a, bigint b) { // EXCEPTION CHECKS - if (a == 0 && b == 0) { throw exception::OutOfRange("qpp::lcm()", "a/b"); } @@ -206,7 +202,6 @@ inline bigint lcm(bigint a, bigint b) { */ inline bigint lcm(const std::vector& as) { // EXCEPTION CHECKS - if (as.empty()) { throw exception::ZeroSize("qpp::lcm()", "as"); } @@ -237,7 +232,6 @@ inline bigint lcm(const std::vector& as) { */ inline std::vector invperm(const std::vector& perm) { // EXCEPTION CHECKS - if (!internal::check_perm(perm)) { throw exception::PermInvalid("qpp::invperm()", "perm"); } @@ -263,7 +257,6 @@ inline std::vector invperm(const std::vector& perm) { inline std::vector compperm(const std::vector& perm, const std::vector& sigma) { // EXCEPTION CHECKS - if (!internal::check_perm(perm)) { throw exception::PermInvalid("qpp::compperm()", "perm"); } @@ -297,7 +290,6 @@ inline std::vector factors(bigint a) { a = std::abs(a); // EXCEPTION CHECKS - if (a == 0 || a == 1) { throw exception::OutOfRange("qpp::factors()", "a"); } @@ -336,7 +328,6 @@ inline std::vector factors(bigint a) { */ inline bigint modmul(bigint a, bigint b, bigint p) { // EXCEPTION CHECKS - if (p < 1) { throw exception::OutOfRange("qpp::modmul()", "p"); } @@ -424,7 +415,6 @@ inline bigint modmul(bigint a, bigint b, bigint p) { */ inline bigint modpow(bigint a, bigint n, bigint p) { // EXCEPTION CHECKS - if (a < 0 || n < 0 || p < 1) { throw exception::OutOfRange("qpp::modpow()", "a/n/p"); } @@ -466,7 +456,6 @@ inline bigint modpow(bigint a, bigint n, bigint p) { */ inline std::tuple egcd(bigint a, bigint b) { // EXCEPTION CHECKS - if (a == 0 && b == 0) { throw exception::OutOfRange("qpp::egcd()", "a/b"); } @@ -505,7 +494,6 @@ inline std::tuple egcd(bigint a, bigint b) { */ inline bigint modinv(bigint a, bigint p) { // EXCEPTION CHECKS - if (a <= 0 || p <= 0) { throw exception::OutOfRange("qpp::modinv()", "a/p"); } @@ -534,7 +522,6 @@ inline bool isprime(bigint p, idx k = 80) { p = std::abs(p); // EXCEPTION CHECKS - if (p < 2) { throw exception::OutOfRange("qpp::isprime()", "p"); } @@ -606,7 +593,6 @@ inline bool isprime(bigint p, idx k = 80) { // A std::optional return type would have been awesome here! inline bigint randprime(bigint a, bigint b, idx N = 1000) { // EXCEPTION CHECKS - if (a > b) { throw exception::OutOfRange("qpp::randprime()", "a/b"); } @@ -656,7 +642,6 @@ convergents(const std::vector& cf) { idx N = cf.size(); // EXCEPTION CHECKS - if (N == 0) { throw exception::ZeroSize("qpp::convergents()", "cf"); } @@ -702,7 +687,6 @@ convergents(const std::vector& cf) { inline std::vector> convergents(realT x, idx N) { // EXCEPTION CHECKS - if (N == 0) { throw exception::OutOfRange("qpp::convergents()", "N"); } diff --git a/include/qpp/operations.hpp b/include/qpp/operations.hpp index 7d8c413c0..c78b88dfe 100644 --- a/include/qpp/operations.hpp +++ b/include/qpp/operations.hpp @@ -72,7 +72,6 @@ apply(const Eigen::MatrixBase& state, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check types if (!std::is_same_v) { throw exception::TypeMismatch("qpp::apply()", "A/state"); @@ -345,7 +344,6 @@ expr_t apply(const Eigen::MatrixBase& state, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(rstate)) { throw exception::ZeroSize("qpp::apply()", "state"); @@ -380,7 +378,6 @@ template const cmat& rA = A.derived(); // EXCEPTION CHECKS - if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::apply()", "A"); } @@ -434,7 +431,6 @@ apply(const Eigen::MatrixBase& A, const std::vector& Ks, const cmat& rA = A.derived(); // EXCEPTION CHECKS - // check zero sizes if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::apply()", "A"); @@ -528,7 +524,6 @@ cmat apply(const Eigen::MatrixBase& A, const std::vector& Ks, const cmat& rA = A.derived(); // EXCEPTION CHECKS - // check zero sizes if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::apply()", "A"); @@ -564,7 +559,6 @@ cmat apply(const Eigen::MatrixBase& A, const std::vector& Ks, */ [[qpp::parallel]] inline cmat kraus2choi(const std::vector& Ks) { // EXCEPTION CHECKS - if (Ks.empty()) { throw exception::ZeroSize("qpp::kraus2choi()", "Ks"); } @@ -632,7 +626,6 @@ cmat apply(const Eigen::MatrixBase& A, const std::vector& Ks, */ inline std::vector choi2kraus(const cmat& A, idx Din, idx Dout) { // EXCEPTION CHECKS - if (!internal::check_nonzero_size(A)) { throw exception::ZeroSize("qpp::choi2kraus()", "A"); } @@ -675,7 +668,6 @@ inline std::vector choi2kraus(const cmat& A, idx Din, idx Dout) { */ inline std::vector choi2kraus(const cmat& A) { // EXCEPTION CHECKS - if (!internal::check_nonzero_size(A)) { throw exception::ZeroSize("qpp::choi2kraus()", "A"); } @@ -706,7 +698,6 @@ inline std::vector choi2kraus(const cmat& A) { */ [[qpp::parallel]] inline cmat choi2super(const cmat& A, idx Din, idx Dout) { // EXCEPTION CHECKS - if (!internal::check_nonzero_size(A)) { throw exception::ZeroSize("qpp::choi2super()", "A"); } @@ -751,7 +742,6 @@ inline std::vector choi2kraus(const cmat& A) { */ inline cmat choi2super(const cmat& A) { // EXCEPTION CHECKS - if (!internal::check_nonzero_size(A)) { throw exception::ZeroSize("qpp::choi2super()", "A"); } @@ -780,7 +770,6 @@ inline cmat choi2super(const cmat& A) { */ [[qpp::parallel]] inline cmat super2choi(const cmat& A) { // EXCEPTION CHECKS - if (!internal::check_nonzero_size(A)) { throw exception::ZeroSize("qpp::super2choi()", "A"); } @@ -832,7 +821,6 @@ inline cmat choi2super(const cmat& A) { */ [[qpp::parallel]] inline cmat kraus2super(const std::vector& Ks) { // EXCEPTION CHECKS - if (Ks.empty()) { throw exception::ZeroSize("qpp::kraus2super()", "Ks"); } @@ -907,7 +895,6 @@ inline cmat choi2super(const cmat& A) { */ inline std::vector super2kraus(const cmat& A) { // EXCEPTION CHECKS - if (!internal::check_nonzero_size(A)) { throw exception::ZeroSize("qpp::super2kraus()", "A"); } @@ -944,7 +931,6 @@ ptrace1(const Eigen::MatrixBase& A, const std::vector& dims) { const typename Eigen::MatrixBase::EvalReturnType& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::ptrace1()", "A"); @@ -1050,7 +1036,6 @@ dyn_mat ptrace1(const Eigen::MatrixBase& A, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::ptrace1()", "A"); @@ -1086,7 +1071,6 @@ ptrace2(const Eigen::MatrixBase& A, const std::vector& dims) { const typename Eigen::MatrixBase::EvalReturnType& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::ptrace2()", "A"); @@ -1183,7 +1167,6 @@ dyn_mat ptrace2(const Eigen::MatrixBase& A, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::ptrace2()", "A"); @@ -1221,7 +1204,6 @@ ptrace(const Eigen::MatrixBase& A, const std::vector& target, const typename Eigen::MatrixBase::EvalReturnType& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::ptrace()", "A"); @@ -1429,7 +1411,6 @@ dyn_mat ptrace(const Eigen::MatrixBase& A, const typename Eigen::MatrixBase::EvalReturnType& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::ptrace()", "A"); @@ -1467,7 +1448,6 @@ dyn_mat [[qpp::critical, qpp::parallel]] ptranspose( const typename Eigen::MatrixBase::EvalReturnType& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::ptranspose()", "A"); @@ -1636,7 +1616,6 @@ ptranspose(const Eigen::MatrixBase& A, const std::vector& target, const typename Eigen::MatrixBase::EvalReturnType& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::ptranspose()", "A"); @@ -1673,7 +1652,6 @@ syspermute(const Eigen::MatrixBase& A, const std::vector& perm, const typename Eigen::MatrixBase::EvalReturnType& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::syspermute()", "A"); @@ -1822,7 +1800,6 @@ syspermute(const Eigen::MatrixBase& A, const std::vector& perm, const typename Eigen::MatrixBase::EvalReturnType& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::syspermute()", "A"); @@ -1871,7 +1848,6 @@ applyCTRL(const Eigen::MatrixBase& state, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check types if (!std::is_same_v) { throw exception::TypeMismatch("qpp::applyCTRL()", "A/state"); @@ -1982,7 +1958,6 @@ applyCTRL(const Eigen::MatrixBase& state, elem = d - elem; } } - // END EXCEPTION CHECKS if (!shift.has_value()) { @@ -2129,7 +2104,6 @@ applyCTRL(const Eigen::MatrixBase& state, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(rstate)) { throw exception::ZeroSize("qpp::applyCTRL()", "state"); @@ -2182,7 +2156,6 @@ applyCTRL_fan(const Eigen::MatrixBase& state, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check types if (!std::is_same_v) { throw exception::TypeMismatch("qpp::applyCTRL_fan()", "A/state"); @@ -2301,9 +2274,7 @@ applyCTRL_fan(const Eigen::MatrixBase& state, elem = d - elem; } } - // END EXCEPTION CHECKS - if (!shift.has_value()) { shift = std::vector(ctrl.size(), 0); } @@ -2452,7 +2423,6 @@ applyCTRL_fan(const Eigen::MatrixBase& state, const dyn_mat& rA = A.derived(); // EXCEPTION CHECKS - // check zero size if (!internal::check_nonzero_size(rstate)) { throw exception::ZeroSize("qpp::applyCTRL_fan()", "state"); @@ -2490,7 +2460,6 @@ template const expr_t& rA = A.derived(); // EXCEPTION CHECKS - // check zero sizes if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::applyQFT()", "A"); @@ -2606,7 +2575,6 @@ template const expr_t& rA = A.derived(); // EXCEPTION CHECKS - // check zero sizes if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::applyTFQ()", "A"); @@ -2718,7 +2686,6 @@ expr_t QFT(const Eigen::MatrixBase& A, idx d = 2, const expr_t& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::QFT()", "A"); @@ -2771,7 +2738,6 @@ expr_t TFQ(const Eigen::MatrixBase& A, idx d = 2, const expr_t& rA = A.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rA)) { throw exception::ZeroSize("qpp::TFQ()", "A"); @@ -2831,7 +2797,6 @@ qRAM(const Eigen::MatrixBase& psi, const qram& data, idx DqRAM) { const dyn_mat& rpsi = psi.derived(); // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(rpsi)) { throw exception::ZeroSize("qpp::qRAM()", "psi"); @@ -2897,7 +2862,6 @@ template dyn_col_vect qRAM(const Eigen::MatrixBase& psi, const qram& data) { // EXCEPTION CHECKS - // check zero-size if (!internal::check_nonzero_size(data)) { throw exception::ZeroSize("qpp::qRAM()", "data"); diff --git a/include/qpp/random.hpp b/include/qpp/random.hpp index 8b0ea3d85..ad0249a88 100644 --- a/include/qpp/random.hpp +++ b/include/qpp/random.hpp @@ -112,7 +112,6 @@ Derived rand([[maybe_unused]] idx rows, [[maybe_unused]] idx cols, template <> inline rmat rand(idx rows, idx cols, realT a, realT b) { // EXCEPTION CHECKS - if (rows == 0 || cols == 0) { throw exception::ZeroSize("qpp::rand()", "rows/cols"); } @@ -129,7 +128,6 @@ inline rmat rand(idx rows, idx cols, realT a, realT b) { template <> inline cmat rand(idx rows, idx cols, realT a, realT b) { // EXCEPTION CHECKS - if (rows == 0 || cols == 0) { throw exception::ZeroSize("qpp::rand()", "rows/cols"); } @@ -202,7 +200,6 @@ Derived randn([[maybe_unused]] idx rows, [[maybe_unused]] idx cols, template <> inline rmat randn(idx rows, idx cols, realT mean, realT sigma) { // EXCEPTION CHECKS - if (rows == 0 || cols == 0) { throw exception::ZeroSize("qpp::randn()", "rows/cols"); } @@ -219,7 +216,6 @@ inline rmat randn(idx rows, idx cols, realT mean, realT sigma) { template <> inline cmat randn(idx rows, idx cols, realT mean, realT sigma) { // EXCEPTION CHECKS - if (rows == 0 || cols == 0) { throw exception::ZeroSize("qpp::randn()", "rows/cols"); } @@ -241,7 +237,6 @@ inline cmat randn(idx rows, idx cols, realT mean, realT sigma) { inline idx randidx(idx a = std::numeric_limits::min(), idx b = std::numeric_limits::max()) { // EXCEPTION CHECKS - if (a > b) { throw exception::OutOfRange("qpp::randidx()", "a/b"); } @@ -264,7 +259,6 @@ inline cmat randU(idx D = 2) // because Eigen 3 QR algorithm is not parallelized { // EXCEPTION CHECKS - if (D == 0) { throw exception::DimsInvalid("qpp::randU()", "D"); } @@ -297,7 +291,6 @@ inline cmat randU(idx D = 2) */ inline cmat randV(idx Din, idx Dout) { // EXCEPTION CHECKS - if (Din == 0 || Dout == 0 || Din > Dout) { throw exception::DimsInvalid("qpp::randV()", "Din/Dout"); } @@ -323,7 +316,6 @@ inline cmat randV(idx Din, idx Dout) { */ [[qpp::parallel]] inline std::vector randkraus(idx N, idx Din, idx Dout) { // EXCEPTION CHECKS - if (N == 0) { throw exception::OutOfRange("qpp::randkraus()", "N"); } @@ -383,7 +375,6 @@ inline std::vector randkraus(idx N, idx D = 2) { */ inline cmat randH(idx D = 2) { // EXCEPTION CHECKS - if (D == 0) { throw exception::DimsInvalid("qpp::randH()", "D"); } @@ -403,7 +394,6 @@ inline cmat randH(idx D = 2) { */ inline ket randket(idx D = 2) { // EXCEPTION CHECKS - if (D == 0) { throw exception::DimsInvalid("qpp::randket()", "D"); } @@ -429,7 +419,6 @@ inline ket randket(idx D = 2) { */ inline cmat randrho(idx D = 2) { // EXCEPTION CHECKS - if (D == 0) { throw exception::DimsInvalid("qpp::randrho()", "D"); } @@ -452,7 +441,6 @@ inline cmat randrho(idx D = 2) { */ inline std::vector randperm(idx N) { // EXCEPTION CHECKS - if (N == 0) { throw exception::ZeroSize("qpp::randperm()", "N"); } @@ -479,7 +467,6 @@ inline std::vector randperm(idx N) { */ inline std::vector randprob(idx N) { // EXCEPTION CHECKS - if (N == 0) { throw exception::ZeroSize("qpp::randprob()"); } diff --git a/include/qpp/statistics.hpp b/include/qpp/statistics.hpp index 6739db6fd..1c3721848 100644 --- a/include/qpp/statistics.hpp +++ b/include/qpp/statistics.hpp @@ -49,7 +49,6 @@ namespace qpp { */ inline std::vector uniform(idx N) { // EXCEPTION CHECKS - if (N == 0) { throw exception::ZeroSize("qpp::uniform()", "N"); } @@ -69,7 +68,6 @@ inline std::vector uniform(idx N) { */ inline std::vector marginalX(const rmat& probXY) { // EXCEPTION CHECKS - if (!internal::check_nonzero_size(probXY)) { throw exception::ZeroSize("qpp::marginalX()", "probXY"); } @@ -95,7 +93,6 @@ inline std::vector marginalX(const rmat& probXY) { */ inline std::vector marginalY(const rmat& probXY) { // EXCEPTION CHECKS - if (!internal::check_nonzero_size(probXY)) { throw exception::ZeroSize("qpp::marginalY()", "probXY"); } @@ -117,7 +114,6 @@ template realT avg(const std::vector& prob, const Container& X, std::enable_if_t>* = nullptr) { // EXCEPTION CHECKS - if (!internal::check_nonzero_size(prob)) { throw exception::ZeroSize("qpp::avg()", "prob"); } @@ -148,7 +144,6 @@ template realT cov(const rmat& probXY, const Container& X, const Container& Y, std::enable_if_t>* = nullptr) { // EXCEPTION CHECKS - if (!internal::check_nonzero_size(X)) { throw exception::ZeroSize("qpp::cov()", "X"); } @@ -188,7 +183,6 @@ template realT var(const std::vector& prob, const Container& X, std::enable_if_t>* = nullptr) { // EXCEPTION CHECKS - if (!internal::check_nonzero_size(prob)) { throw exception::ZeroSize("qpp::var()", "prob"); } @@ -218,7 +212,6 @@ template realT sigma(const std::vector& prob, const Container& X, std::enable_if_t>* = nullptr) { // EXCEPTION CHECKS - if (!internal::check_nonzero_size(prob)) { throw exception::ZeroSize("qpp::sigma()", "prob"); } @@ -244,7 +237,6 @@ template realT cor(const rmat& probXY, const Container& X, const Container& Y, std::enable_if_t>* = nullptr) { // EXCEPTION CHECKS - if (!internal::check_nonzero_size(X)) { throw exception::ZeroSize("qpp::cor()", "X"); } diff --git a/pyqpp/include/pyqpp/classes/qengine_bind.hpp b/pyqpp/include/pyqpp/classes/qengine_bind.hpp index 61a1ab787..42abe6b4d 100644 --- a/pyqpp/include/pyqpp/classes/qengine_bind.hpp +++ b/pyqpp/include/pyqpp/classes/qengine_bind.hpp @@ -79,6 +79,8 @@ void declare_QEngineT(py::module& m) { return result; }, "Measurement statistics for multiple runs") + .def("post_select_ok", &QEngineT::post_select_ok, + "Successful post-selection") .def("reset", &QEngineT::reset, "Resets the engine", py::arg("reset_stats") = true) .def("reset_stats", &QEngineT::reset_stats, diff --git a/unit_tests/tests/classes/qengine.cpp b/unit_tests/tests/classes/qengine.cpp index c24aa5e2f..5ebd9aba0 100644 --- a/unit_tests/tests/classes/qengine.cpp +++ b/unit_tests/tests/classes/qengine.cpp @@ -29,11 +29,11 @@ TEST(qpp_QEngineT_get_dit, AllTests) {} /// BEGIN std::vector QEngineT::get_dits() const TEST(qpp_QEngineT_get_dits, AllTests) {} -/// BEGIN bool QEngineT::get_measured(idx i) const -TEST(qpp_QEngineT_get_measured, SpecificQudit) {} +/// BEGIN bool QEngineT::get_measured_destructively() const +TEST(qpp_QEngineT_get_measured_destructively, AllTests) {} -/// BEGIN std::vector QEngineT::get_non_measured() const -TEST(qpp_QEngineT_get_non_measured, AllTests) {} +/// BEGIN std::vector QEngineT::get_non_measured_destructively() const +TEST(qpp_QEngineT_get_non_measured_destructively, AllTests) {} /// BEGIN std::vector QEngineT::get_probs() const TEST(qpp_QEngineT_get_probs, AllTests) {} @@ -44,6 +44,9 @@ TEST(qpp_QEngineT_get_state, AllTests) {} /// BEGIN internal::QEngineStatistics QEngineT::get_stats() const TEST(qpp_QEngineT_get_stats, AllTests) {} +/// BEGIN bool QEngineT::post_select_ok() const +TEST(qpp_QEngineT_post_select_ok, AllTests) {} + /// BEGIN QEngineT& QEngineT::reset(bool reset_stats = true) TEST(qpp_QEngineT_reset, AllTests) {} @@ -72,5 +75,5 @@ TEST(qpp_QEngineT_traits_is_noisy, AllTests) {} /// BEGIN bool QEngineT::traits_is_pure() const override TEST(qpp_QEngineT_traits_is_pure, AllTests) {} -/// BEGIN std::vector QEngineT::was_measured() const -TEST(qpp_QEngineT_was_measured, AllQudits) {} +/// BEGIN std::vector QEngineT::was_measured_destructively(idx i) const +TEST(qpp_QEngineT_was_measured_destructively, AllTests) {}