Quantum++  v0.8.8
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 {
50  const dyn_col_vect<typename Derived::Scalar>& rphi = phi.derived();
51  const dyn_col_vect<typename Derived::Scalar>& rpsi = psi.derived();
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 #ifdef _WITH_OPENMP_
167 #pragma omp parallel for
168 #endif
169  for ( idx m = 0; m < Dsubsysbar; ++m )
170  result(m) = worker(m);
171 
172  return result;
173 }
174 
185 template<typename Derived>
187  const Eigen::MatrixBase<Derived>& phi,
188  const Eigen::MatrixBase<Derived>& psi,
189  const std::vector<idx>& subsys,
190  idx d = 2)
191 {
192  const dyn_col_vect<typename Derived::Scalar>& rphi = phi.derived();
193  const dyn_col_vect<typename Derived::Scalar>& rpsi = psi.derived();
194 
195  // EXCEPTION CHECKS
196 
197  if ( !internal::_check_nonzero_size(rpsi))
198  throw Exception("qpp::ip()", Exception::Type::ZERO_SIZE);
199 
200  // check valid dims
201  if ( d == 0 )
202  throw Exception("qpp::ip()", Exception::Type::DIMS_INVALID);
203  // END EXCEPTION CHECKS
204 
205  idx n =
206  static_cast<idx>(std::llround(std::log2(rpsi.rows()) /
207  std::log2(d)));
208  std::vector<idx> dims(n, d); // local dimensions vector
209  return ip(phi, psi, subsys, dims);
210 }
211 
212 // full measurements
222 template<typename Derived>
223 std::tuple<idx, std::vector<double>, std::vector<cmat>>
224 measure(const Eigen::MatrixBase<Derived>& A, const std::vector<cmat>& Ks)
225 {
226  const dyn_mat<typename Derived::Scalar>& rA = A.derived();
227 
228  // EXCEPTION CHECKS
229 
230  // check zero-size
232  throw Exception("qpp::measure()", Exception::Type::ZERO_SIZE);
233 
234  // check the Kraus operators
235  if ( Ks.size() == 0 )
236  throw Exception("qpp::measure()", Exception::Type::ZERO_SIZE);
237  if ( !internal::_check_square_mat(Ks[0]))
238  throw Exception("qpp::measure()", Exception::Type::MATRIX_NOT_SQUARE);
239  if ( Ks[0].rows() != rA.rows())
240  throw Exception("qpp::measure()",
242  for ( auto&& it : Ks )
243  if ( it.rows() != Ks[0].rows() || it.cols() != Ks[0].rows())
244  throw Exception("qpp::measure()", Exception::Type::DIMS_NOT_EQUAL);
245  // END EXCEPTION CHECKS
246 
247  // probabilities
248  std::vector<double> prob(Ks.size());
249  // resulting states
250  std::vector<cmat> outstates(Ks.size());
251 
252  //************ density matrix ************//
253  if ( internal::_check_square_mat(rA)) // square matrix
254  {
255  for ( idx i = 0; i < Ks.size(); ++i )
256  {
257  outstates[i] = cmat::Zero(rA.rows(), rA.rows());
258  cmat tmp = Ks[i] * rA * adjoint(Ks[i]); // un-normalized;
259  prob[i] = std::abs(trace(tmp)); // probability
260  if ( prob[i] > eps )
261  outstates[i] = tmp / prob[i]; // normalized
262  }
263  }
264  //************ ket ************//
265  else if ( internal::_check_cvector(rA)) // column vector
266  {
267  for ( idx i = 0; i < Ks.size(); ++i )
268  {
269  outstates[i] = ket::Zero(rA.rows());
270  ket tmp = Ks[i] * rA; // un-normalized;
271  // probability
272  prob[i] = std::pow(norm(tmp), 2);
273  if ( prob[i] > eps )
274  outstates[i] = tmp / std::sqrt(prob[i]); // normalized
275  }
276  }
277  else
278  throw Exception("qpp::measure()",
280 
281  // sample from the probability distribution
282  std::discrete_distribution<idx> dd(std::begin(prob),
283  std::end(prob));
284  idx result = dd(RandomDevices::get_instance()._rng);
285 
286  return std::make_tuple(result, prob, outstates);
287 }
288 
289 // std::initializer_list overload, avoids ambiguity for 2-element lists, see
290 // http://stackoverflow.com
291 // /questions/26750039/ambiguity-when-using-initializer-list-as-parameter
301 template<typename Derived>
302 std::tuple<idx, std::vector<double>, std::vector<cmat>>
303 measure(const Eigen::MatrixBase<Derived>& A,
304  const std::initializer_list<cmat>& Ks)
305 {
306  return measure(A, std::vector<cmat>(Ks));
307 }
308 
319 template<typename Derived>
320 std::tuple<idx, std::vector<double>, std::vector<cmat>>
321 measure(const Eigen::MatrixBase<Derived>& A, const cmat& U)
322 {
323  const dyn_mat<typename Derived::Scalar>& rA = A.derived();
324 
325  // EXCEPTION CHECKS
326 
327  // check zero-size
329  throw Exception("qpp::measure()", Exception::Type::ZERO_SIZE);
330 
331  // check the unitary basis matrix U
333  throw Exception("qpp::measure()", Exception::Type::ZERO_SIZE);
335  throw Exception("qpp::measure()", Exception::Type::MATRIX_NOT_SQUARE);
336  if ( U.rows() != rA.rows())
337  throw Exception("qpp::measure()",
339  // END EXCEPTION CHECKS
340 
341  std::vector<cmat> Ks(U.rows());
342  for ( idx i = 0; i < static_cast<idx>(U.rows()); ++i )
343  Ks[i] = U.col(i) * adjoint(U.col(i));
344 
345  return measure(rA, Ks);
346 }
347 
348 // partial measurements
366 template<typename Derived>
367 std::tuple<idx, std::vector<double>, std::vector<cmat>>
368 measure(const Eigen::MatrixBase<Derived>& A,
369  const std::vector<cmat>& Ks,
370  const std::vector<idx>& subsys,
371  const std::vector<idx>& dims)
372 {
373  const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA
374  = A.derived();
375 
376  // EXCEPTION CHECKS
377 
378  // check zero-size
380  throw Exception("qpp::measure()", Exception::Type::ZERO_SIZE);
381 
382  // check that dimension is valid
383  if ( !internal::_check_dims(dims))
384  throw Exception("qpp::measure()", Exception::Type::DIMS_INVALID);
385 
386  // check that dims match rho matrix
387  if ( !internal::_check_dims_match_mat(dims, rA))
388  throw Exception("qpp::measure()",
390 
391  // check subsys is valid w.r.t. dims
392  if ( !internal::_check_subsys_match_dims(subsys, dims))
393  throw Exception("qpp::measure()",
395 
396  std::vector<idx> subsys_dims(subsys.size());
397  for ( idx i = 0; i < subsys.size(); ++i )
398  subsys_dims[i] = dims[subsys[i]];
399 
400  idx D = prod(std::begin(dims), std::end(dims));
401  idx Dsubsys = prod(std::begin(subsys_dims), std::end(subsys_dims));
402  idx Dsubsysbar = D / Dsubsys;
403 
404  // check the Kraus operators
405  if ( Ks.size() == 0 )
406  throw Exception("qpp::measure()",
408  if ( !internal::_check_square_mat(Ks[0]))
409  throw Exception("qpp::measure()",
411  if ( Dsubsys != static_cast<idx>(Ks[0].rows()))
412  throw Exception("qpp::measure()",
414  for ( auto&& it : Ks )
415  if ( it.rows() != Ks[0].rows() || it.cols() != Ks[0].rows())
416  throw Exception("qpp::measure()",
418  // END EXCEPTION CHECKS
419 
420  // probabilities
421  std::vector<double> prob(Ks.size());
422  // resulting states
423  std::vector<cmat> outstates(Ks.size(), cmat::Zero(Dsubsysbar, Dsubsysbar));
424 
425  //************ density matrix ************//
426  if ( internal::_check_square_mat(rA)) // square matrix
427  {
428  for ( idx i = 0; i < Ks.size(); ++i )
429  {
430  cmat tmp = apply(rA, Ks[i], subsys, dims);
431  tmp = ptrace(tmp, subsys, dims);
432  prob[i] = std::abs(trace(tmp)); // probability
433  if ( prob[i] > eps )
434  {
435  // normalized output state
436  // corresponding to measurement result i
437  outstates[i] = tmp / prob[i];
438  }
439  }
440  }
441  //************ ket ************//
442  else if ( internal::_check_cvector(rA)) // column vector
443  {
444  for ( idx i = 0; i < Ks.size(); ++i )
445  {
446  ket tmp = apply(rA, Ks[i], subsys, dims);
447  prob[i] = std::pow(norm(tmp), 2);
448  if ( prob[i] > eps )
449  {
450  // normalized output state
451  // corresponding to measurement result i
452  tmp /= std::sqrt(prob[i]);
453  outstates[i] = ptrace(tmp, subsys, dims);
454  }
455  }
456  }
457  else
458  throw Exception("qpp::measure()",
460 
461  // sample from the probability distribution
462  std::discrete_distribution<idx> dd(std::begin(prob),
463  std::end(prob));
464  idx result = dd(RandomDevices::get_instance()._rng);
465 
466  return std::make_tuple(result, prob, outstates);
467 }
468 
469 // std::initializer_list overload, avoids ambiguity for 2-element lists, see
470 // http://stackoverflow.com
471 // /questions/26750039/ambiguity-when-using-initializer-list-as-parameter
489 template<typename Derived>
490 std::tuple<idx, std::vector<double>, std::vector<cmat>>
491 measure(const Eigen::MatrixBase<Derived>& A,
492  const std::initializer_list<cmat>& Ks,
493  const std::vector<idx>& subsys,
494  const std::vector<idx>& dims)
495 {
496  return measure(A, std::vector<cmat>(Ks), subsys, dims);
497 }
498 
516 template<typename Derived>
517 std::tuple<idx, std::vector<double>, std::vector<cmat>>
518 measure(const Eigen::MatrixBase<Derived>& A,
519  const std::vector<cmat>& Ks,
520  const std::vector<idx>& subsys,
521  idx d = 2)
522 {
523  const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA
524  = A.derived();
525 
526  // EXCEPTION CHECKS
527 
528  // check zero size
530  throw Exception("qpp::measure()", Exception::Type::ZERO_SIZE);
531 
532  // check valid dims
533  if ( d == 0 )
534  throw Exception("qpp::measure()", Exception::Type::DIMS_INVALID);
535  // END EXCEPTION CHECKS
536 
537  idx n =
538  static_cast<idx>(std::llround(std::log2(rA.rows()) /
539  std::log2(d)));
540  std::vector<idx> dims(n, d); // local dimensions vector
541 
542  return measure(rA, Ks, subsys, dims);
543 }
544 
545 // std::initializer_list overload, avoids ambiguity for 2-element lists, see
546 // http://stackoverflow.com
547 // /questions/26750039/ambiguity-when-using-initializer-list-as-parameter
565 template<typename Derived>
566 std::tuple<idx, std::vector<double>, std::vector<cmat>>
567 measure(const Eigen::MatrixBase<Derived>& A,
568  const std::initializer_list<cmat>& Ks,
569  const std::vector<idx>& subsys,
570  idx d = 2)
571 {
572  return measure(A, std::vector<cmat>(Ks), subsys, d);
573 }
574 
593 template<typename Derived>
594 std::tuple<idx, std::vector<double>, std::vector<cmat>>
595 
596 measure(const Eigen::MatrixBase<Derived>& A,
597  const cmat& V,
598  const std::vector<idx>& subsys,
599  const std::vector<idx>& dims)
600 {
601  const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA
602  = A.derived();
603 
604  // EXCEPTION CHECKS
605 
606  // check zero-size
608  throw Exception("qpp::measure()", Exception::Type::ZERO_SIZE);
609 
610  // check that dimension is valid
611  if ( !internal::_check_dims(dims))
612  throw Exception("qpp::measure()", Exception::Type::DIMS_INVALID);
613 
614  // check subsys is valid w.r.t. dims
615  if ( !internal::_check_subsys_match_dims(subsys, dims))
616  throw Exception("qpp::measure()",
618 
619  std::vector<idx> subsys_dims(subsys.size());
620  for ( idx i = 0; i < subsys.size(); ++i )
621  subsys_dims[i] = dims[subsys[i]];
622 
623  idx Dsubsys = prod(std::begin(subsys_dims), std::end(subsys_dims));
624 
625  // check the matrix V
627  throw Exception("qpp::measure()", Exception::Type::ZERO_SIZE);
628 // if (!internal::_check_square_mat(U))
629 // throw Exception("qpp::measure()", Exception::Type::MATRIX_NOT_SQUARE);
630  if ( Dsubsys != static_cast<idx>(V.rows()))
631  throw Exception("qpp::measure()",
633  // END EXCEPTION CHECKS
634 
635  // number of basis (rank-1 POVM) elements
636  idx M = static_cast<idx>(V.cols());
637 
638  //************ ket ************//
639  if ( internal::_check_cvector(rA))
640  {
641  const ket& rpsi = A.derived();
642  // check that dims match state vector
643  if ( !internal::_check_dims_match_cvect(dims, rA))
644  throw Exception("qpp::measure()",
646 
647  std::vector<double> prob(M); // probabilities
648  std::vector<cmat> outstates(M); // resulting states
649 
650 #ifdef _WITH_OPENMP_
651 #pragma omp parallel for
652 #endif
653  for ( idx i = 0; i < M; ++i )
654  outstates[i] = ip(static_cast<const ket&>(V.col(i)),
655  rpsi, subsys, dims);
656 
657  for ( idx i = 0; i < M; ++i )
658  {
659  double tmp = norm(outstates[i]);
660  prob[i] = tmp * tmp;
661  if ( prob[i] > eps )
662  {
663  // normalized output state
664  // corresponding to measurement result m
665  outstates[i] /= tmp;
666  }
667  }
668 
669  // sample from the probability distribution
670  std::discrete_distribution<idx> dd(std::begin(prob),
671  std::end(prob));
672  idx result = dd(RandomDevices::get_instance()._rng);
673 
674  return std::make_tuple(result, prob, outstates);
675  }
676  //************ density matrix ************//
677  else if ( internal::_check_square_mat(rA))
678  {
679  // check that dims match rho matrix
680  if ( !internal::_check_dims_match_mat(dims, rA))
681  throw Exception("qpp::measure()",
683 
684  std::vector<cmat> Ks(M);
685  for ( idx i = 0; i < M; ++i )
686  Ks[i] = V.col(i) * adjoint(V.col(i));
687 
688  return measure(rA, Ks, subsys, dims);
689  }
690  //************ Exception: not ket nor density matrix ************//
691  throw Exception("qpp::measure()",
693 }
694 
713 template<typename Derived>
714 std::tuple<idx, std::vector<double>, std::vector<cmat>>
715 
716 measure(const Eigen::MatrixBase<Derived>& A,
717  const cmat& V,
718  const std::vector<idx>& subsys,
719  idx d = 2)
720 {
721  const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA
722  = A.derived();
723 
724  // EXCEPTION CHECKS
725 
726  // check zero size
728  throw Exception("qpp::measure()", Exception::Type::ZERO_SIZE);
729 
730  // check valid dims
731  if ( d == 0 )
732  throw Exception("qpp::measure()", Exception::Type::DIMS_INVALID);
733  // END EXCEPTION CHECKS
734 
735  idx n =
736  static_cast<idx>(std::llround(std::log2(rA.rows()) /
737  std::log2(d)));
738  std::vector<idx> dims(n, d); // local dimensions vector
739 
740  return measure(rA, V, subsys, dims);
741 }
742 
757 template<typename Derived>
758 std::tuple<std::vector<idx>, double, cmat>
759 measure_seq(const Eigen::MatrixBase<Derived>& A,
760  std::vector<idx> subsys,
761  std::vector<idx> dims)
762 {
763  typename Eigen::MatrixBase<Derived>::EvalReturnType cA = A;
764 
765  // EXCEPTION CHECKS
766 
767  // check zero-size
769  throw Exception("qpp::measure_seq()", Exception::Type::ZERO_SIZE);
770 
771  // check that dimension is valid
772  if ( !internal::_check_dims(dims))
773  throw Exception("qpp::measure_seq()", Exception::Type::DIMS_INVALID);
774 
775  // check that dims match rho matrix
776  if ( !internal::_check_dims_match_mat(dims, cA))
777  throw Exception("qpp::measure_seq()",
779 
780  // check subsys is valid w.r.t. dims
781  if ( !internal::_check_subsys_match_dims(subsys, dims))
782  throw Exception("qpp::measure_seq()",
784  // END EXCEPTION CHECKS
785 
786  std::vector<idx> result;
787  double prob = 1;
788 
789  // sort subsys in decreasing order,
790  // the order of measurements does not matter
791  std::sort(std::begin(subsys), std::end(subsys), std::greater<idx>{});
792 
793  //************ density matrix or column vector ************//
795  {
796  while (subsys.size() > 0)
797  {
798  auto tmp = measure(
799  cA, Gates::get_instance().Id(dims[subsys[0]]),
800  {subsys[0]}, dims
801  );
802  result.push_back(std::get<0>(tmp));
803  prob *= std::get<1>(tmp)[std::get<0>(tmp)];
804  cA = std::get<2>(tmp)[std::get<0>(tmp)];
805 
806  // remove the subsystem
807  dims.erase(std::next(std::begin(dims), subsys[0]));
808  subsys.erase(std::begin(subsys));
809  }
810  // order result in increasing order with respect to subsys
811  std::reverse(std::begin(result), std::end(result));
812  }
813  else
814  throw Exception("qpp::measure_seq()",
816 
817  return std::make_tuple(result, prob, cA);
818 }
819 
834 template<typename Derived>
835 std::tuple<std::vector<idx>, double, cmat>
836 measure_seq(const Eigen::MatrixBase<Derived>& A,
837  std::vector<idx> subsys,
838  idx d = 2)
839 {
840  const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA
841  = A.derived();
842 
843  // EXCEPTION CHECKS
844 
845  // check zero size
847  throw Exception("qpp::measure_seq()", Exception::Type::ZERO_SIZE);
848 
849  // check valid dims
850  if ( d == 0 )
851  throw Exception("qpp::measure_seq()", Exception::Type::DIMS_INVALID);
852  // END EXCEPTION CHECKS
853 
854  idx n =
855  static_cast<idx>(std::llround(std::log2(rA.rows()) /
856  std::log2(d)));
857  std::vector<idx> dims(n, d); // local dimensions vector
858 
859  return measure_seq(rA, subsys, dims);
860 }
861 
862 } /* namespace qpp */
863 
864 #endif /* INSTRUMENTS_H_ */
bool _check_cvector(const Eigen::MatrixBase< Derived > &A)
Definition: util.h:105
constexpr idx maxn
Maximum number of allowed qu(d)its (subsystems)
Definition: constants.h:74
bool _check_subsys_match_dims(const std::vector< idx > &subsys, const std::vector< idx > &dims)
Definition: util.h:183
bool _check_dims_match_mat(const std::vector< idx > &dims, const Eigen::MatrixBase< Derived > &A)
Definition: util.h:141
bool _check_dims_match_cvect(const std::vector< idx > &dims, const Eigen::MatrixBase< Derived > &V)
Definition: util.h:152
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:67
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:492
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:84
std::vector< T > complement(std::vector< T > subsys, idx N)
Constructs the complement of a subsystem vector.
Definition: functions.h:1818
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:759
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:224
idx _multiidx2n(const idx *midx, idx numdims, const idx *dims) noexcept
Definition: util.h:61
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:112
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:1218
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:48
std::size_t idx
Non-negative integer index.
Definition: types.h:36
bool _check_dims(const std::vector< idx > &dims)
Definition: util.h:125