Quantum++  v0.8.6
C++11 quantum computing library
instruments.h
Go to the documentation of this file.
1 /*
2  * Quantum++
3  *
4  * Copyright (c) 2013 - 2016 Vlad Gheorghiu (vgheorgh@gmail.com)
5  *
6  * This file is part of Quantum++.
7  *
8  * Quantum++ is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * Quantum++ is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with Quantum++. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
27 #ifndef INSTRUMENTS_H_
28 #define INSTRUMENTS_H_
29 
30 // instruments
31 namespace qpp
32 {
43 template<typename Derived>
45  const Eigen::MatrixBase<Derived>& phi,
46  const Eigen::MatrixBase<Derived>& psi,
47  const std::vector<idx>& subsys,
48  const std::vector<idx>& dims)
49 {
52 
53  // EXCEPTION CHECKS
54 
55  // check zero-size
57  throw Exception("qpp::ip()", Exception::Type::ZERO_SIZE);
58 
59  // check zero-size
61  throw Exception("qpp::ip()", Exception::Type::ZERO_SIZE);
62 
63  // check column vector
64  if (!internal::_check_cvector(rphi))
65  throw Exception("qpp::schmidtcoeffs()",
67 
68  // check column vector
69  if (!internal::_check_cvector(rpsi))
70  throw Exception("qpp::schmidtcoeffs()",
72 
73  // check that dims is a valid dimension vector
74  if (!internal::_check_dims(dims))
75  throw Exception("qpp::ip()", Exception::Type::DIMS_INVALID);
76 
77  // check that subsys are valid
78  if (!internal::_check_subsys_match_dims(subsys, dims))
79  throw Exception("qpp::ip()",
81 
82  // check that dims match state vector psi
83  if (!internal::_check_dims_match_cvect(dims, rpsi))
84  throw Exception("qpp::ip()",
86 
87  // check that subsys match state vector phi
88  std::vector<idx> subsys_dims(subsys.size());
89  for (idx i = 0; i < subsys.size(); ++i)
90  subsys_dims[i] = dims[subsys[i]];
91  if (!internal::_check_dims_match_cvect(subsys_dims, rphi))
92  throw Exception("qpp::ip()",
94  // END EXCEPTION CHECKS
95 
96  idx Dsubsys = prod(std::begin(subsys_dims), std::end(subsys_dims));
97 
98  idx D = static_cast<idx>(rpsi.rows());
99  idx Dsubsysbar = D / Dsubsys;
100 
101  idx n = dims.size();
102  idx nsubsys = subsys.size();
103  idx nsubsysbar = n - nsubsys;
104 
105  idx Cdims[maxn];
106  idx Csubsys[maxn];
107  idx Cdimssubsys[maxn];
108  idx Csubsysbar[maxn];
109  idx Cdimssubsysbar[maxn];
110 
111  std::vector<idx> subsys_bar = complement(subsys, n);
112  std::copy(std::begin(subsys_bar), std::end(subsys_bar),
113  std::begin(Csubsysbar));
114 
115  for (idx i = 0; i < n; ++i)
116  {
117  Cdims[i] = dims[i];
118  }
119  for (idx i = 0; i < nsubsys; ++i)
120  {
121  Csubsys[i] = subsys[i];
122  Cdimssubsys[i] = dims[subsys[i]];
123  }
124  for (idx i = 0; i < nsubsysbar; ++i)
125  {
126  Cdimssubsysbar[i] = dims[subsys_bar[i]];
127  }
128 
129  auto worker = [=](idx b) noexcept
130  -> typename Derived::Scalar
131  {
132  idx Cmidxrow[maxn];
133  idx Cmidxrowsubsys[maxn];
134  idx Cmidxcolsubsysbar[maxn];
135 
136  /* get the col multi-indexes of the complement */
137  internal::_n2multiidx(b, nsubsysbar,
138  Cdimssubsysbar, Cmidxcolsubsysbar);
139  /* write it in the global row multi-index */
140  for (idx k = 0; k < nsubsysbar; ++k)
141  {
142  Cmidxrow[Csubsysbar[k]] = Cmidxcolsubsysbar[k];
143  }
144 
145  typename Derived::Scalar result = 0;
146  for (idx a = 0; a < Dsubsys; ++a)
147  {
148  /* get the row multi-indexes of the subsys */
149  internal::_n2multiidx(a, nsubsys,
150  Cdimssubsys, Cmidxrowsubsys);
151  /* write it in the global row multi-index */
152  for (idx k = 0; k < nsubsys; ++k)
153  {
154  Cmidxrow[Csubsys[k]] = Cmidxrowsubsys[k];
155  }
156  // compute the row index
157  idx i = internal::_multiidx2n(Cmidxrow, n, Cdims);
158 
159  result += std::conj(rphi(a)) * rpsi(i);
160  }
161 
162  return result;
163  }; /* end worker */
164 
165  dyn_col_vect<typename Derived::Scalar> result(Dsubsysbar);
166 #pragma omp parallel for
167  for (idx m = 0; m < Dsubsysbar; ++m)
168  result(m) = worker(m);
169 
170  return result;
171 }
172 
183 template<typename Derived>
185  const Eigen::MatrixBase<Derived>& phi,
186  const Eigen::MatrixBase<Derived>& psi,
187  const std::vector<idx>& subsys,
188  idx d = 2)
189 {
190  const dyn_col_vect<typename Derived::Scalar>& rphi = phi;
191  const dyn_col_vect<typename Derived::Scalar>& rpsi = psi;
192 
193  // EXCEPTION CHECKS
194 
196  throw Exception("qpp::ip()", Exception::Type::ZERO_SIZE);
197 
198  // check valid dims
199  if (d == 0)
200  throw Exception("qpp::ip()", Exception::Type::DIMS_INVALID);
201  // END EXCEPTION CHECKS
202 
203  idx n =
204  static_cast<idx>(std::llround(std::log2(rpsi.rows()) /
205  std::log2(d)));
206  std::vector<idx> dims(n, d); // local dimensions vector
207  return ip(phi, psi, subsys, dims);
208 }
209 
210 // full measurements
220 template<typename Derived>
221 std::tuple<idx, std::vector<double>, std::vector<cmat>>
222 measure(const Eigen::MatrixBase<Derived>& A, const std::vector<cmat>& Ks)
223 {
224  const dyn_mat<typename Derived::Scalar>& rA = A;
225 
226  // EXCEPTION CHECKS
227 
228  // check zero-size
230  throw Exception("qpp::measure()", Exception::Type::ZERO_SIZE);
231 
232  // check the Kraus operators
233  if (Ks.size() == 0)
234  throw Exception("qpp::measure()", Exception::Type::ZERO_SIZE);
235  if (!internal::_check_square_mat(Ks[0]))
236  throw Exception("qpp::measure()", Exception::Type::MATRIX_NOT_SQUARE);
237  if (Ks[0].rows() != rA.rows())
238  throw Exception("qpp::measure()",
240  for (auto&& it : Ks)
241  if (it.rows() != Ks[0].rows() || it.cols() != Ks[0].rows())
242  throw Exception("qpp::measure()", Exception::Type::DIMS_NOT_EQUAL);
243  // END EXCEPTION CHECKS
244 
245  // probabilities
246  std::vector<double> prob(Ks.size());
247  // resulting states
248  std::vector<cmat> outstates(Ks.size());
249 
250  //************ density matrix ************//
251  if (internal::_check_square_mat(rA)) // square matrix
252  {
253  for (idx i = 0; i < Ks.size(); ++i)
254  {
255  outstates[i] = cmat::Zero(rA.rows(), rA.rows());
256  cmat tmp = Ks[i] * rA * adjoint(Ks[i]); // un-normalized;
257  prob[i] = std::abs(trace(tmp)); // probability
258  if (prob[i] > eps)
259  outstates[i] = tmp / prob[i]; // normalized
260  }
261  }
262  //************ ket ************//
263  else if (internal::_check_cvector(rA)) // column vector
264  {
265  for (idx i = 0; i < Ks.size(); ++i)
266  {
267  outstates[i] = ket::Zero(rA.rows());
268  ket tmp = Ks[i] * rA; // un-normalized;
269  // probability
270  prob[i] = std::pow(norm(tmp), 2);
271  if (prob[i] > eps)
272  outstates[i] = tmp / std::sqrt(prob[i]); // normalized
273  }
274  }
275  else
276  throw Exception("qpp::measure()",
278 
279  // sample from the probability distribution
280  std::discrete_distribution<idx> dd(std::begin(prob),
281  std::end(prob));
282  idx result = dd(RandomDevices::get_instance()._rng);
283 
284  return std::make_tuple(result, prob, outstates);
285 }
286 
287 // std::initializer_list overload, avoids ambiguity for 2-element lists, see
288 // http://stackoverflow.com
289 // /questions/26750039/ambiguity-when-using-initializer-list-as-parameter
299 template<typename Derived>
300 std::tuple<idx, std::vector<double>, std::vector<cmat>>
301 measure(const Eigen::MatrixBase<Derived>& A,
302  const std::initializer_list<cmat>& Ks)
303 {
304  return measure(A, std::vector<cmat>(Ks));
305 }
306 
317 template<typename Derived>
318 std::tuple<idx, std::vector<double>, std::vector<cmat>>
319 measure(const Eigen::MatrixBase<Derived>& A, const cmat& U)
320 {
321  const dyn_mat<typename Derived::Scalar>& rA = A;
322 
323  // EXCEPTION CHECKS
324 
325  // check zero-size
327  throw Exception("qpp::measure()", Exception::Type::ZERO_SIZE);
328 
329  // check the unitary basis matrix U
331  throw Exception("qpp::measure()", Exception::Type::ZERO_SIZE);
333  throw Exception("qpp::measure()", Exception::Type::MATRIX_NOT_SQUARE);
334  if (U.rows() != rA.rows())
335  throw Exception("qpp::measure()",
337  // END EXCEPTION CHECKS
338 
339  std::vector<cmat> Ks(U.rows());
340  for (idx i = 0; i < static_cast<idx>(U.rows()); ++i)
341  Ks[i] = U.col(i) * adjoint(U.col(i));
342 
343  return measure(rA, Ks);
344 }
345 
346 // partial measurements
364 template<typename Derived>
365 std::tuple<idx, std::vector<double>, std::vector<cmat>>
366 measure(const Eigen::MatrixBase<Derived>& A,
367  const std::vector<cmat>& Ks,
368  const std::vector<idx>& subsys,
369  const std::vector<idx>& dims)
370 {
371  const cmat& rA = A;
372 
373  // EXCEPTION CHECKS
374 
375  // check zero-size
377  throw Exception("qpp::measure()", Exception::Type::ZERO_SIZE);
378 
379  // check that dimension is valid
380  if (!internal::_check_dims(dims))
381  throw Exception("qpp::measure()", Exception::Type::DIMS_INVALID);
382 
383  // check that dims match rho matrix
384  if (!internal::_check_dims_match_mat(dims, rA))
385  throw Exception("qpp::measure()",
387 
388  // check subsys is valid w.r.t. dims
389  if (!internal::_check_subsys_match_dims(subsys, dims))
390  throw Exception("qpp::measure()",
392 
393  std::vector<idx> subsys_dims(subsys.size());
394  for (idx i = 0; i < subsys.size(); ++i)
395  subsys_dims[i] = dims[subsys[i]];
396 
397  idx D = prod(std::begin(dims), std::end(dims));
398  idx Dsubsys = prod(std::begin(subsys_dims), std::end(subsys_dims));
399  idx Dsubsysbar = D / Dsubsys;
400 
401  // check the Kraus operators
402  if (Ks.size() == 0)
403  throw Exception("qpp::measure()",
405  if (!internal::_check_square_mat(Ks[0]))
406  throw Exception("qpp::measure()",
408  if (Dsubsys != static_cast<idx>(Ks[0].rows()))
409  throw Exception("qpp::measure()",
411  for (auto&& it : Ks)
412  if (it.rows() != Ks[0].rows() || it.cols() != Ks[0].rows())
413  throw Exception("qpp::measure()",
415  // END EXCEPTION CHECKS
416 
417  // probabilities
418  std::vector<double> prob(Ks.size());
419  // resulting states
420  std::vector<cmat> outstates(Ks.size(), cmat::Zero(Dsubsysbar, Dsubsysbar));
421 
422  //************ density matrix ************//
423  if (internal::_check_square_mat(rA)) // square matrix
424  {
425  for (idx i = 0; i < Ks.size(); ++i)
426  {
427  cmat tmp = apply(rA, Ks[i], subsys, dims);
428  tmp = ptrace(tmp, subsys, dims);
429  prob[i] = std::abs(trace(tmp)); // probability
430  if (prob[i] > eps)
431  {
432  // normalized output state
433  // corresponding to measurement result i
434  outstates[i] = tmp / prob[i];
435  }
436  }
437  }
438  //************ ket ************//
439  else if (internal::_check_cvector(rA)) // column vector
440  {
441  for (idx i = 0; i < Ks.size(); ++i)
442  {
443  ket tmp = apply(rA, Ks[i], subsys, dims);
444  prob[i] = std::pow(norm(tmp), 2);
445  if (prob[i] > eps)
446  {
447  // normalized output state
448  // corresponding to measurement result i
449  tmp /= std::sqrt(prob[i]);
450  outstates[i] = ptrace(tmp, subsys, dims);
451  }
452  }
453  }
454  else
455  throw Exception("qpp::measure()",
457 
458  // sample from the probability distribution
459  std::discrete_distribution<idx> dd(std::begin(prob),
460  std::end(prob));
461  idx result = dd(RandomDevices::get_instance()._rng);
462 
463  return std::make_tuple(result, prob, outstates);
464 }
465 
466 // std::initializer_list overload, avoids ambiguity for 2-element lists, see
467 // http://stackoverflow.com
468 // /questions/26750039/ambiguity-when-using-initializer-list-as-parameter
486 template<typename Derived>
487 std::tuple<idx, std::vector<double>, std::vector<cmat>>
488 measure(const Eigen::MatrixBase<Derived>& A,
489  const std::initializer_list<cmat>& Ks,
490  const std::vector<idx>& subsys,
491  const std::vector<idx>& dims)
492 {
493  return measure(A, std::vector<cmat>(Ks), subsys, dims);
494 }
495 
513 template<typename Derived>
514 std::tuple<idx, std::vector<double>, std::vector<cmat>>
515 measure(const Eigen::MatrixBase<Derived>& A,
516  const std::vector<cmat>& Ks,
517  const std::vector<idx>& subsys,
518  idx d = 2)
519 {
520  const cmat& rA = A;
521 
522  // EXCEPTION CHECKS
523 
524  // check zero size
526  throw Exception("qpp::measure()", Exception::Type::ZERO_SIZE);
527 
528  // check valid dims
529  if (d == 0)
530  throw Exception("qpp::measure()", Exception::Type::DIMS_INVALID);
531  // END EXCEPTION CHECKS
532 
533  idx n =
534  static_cast<idx>(std::llround(std::log2(rA.rows()) /
535  std::log2(d)));
536  std::vector<idx> dims(n, d); // local dimensions vector
537 
538  return measure(rA, Ks, subsys, dims);
539 }
540 
541 // std::initializer_list overload, avoids ambiguity for 2-element lists, see
542 // http://stackoverflow.com
543 // /questions/26750039/ambiguity-when-using-initializer-list-as-parameter
561 template<typename Derived>
562 std::tuple<idx, std::vector<double>, std::vector<cmat>>
563 measure(const Eigen::MatrixBase<Derived>& A,
564  const std::initializer_list<cmat>& Ks,
565  const std::vector<idx>& subsys,
566  idx d = 2)
567 {
568  return measure(A, std::vector<cmat>(Ks), subsys, d);
569 }
570 
589 template<typename Derived>
590 std::tuple<idx, std::vector<double>, std::vector<cmat>>
591 
592 measure(const Eigen::MatrixBase<Derived>& A,
593  const cmat& V,
594  const std::vector<idx>& subsys,
595  const std::vector<idx>& dims)
596 {
597  const cmat& rA = A;
598 
599  // EXCEPTION CHECKS
600 
601  // check zero-size
603  throw Exception("qpp::measure()", Exception::Type::ZERO_SIZE);
604 
605  // check that dimension is valid
606  if (!internal::_check_dims(dims))
607  throw Exception("qpp::measure()", Exception::Type::DIMS_INVALID);
608 
609  // check subsys is valid w.r.t. dims
610  if (!internal::_check_subsys_match_dims(subsys, dims))
611  throw Exception("qpp::measure()",
613 
614  std::vector<idx> subsys_dims(subsys.size());
615  for (idx i = 0; i < subsys.size(); ++i)
616  subsys_dims[i] = dims[subsys[i]];
617 
618  idx Dsubsys = prod(std::begin(subsys_dims), std::end(subsys_dims));
619 
620  // check the matrix V
622  throw Exception("qpp::measure()", Exception::Type::ZERO_SIZE);
623 // if (!internal::_check_square_mat(U))
624 // throw Exception("qpp::measure()", Exception::Type::MATRIX_NOT_SQUARE);
625  if (Dsubsys != static_cast<idx>(V.rows()))
626  throw Exception("qpp::measure()",
628  // END EXCEPTION CHECKS
629 
630  // number of basis (rank-1 POVM) elements
631  idx M = static_cast<idx>(V.cols());
632 
633  //************ ket ************//
634  if (internal::_check_cvector(rA))
635  {
636  const ket& rpsi = A;
637  // check that dims match state vector
638  if (!internal::_check_dims_match_cvect(dims, rA))
639  throw Exception("qpp::measure()",
641 
642  std::vector<double> prob(M); // probabilities
643  std::vector<cmat> outstates(M); // resulting states
644 
645 #pragma omp parallel for
646  for (idx i = 0; i < M; ++i)
647  outstates[i] = ip(static_cast<const ket&>(V.col(i)),
648  rpsi, subsys, dims);
649 
650  for (idx i = 0; i < M; ++i)
651  {
652  double tmp = norm(outstates[i]);
653  prob[i] = tmp * tmp;
654  if (prob[i] > eps)
655  {
656  // normalized output state
657  // corresponding to measurement result m
658  outstates[i] /= tmp;
659  }
660  }
661 
662  // sample from the probability distribution
663  std::discrete_distribution<idx> dd(std::begin(prob),
664  std::end(prob));
665  idx result = dd(RandomDevices::get_instance()._rng);
666 
667  return std::make_tuple(result, prob, outstates);
668  }
669  //************ density matrix ************//
670  else if (internal::_check_square_mat(rA))
671  {
672  // check that dims match rho matrix
673  if (!internal::_check_dims_match_mat(dims, rA))
674  throw Exception("qpp::measure()",
676 
677  std::vector<cmat> Ks(M);
678  for (idx i = 0; i < M; ++i)
679  Ks[i] = V.col(i) * adjoint(V.col(i));
680 
681  return measure(rA, Ks, subsys, dims);
682  }
683  //************ Exception: not ket nor density matrix ************//
684  throw Exception("qpp::measure()",
686 }
687 
706 template<typename Derived>
707 std::tuple<idx, std::vector<double>, std::vector<cmat>>
708 
709 measure(const Eigen::MatrixBase<Derived>& A,
710  const cmat& V,
711  const std::vector<idx>& subsys,
712  idx d = 2)
713 {
714  const cmat& rA = A;
715 
716  // EXCEPTION CHECKS
717 
718  // check zero size
720  throw Exception("qpp::measure()", Exception::Type::ZERO_SIZE);
721 
722  // check valid dims
723  if (d == 0)
724  throw Exception("qpp::measure()", Exception::Type::DIMS_INVALID);
725  // END EXCEPTION CHECKS
726 
727  idx n =
728  static_cast<idx>(std::llround(std::log2(rA.rows()) /
729  std::log2(d)));
730  std::vector<idx> dims(n, d); // local dimensions vector
731 
732  return measure(rA, V, subsys, dims);
733 }
734 
749 template<typename Derived>
750 std::tuple<std::vector<idx>, double, cmat>
751 measure_seq(const Eigen::MatrixBase<Derived>& A,
752  std::vector<idx> subsys,
753  std::vector<idx> dims)
754 {
756 
757  // EXCEPTION CHECKS
758 
759  // check zero-size
761  throw Exception("qpp::measure_seq()", Exception::Type::ZERO_SIZE);
762 
763  // check that dimension is valid
764  if (!internal::_check_dims(dims))
765  throw Exception("qpp::measure_seq()", Exception::Type::DIMS_INVALID);
766 
767  // check that dims match rho matrix
768  if (!internal::_check_dims_match_mat(dims, cA))
769  throw Exception("qpp::measure_seq()",
771 
772  // check subsys is valid w.r.t. dims
773  if (!internal::_check_subsys_match_dims(subsys, dims))
774  throw Exception("qpp::measure_seq()",
776  // END EXCEPTION CHECKS
777 
778  std::vector<idx> result;
779  double prob = 1;
780 
781  // sort subsys in decreasing order,
782  // the order of measurements does not matter
783  std::sort(std::begin(subsys), std::end(subsys), std::greater<idx>{});
784 
785  //************ density matrix or column vector ************//
787  {
788  while (subsys.size() > 0)
789  {
790  auto tmp = measure(
791  cA, Gates::get_instance().Id(dims[subsys[0]]),
792  {subsys[0]}, dims
793  );
794  result.push_back(std::get<0>(tmp));
795  prob *= std::get<1>(tmp)[std::get<0>(tmp)];
796  cA = std::get<2>(tmp)[std::get<0>(tmp)];
797 
798  // remove the subsystem
799  dims.erase(std::next(std::begin(dims), subsys[0]));
800  subsys.erase(std::begin(subsys));
801  }
802  // order result in increasing order with respect to subsys
803  std::reverse(std::begin(result), std::end(result));
804  }
805  else
806  throw Exception("qpp::measure_seq()",
808 
809  return std::make_tuple(result, prob, cA);
810 }
811 
826 template<typename Derived>
827 std::tuple<std::vector<idx>, double, cmat>
828 measure_seq(const Eigen::MatrixBase<Derived>& A,
829  std::vector<idx> subsys,
830  idx d = 2)
831 {
832  const cmat& rA = A;
833 
834  // EXCEPTION CHECKS
835 
836  // check zero size
838  throw Exception("qpp::measure_seq()", Exception::Type::ZERO_SIZE);
839 
840  // check valid dims
841  if (d == 0)
842  throw Exception("qpp::measure_seq()", Exception::Type::DIMS_INVALID);
843  // END EXCEPTION CHECKS
844 
845  idx n =
846  static_cast<idx>(std::llround(std::log2(rA.rows()) /
847  std::log2(d)));
848  std::vector<idx> dims(n, d); // local dimensions vector
849 
850  return measure_seq(rA, subsys, dims);
851 }
852 
853 } /* namespace qpp */
854 
855 #endif /* INSTRUMENTS_H_ */
bool _check_cvector(const Eigen::MatrixBase< Derived > &A)
Definition: util.h:104
constexpr idx maxn
Maximum number of allowed qu(d)its (subsystems)
Definition: constants.h:80
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
bool _check_dims_match_cvect(const std::vector< idx > &dims, const Eigen::MatrixBase< Derived > &V)
Definition: util.h:155
Derived::Scalar prod(const Eigen::MatrixBase< Derived > &A)
Element-wise product of A.
Definition: functions.h:231
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
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:486
Quantum++ main namespace.
Definition: codes.h:30
double norm(const Eigen::MatrixBase< Derived > &A)
Frobenius norm.
Definition: functions.h:252
bool _check_square_mat(const Eigen::MatrixBase< Derived > &A)
Definition: util.h:77
std::vector< T > complement(std::vector< T > subsys, idx N)
Constructs the complement of a subsystem vector.
Definition: functions.h:1806
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:751
dyn_mat< typename Derived::Scalar > adjoint(const Eigen::MatrixBase< Derived > &A)
Adjoint.
Definition: functions.h:84
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:222
idx _multiidx2n(const idx *midx, idx numdims, const idx *dims) noexcept
Definition: util.h:54
Generates custom exceptions, used when validating function parameters.
Definition: exception.h:39
dyn_col_vect< typename Derived::Scalar > ip(const Eigen::MatrixBase< Derived > &phi, const Eigen::MatrixBase< Derived > &psi, const std::vector< idx > &subsys, const std::vector< idx > &dims)
Generalized inner product.
Definition: instruments.h:44
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:1186
Derived::Scalar trace(const Eigen::MatrixBase< Derived > &A)
Trace.
Definition: functions.h:127
Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > dyn_col_vect
Dynamic Eigen column vector over the field specified by Scalar.
Definition: types.h:95
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
void _n2multiidx(idx n, idx numdims, const idx *dims, idx *result) noexcept
Definition: util.h:41
std::size_t idx
Non-negative integer index.
Definition: types.h:36
bool _check_dims(const std::vector< idx > &dims)
Definition: util.h:126