Quantum++  v1.0-rc3
A modern C++11 quantum computing library
instruments.h
Go to the documentation of this file.
1 /*
2  * This file is part of Quantum++.
3  *
4  * MIT License
5  *
6  * Copyright (c) 2013 - 2018 Vlad Gheorghiu (vgheorgh@gmail.com)
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  */
26 
32 #ifndef INSTRUMENTS_H_
33 #define INSTRUMENTS_H_
34 
35 namespace qpp {
46 template <typename Derived>
47 dyn_col_vect<typename Derived::Scalar>
48 ip(const Eigen::MatrixBase<Derived>& phi, const Eigen::MatrixBase<Derived>& psi,
49  const std::vector<idx>& subsys, const std::vector<idx>& dims) {
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::ZeroSize("qpp::ip()");
58 
59  // check zero-size
61  throw exception::ZeroSize("qpp::ip()");
62 
63  // check column vector
64  if (!internal::check_cvector(rphi))
65  throw exception::MatrixNotCvector("qpp::ip()");
66 
67  // check column vector
68  if (!internal::check_cvector(rpsi))
69  throw exception::MatrixNotCvector("qpp::ip()");
70 
71  // check that dims is a valid dimension vector
72  if (!internal::check_dims(dims))
73  throw exception::DimsInvalid("qpp::ip()");
74 
75  // check that subsys are valid
76  if (!internal::check_subsys_match_dims(subsys, dims))
77  throw exception::SubsysMismatchDims("qpp::ip()");
78 
79  // check that dims match state vector psi
80  if (!internal::check_dims_match_cvect(dims, rpsi))
81  throw exception::DimsMismatchCvector("qpp::ip()");
82 
83  // check that subsys match state vector phi
84  std::vector<idx> subsys_dims(subsys.size());
85  for (idx i = 0; i < subsys.size(); ++i)
86  subsys_dims[i] = dims[subsys[i]];
87  if (!internal::check_dims_match_cvect(subsys_dims, rphi))
88  throw exception::DimsMismatchCvector("qpp::ip()");
89  // END EXCEPTION CHECKS
90 
91  idx Dsubsys = prod(std::begin(subsys_dims), std::end(subsys_dims));
92 
93  idx D = static_cast<idx>(rpsi.rows());
94  idx Dsubsys_bar = D / Dsubsys;
95 
96  idx N = dims.size();
97  idx Nsubsys = subsys.size();
98  idx Nsubsys_bar = N - Nsubsys;
99 
100  idx Cdims[maxn];
101  idx Csubsys[maxn];
102  idx Cdimssubsys[maxn];
103  idx Csubsys_bar[maxn];
104  idx Cdimssubsys_bar[maxn];
105 
106  std::vector<idx> subsys_bar = complement(subsys, N);
107  std::copy(std::begin(subsys_bar), std::end(subsys_bar),
108  std::begin(Csubsys_bar));
109 
110  for (idx i = 0; i < N; ++i) {
111  Cdims[i] = dims[i];
112  }
113  for (idx i = 0; i < Nsubsys; ++i) {
114  Csubsys[i] = subsys[i];
115  Cdimssubsys[i] = dims[subsys[i]];
116  }
117  for (idx i = 0; i < Nsubsys_bar; ++i) {
118  Cdimssubsys_bar[i] = dims[subsys_bar[i]];
119  }
120 
121  auto worker = [&](idx b) noexcept->typename Derived::Scalar {
122  idx Cmidxrow[maxn];
123  idx Cmidxrowsubsys[maxn];
124  idx Cmidxcolsubsys_bar[maxn];
125 
126  /* get the col multi-indexes of the complement */
127  internal::n2multiidx(b, Nsubsys_bar, Cdimssubsys_bar,
128  Cmidxcolsubsys_bar);
129  /* write it in the global row multi-index */
130  for (idx k = 0; k < Nsubsys_bar; ++k) {
131  Cmidxrow[Csubsys_bar[k]] = Cmidxcolsubsys_bar[k];
132  }
133 
134  typename Derived::Scalar result = 0;
135  for (idx a = 0; a < Dsubsys; ++a) {
136  /* get the row multi-indexes of the subsys */
137  internal::n2multiidx(a, Nsubsys, Cdimssubsys, Cmidxrowsubsys);
138  /* write it in the global row multi-index */
139  for (idx k = 0; k < Nsubsys; ++k) {
140  Cmidxrow[Csubsys[k]] = Cmidxrowsubsys[k];
141  }
142  // compute the row index
143  idx i = internal::multiidx2n(Cmidxrow, N, Cdims);
144 
145  result += std::conj(rphi(a)) * rpsi(i);
146  }
147 
148  return result;
149  }; /* end worker */
150 
151  dyn_col_vect<typename Derived::Scalar> result(Dsubsys_bar);
152 #ifdef WITH_OPENMP_
153 #pragma omp parallel for
154 #endif // WITH_OPENMP_
155  for (idx m = 0; m < Dsubsys_bar; ++m)
156  result(m) = worker(m);
157 
158  return result;
159 }
160 
171 template <typename Derived>
173 ip(const Eigen::MatrixBase<Derived>& phi, const Eigen::MatrixBase<Derived>& psi,
174  const std::vector<idx>& subsys, idx d = 2) {
175  const dyn_col_vect<typename Derived::Scalar>& rphi = phi.derived();
176  const dyn_col_vect<typename Derived::Scalar>& rpsi = psi.derived();
177 
178  // EXCEPTION CHECKS
179 
180  if (!internal::check_nonzero_size(rpsi))
181  throw exception::ZeroSize("qpp::ip()");
182 
183  // check valid dims
184  if (d < 2)
185  throw exception::DimsInvalid("qpp::ip()");
186  // END EXCEPTION CHECKS
187 
188  idx N = internal::get_num_subsys(static_cast<idx>(rpsi.rows()), d);
189  std::vector<idx> dims(N, d); // local dimensions vector
190  return ip(phi, psi, subsys, dims);
191 }
192 
193 // full measurements
203 template <typename Derived>
204 std::tuple<idx, std::vector<double>, std::vector<cmat>>
205 measure(const Eigen::MatrixBase<Derived>& A, const std::vector<cmat>& Ks) {
206  const dyn_mat<typename Derived::Scalar>& rA = A.derived();
207 
208  // EXCEPTION CHECKS
209 
210  // check zero-size
212  throw exception::ZeroSize("qpp::measure()");
213 
214  // check the Kraus operators
215  if (Ks.size() == 0)
216  throw exception::ZeroSize("qpp::measure()");
217  if (!internal::check_square_mat(Ks[0]))
218  throw exception::MatrixNotSquare("qpp::measure()");
219  if (Ks[0].rows() != rA.rows())
220  throw exception::DimsMismatchMatrix("qpp::measure()");
221  for (auto&& it : Ks)
222  if (it.rows() != Ks[0].rows() || it.cols() != Ks[0].rows())
223  throw exception::DimsNotEqual("qpp::measure()");
224  // END EXCEPTION CHECKS
225 
226  // probabilities
227  std::vector<double> prob(Ks.size());
228  // resulting states
229  std::vector<cmat> outstates(Ks.size());
230 
231  //************ density matrix ************//
232  if (internal::check_square_mat(rA)) // square matrix
233  {
234  for (idx i = 0; i < Ks.size(); ++i) {
235  outstates[i] = cmat::Zero(rA.rows(), rA.rows());
236  cmat tmp = Ks[i] * rA * adjoint(Ks[i]); // un-normalized;
237  prob[i] = std::abs(trace(tmp)); // probability
238  if (prob[i] > eps)
239  outstates[i] = tmp / prob[i]; // normalized
240  }
241  }
242  //************ ket ************//
243  else if (internal::check_cvector(rA)) // column vector
244  {
245  for (idx i = 0; i < Ks.size(); ++i) {
246  outstates[i] = ket::Zero(rA.rows());
247  ket tmp = Ks[i] * rA; // un-normalized;
248  // probability
249  prob[i] = std::pow(norm(tmp), 2);
250  if (prob[i] > eps)
251  outstates[i] = tmp / std::sqrt(prob[i]); // normalized
252  }
253  } else
254  throw exception::MatrixNotSquareNorCvector("qpp::measure()");
255 
256  // sample from the probability distribution
257  std::discrete_distribution<idx> dd(std::begin(prob), std::end(prob));
258  idx result = dd(RandomDevices::get_instance().get_prng());
259 
260  return std::make_tuple(result, prob, outstates);
261 }
262 
263 // std::initializer_list overload, avoids ambiguity for 2-element lists, see
264 // http://stackoverflow.com
265 // /questions/26750039/ambiguity-when-using-initializer-list-as-parameter
275 template <typename Derived>
276 std::tuple<idx, std::vector<double>, std::vector<cmat>>
277 measure(const Eigen::MatrixBase<Derived>& A,
278  const std::initializer_list<cmat>& Ks) {
279  return measure(A, std::vector<cmat>(Ks));
280 }
281 
292 template <typename Derived>
293 std::tuple<idx, std::vector<double>, std::vector<cmat>>
294 measure(const Eigen::MatrixBase<Derived>& A, const cmat& U) {
295  const dyn_mat<typename Derived::Scalar>& rA = A.derived();
296 
297  // EXCEPTION CHECKS
298 
299  // check zero-size
301  throw exception::ZeroSize("qpp::measure()");
302 
303  // check the unitary basis matrix U
305  throw exception::ZeroSize("qpp::measure()");
307  throw exception::MatrixNotSquare("qpp::measure()");
308  if (U.rows() != rA.rows())
309  throw exception::DimsMismatchMatrix("qpp::measure()");
310  // END EXCEPTION CHECKS
311 
312  std::vector<cmat> Ks(U.rows());
313  for (idx i = 0; i < static_cast<idx>(U.rows()); ++i)
314  Ks[i] = U.col(i) * adjoint(U.col(i));
315 
316  return measure(rA, Ks);
317 }
318 
319 // partial measurements
337 template <typename Derived>
338 std::tuple<idx, std::vector<double>, std::vector<cmat>>
339 measure(const Eigen::MatrixBase<Derived>& A, const std::vector<cmat>& Ks,
340  const std::vector<idx>& subsys, const std::vector<idx>& dims) {
341  const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA = A.derived();
342 
343  // EXCEPTION CHECKS
344 
345  // check zero-size
347  throw exception::ZeroSize("qpp::measure()");
348 
349  // check that dimension is valid
350  if (!internal::check_dims(dims))
351  throw exception::DimsInvalid("qpp::measure()");
352 
353  // check that dims match rho matrix
354  if (!internal::check_dims_match_mat(dims, rA))
355  throw exception::DimsMismatchMatrix("qpp::measure()");
356 
357  // check subsys is valid w.r.t. dims
358  if (!internal::check_subsys_match_dims(subsys, dims))
359  throw exception::SubsysMismatchDims("qpp::measure()");
360 
361  std::vector<idx> subsys_dims(subsys.size());
362  for (idx i = 0; i < subsys.size(); ++i)
363  subsys_dims[i] = dims[subsys[i]];
364 
365  idx D = prod(std::begin(dims), std::end(dims));
366  idx Dsubsys = prod(std::begin(subsys_dims), std::end(subsys_dims));
367  idx Dsubsys_bar = D / Dsubsys;
368 
369  // check the Kraus operators
370  if (Ks.size() == 0)
371  throw exception::ZeroSize("qpp::measure()");
372  if (!internal::check_square_mat(Ks[0]))
373  throw exception::MatrixNotSquare("qpp::measure()");
374  if (Dsubsys != static_cast<idx>(Ks[0].rows()))
375  throw exception::DimsMismatchMatrix("qpp::measure()");
376  for (auto&& it : Ks)
377  if (it.rows() != Ks[0].rows() || it.cols() != Ks[0].rows())
378  throw exception::DimsNotEqual("qpp::measure()");
379  // END EXCEPTION CHECKS
380 
381  // probabilities
382  std::vector<double> prob(Ks.size());
383  // resulting states
384  std::vector<cmat> outstates(Ks.size(),
385  cmat::Zero(Dsubsys_bar, Dsubsys_bar));
386 
387  //************ density matrix ************//
388  if (internal::check_square_mat(rA)) // square matrix
389  {
390  for (idx i = 0; i < Ks.size(); ++i) {
391  cmat tmp = apply(rA, Ks[i], subsys, dims);
392  tmp = ptrace(tmp, subsys, dims);
393  prob[i] = std::abs(trace(tmp)); // probability
394  if (prob[i] > eps) {
395  // normalized output state
396  // corresponding to measurement result i
397  outstates[i] = tmp / prob[i];
398  }
399  }
400  }
401  //************ ket ************//
402  else if (internal::check_cvector(rA)) // column vector
403  {
404  for (idx i = 0; i < Ks.size(); ++i) {
405  ket tmp = apply(rA, Ks[i], subsys, dims);
406  prob[i] = std::pow(norm(tmp), 2);
407  if (prob[i] > eps) {
408  // normalized output state
409  // corresponding to measurement result i
410  tmp /= std::sqrt(prob[i]);
411  outstates[i] = ptrace(tmp, subsys, dims);
412  }
413  }
414  } else
415  throw exception::MatrixNotSquareNorCvector("qpp::measure()");
416 
417  // sample from the probability distribution
418  std::discrete_distribution<idx> dd(std::begin(prob), std::end(prob));
419  idx result = dd(RandomDevices::get_instance().get_prng());
420 
421  return std::make_tuple(result, prob, outstates);
422 }
423 
424 // std::initializer_list overload, avoids ambiguity for 2-element lists, see
425 // http://stackoverflow.com
426 // /questions/26750039/ambiguity-when-using-initializer-list-as-parameter
444 template <typename Derived>
445 std::tuple<idx, std::vector<double>, std::vector<cmat>>
446 measure(const Eigen::MatrixBase<Derived>& A,
447  const std::initializer_list<cmat>& Ks, const std::vector<idx>& subsys,
448  const std::vector<idx>& dims) {
449  return measure(A, std::vector<cmat>(Ks), subsys, dims);
450 }
451 
469 template <typename Derived>
470 std::tuple<idx, std::vector<double>, std::vector<cmat>>
471 measure(const Eigen::MatrixBase<Derived>& A, const std::vector<cmat>& Ks,
472  const std::vector<idx>& subsys, idx d = 2) {
473  const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA = A.derived();
474 
475  // EXCEPTION CHECKS
476 
477  // check zero size
479  throw exception::ZeroSize("qpp::measure()");
480 
481  // check valid dims
482  if (d < 2)
483  throw exception::DimsInvalid("qpp::measure()");
484  // END EXCEPTION CHECKS
485 
486  idx N = internal::get_num_subsys(static_cast<idx>(rA.rows()), d);
487  std::vector<idx> dims(N, d); // local dimensions vector
488 
489  return measure(rA, Ks, subsys, dims);
490 }
491 
492 // std::initializer_list overload, avoids ambiguity for 2-element lists, see
493 // http://stackoverflow.com
494 // /questions/26750039/ambiguity-when-using-initializer-list-as-parameter
512 template <typename Derived>
513 std::tuple<idx, std::vector<double>, std::vector<cmat>>
514 measure(const Eigen::MatrixBase<Derived>& A,
515  const std::initializer_list<cmat>& Ks, const std::vector<idx>& subsys,
516  idx d = 2) {
517  return measure(A, std::vector<cmat>(Ks), subsys, d);
518 }
519 
538 template <typename Derived>
539 std::tuple<idx, std::vector<double>, std::vector<cmat>>
540 measure(const Eigen::MatrixBase<Derived>& A, const cmat& V,
541  const std::vector<idx>& subsys, const std::vector<idx>& dims) {
542  const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA = A.derived();
543 
544  // EXCEPTION CHECKS
545 
546  // check zero-size
548  throw exception::ZeroSize("qpp::measure()");
549 
550  // check that dimension is valid
551  if (!internal::check_dims(dims))
552  throw exception::DimsInvalid("qpp::measure()");
553 
554  // check subsys is valid w.r.t. dims
555  if (!internal::check_subsys_match_dims(subsys, dims))
556  throw exception::SubsysMismatchDims("qpp::measure()");
557 
558  std::vector<idx> subsys_dims(subsys.size());
559  for (idx i = 0; i < subsys.size(); ++i)
560  subsys_dims[i] = dims[subsys[i]];
561 
562  idx Dsubsys = prod(std::begin(subsys_dims), std::end(subsys_dims));
563 
564  // check the matrix V
566  throw exception::ZeroSize("qpp::measure()");
567  if (Dsubsys != static_cast<idx>(V.rows()))
568  throw exception::DimsMismatchMatrix("qpp::measure()");
569  // END EXCEPTION CHECKS
570 
571  // number of basis (rank-1 POVM) elements
572  idx M = static_cast<idx>(V.cols());
573 
574  //************ ket ************//
575  if (internal::check_cvector(rA)) {
576  const ket& rpsi = A.derived();
577  // check that dims match state vector
578  if (!internal::check_dims_match_cvect(dims, rA))
579  throw exception::DimsMismatchCvector("qpp::measure()");
580 
581  std::vector<double> prob(M); // probabilities
582  std::vector<cmat> outstates(M); // resulting states
583 
584 #ifdef WITH_OPENMP_
585 #pragma omp parallel for
586 #endif // WITH_OPENMP_
587  for (idx i = 0; i < M; ++i)
588  outstates[i] =
589  ip(static_cast<const ket&>(V.col(i)), rpsi, subsys, dims);
590 
591  for (idx i = 0; i < M; ++i) {
592  double tmp = norm(outstates[i]);
593  prob[i] = tmp * tmp;
594  if (prob[i] > eps) {
595  // normalized output state
596  // corresponding to measurement result m
597  outstates[i] /= tmp;
598  }
599  }
600 
601  // sample from the probability distribution
602  std::discrete_distribution<idx> dd(std::begin(prob), std::end(prob));
603  idx result = dd(RandomDevices::get_instance().get_prng());
604 
605  return std::make_tuple(result, prob, outstates);
606  }
607  //************ density matrix ************//
608  else if (internal::check_square_mat(rA)) {
609  // check that dims match rho matrix
610  if (!internal::check_dims_match_mat(dims, rA))
611  throw exception::DimsMismatchMatrix("qpp::measure()");
612 
613  std::vector<cmat> Ks(M);
614  for (idx i = 0; i < M; ++i)
615  Ks[i] = V.col(i) * adjoint(V.col(i));
616 
617  return measure(rA, Ks, subsys, dims);
618  }
619  //************ Exception: not ket nor density matrix ************//
620  throw exception::MatrixNotSquareNorCvector("qpp::measure()");
621 }
622 
641 template <typename Derived>
642 std::tuple<idx, std::vector<double>, std::vector<cmat>>
643 measure(const Eigen::MatrixBase<Derived>& A, const cmat& V,
644  const std::vector<idx>& subsys, idx d = 2) {
645  const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA = A.derived();
646 
647  // EXCEPTION CHECKS
648 
649  // check zero size
651  throw exception::ZeroSize("qpp::measure()");
652 
653  // check valid dims
654  if (d < 2)
655  throw exception::DimsInvalid("qpp::measure()");
656  // END EXCEPTION CHECKS
657 
658  idx N = internal::get_num_subsys(static_cast<idx>(rA.rows()), d);
659  std::vector<idx> dims(N, d); // local dimensions vector
660 
661  return measure(rA, V, subsys, dims);
662 }
663 
678 template <typename Derived>
679 std::tuple<std::vector<idx>, double, cmat>
680 measure_seq(const Eigen::MatrixBase<Derived>& A, std::vector<idx> subsys,
681  std::vector<idx> dims) {
682  // typename std::remove_const<
683  // typename Eigen::MatrixBase<Derived>::EvalReturnType
684  // >::type cA = A.derived();
685 
686  dyn_mat<typename Derived::Scalar> cA = A.derived();
687 
688  // EXCEPTION CHECKS
689 
690  // check zero-size
692  throw exception::ZeroSize("qpp::measure_seq()");
693 
694  // check that dimension is valid
695  if (!internal::check_dims(dims))
696  throw exception::DimsInvalid("qpp::measure_seq()");
697 
698  // check square matrix or column vector
699  if (internal::check_square_mat(cA)) {
700  // check that dims match rho matrix
701  if (!internal::check_dims_match_mat(dims, cA))
702  throw exception::DimsMismatchMatrix("qpp::measure_seq()");
703  } else if (internal::check_cvector(cA)) {
704  // check that dims match psi column vector
705  if (!internal::check_dims_match_cvect(dims, cA))
706  throw exception::DimsMismatchMatrix("qpp::measure_seq()");
707  } else
708  throw exception::MatrixNotSquareNorCvector("qpp::measure_seq()");
709 
710  // check subsys is valid w.r.t. dims
711  if (!internal::check_subsys_match_dims(subsys, dims))
712  throw exception::SubsysMismatchDims("qpp::measure_seq()");
713  // END EXCEPTION CHECKS
714 
715  std::vector<idx> result;
716  double prob = 1;
717 
718  // sort subsys in decreasing order,
719  // the order of measurements does not matter
720  std::sort(std::begin(subsys), std::end(subsys), std::greater<idx>{});
721 
722  //************ density matrix or column vector ************//
723  while (subsys.size() > 0) {
724  auto tmp = measure(cA, Gates::get_instance().Id(dims[subsys[0]]),
725  {subsys[0]}, dims);
726  result.push_back(std::get<0>(tmp));
727  prob *= std::get<1>(tmp)[std::get<0>(tmp)];
728  cA = std::get<2>(tmp)[std::get<0>(tmp)];
729 
730  // remove the subsystem
731  dims.erase(std::next(std::begin(dims), subsys[0]));
732  subsys.erase(std::begin(subsys));
733  }
734  // order result in increasing order with respect to subsys
735  std::reverse(std::begin(result), std::end(result));
736 
737  return std::make_tuple(result, prob, cA);
738 }
739 
754 template <typename Derived>
755 std::tuple<std::vector<idx>, double, cmat>
756 measure_seq(const Eigen::MatrixBase<Derived>& A, std::vector<idx> subsys,
757  idx d = 2) {
758  const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA = A.derived();
759 
760  // EXCEPTION CHECKS
761 
762  // check zero size
764  throw exception::ZeroSize("qpp::measure_seq()");
765 
766  // check valid dims
767  if (d < 2)
768  throw exception::DimsInvalid("qpp::measure_seq()");
769  // END EXCEPTION CHECKS
770 
771  idx N = internal::get_num_subsys(static_cast<idx>(rA.rows()), d);
772  std::vector<idx> dims(N, d); // local dimensions vector
773 
774  return measure_seq(rA, subsys, dims);
775 }
776 
777 } /* namespace qpp */
778 
779 #endif /* INSTRUMENTS_H_ */
bool check_nonzero_size(const T &x) noexcept
Definition: util.h:123
Dimensions not equal exception.
Definition: exception.h:282
Dimension(s) mismatch matrix size exception.
Definition: exception.h:298
constexpr idx maxn
Maximum number of allowed qubits/qudits (subsystems)
Definition: constants.h:73
bool check_subsys_match_dims(const std::vector< idx > &subsys, const std::vector< idx > &dims)
Definition: util.h:210
bool check_cvector(const Eigen::MatrixBase< Derived > &A)
Definition: util.h:117
constexpr double eps
Used to decide whether a number or expression in double precision is zero or not. ...
Definition: constants.h:66
Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > dyn_mat
Dynamic Eigen matrix over the field specified by Scalar.
Definition: types.h:81
bool check_dims_match_mat(const std::vector< idx > &dims, const Eigen::MatrixBase< Derived > &A)
Definition: util.h:150
idx multiidx2n(const idx *const midx, idx numdims, const idx *const dims) noexcept
Definition: util.h:71
void n2multiidx(idx n, idx numdims, const idx *const dims, idx *result) noexcept
Definition: util.h:43
Subsystems mismatch dimensions exception.
Definition: exception.h:363
Eigen::VectorXcd ket
Complex (double precision) dynamic Eigen column vector.
Definition: types.h:54
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:440
Matrix is not a column vector exception.
Definition: exception.h:162
Quantum++ main namespace.
Definition: codes.h:35
idx get_num_subsys(idx sz, idx d)
Definition: util.h:366
Matrix is not square nor column vector exception.
Definition: exception.h:207
Invalid dimension(s) exception.
Definition: exception.h:267
bool check_dims_match_cvect(const std::vector< idx > &dims, const Eigen::MatrixBase< Derived > &A)
Definition: util.h:165
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:680
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:205
Dimension(s) mismatch column vector size exception.
Definition: exception.h:314
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:48
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:1176
bool check_square_mat(const Eigen::MatrixBase< Derived > &A)
Definition: util.h:99
Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > dyn_col_vect
Dynamic Eigen column vector over the field specified by Scalar.
Definition: types.h:93
static RandomDevices & get_instance() noexcept(std::is_nothrow_constructible< RandomDevices >::value)
Definition: singleton.h:92
Eigen::MatrixXcd cmat
Complex (double precision) dynamic Eigen matrix.
Definition: types.h:64
bool check_dims(const std::vector< idx > &dims)
Definition: util.h:134
std::size_t idx
Non-negative integer index.
Definition: types.h:39
Matrix is not square exception.
Definition: exception.h:147
Object has zero size exception.
Definition: exception.h:132