32 #ifndef INSTRUMENTS_H_ 33 #define INSTRUMENTS_H_ 46 template <
typename Derived>
47 dyn_col_vect<typename Derived::Scalar>
48 ip(
const Eigen::MatrixBase<Derived>& phi,
const Eigen::MatrixBase<Derived>& psi,
49 const std::vector<idx>& subsys,
const std::vector<idx>& dims) {
50 const dyn_col_vect<typename Derived::Scalar>& rphi = phi.derived();
51 const dyn_col_vect<typename Derived::Scalar>& rpsi = psi.derived();
56 if (!internal::check_nonzero_size(rphi))
57 throw exception::ZeroSize(
"qpp::ip()");
60 if (!internal::check_nonzero_size(rpsi))
61 throw exception::ZeroSize(
"qpp::ip()");
64 if (!internal::check_cvector(rphi))
65 throw exception::MatrixNotCvector(
"qpp::ip()");
68 if (!internal::check_cvector(rpsi))
69 throw exception::MatrixNotCvector(
"qpp::ip()");
72 if (!internal::check_dims(dims))
73 throw exception::DimsInvalid(
"qpp::ip()");
76 if (!internal::check_subsys_match_dims(subsys, dims))
77 throw exception::SubsysMismatchDims(
"qpp::ip()");
80 if (!internal::check_dims_match_cvect(dims, rpsi))
81 throw exception::DimsMismatchCvector(
"qpp::ip()");
84 std::vector<idx> subsys_dims(subsys.size());
85 for (idx i = 0; i < subsys.size(); ++i)
86 subsys_dims[i] = dims[subsys[i]];
87 if (!internal::check_dims_match_cvect(subsys_dims, rphi))
88 throw exception::DimsMismatchCvector(
"qpp::ip()");
91 idx Dsubsys = prod(std::begin(subsys_dims), std::end(subsys_dims));
93 idx D =
static_cast<idx
>(rpsi.rows());
94 idx Dsubsys_bar = D / Dsubsys;
97 idx n_subsys = subsys.size();
98 idx n_subsys_bar = n - n_subsys;
102 idx Cdimssubsys[maxn];
103 idx Csubsys_bar[maxn];
104 idx Cdimssubsys_bar[maxn];
106 std::vector<idx> subsys_bar = complement(subsys, n);
107 std::copy(std::begin(subsys_bar), std::end(subsys_bar),
108 std::begin(Csubsys_bar));
110 for (idx i = 0; i < n; ++i) {
113 for (idx i = 0; i < n_subsys; ++i) {
114 Csubsys[i] = subsys[i];
115 Cdimssubsys[i] = dims[subsys[i]];
117 for (idx i = 0; i < n_subsys_bar; ++i) {
118 Cdimssubsys_bar[i] = dims[subsys_bar[i]];
121 auto worker = [&](idx b) noexcept->typename Derived::Scalar {
123 idx Cmidxrowsubsys[maxn];
124 idx Cmidxcolsubsys_bar[maxn];
127 internal::n2multiidx(b, n_subsys_bar, Cdimssubsys_bar,
130 for (idx k = 0; k < n_subsys_bar; ++k) {
131 Cmidxrow[Csubsys_bar[k]] = Cmidxcolsubsys_bar[k];
134 typename Derived::Scalar result = 0;
135 for (idx a = 0; a < Dsubsys; ++a) {
137 internal::n2multiidx(a, n_subsys, Cdimssubsys, Cmidxrowsubsys);
139 for (idx k = 0; k < n_subsys; ++k) {
140 Cmidxrow[Csubsys[k]] = Cmidxrowsubsys[k];
143 idx i = internal::multiidx2n(Cmidxrow, n, Cdims);
145 result += std::conj(rphi(a)) * rpsi(i);
151 dyn_col_vect<typename Derived::Scalar> result(Dsubsys_bar);
153 #pragma omp parallel for 154 #endif // WITH_OPENMP_ 155 for (idx m = 0; m < Dsubsys_bar; ++m)
156 result(m) = worker(m);
171 template <
typename Derived>
172 dyn_col_vect<typename Derived::Scalar>
173 ip(
const Eigen::MatrixBase<Derived>& phi,
const Eigen::MatrixBase<Derived>& psi,
174 const std::vector<idx>& subsys, idx d = 2) {
175 const dyn_col_vect<typename Derived::Scalar>& rphi = phi.derived();
176 const dyn_col_vect<typename Derived::Scalar>& rpsi = psi.derived();
180 if (!internal::check_nonzero_size(rpsi))
181 throw exception::ZeroSize(
"qpp::ip()");
185 throw exception::DimsInvalid(
"qpp::ip()");
188 idx n = internal::get_num_subsys(static_cast<idx>(rpsi.rows()), d);
189 std::vector<idx> dims(n, d);
191 return ip(phi, psi, subsys, dims);
204 template <
typename Derived>
205 std::tuple<idx, std::vector<double>, std::vector<cmat>>
206 measure(
const Eigen::MatrixBase<Derived>& A,
const std::vector<cmat>& Ks) {
207 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
212 if (!internal::check_nonzero_size(rA))
213 throw exception::ZeroSize(
"qpp::measure()");
217 throw exception::ZeroSize(
"qpp::measure()");
218 if (!internal::check_square_mat(Ks[0]))
219 throw exception::MatrixNotSquare(
"qpp::measure()");
220 if (Ks[0].rows() != rA.rows())
221 throw exception::DimsMismatchMatrix(
"qpp::measure()");
222 for (
auto&& elem : Ks)
223 if (elem.rows() != Ks[0].rows() || elem.cols() != Ks[0].rows())
224 throw exception::DimsNotEqual(
"qpp::measure()");
228 std::vector<double> prob(Ks.size());
230 std::vector<cmat> outstates(Ks.size());
233 if (internal::check_square_mat(rA))
235 for (idx i = 0; i < Ks.size(); ++i) {
236 outstates[i] = cmat::Zero(rA.rows(), rA.rows());
237 cmat tmp = Ks[i] * rA * adjoint(Ks[i]);
238 prob[i] = std::abs(trace(tmp));
240 outstates[i] = tmp / prob[i];
244 else if (internal::check_cvector(rA))
246 for (idx i = 0; i < Ks.size(); ++i) {
247 outstates[i] = ket::Zero(rA.rows());
248 ket tmp = Ks[i] * rA;
250 prob[i] = std::pow(norm(tmp), 2);
252 outstates[i] = tmp / std::sqrt(prob[i]);
255 throw exception::MatrixNotSquareNorCvector(
"qpp::measure()");
258 std::discrete_distribution<idx> dd(std::begin(prob), std::end(prob));
260 #ifdef NO_THREAD_LOCAL_ 261 RandomDevices::get_instance().get_prng();
263 RandomDevices::get_thread_local_instance().get_prng();
265 idx result = dd(gen);
267 return std::make_tuple(result, prob, outstates);
282 template <
typename Derived>
283 std::tuple<idx, std::vector<double>, std::vector<cmat>>
284 measure(
const Eigen::MatrixBase<Derived>& A,
285 const std::initializer_list<cmat>& Ks) {
286 return measure(A, std::vector<cmat>(Ks));
301 template <
typename Derived>
302 std::tuple<idx, std::vector<double>, std::vector<cmat>>
303 measure(
const Eigen::MatrixBase<Derived>& A,
const cmat& U) {
304 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
309 if (!internal::check_nonzero_size(rA))
310 throw exception::ZeroSize(
"qpp::measure()");
313 if (!internal::check_nonzero_size(U))
314 throw exception::ZeroSize(
"qpp::measure()");
315 if (!internal::check_square_mat(U))
316 throw exception::MatrixNotSquare(
"qpp::measure()");
317 if (U.rows() != rA.rows())
318 throw exception::DimsMismatchMatrix(
"qpp::measure()");
321 std::vector<cmat> Ks(U.rows());
322 for (idx i = 0; i < static_cast<idx>(U.rows()); ++i)
323 Ks[i] = U.col(i) * adjoint(U.col(i));
325 return measure(rA, Ks);
346 template <
typename Derived>
347 std::tuple<idx, std::vector<double>, std::vector<cmat>>
348 measure(
const Eigen::MatrixBase<Derived>& A,
const std::vector<cmat>& Ks,
349 const std::vector<idx>& target,
const std::vector<idx>& dims,
350 bool destructive =
true) {
351 const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA = A.derived();
356 if (!internal::check_nonzero_size(rA))
357 throw exception::ZeroSize(
"qpp::measure()");
360 if (!internal::check_dims(dims))
361 throw exception::DimsInvalid(
"qpp::measure()");
364 if (!internal::check_subsys_match_dims(target, dims))
365 throw exception::SubsysMismatchDims(
"qpp::measure()");
368 if (internal::check_cvector(rA)) {
369 if (!internal::check_dims_match_cvect(dims, rA))
370 throw exception::DimsMismatchCvector(
"qpp::measure()");
371 }
else if (internal::check_square_mat(rA)) {
372 if (!internal::check_dims_match_mat(dims, rA))
373 throw exception::DimsMismatchMatrix(
"qpp::measure()");
375 throw exception::MatrixNotSquareNorCvector(
"qpp::measure()");
377 std::vector<idx> subsys_dims(target.size());
378 for (idx i = 0; i < target.size(); ++i)
379 subsys_dims[i] = dims[target[i]];
381 idx D = prod(std::begin(dims), std::end(dims));
382 idx Dsubsys = prod(std::begin(subsys_dims), std::end(subsys_dims));
383 idx Dsubsys_bar = D / Dsubsys;
387 throw exception::ZeroSize(
"qpp::measure()");
388 if (!internal::check_square_mat(Ks[0]))
389 throw exception::MatrixNotSquare(
"qpp::measure()");
390 if (Dsubsys != static_cast<idx>(Ks[0].rows()))
391 throw exception::DimsMismatchMatrix(
"qpp::measure()");
392 for (
auto&& elem : Ks)
393 if (elem.rows() != Ks[0].rows() || elem.cols() != Ks[0].rows())
394 throw exception::DimsNotEqual(
"qpp::measure()");
398 std::vector<double> prob(Ks.size());
400 std::vector<cmat> outstates;
403 outstates.resize(Ks.size(), cmat::Zero(Dsubsys_bar, Dsubsys_bar));
405 outstates.resize(Ks.size(), cmat::Zero(D, D));
408 if (internal::check_cvector(rA))
410 for (idx i = 0; i < Ks.size(); ++i) {
411 ket tmp = apply(rA, Ks[i], target, dims);
412 prob[i] = std::pow(norm(tmp), 2);
416 tmp /= std::sqrt(prob[i]);
418 outstates[i] = ptrace(tmp, target, dims);
427 for (idx i = 0; i < Ks.size(); ++i) {
428 cmat tmp = apply(rA, Ks[i], target, dims);
430 tmp = ptrace(tmp, target, dims);
431 prob[i] = std::abs(trace(tmp));
435 outstates[i] = tmp / prob[i];
440 std::discrete_distribution<idx> dd(std::begin(prob), std::end(prob));
442 #ifdef NO_THREAD_LOCAL_ 443 RandomDevices::get_instance().get_prng();
445 RandomDevices::get_thread_local_instance().get_prng();
447 idx result = dd(gen);
449 return std::make_tuple(result, prob, outstates);
472 template <
typename Derived>
473 std::tuple<idx, std::vector<double>, std::vector<cmat>>
474 measure(
const Eigen::MatrixBase<Derived>& A,
475 const std::initializer_list<cmat>& Ks,
const std::vector<idx>& target,
476 const std::vector<idx>& dims,
bool destructive =
true) {
477 return measure(A, std::vector<cmat>(Ks), target, dims, destructive);
497 template <
typename Derived>
498 std::tuple<idx, std::vector<double>, std::vector<cmat>>
499 measure(
const Eigen::MatrixBase<Derived>& A,
const std::vector<cmat>& Ks,
500 const std::vector<idx>& target, idx d = 2,
bool destructive =
true) {
501 const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA = A.derived();
506 if (!internal::check_nonzero_size(rA))
507 throw exception::ZeroSize(
"qpp::measure()");
511 throw exception::DimsInvalid(
"qpp::measure()");
514 idx n = internal::get_num_subsys(static_cast<idx>(rA.rows()), d);
515 std::vector<idx> dims(n, d);
517 return measure(rA, Ks, target, dims, destructive);
540 template <
typename Derived>
541 std::tuple<idx, std::vector<double>, std::vector<cmat>>
542 measure(
const Eigen::MatrixBase<Derived>& A,
543 const std::initializer_list<cmat>& Ks,
const std::vector<idx>& target,
544 idx d = 2,
bool destructive =
true) {
545 return measure(A, std::vector<cmat>(Ks), target, d, destructive);
571 template <
typename Derived>
572 std::tuple<idx, std::vector<double>, std::vector<cmat>>
573 measure(
const Eigen::MatrixBase<Derived>& A,
const cmat& V,
574 const std::vector<idx>& target,
const std::vector<idx>& dims,
575 bool destructive =
true) {
576 const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA = A.derived();
581 if (!internal::check_nonzero_size(rA))
582 throw exception::ZeroSize(
"qpp::measure()");
585 if (!internal::check_dims(dims))
586 throw exception::DimsInvalid(
"qpp::measure()");
589 if (!internal::check_subsys_match_dims(target, dims))
590 throw exception::SubsysMismatchDims(
"qpp::measure()");
593 if (internal::check_cvector(rA)) {
594 if (!internal::check_dims_match_cvect(dims, rA))
595 throw exception::DimsMismatchCvector(
"qpp::measure()");
596 }
else if (internal::check_square_mat(rA)) {
597 if (!internal::check_dims_match_mat(dims, rA))
598 throw exception::DimsMismatchMatrix(
"qpp::measure()");
600 throw exception::MatrixNotSquareNorCvector(
"qpp::measure()");
602 std::vector<idx> subsys_dims(target.size());
603 for (idx i = 0; i < target.size(); ++i)
604 subsys_dims[i] = dims[target[i]];
606 idx Dsubsys = prod(std::begin(subsys_dims), std::end(subsys_dims));
609 if (!internal::check_nonzero_size(V))
610 throw exception::ZeroSize(
"qpp::measure()");
611 if (Dsubsys != static_cast<idx>(V.rows()))
612 throw exception::DimsMismatchMatrix(
"qpp::measure()");
616 idx M =
static_cast<idx
>(V.cols());
619 if (internal::check_cvector(rA)) {
620 const ket& rpsi = A.derived();
621 std::vector<double> prob(M);
622 std::vector<cmat> outstates(M);
625 #pragma omp parallel for 626 #endif // WITH_OPENMP_ 627 for (idx i = 0; i < M; ++i) {
630 ip(static_cast<const ket&>(V.col(i)), rpsi, target, dims);
632 outstates[i] = apply(rpsi, prj(V.col(i)), target, dims);
635 for (idx i = 0; i < M; ++i) {
636 double tmp = norm(outstates[i]);
646 std::discrete_distribution<idx> dd(std::begin(prob), std::end(prob));
648 #ifdef NO_THREAD_LOCAL_ 649 RandomDevices::get_instance().get_prng();
651 RandomDevices::get_thread_local_instance().get_prng();
653 idx result = dd(gen);
655 return std::make_tuple(result, prob, outstates);
659 std::vector<cmat> Ks(M);
660 for (idx i = 0; i < M; ++i)
661 Ks[i] = V.col(i) * adjoint(V.col(i));
663 return measure(rA, Ks, target, dims, destructive);
690 template <
typename Derived>
691 std::tuple<idx, std::vector<double>, std::vector<cmat>>
692 measure(
const Eigen::MatrixBase<Derived>& A,
const cmat& V,
693 const std::vector<idx>& target, idx d = 2,
bool destructive =
true) {
694 const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA = A.derived();
699 if (!internal::check_nonzero_size(rA))
700 throw exception::ZeroSize(
"qpp::measure()");
704 throw exception::DimsInvalid(
"qpp::measure()");
707 idx n = internal::get_num_subsys(static_cast<idx>(rA.rows()), d);
708 std::vector<idx> dims(n, d);
710 return measure(rA, V, target, dims, destructive);
730 template <
typename Derived>
731 std::tuple<std::vector<idx>, double, cmat>
732 measure_seq(
const Eigen::MatrixBase<Derived>& A, std::vector<idx> target,
733 std::vector<idx> dims,
bool destructive =
true) {
738 dyn_mat<typename Derived::Scalar> rA = A.derived();
743 if (!internal::check_nonzero_size(rA))
744 throw exception::ZeroSize(
"qpp::measure_seq()");
747 if (!internal::check_dims(dims))
748 throw exception::DimsInvalid(
"qpp::measure_seq()");
751 if (internal::check_cvector(rA)) {
752 if (!internal::check_dims_match_cvect(dims, rA))
753 throw exception::DimsMismatchCvector(
"qpp::measure_seq()");
754 }
else if (internal::check_square_mat(rA)) {
755 if (!internal::check_dims_match_mat(dims, rA))
756 throw exception::DimsMismatchMatrix(
"qpp::measure_seq()");
758 throw exception::MatrixNotSquareNorCvector(
"qpp::measure_seq()");
761 if (!internal::check_subsys_match_dims(target, dims))
762 throw exception::SubsysMismatchDims(
"qpp::measure_seq()");
765 std::vector<idx> result;
770 std::sort(std::begin(target), std::end(target), std::greater<idx>{});
773 while (target.size() > 0) {
774 auto tmp = measure(rA, Gates::get_instance().Id(dims[target[0]]),
775 {target[0]}, dims, destructive);
776 result.emplace_back(std::get<0>(tmp));
777 prob *= std::get<1>(tmp)[std::get<0>(tmp)];
778 rA = std::get<2>(tmp)[std::get<0>(tmp)];
782 dims.erase(std::next(std::begin(dims), target[0]));
784 target.erase(std::begin(target));
787 std::reverse(std::begin(result), std::end(result));
789 return std::make_tuple(result, prob, rA);
809 template <
typename Derived>
810 std::tuple<std::vector<idx>, double, cmat>
811 measure_seq(
const Eigen::MatrixBase<Derived>& A, std::vector<idx> target,
812 idx d = 2,
bool destructive =
true) {
813 const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA = A.derived();
818 if (!internal::check_nonzero_size(rA))
819 throw exception::ZeroSize(
"qpp::measure_seq()");
823 throw exception::DimsInvalid(
"qpp::measure_seq()");
826 idx n = internal::get_num_subsys(static_cast<idx>(rA.rows()), d);
827 std::vector<idx> dims(n, d);
829 return measure_seq(rA, target, dims, destructive);
843 template <
typename Derived>
844 dyn_mat<typename Derived::Scalar> reset(
const Eigen::MatrixBase<Derived>& A,
845 std::vector<idx> target,
846 std::vector<idx> dims) {
847 const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA = A.derived();
852 if (!internal::check_nonzero_size(rA))
853 throw exception::ZeroSize(
"qpp::reset()");
856 if (!internal::check_dims(dims))
857 throw exception::DimsInvalid(
"qpp::reset()");
860 if (internal::check_cvector(rA)) {
861 if (!internal::check_dims_match_cvect(dims, rA))
862 throw exception::DimsMismatchCvector(
"qpp::reset()");
863 }
else if (internal::check_square_mat(rA)) {
864 if (!internal::check_dims_match_mat(dims, rA))
865 throw exception::DimsMismatchMatrix(
"qpp::reset()");
867 throw exception::MatrixNotSquareNorCvector(
"qpp::reset()");
870 if (!internal::check_subsys_match_dims(target, dims))
871 throw exception::SubsysMismatchDims(
"qpp::reset()");
874 dyn_mat<typename Derived::Scalar> result;
875 std::vector<idx> resZ;
877 std::tie(resZ, std::ignore, result) = measure_seq(rA, target, dims,
false);
878 for (idx i = 0; i < target.size(); ++i) {
880 powm(Gates::get_instance().Xd(dims[i]), dims[i] - resZ[i]);
881 result = apply(result, correction, {target[i]}, dims);
898 template <
typename Derived>
899 dyn_mat<typename Derived::Scalar> reset(
const Eigen::MatrixBase<Derived>& A,
900 std::vector<idx> target, idx d = 2) {
901 const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA = A.derived();
906 if (!internal::check_nonzero_size(rA))
907 throw exception::ZeroSize(
"qpp::reset()");
911 throw exception::DimsInvalid(
"qpp::reset()");
914 idx n = internal::get_num_subsys(static_cast<idx>(rA.rows()), d);
915 std::vector<idx> dims(n, d);
917 return reset(rA, target, dims);
930 template <
typename Derived>
931 dyn_mat<typename Derived::Scalar> discard(
const Eigen::MatrixBase<Derived>& A,
932 std::vector<idx> target,
933 std::vector<idx> dims) {
934 const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA = A.derived();
939 if (!internal::check_nonzero_size(rA))
940 throw exception::ZeroSize(
"qpp::discard()");
943 if (!internal::check_dims(dims))
944 throw exception::DimsInvalid(
"qpp::discard()");
947 if (internal::check_cvector(rA)) {
948 if (!internal::check_dims_match_cvect(dims, rA))
949 throw exception::DimsMismatchCvector(
"qpp::discard()");
950 }
else if (internal::check_square_mat(rA)) {
951 if (!internal::check_dims_match_mat(dims, rA))
952 throw exception::DimsMismatchMatrix(
"qpp::discard()");
954 throw exception::MatrixNotSquareNorCvector(
"qpp::discard()");
957 if (!internal::check_subsys_match_dims(target, dims))
958 throw exception::SubsysMismatchDims(
"qpp::discard()");
961 dyn_mat<typename Derived::Scalar> result;
962 std::tie(std::ignore, std::ignore, result) = measure_seq(rA, target, dims);
977 template <
typename Derived>
978 dyn_mat<typename Derived::Scalar> discard(
const Eigen::MatrixBase<Derived>& A,
979 std::vector<idx> target, idx d = 2) {
980 const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA = A.derived();
985 if (!internal::check_nonzero_size(rA))
986 throw exception::ZeroSize(
"qpp::discard()");
990 throw exception::DimsInvalid(
"qpp::discard()");
993 idx n = internal::get_num_subsys(static_cast<idx>(rA.rows()), d);
994 std::vector<idx> dims(n, d);
996 return discard(rA, target, dims);
Quantum++ main namespace.
Definition: circuits.h:35