From ba1d34acf5e7deee0f637cddc3de90ffd29912a7 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sun, 3 Nov 2024 11:46:01 +0500 Subject: [PATCH 01/11] noncliff: better error message for inapplicable project! of GeneralizedStabilizer --- src/nonclifford.jl | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/nonclifford.jl b/src/nonclifford.jl index 70f99e42f..2573cfaa6 100644 --- a/src/nonclifford.jl +++ b/src/nonclifford.jl @@ -172,15 +172,33 @@ function _allthreesumtozero(a,b,c) true end -function project!(sm::GeneralizedStabilizer, p::PauliOperator) + +project!(::GeneralizedStabilizer, ::PauliOperator) = + error("The method `project!` is not applicable for `GeneralizedStabilizer` when measuring the hermitian `PauliOperator`, โ„ณ.\n\n" * + "The `GeneralizedStabilizer` ๐œ is updated by measuring โ„ณ = ๐’ถโ‹…๐’นโ‚˜โ‹…๐“ˆโ‚™, resulting in the new state ๐œโ€ฒ defined as:\n\n" * + " ๐œโ€ฒ = ยผ(โ„ + โ„ณ)๐œ(โ„ + โ„ณ) = (๐œ™โ€ฒ, โ„ฌ(๐’ฎโ€ฒ, ๐’Ÿโ€ฒ)) = ๐›ด ๐œ™แตขโฑผ' ๐’ซแตข ๐œŒ ๐’ซโฑผโ€ ,\n\n" * + "where (๐’ฎโ€ฒ, ๐’Ÿโ€ฒ) is derived from (๐’ฎ, ๐’Ÿ) through the traditional stabilizer update, and ๐œ™' represents the updated density matrix.\n\n" * + "Note that ยผ(โ„ โˆ’ โ„ณ)๐œ(โ„ โˆ’ โ„ณ) can be obtained by changing the sign of ๐’ถ.\n\n" * + "This projection requires a probabilistic approach, as measurement outcomes depend on the expectation value of the `PauliOperator`.\n\n" * + "Specifically, this expectation value is derived from the trace Tr[๐œโ€ฒ] = Tr[๐œ™แตขโฑผโ€ฒ] in the expression:\n\n" * + " ๐œโ€ฒ = ๐›ด ๐œ™แตขโฑผ' ๐’ซแตข ๐œŒ ๐’ซโฑผโ€ ,\n\n" * + "where ๐œ™แตขโฑผโ€ฒ is the updated density matrix. \n\n" * + "The trace Tr[๐œโ€ฒ] = Tr[๐œ™แตขโฑผโ€ฒ] represents the probability of measuring either 0 or a non-zero outcome and serves as the normalization required for ๐œโ€ฒ.\n\n" * + "To correctly perform the 'nondeterministic' projection, please use `projectrand!(::GeneralizedStabilizer, ::PauliOperator)`.\n\n" * + "Moreover, `project!` in this library operates as a 'deterministic' method to verify whether a measurement operator commutes with stabilizers.\n\n" * + "Based on this commutation, it executes additional steps to determine the resultant state after projection.\n\n" * + "Therefore, there are semantic nuances in defining `project!` consistently for `GeneralizedStabilizer`, particularly regarding the interpretations of `anticom` and `res` in this context.\n\n" * + "๐’ฉ๐’ช๐’ฏโ„ฐ๐’ฎ:\n" * + "- `rowdecompose(โ„ณ, ๐œ.stab)`: Provides the decomposition of โ„ณ in terms of stabilizer and destabilizer rows of the given tableau of ๐œ.\n\n" * + "- `expect(โ„ณ, ๐œ)`: Returns the updated density matrix ๐œ™แตขโฑผโ€ฒ, where the trace Tr[๐œ™แตขโฑผโ€ฒ] provides the expectation value of measuring โ„ณ.\n\n") + +function projectrand!(sm::GeneralizedStabilizer, p::PauliOperator) eval = expect(p, sm) probโ‚ = (real(eval)+1)/2 error("This functionality is not implemented yet") end -function _projโ‚‹(sm::GeneralizedStabilizer, p::PauliOperator) -end -function _projโ‚Š(sm::GeneralizedStabilizer, p::PauliOperator) +function _proj(sm::GeneralizedStabilizer, p::PauliOperator) end nqubits(sm::GeneralizedStabilizer) = nqubits(sm.stab) From aa63d6a91230aef5f717c9c740969efea475d96b Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sun, 3 Nov 2024 20:28:11 +0500 Subject: [PATCH 02/11] improve formatting w.r.t to console output --- src/nonclifford.jl | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/src/nonclifford.jl b/src/nonclifford.jl index 2573cfaa6..857b6d7da 100644 --- a/src/nonclifford.jl +++ b/src/nonclifford.jl @@ -174,23 +174,31 @@ end project!(::GeneralizedStabilizer, ::PauliOperator) = - error("The method `project!` is not applicable for `GeneralizedStabilizer` when measuring the hermitian `PauliOperator`, โ„ณ.\n\n" * - "The `GeneralizedStabilizer` ๐œ is updated by measuring โ„ณ = ๐’ถโ‹…๐’นโ‚˜โ‹…๐“ˆโ‚™, resulting in the new state ๐œโ€ฒ defined as:\n\n" * - " ๐œโ€ฒ = ยผ(โ„ + โ„ณ)๐œ(โ„ + โ„ณ) = (๐œ™โ€ฒ, โ„ฌ(๐’ฎโ€ฒ, ๐’Ÿโ€ฒ)) = ๐›ด ๐œ™แตขโฑผ' ๐’ซแตข ๐œŒ ๐’ซโฑผโ€ ,\n\n" * - "where (๐’ฎโ€ฒ, ๐’Ÿโ€ฒ) is derived from (๐’ฎ, ๐’Ÿ) through the traditional stabilizer update, and ๐œ™' represents the updated density matrix.\n\n" * - "Note that ยผ(โ„ โˆ’ โ„ณ)๐œ(โ„ โˆ’ โ„ณ) can be obtained by changing the sign of ๐’ถ.\n\n" * - "This projection requires a probabilistic approach, as measurement outcomes depend on the expectation value of the `PauliOperator`.\n\n" * - "Specifically, this expectation value is derived from the trace Tr[๐œโ€ฒ] = Tr[๐œ™แตขโฑผโ€ฒ] in the expression:\n\n" * - " ๐œโ€ฒ = ๐›ด ๐œ™แตขโฑผ' ๐’ซแตข ๐œŒ ๐’ซโฑผโ€ ,\n\n" * - "where ๐œ™แตขโฑผโ€ฒ is the updated density matrix. \n\n" * - "The trace Tr[๐œโ€ฒ] = Tr[๐œ™แตขโฑผโ€ฒ] represents the probability of measuring either 0 or a non-zero outcome and serves as the normalization required for ๐œโ€ฒ.\n\n" * - "To correctly perform the 'nondeterministic' projection, please use `projectrand!(::GeneralizedStabilizer, ::PauliOperator)`.\n\n" * - "Moreover, `project!` in this library operates as a 'deterministic' method to verify whether a measurement operator commutes with stabilizers.\n\n" * - "Based on this commutation, it executes additional steps to determine the resultant state after projection.\n\n" * - "Therefore, there are semantic nuances in defining `project!` consistently for `GeneralizedStabilizer`, particularly regarding the interpretations of `anticom` and `res` in this context.\n\n" * + error("The method `project!` is not applicable for `GeneralizedStabilizer` with \n" * + "measurements involving the hermitian Pauli operator โ„ณ. The `GeneralizedStabilizer` ๐œ \n" * + "is updated by measuring โ„ณ = ๐’ถโ‹…๐’นโ‚˜โ‹…๐“ˆโ‚™, resulting in the new state ๐œโ€ฒ defined as: \n" * + "๐œโ€ฒ = ยผ(โ„ + โ„ณ)๐œ(โ„ + โ„ณ) = (๐œ™โ€ฒ, โ„ฌ(๐’ฎโ€ฒ, ๐’Ÿโ€ฒ)), where (๐’ฎโ€ฒ, ๐’Ÿโ€ฒ) is derived from (๐’ฎ, ๐’Ÿ) \n" * + "through the traditional stabilizer update, and ๐œ™' represents the updated density \n" * + "matrix. Note that ยผ(โ„ โˆ’ โ„ณ)๐œ(โ„ โˆ’ โ„ณ) can be obtained by changing the sign of ๐’ถ.\n\n" * + "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n" * + "The projection requires a probabilistic approach, as measurement outcomes depend on \n" * + "the expectation value of the `PauliOperator`. Specifically, the expectation value is \n" * + "derived from the trace Tr[๐œโ€ฒ] = Tr[๐œ™แตขโฑผโ€ฒ] in the expression: ๐œโ€ฒ = ๐›ด ๐œ™แตขโฑผ' ๐’ซแตข ๐œŒ ๐’ซโฑผโ€ , where ๐œ™แตขโฑผโ€ฒ\n" * + "is the updated ๐œ™-matrix. The trace Tr[๐œโ€ฒ] = Tr[๐œ™แตขโฑผโ€ฒ] represents the probability of \n" * + "measuring either 0 or a non-zero outcome and serves as the normalization required for ๐œโ€ฒ.\n\n" * + "To correctly perform the 'nondeterministic' projection, please use `projectrand!`.\n\n" * + "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n" * + "Moreover, `project!` in this library operates as a 'deterministic' method to verify \n" * + "whether a measurement operator commutes with stabilizers. Based on this commutation, it \n" * + "executes additional steps to determine the resultant state after projection. Thus, there \n" * + "are semantic nuances in defining `project!` consistently for`GeneralizedStabilizer`, \n" * + "particularly regarding the interpretations of `anticom` and `res` in this context.\n\n" * + "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n" * "๐’ฉ๐’ช๐’ฏโ„ฐ๐’ฎ:\n" * - "- `rowdecompose(โ„ณ, ๐œ.stab)`: Provides the decomposition of โ„ณ in terms of stabilizer and destabilizer rows of the given tableau of ๐œ.\n\n" * - "- `expect(โ„ณ, ๐œ)`: Returns the updated density matrix ๐œ™แตขโฑผโ€ฒ, where the trace Tr[๐œ™แตขโฑผโ€ฒ] provides the expectation value of measuring โ„ณ.\n\n") + "- `rowdecompose(โ„ณ, ๐œ.stab)`: Provides the decomposition of โ„ณ in terms of stabilizer \n" * + "and destabilizer rows of the given tableau of ๐œ.\n\n" * + "- `expect(โ„ณ, ๐œ)`: Returns the updated ๐œ™-matrix ๐œ™แตขโฑผโ€ฒ, where the trace Tr[๐œ™แตขโฑผโ€ฒ] provides \n" * + "the expectation value of measuring โ„ณ.\n\n") function projectrand!(sm::GeneralizedStabilizer, p::PauliOperator) eval = expect(p, sm) From a8a858998e5f4483e2bb004867012dfb7f0f41a0 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Wed, 6 Nov 2024 04:59:07 +0500 Subject: [PATCH 03/11] add wonderful code review suggestion --- src/QuantumClifford.jl | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/QuantumClifford.jl b/src/QuantumClifford.jl index 6732cc6f8..682b4afdc 100644 --- a/src/QuantumClifford.jl +++ b/src/QuantumClifford.jl @@ -98,6 +98,42 @@ function __init__() BIG_INT_MINUS_ONE[] = BigInt(-1) BIG_INT_TWO[] = BigInt(2) BIG_INT_FOUR[] = BigInt(4) + + # Register error hint for the `project!` method for GeneralizedStabilizer + Base.Experimental.register_error_hint(MethodError) do io, exc, argtypes, kwargs + if exc.f == project! + print(io, "\n\n") + print(io, "The method `project!` is not applicable for `GeneralizedStabilizer` with measurements\n") + print(io, "involving the Hermitian Pauli operator M. \n") + print(io, "The `GeneralizedStabilizer` ๐œ is updated by measuring M = ๐’ถโ‹…๐’นโ‚˜โ‹…๐“ˆโ‚™, resulting in the new\n") + print(io, "state ๐œโ€ฒ defined as: ๐œโ€ฒ = ยผ(I + M)๐œ(I + M) = (ฯ•โ€ฒ, B(๐’ฎโ€ฒ, ๐’Ÿโ€ฒ)) where (๐’ฎโ€ฒ, ๐’Ÿโ€ฒ) is derived\n") + print(io, "from (๐’ฎ, ๐’Ÿ) through the traditional stabilizer update, and ๐œ™' represents the updated\n") + print(io, "density matrix. Note that ยผ(I โˆ’ M)๐œ(I โˆ’ M) can be obtained by changing the sign of ๐’ถ.\n\n") + print(io, "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n") + print(io, "The projection requires a probabilistic approach, as measurement outcomes depend on \n") + print(io, "the expectation value of the `PauliOperator`. Specifically, the expectation value is \n") + print(io, "derived from the trace Tr[๐œโ€ฒ] = Tr[ฯ•แตขโฑผโ€ฒ] in the expression: ๐œโ€ฒ = โˆ‘ ฯ•แตขโฑผ Pแตข ฯ Pโฑผโ€  , where ๐œ™แตขโฑผโ€ฒ\n") + print(io, "is the updated ๐œ™-matrix. The trace Tr[๐œโ€ฒ] = Tr[ฯ•แตขโฑผโ€ฒ] represents the probability of \n") + print(io, "measuring either 0 or a non-zero outcome and serves as the normalization required for ๐œโ€ฒ.\n\n") + + print(io, "To correctly perform the 'nondeterministic' projection, please use ") + printstyled(io, "`projectrand!`", color=:cyan) + print(io, ".\n\n") + + print(io, "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n") + print(io, "Moreover, `project!` in this library operates as a 'deterministic' method to verify \n") + print(io, "whether a measurement operator commutes with stabilizers. Based on this commutation, it \n") + print(io, "executes additional steps to determine the resultant state after projection. Thus, there \n") + print(io, "are semantic nuances in defining `project!` consistently for `GeneralizedStabilizer`, \n") + print(io, "particularly regarding the interpretations of `anticom` and `res` in this context.\n\n") + print(io, "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n") + print(io, "๐’ฉ๐’ช๐’ฏโ„ฐ๐’ฎ:\n") + print(io, "- `rowdecompose(M, ๐œ.stab)`: Provides the decomposition of M in terms of stabilizer \n") + print(io, "and destabilizer rows of the given tableau of ๐œ.\n\n") + print(io, "- `expect(M, ๐œ)`: Returns the updated ฯ•-matrix ฯ•แตขโฑผโ€ฒ, where the trace Tr[ฯ•แตขโฑผโ€ฒ] provides \n") + print(io,"the expectation value of measuring โ„ณ.\n\n") + end + end end const NoZeroQubit = ArgumentError("Qubit indices have to be larger than zero, but you are attempting to create a gate acting on a qubit with a non-positive index. Ensure indexing always starts from 1.") From b4f839cde4831eb145ae8d68cb00eac73b027180 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Wed, 6 Nov 2024 05:30:19 +0500 Subject: [PATCH 04/11] fix doctest --- src/nonclifford.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nonclifford.jl b/src/nonclifford.jl index c33435188..b16f70b62 100644 --- a/src/nonclifford.jl +++ b/src/nonclifford.jl @@ -215,7 +215,7 @@ with ฯ•แตขโฑผ | Pแตข | Pโฑผ: 0.853553+0.0im | + _ | + _ 0.146447+0.0im | + Z | + Z -julia> expect(P"-X", sm) +julia> ฯ‡โ€ฒ = expect(P"-X", sm) 0.7071067811865475 + 0.0im julia> probโ‚ = (real(ฯ‡โ€ฒ)+1)/2 From 80e998196eadf128eb1de54b7bd118fa463091e5 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Wed, 6 Nov 2024 05:54:17 +0500 Subject: [PATCH 05/11] since invsparsity is private, fix the doctest errors using QuantumClifford.invsparsity --- src/nonclifford.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nonclifford.jl b/src/nonclifford.jl index b16f70b62..62045bf2f 100644 --- a/src/nonclifford.jl +++ b/src/nonclifford.jl @@ -438,7 +438,7 @@ A mixture โˆ‘ ฯ•แตขโฑผ Pแตข ฯ Pโฑผโ€  where ฯ is with ฯ•แตขโฑผ | Pแตข | Pโฑผ: 1.0+0.0im | + _ | + _ -julia> apply!(sm, pcT) |> invsparsity +julia> apply!(sm, pcT) |> QuantumClifford.invsparsity 4 ``` @@ -447,7 +447,7 @@ matrix `ฯ•แตขโฑผ`โ€‹ of a PauliChannel, providing a measure of the channel complexity. ```jldoctest -julia> invsparsity(pcT) +julia> QuantumClifford.invsparsity(pcT) 4 ``` From 0c2a527fc3f88c298911a2203ca387960836303d Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Wed, 6 Nov 2024 19:20:29 +0500 Subject: [PATCH 06/11] improve doctest quality --- src/nonclifford.jl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/nonclifford.jl b/src/nonclifford.jl index 62045bf2f..e55f6e782 100644 --- a/src/nonclifford.jl +++ b/src/nonclifford.jl @@ -428,7 +428,9 @@ of a [`GeneralizedStabilizer`](@ref), representing the inverse sparsity of `ฯ‡`. It provides a measure of the state's complexity, with bounds `ฮ›(ฯ‡) โ‰ค 4โฟ`. -```jldoctest +```jldoctest heuristic +julia> using QuantumClifford: invsparsity; # hide + julia> sm = GeneralizedStabilizer(S"X") A mixture โˆ‘ ฯ•แตขโฑผ Pแตข ฯ Pโฑผโ€  where ฯ is ๐’Ÿโ„ฏ๐“ˆ๐“‰๐’ถ๐’ท @@ -438,7 +440,7 @@ A mixture โˆ‘ ฯ•แตขโฑผ Pแตข ฯ Pโฑผโ€  where ฯ is with ฯ•แตขโฑผ | Pแตข | Pโฑผ: 1.0+0.0im | + _ | + _ -julia> apply!(sm, pcT) |> QuantumClifford.invsparsity +julia> apply!(sm, pcT) |> invsparsity 4 ``` @@ -446,8 +448,8 @@ Similarly, it calculates the number of non-zero elements in the density matrix `ฯ•แตขโฑผ`โ€‹ of a PauliChannel, providing a measure of the channel complexity. -```jldoctest -julia> QuantumClifford.invsparsity(pcT) +```jldoctest heuristic +julia> invsparsity(pcT) 4 ``` From 8f45805a5ca5d07342af311947455268da6d4512 Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Fri, 8 Nov 2024 15:44:19 -0500 Subject: [PATCH 07/11] remove unnecessary namespace redirection --- src/nonclifford.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nonclifford.jl b/src/nonclifford.jl index e55f6e782..fd0e028ff 100644 --- a/src/nonclifford.jl +++ b/src/nonclifford.jl @@ -237,7 +237,7 @@ function _proj(sm::GeneralizedStabilizer, p::PauliOperator) end function project!(::GeneralizedStabilizer, ::PauliOperator) - throw(Base.Experimental.MethodError(project!, (GeneralizedStabilizer, PauliOperator))) + throw(MethodError(project!, (GeneralizedStabilizer, PauliOperator))) end nqubits(sm::GeneralizedStabilizer) = nqubits(sm.stab) From cb10d814f8de906c6e27fed9fb8dcf2f5bdeb82e Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Fri, 8 Nov 2024 15:45:40 -0500 Subject: [PATCH 08/11] use the correct arguments for constructing the method error --- src/nonclifford.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nonclifford.jl b/src/nonclifford.jl index fd0e028ff..a70bb2a01 100644 --- a/src/nonclifford.jl +++ b/src/nonclifford.jl @@ -236,8 +236,8 @@ function _proj(sm::GeneralizedStabilizer, p::PauliOperator) error("This functionality is not implemented yet") end -function project!(::GeneralizedStabilizer, ::PauliOperator) - throw(MethodError(project!, (GeneralizedStabilizer, PauliOperator))) +function project!(s::GeneralizedStabilizer, p::PauliOperator) + throw(MethodError(project!, (s, p))) end nqubits(sm::GeneralizedStabilizer) = nqubits(sm.stab) From a1d135ef1be3a8f195d711da44f81ca90b42eff8 Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Fri, 8 Nov 2024 15:51:37 -0500 Subject: [PATCH 09/11] print the hint only for the appropriate project! method (otherwise it would print for things like `project!(1)`) and guard against this experimental feature being dropped --- src/QuantumClifford.jl | 68 ++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/src/QuantumClifford.jl b/src/QuantumClifford.jl index 682b4afdc..e0766c82d 100644 --- a/src/QuantumClifford.jl +++ b/src/QuantumClifford.jl @@ -99,39 +99,41 @@ function __init__() BIG_INT_TWO[] = BigInt(2) BIG_INT_FOUR[] = BigInt(4) - # Register error hint for the `project!` method for GeneralizedStabilizer - Base.Experimental.register_error_hint(MethodError) do io, exc, argtypes, kwargs - if exc.f == project! - print(io, "\n\n") - print(io, "The method `project!` is not applicable for `GeneralizedStabilizer` with measurements\n") - print(io, "involving the Hermitian Pauli operator M. \n") - print(io, "The `GeneralizedStabilizer` ๐œ is updated by measuring M = ๐’ถโ‹…๐’นโ‚˜โ‹…๐“ˆโ‚™, resulting in the new\n") - print(io, "state ๐œโ€ฒ defined as: ๐œโ€ฒ = ยผ(I + M)๐œ(I + M) = (ฯ•โ€ฒ, B(๐’ฎโ€ฒ, ๐’Ÿโ€ฒ)) where (๐’ฎโ€ฒ, ๐’Ÿโ€ฒ) is derived\n") - print(io, "from (๐’ฎ, ๐’Ÿ) through the traditional stabilizer update, and ๐œ™' represents the updated\n") - print(io, "density matrix. Note that ยผ(I โˆ’ M)๐œ(I โˆ’ M) can be obtained by changing the sign of ๐’ถ.\n\n") - print(io, "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n") - print(io, "The projection requires a probabilistic approach, as measurement outcomes depend on \n") - print(io, "the expectation value of the `PauliOperator`. Specifically, the expectation value is \n") - print(io, "derived from the trace Tr[๐œโ€ฒ] = Tr[ฯ•แตขโฑผโ€ฒ] in the expression: ๐œโ€ฒ = โˆ‘ ฯ•แตขโฑผ Pแตข ฯ Pโฑผโ€  , where ๐œ™แตขโฑผโ€ฒ\n") - print(io, "is the updated ๐œ™-matrix. The trace Tr[๐œโ€ฒ] = Tr[ฯ•แตขโฑผโ€ฒ] represents the probability of \n") - print(io, "measuring either 0 or a non-zero outcome and serves as the normalization required for ๐œโ€ฒ.\n\n") - - print(io, "To correctly perform the 'nondeterministic' projection, please use ") - printstyled(io, "`projectrand!`", color=:cyan) - print(io, ".\n\n") - - print(io, "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n") - print(io, "Moreover, `project!` in this library operates as a 'deterministic' method to verify \n") - print(io, "whether a measurement operator commutes with stabilizers. Based on this commutation, it \n") - print(io, "executes additional steps to determine the resultant state after projection. Thus, there \n") - print(io, "are semantic nuances in defining `project!` consistently for `GeneralizedStabilizer`, \n") - print(io, "particularly regarding the interpretations of `anticom` and `res` in this context.\n\n") - print(io, "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n") - print(io, "๐’ฉ๐’ช๐’ฏโ„ฐ๐’ฎ:\n") - print(io, "- `rowdecompose(M, ๐œ.stab)`: Provides the decomposition of M in terms of stabilizer \n") - print(io, "and destabilizer rows of the given tableau of ๐œ.\n\n") - print(io, "- `expect(M, ๐œ)`: Returns the updated ฯ•-matrix ฯ•แตขโฑผโ€ฒ, where the trace Tr[ฯ•แตขโฑผโ€ฒ] provides \n") - print(io,"the expectation value of measuring โ„ณ.\n\n") + # Register error hint for the `project!` method for GeneralizedStabilizer + if isdefined(Base.Experimental, :register_error_hint) + Base.Experimental.register_error_hint(MethodError) do io, exc, argtypes, kwargs + if exc.f === project! && exc.argtypes[1] == GeneralizedStabilizer + print(io, "\n\n") + print(io, "The method `project!` is not applicable for `GeneralizedStabilizer` with measurements\n") + print(io, "involving the Hermitian Pauli operator M. \n") + print(io, "The `GeneralizedStabilizer` ๐œ is updated by measuring M = ๐’ถโ‹…๐’นโ‚˜โ‹…๐“ˆโ‚™, resulting in the new\n") + print(io, "state ๐œโ€ฒ defined as: ๐œโ€ฒ = ยผ(I + M)๐œ(I + M) = (ฯ•โ€ฒ, B(๐’ฎโ€ฒ, ๐’Ÿโ€ฒ)) where (๐’ฎโ€ฒ, ๐’Ÿโ€ฒ) is derived\n") + print(io, "from (๐’ฎ, ๐’Ÿ) through the traditional stabilizer update, and ๐œ™' represents the updated\n") + print(io, "density matrix. Note that ยผ(I โˆ’ M)๐œ(I โˆ’ M) can be obtained by changing the sign of ๐’ถ.\n\n") + print(io, "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n") + print(io, "The projection requires a probabilistic approach, as measurement outcomes depend on \n") + print(io, "the expectation value of the `PauliOperator`. Specifically, the expectation value is \n") + print(io, "derived from the trace Tr[๐œโ€ฒ] = Tr[ฯ•แตขโฑผโ€ฒ] in the expression: ๐œโ€ฒ = โˆ‘ ฯ•แตขโฑผ Pแตข ฯ Pโฑผโ€  , where ๐œ™แตขโฑผโ€ฒ\n") + print(io, "is the updated ๐œ™-matrix. The trace Tr[๐œโ€ฒ] = Tr[ฯ•แตขโฑผโ€ฒ] represents the probability of \n") + print(io, "measuring either 0 or a non-zero outcome and serves as the normalization required for ๐œโ€ฒ.\n\n") + + print(io, "To correctly perform the 'nondeterministic' projection, please use ") + printstyled(io, "`projectrand!`", color=:cyan) + print(io, ".\n\n") + + print(io, "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n") + print(io, "Moreover, `project!` in this library operates as a 'deterministic' method to verify \n") + print(io, "whether a measurement operator commutes with stabilizers. Based on this commutation, it \n") + print(io, "executes additional steps to determine the resultant state after projection. Thus, there \n") + print(io, "are semantic nuances in defining `project!` consistently for `GeneralizedStabilizer`, \n") + print(io, "particularly regarding the interpretations of `anticom` and `res` in this context.\n\n") + print(io, "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n") + print(io, "๐’ฉ๐’ช๐’ฏโ„ฐ๐’ฎ:\n") + print(io, "- `rowdecompose(M, ๐œ.stab)`: Provides the decomposition of M in terms of stabilizer \n") + print(io, "and destabilizer rows of the given tableau of ๐œ.\n\n") + print(io, "- `expect(M, ๐œ)`: Returns the updated ฯ•-matrix ฯ•แตขโฑผโ€ฒ, where the trace Tr[ฯ•แตขโฑผโ€ฒ] provides \n") + print(io,"the expectation value of measuring โ„ณ.\n\n") + end end end end From 83fd02696a0d7fa2bfd202fccb3d070087d36cd2 Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Fri, 8 Nov 2024 16:09:26 -0500 Subject: [PATCH 10/11] simplify message and multi-line printing syntax --- src/QuantumClifford.jl | 40 +++++++++------------------------------- 1 file changed, 9 insertions(+), 31 deletions(-) diff --git a/src/QuantumClifford.jl b/src/QuantumClifford.jl index e0766c82d..22d506e2f 100644 --- a/src/QuantumClifford.jl +++ b/src/QuantumClifford.jl @@ -102,37 +102,15 @@ function __init__() # Register error hint for the `project!` method for GeneralizedStabilizer if isdefined(Base.Experimental, :register_error_hint) Base.Experimental.register_error_hint(MethodError) do io, exc, argtypes, kwargs - if exc.f === project! && exc.argtypes[1] == GeneralizedStabilizer - print(io, "\n\n") - print(io, "The method `project!` is not applicable for `GeneralizedStabilizer` with measurements\n") - print(io, "involving the Hermitian Pauli operator M. \n") - print(io, "The `GeneralizedStabilizer` ๐œ is updated by measuring M = ๐’ถโ‹…๐’นโ‚˜โ‹…๐“ˆโ‚™, resulting in the new\n") - print(io, "state ๐œโ€ฒ defined as: ๐œโ€ฒ = ยผ(I + M)๐œ(I + M) = (ฯ•โ€ฒ, B(๐’ฎโ€ฒ, ๐’Ÿโ€ฒ)) where (๐’ฎโ€ฒ, ๐’Ÿโ€ฒ) is derived\n") - print(io, "from (๐’ฎ, ๐’Ÿ) through the traditional stabilizer update, and ๐œ™' represents the updated\n") - print(io, "density matrix. Note that ยผ(I โˆ’ M)๐œ(I โˆ’ M) can be obtained by changing the sign of ๐’ถ.\n\n") - print(io, "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n") - print(io, "The projection requires a probabilistic approach, as measurement outcomes depend on \n") - print(io, "the expectation value of the `PauliOperator`. Specifically, the expectation value is \n") - print(io, "derived from the trace Tr[๐œโ€ฒ] = Tr[ฯ•แตขโฑผโ€ฒ] in the expression: ๐œโ€ฒ = โˆ‘ ฯ•แตขโฑผ Pแตข ฯ Pโฑผโ€  , where ๐œ™แตขโฑผโ€ฒ\n") - print(io, "is the updated ๐œ™-matrix. The trace Tr[๐œโ€ฒ] = Tr[ฯ•แตขโฑผโ€ฒ] represents the probability of \n") - print(io, "measuring either 0 or a non-zero outcome and serves as the normalization required for ๐œโ€ฒ.\n\n") - - print(io, "To correctly perform the 'nondeterministic' projection, please use ") - printstyled(io, "`projectrand!`", color=:cyan) - print(io, ".\n\n") - - print(io, "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n") - print(io, "Moreover, `project!` in this library operates as a 'deterministic' method to verify \n") - print(io, "whether a measurement operator commutes with stabilizers. Based on this commutation, it \n") - print(io, "executes additional steps to determine the resultant state after projection. Thus, there \n") - print(io, "are semantic nuances in defining `project!` consistently for `GeneralizedStabilizer`, \n") - print(io, "particularly regarding the interpretations of `anticom` and `res` in this context.\n\n") - print(io, "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n") - print(io, "๐’ฉ๐’ช๐’ฏโ„ฐ๐’ฎ:\n") - print(io, "- `rowdecompose(M, ๐œ.stab)`: Provides the decomposition of M in terms of stabilizer \n") - print(io, "and destabilizer rows of the given tableau of ๐œ.\n\n") - print(io, "- `expect(M, ๐œ)`: Returns the updated ฯ•-matrix ฯ•แตขโฑผโ€ฒ, where the trace Tr[ฯ•แตขโฑผโ€ฒ] provides \n") - print(io,"the expectation value of measuring โ„ณ.\n\n") + if exc.f === project! && argtypes[1] <: GeneralizedStabilizer + print(io, """ + \nThe method `project!` is not appropriate for use with`GeneralizedStabilizer`. + You probably are looking for `projectrand!`. + `project!` in this library is a low-level "linear algebra" method to verify + whether a measurement operator commutes with a set of stabilizers, and to + potentially simplify the tableau and provide the index of the anticommuting + term in that tableau. This linear algebra operation is not defined for + `GeneralStabilizer` as there is no single tableau to provide an index into.""") end end end From 087edb67deb73634212f0cda84b821ea2b1df802 Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Fri, 8 Nov 2024 16:11:41 -0500 Subject: [PATCH 11/11] add tests --- test/test_nonclifford.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_nonclifford.jl b/test/test_nonclifford.jl index b26239de8..79773b56c 100644 --- a/test/test_nonclifford.jl +++ b/test/test_nonclifford.jl @@ -59,3 +59,4 @@ end @test_throws ArgumentError PauliChannel(((P"X", P"Z"), (P"X", P"Z")), (1,)) @test_throws ArgumentError UnitaryPauliChannel((P"X", P"ZZ"), (1,2)) @test_throws ArgumentError UnitaryPauliChannel((P"X", P"Z"), (1,)) +@test_throws MethodError project!(GeneralizedStabilizer(S"X"), P"X")