27 #ifndef INSTRUMENTS_H_
28 #define INSTRUMENTS_H_
43 template<
typename Derived>
44 std::tuple<idx, std::vector < double>, std::vector<cmat>>
46 measure(
const Eigen::MatrixBase<Derived>& A,
const std::vector <cmat>& Ks)
60 if (Ks[0].rows() != rA.rows())
64 if (it.rows() != Ks[0].rows() || it.cols() != Ks[0].rows())
69 std::vector <double> prob(Ks.size());
71 std::vector <cmat> outstates(Ks.size());
76 for (
idx i = 0; i < Ks.size(); ++i)
78 outstates[i] = cmat::Zero(rA.rows(), rA.rows());
80 prob[i] = std::abs(
trace(tmp));
82 outstates[i] = tmp / prob[i];
88 for (
idx i = 0; i < Ks.size(); ++i)
90 outstates[i] = ket::Zero(rA.rows());
93 prob[i] = std::pow(
norm(tmp), 2);
95 outstates[i] = tmp / std::sqrt(prob[i]);
103 std::discrete_distribution<idx> dd(std::begin(prob),
107 return std::make_tuple(result, prob, outstates);
122 template<
typename Derived>
123 std::tuple<idx, std::vector < double>, std::vector<cmat>>
126 const std::initializer_list<cmat>& Ks)
128 return measure(A, std::vector<cmat>(Ks));
141 template<
typename Derived>
142 std::tuple<idx, std::vector < double>, std::vector<cmat>>
158 if (U.rows() != rA.rows())
163 std::vector <cmat> Ks(U.rows());
164 for (
idx i = 0; i < static_cast<idx>(U.rows()); i++)
165 Ks[i] = U.col(i) *
adjoint(U.col(i));
188 template<
typename Derived>
189 std::tuple<idx, std::vector < double>, std::vector<cmat>>
192 const std::vector <cmat>& Ks,
193 const std::vector <idx>& subsys,
194 const std::vector <idx>& dims)
218 std::vector <idx> subsys_dims(subsys.size());
219 for (
idx i = 0; i < subsys.size(); ++i)
220 subsys_dims[i] = dims[subsys[i]];
222 idx D =
prod(std::begin(dims), std::end(dims));
223 idx Dsubsys =
prod(std::begin(subsys_dims), std::end(subsys_dims));
224 idx Dbar = D / Dsubsys;
233 if (Dsubsys != static_cast<idx>(Ks[0].rows()))
237 if (it.rows() != Ks[0].rows() || it.cols() != Ks[0].rows())
243 std::vector <double> prob(Ks.size());
245 std::vector <cmat> outstates(Ks.size());
250 for (
idx i = 0; i < Ks.size(); ++i)
252 outstates[i] = cmat::Zero(Dbar, Dbar);
253 cmat tmp =
apply(rA, Ks[i], subsys, dims);
254 tmp =
ptrace(tmp, subsys, dims);
255 prob[i] = std::abs(
trace(tmp));
260 outstates[i] = tmp / prob[i];
267 for (
idx i = 0; i < Ks.size(); ++i)
269 outstates[i] = cmat::Zero(Dbar, Dbar);
270 ket tmp =
apply(rA, Ks[i], subsys, dims);
271 prob[i] = std::pow(
norm(tmp), 2);
276 tmp /= std::sqrt(prob[i]);
277 outstates[i] =
ptrace(tmp, subsys, dims);
286 std::discrete_distribution<idx> dd(std::begin(prob),
290 return std::make_tuple(result, prob, outstates);
313 template<
typename Derived>
314 std::tuple<idx, std::vector < double>, std::vector<cmat>>
317 const std::initializer_list<cmat>& Ks,
318 const std::vector <idx>& subsys,
319 const std::vector <idx>& dims)
321 return measure(A, std::vector<cmat>(Ks), subsys, dims);
341 template<
typename Derived>
342 std::tuple<idx, std::vector < double>, std::vector<cmat>>
345 const std::vector <cmat>& Ks,
346 const std::vector <idx>& subsys,
356 static_cast<idx>(std::llround(std::log2(rA.rows()) /
358 std::vector <idx> dims(n, d);
360 return measure(rA, Ks, subsys, dims);
383 template<
typename Derived>
384 std::tuple<idx, std::vector < double>, std::vector<cmat>>
387 const std::initializer_list<cmat>& Ks,
388 const std::vector <idx>& subsys,
391 return measure(A, std::vector<cmat>(Ks), subsys, d);
411 template<
typename Derived>
412 std::tuple<idx, std::vector < double>, std::vector<cmat>>
416 const std::vector <idx>& subsys,
417 const std::vector <idx>& dims)
441 std::vector <idx> subsys_dims(subsys.size());
442 for (
idx i = 0; i < subsys.size(); ++i)
443 subsys_dims[i] = dims[subsys[i]];
445 idx Dsubsys =
prod(std::begin(subsys_dims), std::end(subsys_dims));
452 if (Dsubsys != static_cast<idx>(U.rows()))
457 std::vector <cmat> Ks(U.rows());
458 for (
idx i = 0; i < static_cast<idx>(U.rows()); i++)
459 Ks[i] = U.col(i) *
adjoint(U.col(i));
461 return measure(rA, Ks, subsys, dims);
481 template<
typename Derived>
482 std::tuple<idx, std::vector < double>, std::vector<cmat>>
486 const std::vector <idx>& subsys,
496 static_cast<idx>(std::llround(std::log2(rA.rows()) /
498 std::vector <idx> dims(n, d);
500 return measure(rA, U, subsys, dims);
517 template<
typename Derived>
518 std::tuple<std::vector < idx>, double,
cmat>
521 std::vector <idx> subsys,
522 std::vector <idx> dims)
548 std::vector <idx> result;
553 std::sort(std::begin(subsys), std::end(subsys), std::greater<idx>{});
558 while (subsys.size() > 0)
562 result.push_back(std::get<0>(tmp));
563 prob *= std::get<1>(tmp)[std::get<0>(tmp)];
564 cA = std::get<2>(tmp)[std::get<0>(tmp)];
567 dims.erase(std::next(std::begin(dims), subsys[0]));
568 subsys.erase(std::begin(subsys));
571 std::reverse(std::begin(result), std::end(result));
577 return std::make_tuple(result, prob, cA);
594 template<
typename Derived>
595 std::tuple<std::vector < idx>, double,
cmat>
598 std::vector <idx> subsys,
idx d = 2)
607 static_cast<idx>(std::llround(std::log2(rA.rows()) /
609 std::vector <idx> dims(n, d);
bool _check_cvector(const Eigen::MatrixBase< Derived > &A)
Definition: util.h:104
bool _check_subsys_match_dims(const std::vector< idx > &subsys, const std::vector< idx > &dims)
Definition: util.h:190
bool _check_dims_match_mat(const std::vector< idx > &dims, const Eigen::MatrixBase< Derived > &A)
Definition: util.h:142
Derived::Scalar prod(const Eigen::MatrixBase< Derived > &A)
Element-wise product of A.
Definition: functions.h:213
constexpr double eps
Used to decide whether a number or expression in double precision is zero or not. ...
Definition: constants.h:73
Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > dyn_mat
Dynamic Eigen matrix over the field specified by Scalar.
Definition: types.h:83
std::tuple< std::vector< idx >, double, cmat > measure_seq(const Eigen::MatrixBase< Derived > &A, std::vector< idx > subsys, std::vector< idx > dims)
Sequentially measures the part subsys of the multi-partite state vector or density matrix A in the co...
Definition: instruments.h:520
Eigen::VectorXcd ket
Complex (double precision) dynamic Eigen column vector.
Definition: types.h:56
dyn_mat< typename Derived1::Scalar > apply(const Eigen::MatrixBase< Derived1 > &state, const Eigen::MatrixBase< Derived2 > &A, const std::vector< idx > &subsys, const std::vector< idx > &dims)
Applies the gate A to the part subsys of the multi-partite state vector or density matrix state...
Definition: operations.h:412
Quantum++ main namespace.
Definition: codes.h:30
double norm(const Eigen::MatrixBase< Derived > &A)
Frobenius norm.
Definition: functions.h:231
bool _check_square_mat(const Eigen::MatrixBase< Derived > &A)
Definition: util.h:77
dyn_mat< typename Derived::Scalar > adjoint(const Eigen::MatrixBase< Derived > &A)
Adjoint.
Definition: functions.h:84
Generates custom exceptions, used when validating function parameters.
Definition: exception.h:39
bool _check_nonzero_size(const T &x) noexcept
Definition: util.h:113
dyn_mat< typename Derived::Scalar > ptrace(const Eigen::MatrixBase< Derived > &A, const std::vector< idx > &subsys, const std::vector< idx > &dims)
Partial trace.
Definition: operations.h:1079
Derived::Scalar trace(const Eigen::MatrixBase< Derived > &A)
Trace.
Definition: functions.h:121
static RandomDevices & get_instance() noexcept(std::is_nothrow_constructible< RandomDevices >::value)
Definition: singleton.h:90
Eigen::MatrixXcd cmat
Complex (double precision) dynamic Eigen matrix.
Definition: types.h:66
std::tuple< idx, std::vector< double >, std::vector< cmat > > measure(const Eigen::MatrixBase< Derived > &A, const std::vector< cmat > &Ks)
Measures the state A using the set of Kraus operators Ks.
Definition: instruments.h:46
std::size_t idx
Non-negative integer index.
Definition: types.h:36
bool _check_dims(const std::vector< idx > &dims)
Definition: util.h:126