42 template <
typename Derived>
43 double entropy(
const Eigen::MatrixBase<Derived>& A) {
44 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
49 if (!internal::check_nonzero_size(rA))
50 throw exception::ZeroSize(
"qpp::entropy()");
53 if (!internal::check_square_mat(rA))
54 throw exception::MatrixNotSquare(
"qpp::entropy()");
59 for (idx i = 0; i < static_cast<idx>(ev.rows()); ++i)
61 result -= ev(i) * std::log2(ev(i));
72 inline double entropy(
const std::vector<double>& prob) {
76 if (!internal::check_nonzero_size(prob))
77 throw exception::ZeroSize(
"qpp::entropy()");
81 for (idx i = 0; i < prob.size(); ++i)
82 if (std::abs(prob[i]) != 0)
83 result -= std::abs(prob[i]) * std::log2(std::abs(prob[i]));
100 template <
typename Derived>
101 double renyi(
const Eigen::MatrixBase<Derived>& A,
double alpha) {
102 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
107 if (!internal::check_nonzero_size(rA))
108 throw exception::ZeroSize(
"qpp::renyi()");
111 if (!internal::check_square_mat(rA))
112 throw exception::MatrixNotSquare(
"qpp::renyi()");
115 throw exception::OutOfRange(
"qpp::renyi()");
119 return std::log2(rA.rows());
125 return -std::log2(svals(rA)[0]);
129 for (idx i = 0; i < static_cast<idx>(sv.rows()); ++i)
131 result += std::pow(sv(i), alpha);
133 return std::log2(result) / (1 - alpha);
148 inline double renyi(
const std::vector<double>& prob,
double alpha) {
152 if (!internal::check_nonzero_size(prob))
153 throw exception::ZeroSize(
"qpp::renyi()");
156 throw exception::OutOfRange(
"qpp::renyi()");
159 return std::log2(prob.size());
162 return entropy(prob);
168 for (idx i = 0; i < prob.size(); ++i)
169 if (std::abs(prob[i]) > max)
170 max = std::abs(prob[i]);
172 return -std::log2(max);
176 for (idx i = 0; i < prob.size(); ++i)
177 if (std::abs(prob[i]) != 0)
178 result += std::pow(std::abs(prob[i]), alpha);
180 return std::log2(result) / (1 - alpha);
193 template <
typename Derived>
194 double tsallis(
const Eigen::MatrixBase<Derived>& A,
double q) {
195 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
200 if (!internal::check_nonzero_size(rA))
201 throw exception::ZeroSize(
"qpp::tsallis()");
204 if (!internal::check_square_mat(rA))
205 throw exception::MatrixNotSquare(
"qpp::tsallis()");
208 throw exception::OutOfRange(
"qpp::tsallis()");
212 return entropy(rA) * std::log(2);
216 for (idx i = 0; i < static_cast<idx>(ev.rows()); ++i)
218 result += std::pow(ev(i), q);
220 return (result - 1) / (1 - q);
234 inline double tsallis(
const std::vector<double>& prob,
double q) {
238 if (!internal::check_nonzero_size(prob))
239 throw exception::ZeroSize(
"qpp::tsallis()");
242 throw exception::OutOfRange(
"qpp::tsallis()");
246 return entropy(prob) * std::log(2);
249 for (idx i = 0; i < prob.size(); ++i)
250 if (std::abs(prob[i]) != 0)
251 result += std::pow(std::abs(prob[i]), q);
253 return (result - 1) / (1 - q);
265 template <
typename Derived>
266 double qmutualinfo(
const Eigen::MatrixBase<Derived>& A,
267 const std::vector<idx>& subsysA,
268 const std::vector<idx>& subsysB,
269 const std::vector<idx>& dims) {
270 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
275 if (!internal::check_nonzero_size(rA))
276 throw exception::ZeroSize(
"qpp::qmutualinfo()");
279 if (!internal::check_dims(dims))
280 throw exception::DimsInvalid(
"qpp::qmutualinfo()");
283 if (!internal::check_square_mat(rA))
284 throw exception::MatrixNotSquare(
"qpp::qmutualinfo()");
287 if (!internal::check_dims_match_mat(dims, rA))
288 throw exception::DimsMismatchMatrix(
"qpp::qmutualinfo()");
291 if (!internal::check_subsys_match_dims(subsysA, dims) ||
292 !internal::check_subsys_match_dims(subsysB, dims))
293 throw exception::SubsysMismatchDims(
"qpp::qmutualinfo()");
297 std::vector<idx> full_system(dims.size());
298 std::iota(std::begin(full_system), std::end(full_system), 0);
301 std::vector<idx> subsysAsorted{subsysA};
302 std::vector<idx> subsysBsorted{subsysB};
305 std::sort(std::begin(subsysAsorted), std::end(subsysAsorted));
306 std::sort(std::begin(subsysBsorted), std::end(subsysBsorted));
309 std::vector<idx> subsysAB;
310 std::set_union(std::begin(subsysAsorted), std::end(subsysAsorted),
311 std::begin(subsysBsorted), std::end(subsysBsorted),
312 std::back_inserter(subsysAB));
315 std::vector<idx> subsysA_bar = complement(subsysA, dims.size());
316 std::vector<idx> subsysB_bar = complement(subsysB, dims.size());
317 std::vector<idx> subsysAB_bar = complement(subsysAB, dims.size());
319 cmat rhoA = ptrace(rA, subsysA_bar, dims);
320 cmat rhoB = ptrace(rA, subsysB_bar, dims);
321 cmat rhoAB = ptrace(rA, subsysAB_bar, dims);
323 return entropy(rhoA) + entropy(rhoB) - entropy(rhoAB);
335 template <
typename Derived>
336 double qmutualinfo(
const Eigen::MatrixBase<Derived>& A,
337 const std::vector<idx>& subsysA,
338 const std::vector<idx>& subsysB, idx d = 2) {
339 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
344 if (!internal::check_nonzero_size(rA))
345 throw exception::ZeroSize(
"qpp::qmutualinfo()");
349 throw exception::DimsInvalid(
"qpp::qmutualinfo()");
352 idx n = internal::get_num_subsys(static_cast<idx>(rA.rows()), d);
353 std::vector<idx> dims(n, d);
355 return qmutualinfo(rA, subsysA, subsysB, dims);
Quantum++ main namespace.
Definition: circuits.h:35