diff --git a/ccsrc/include/simulator/vector/detail/cpu_vector_policy.h b/ccsrc/include/simulator/vector/detail/cpu_vector_policy.h index 2b1a917d1..a824a605f 100644 --- a/ccsrc/include/simulator/vector/detail/cpu_vector_policy.h +++ b/ccsrc/include/simulator/vector/detail/cpu_vector_policy.h @@ -95,6 +95,8 @@ struct CPUVectorPolicyBase { static py_qs_data_t ExpectationOfCsr(const std::shared_ptr>& a, const std::shared_ptr>& b, const qs_data_p_t& bra, const qs_data_p_t& ket, index_t dim); + static VT GetCumulativeProbs(const qs_data_p_t& qs_p, index_t dim); + static VT LowerBound(const VT& cum_prob, const VT& sampled_probs); // X like operator // ======================================================================================================== diff --git a/ccsrc/include/simulator/vector/detail/gpu_vector_policy.cuh b/ccsrc/include/simulator/vector/detail/gpu_vector_policy.cuh index 738706f24..f75bfbfa7 100644 --- a/ccsrc/include/simulator/vector/detail/gpu_vector_policy.cuh +++ b/ccsrc/include/simulator/vector/detail/gpu_vector_policy.cuh @@ -86,6 +86,8 @@ struct GPUVectorPolicyBase { static py_qs_data_t ExpectationOfCsr(const std::shared_ptr>& a, const std::shared_ptr>& b, const qs_data_p_t& bra, const qs_data_p_t& ket, index_t dim); + static VT GetCumulativeProbs(const qs_data_p_t& qs_p, index_t dim); + static VT LowerBound(const VT& cum_prob, const VT& sampled_probs); // X like operator // ======================================================================================================== diff --git a/ccsrc/include/simulator/vector/vector_state.tpp b/ccsrc/include/simulator/vector/vector_state.tpp index 175a5e244..11ca716ef 100644 --- a/ccsrc/include/simulator/vector/vector_state.tpp +++ b/ccsrc/include/simulator/vector/vector_state.tpp @@ -1303,8 +1303,8 @@ VT VectorState::SamplingMeasurementEndingWithoutNoise(co auto sim = derived_t(n_qubits, static_cast(rng()), qs); VT already_measured(this->n_qubits, 0); - circuit_t mea_circ; - + VT m_qids; + circuit_t other_circ; for (auto& g : circ) { if (g->GetID() == GateID::M) { auto m_qid = g->GetObjQubits()[0]; @@ -1312,12 +1312,28 @@ VT VectorState::SamplingMeasurementEndingWithoutNoise(co throw std::runtime_error("Quantum circuit is not a measurement ending circuit."); } already_measured[m_qid] = 1; - mea_circ.push_back(g); + m_qids.push_back(m_qid); } else { - sim.ApplyGate(g, pr, false); + other_circ.push_back(g); + } + } + sim.ApplyCircuit(other_circ, pr); + + auto cum_prob = qs_policy_t_::GetCumulativeProbs(sim.qs, dim); + VT sampled_probs(shots); + for (size_t i = 0; i < shots; ++i) { + sampled_probs[i] = static_cast(sim.rng_()); + } + std::sort(sampled_probs.begin(), sampled_probs.end()); + auto res = qs_policy_t_::LowerBound(cum_prob, sampled_probs); + VT out; + // Measure all qubits and filter actually measurement qubit. + for (auto r : res) { + for (auto i : m_qids) { + out.push_back((r >> i) & 1); } } - return sim.Sampling(mea_circ, pr, shots, key_map, seed); + return out; } } // namespace mindquantum::sim::vector::detail diff --git a/ccsrc/lib/simulator/vector/detail/cpu_common/cpu_vector_core_policy.cpp b/ccsrc/lib/simulator/vector/detail/cpu_common/cpu_vector_core_policy.cpp index 95a0e6399..b9b81e256 100644 --- a/ccsrc/lib/simulator/vector/detail/cpu_common/cpu_vector_core_policy.cpp +++ b/ccsrc/lib/simulator/vector/detail/cpu_common/cpu_vector_core_policy.cpp @@ -14,12 +14,16 @@ * limitations under the License. */ #include +#include +#include #include +#include #include #include "config/details/macros.h" #include "config/openmp.h" #include "config/type_promotion.h" +#include "core/mq_base_types.h" #include "core/utils.h" #include "math/pr/parameter_resolver.h" #include "simulator/utils.h" @@ -281,6 +285,56 @@ auto CPUVectorPolicyBase::GroundStateOfZZs(const std::map +void ShowVec(const std::vector& a) { + for (auto i : a) { + std::cout << i << ", "; + } + std::cout << std::endl; +} + +template +VT CPUVectorPolicyBase::GetCumulativeProbs(const qs_data_p_t& qs_out, index_t dim) { + auto qs = qs_out; + bool will_free = false; + if (qs == nullptr) { + qs = derived_::InitState(dim); + will_free = true; + } + VT prob(dim); + // Can be optimized by parallel prefix sum algorithm. + prob[0] = qs[0].real() * qs[0].real() + qs[0].imag() * qs[0].imag(); + for (size_t i = 1; i < dim; ++i) { + prob[i] = qs[i].real() * qs[i].real() + qs[i].imag() * qs[i].imag() + prob[i - 1]; + } + + prob[dim - 1] = 1.0; + if (will_free) { + free(qs); + } + return prob; +} + +template +VT CPUVectorPolicyBase::LowerBound(const VT& cum_prob, + const VT& sampled_probs) { + size_t samp_size = sampled_probs.size(); + VT out(samp_size); + size_t samp_idx = 0, dist_idx = 0; + while (true) { + if (samp_idx >= samp_size) { + break; + } + if (sampled_probs[samp_idx] < cum_prob[dist_idx]) { + out[samp_idx] = dist_idx; + samp_idx += 1; + } else { + dist_idx += 1; + } + } + return out; +} + #ifdef __x86_64__ template struct CPUVectorPolicyBase; template struct CPUVectorPolicyBase; diff --git a/ccsrc/lib/simulator/vector/detail/gpu/gpu_vector_core_gate_expect.cu b/ccsrc/lib/simulator/vector/detail/gpu/gpu_vector_core_gate_expect.cu index 3bee4e8c0..36bd0e497 100644 --- a/ccsrc/lib/simulator/vector/detail/gpu/gpu_vector_core_gate_expect.cu +++ b/ccsrc/lib/simulator/vector/detail/gpu/gpu_vector_core_gate_expect.cu @@ -931,7 +931,6 @@ auto GPUVectorPolicyBase::ExpectDiffGivens(const qs_data_p auto obj_rev_high_mask = mask.obj_rev_high_mask; auto obj_low_mask = mask.obj_low_mask; auto obj_rev_low_mask = mask.obj_rev_low_mask; - auto obj_mask = mask.obj_mask; auto obj_min_mask = mask.obj_min_mask; auto obj_max_mask = mask.obj_max_mask; auto ctrl_mask = mask.ctrl_mask; diff --git a/ccsrc/lib/simulator/vector/detail/gpu/gpu_vector_core_policy.cu b/ccsrc/lib/simulator/vector/detail/gpu/gpu_vector_core_policy.cu index c19fa29c4..5da11cada 100644 --- a/ccsrc/lib/simulator/vector/detail/gpu/gpu_vector_core_policy.cu +++ b/ccsrc/lib/simulator/vector/detail/gpu/gpu_vector_core_policy.cu @@ -16,6 +16,7 @@ #include #include +#include #include #include "config/openmp.h" @@ -334,6 +335,54 @@ auto GPUVectorPolicyBase::Copy(const qs_data_p_t& qs, inde return out; }; +template +VT GPUVectorPolicyBase::GetCumulativeProbs(const qs_data_p_t& qs_out, index_t dim) { + auto qs = qs_out; + bool will_free = false; + if (qs == nullptr) { + qs = derived_::InitState(dim); + will_free = true; + } + calc_type* prob; + auto state = cudaMalloc((void**) &prob, sizeof(calc_type) * dim); // NOLINT + if (state != cudaSuccess) { + throw std::runtime_error("Malloc GPU memory failed: " + std::string(cudaGetErrorName(state)) + ", " + + cudaGetErrorString(state)); + } + thrust::counting_iterator i(0); + thrust::for_each( + i, i + dim, [=] __device__(index_t i) { prob[i] = qs[i].real() * qs[i].real() + qs[i].imag() * qs[i].imag(); }); + thrust::device_ptr prob_ptr(prob); + thrust::inclusive_scan(thrust::device, prob, prob + dim, prob); + if (will_free) { + derived::FreeState(&qs); + } + VT out(dim); + thrust::copy(prob_ptr, prob_ptr + dim, out.begin()); + cudaFree(prob); + return out; +} + +template +VT GPUVectorPolicyBase::LowerBound(const VT& cum_prob, + const VT& sampled_probs) { + size_t samp_size = sampled_probs.size(); + VT out(samp_size); + size_t samp_idx = 0, dist_idx = 0; + while (true) { + if (samp_idx >= samp_size) { + break; + } + if (sampled_probs[samp_idx] < cum_prob[dist_idx]) { + out[samp_idx] = dist_idx; + samp_idx += 1; + } else { + dist_idx += 1; + } + } + return out; +} + template struct GPUVectorPolicyBase; template struct GPUVectorPolicyBase; diff --git a/mindquantum/core/circuit/circuit.py b/mindquantum/core/circuit/circuit.py index d49fbddba..759e91321 100644 --- a/mindquantum/core/circuit/circuit.py +++ b/mindquantum/core/circuit/circuit.py @@ -835,7 +835,7 @@ def is_measure_end(self): high[idx] += 1 if isinstance(gate, mq_gates.Measure): m_idx = gate.obj_qubits[0] - if high[m_idx] != self.all_qubits.map[m_idx]: + if high[m_idx] != circ.all_qubits.map[m_idx]: return False return True diff --git a/tests/st/test_io/test_svg.py b/tests/st/test_io/test_svg.py index 3c345f45b..7316eb70a 100644 --- a/tests/st/test_io/test_svg.py +++ b/tests/st/test_io/test_svg.py @@ -29,7 +29,7 @@ def test_measure_svg(): res = sim.sampling(circ, shots=100, seed=42) text = res.svg()._repr_svg_().split('bar') # pylint: disable=protected-access text = "bar".join([text[0]] + ['"'.join(i.split('"')[1:]) for i in text[1:]]) - len_text_exp = 9257 + len_text_exp = 9258 assert len(text) == len_text_exp