32 #ifndef ENTANGLEMENT_H_ 33 #define ENTANGLEMENT_H_ 47 template <
typename Derived>
48 dyn_col_vect<double> schmidtcoeffs(
const Eigen::MatrixBase<Derived>& A,
49 const std::vector<idx>& dims) {
50 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
55 if (!internal::check_nonzero_size(rA))
56 throw exception::ZeroSize(
"qpp::schmidtcoeffs()");
59 throw exception::NotBipartite(
"qpp::schmidtcoeffs()");
61 if (!internal::check_cvector(rA))
62 throw exception::MatrixNotCvector(
"qpp::schmidtcoeffs()");
64 if (!internal::check_dims_match_cvect(dims, rA))
65 throw exception::DimsMismatchCvector(
"qpp::schmidtcoeffs()");
68 return svals(transpose(reshape(rA, dims[1], dims[0])));
82 template <
typename Derived>
83 dyn_col_vect<double> schmidtcoeffs(
const Eigen::MatrixBase<Derived>& A,
85 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
90 if (!internal::check_nonzero_size(A))
91 throw exception::ZeroSize(
"qpp::schmidtcoeffs()");
95 throw exception::DimsInvalid(
"qpp::schmidtcoeffs()");
98 idx n = internal::get_num_subsys(static_cast<idx>(rA.rows()), d);
99 std::vector<idx> dims(n, d);
101 return schmidtcoeffs(A, dims);
112 template <
typename Derived>
113 cmat schmidtA(
const Eigen::MatrixBase<Derived>& A,
114 const std::vector<idx>& dims) {
115 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
120 if (!internal::check_nonzero_size(rA))
121 throw exception::ZeroSize(
"qpp::schmidtA()");
123 if (dims.size() != 2)
124 throw exception::NotBipartite(
"qpp::schmidtA()");
126 if (!internal::check_cvector(rA))
127 throw exception::MatrixNotCvector(
"qpp::schmidtA()");
129 if (!internal::check_dims_match_cvect(dims, rA))
130 throw exception::DimsMismatchCvector(
"qpp::schmidtA()");
133 return svdU(transpose(reshape(rA, dims[1], dims[0])));
144 template <
typename Derived>
145 cmat schmidtA(
const Eigen::MatrixBase<Derived>& A, idx d = 2) {
146 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
151 if (!internal::check_nonzero_size(A))
152 throw exception::ZeroSize(
"qpp::schmidtA()");
156 throw exception::DimsInvalid(
"qpp::schmidtA()");
159 idx n = internal::get_num_subsys(static_cast<idx>(rA.rows()), d);
160 std::vector<idx> dims(n, d);
162 return schmidtA(A, dims);
173 template <
typename Derived>
174 cmat schmidtB(
const Eigen::MatrixBase<Derived>& A,
175 const std::vector<idx>& dims) {
176 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
181 if (!internal::check_nonzero_size(rA))
182 throw exception::ZeroSize(
"qpp::schmidtB()");
184 if (dims.size() != 2)
185 throw exception::NotBipartite(
"qpp::schmidtB()");
187 if (!internal::check_cvector(rA))
188 throw exception::MatrixNotCvector(
"qpp::schmidtB()");
190 if (!internal::check_dims_match_cvect(dims, rA))
191 throw exception::DimsMismatchCvector(
"qpp::schmidtB()");
196 return svdV(transpose(reshape(conjugate(rA), dims[1], dims[0])));
207 template <
typename Derived>
208 cmat schmidtB(
const Eigen::MatrixBase<Derived>& A, idx d = 2) {
209 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
214 if (!internal::check_nonzero_size(A))
215 throw exception::ZeroSize(
"qpp::schmidtB()");
219 throw exception::DimsInvalid(
"qpp::schmidtB()");
222 idx n = internal::get_num_subsys(static_cast<idx>(rA.rows()), d);
223 std::vector<idx> dims(n, d);
225 return schmidtB(A, dims);
240 template <
typename Derived>
241 std::vector<double> schmidtprobs(
const Eigen::MatrixBase<Derived>& A,
242 const std::vector<idx>& dims) {
243 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
248 if (!internal::check_nonzero_size(rA))
249 throw exception::ZeroSize(
"qpp::schmidtprobs()");
251 if (dims.size() != 2)
252 throw exception::NotBipartite(
"qpp::schmidtprobs()");
254 if (!internal::check_cvector(rA))
255 throw exception::MatrixNotCvector(
"qpp::schmidtprobs()");
257 if (!internal::check_dims_match_cvect(dims, rA))
258 throw exception::DimsMismatchCvector(
"qpp::schmidtprobs()");
261 std::vector<double> result;
262 dyn_col_vect<double> scf = schmidtcoeffs(rA, dims);
263 for (idx i = 0; i < static_cast<idx>(scf.rows()); ++i)
264 result.emplace_back(std::pow(scf(i), 2));
281 template <
typename Derived>
282 std::vector<double> schmidtprobs(
const Eigen::MatrixBase<Derived>& A,
284 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
289 if (!internal::check_nonzero_size(A))
290 throw exception::ZeroSize(
"qpp::schmidtprobs()");
294 throw exception::DimsInvalid(
"qpp::schmidtprobs()");
297 idx n = internal::get_num_subsys(static_cast<idx>(rA.rows()), d);
298 std::vector<idx> dims(n, d);
300 return schmidtprobs(A, dims);
314 template <
typename Derived>
315 double entanglement(
const Eigen::MatrixBase<Derived>& A,
316 const std::vector<idx>& dims) {
317 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
322 if (!internal::check_nonzero_size(rA))
323 throw exception::ZeroSize(
"qpp::entanglement()");
325 if (dims.size() != 2)
326 throw exception::NotBipartite(
"qpp::entanglement()");
328 if (!internal::check_cvector(rA))
329 throw exception::MatrixNotCvector(
"qpp::entanglement()");
331 if (!internal::check_dims_match_cvect(dims, rA))
332 throw exception::DimsMismatchCvector(
"qpp::entanglement()");
335 return entropy(schmidtprobs(rA, dims));
349 template <
typename Derived>
350 double entanglement(
const Eigen::MatrixBase<Derived>& A, idx d = 2) {
351 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
356 if (!internal::check_nonzero_size(A))
357 throw exception::ZeroSize(
"qpp::entanglement()");
361 throw exception::DimsInvalid(
"qpp::entanglement()");
364 idx n = internal::get_num_subsys(static_cast<idx>(rA.rows()), d);
365 std::vector<idx> dims(n, d);
367 return entanglement(A, dims);
382 template <
typename Derived>
383 double gconcurrence(
const Eigen::MatrixBase<Derived>& A) {
384 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
389 if (!internal::check_nonzero_size(rA))
390 throw exception::ZeroSize(
"qpp::gconcurrence()");
392 if (!internal::check_cvector(rA))
393 throw exception::MatrixNotCvector(
"qpp::gconcurrence()");
395 idx d = internal::get_dim_subsys(static_cast<idx>(rA.rows()), 2);
398 if (d * d != static_cast<idx>(rA.rows()))
399 throw exception::DimsNotEqual(
"qpp::gconcurrence()");
403 return d * std::abs(std::exp(2. / d * logdet(reshape(rA, d, d))));
413 template <
typename Derived>
414 double negativity(
const Eigen::MatrixBase<Derived>& A,
415 const std::vector<idx>& dims) {
416 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
421 if (!internal::check_nonzero_size(rA))
422 throw exception::ZeroSize(
"qpp::negativity()");
424 if (dims.size() != 2)
425 throw exception::NotBipartite(
"qpp::negativity()");
427 if (!internal::check_square_mat(rA))
428 throw exception::MatrixNotSquare(
"qpp::negativity()");
430 if (!internal::check_dims_match_mat(dims, rA))
431 throw exception::DimsMismatchMatrix(
"qpp::negativity()");
434 return (schatten(ptranspose(rA, {0}, dims), 1) - 1.) / 2.;
444 template <
typename Derived>
445 double negativity(
const Eigen::MatrixBase<Derived>& A, idx d = 2) {
446 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
451 if (!internal::check_nonzero_size(A))
452 throw exception::ZeroSize(
"qpp::negativity()");
456 throw exception::DimsInvalid(
"qpp::negativity()");
459 idx n = internal::get_num_subsys(static_cast<idx>(rA.rows()), d);
460 std::vector<idx> dims(n, d);
462 return negativity(A, dims);
472 template <
typename Derived>
473 double lognegativity(
const Eigen::MatrixBase<Derived>& A,
474 const std::vector<idx>& dims) {
475 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
480 if (!internal::check_nonzero_size(rA))
481 throw exception::ZeroSize(
"qpp::lognegativity()");
483 if (dims.size() != 2)
484 throw exception::NotBipartite(
"qpp::lognegativity()");
486 if (!internal::check_square_mat(rA))
487 throw exception::MatrixNotSquare(
"qpp::lognegativity()");
489 if (!internal::check_dims_match_mat(dims, rA))
490 throw exception::DimsMismatchMatrix(
"qpp::lognegativity()");
493 return std::log2(2 * negativity(rA, dims) + 1);
503 template <
typename Derived>
504 double lognegativity(
const Eigen::MatrixBase<Derived>& A, idx d = 2) {
505 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
510 if (!internal::check_nonzero_size(A))
511 throw exception::ZeroSize(
"qpp::lognegativity()");
515 throw exception::DimsInvalid(
"qpp::lognegativity()");
518 idx n = internal::get_num_subsys(static_cast<idx>(rA.rows()), d);
519 std::vector<idx> dims(n, d);
521 return lognegativity(A, dims);
530 template <
typename Derived>
531 double concurrence(
const Eigen::MatrixBase<Derived>& A) {
532 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
537 if (!internal::check_nonzero_size(rA))
538 throw exception::ZeroSize(
"qpp::concurrence()");
540 if (!internal::check_square_mat(rA))
541 throw exception::MatrixNotSquare(
"qpp::concurrence()");
544 throw exception::NotQubitSubsys(
"qpp::concurrence()");
547 cmat sigmaY = Gates::get_instance().Y;
548 dyn_col_vect<double> lambdas =
549 evals(rA * kron(sigmaY, sigmaY) * conjugate(rA) * kron(sigmaY, sigmaY))
552 std::vector<double> lambdas_sorted(lambdas.data(),
553 lambdas.data() + lambdas.size());
555 std::sort(std::begin(lambdas_sorted), std::end(lambdas_sorted),
556 std::greater<double>());
557 std::transform(std::begin(lambdas_sorted), std::end(lambdas_sorted),
558 std::begin(lambdas_sorted), [](
double elem) {
559 return std::sqrt(std::abs(elem));
562 return std::max(0., lambdas_sorted[0] - lambdas_sorted[1] -
563 lambdas_sorted[2] - lambdas_sorted[3]);
Quantum++ main namespace.
Definition: circuits.h:35