Quantum++  v1.2
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 - 2019 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 psi column vector
80  if (!internal::check_dims_match_cvect(dims, rpsi))
81  throw exception::DimsMismatchCvector("qpp::ip()");
82 
83  // check that subsys match pho column vector
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 n_subsys = subsys.size();
98  idx n_subsys_bar = n - n_subsys;
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 < n_subsys; ++i) {
114  Csubsys[i] = subsys[i];
115  Cdimssubsys[i] = dims[subsys[i]];
116  }
117  for (idx i = 0; i < n_subsys_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, n_subsys_bar, Cdimssubsys_bar,
128  Cmidxcolsubsys_bar);
129  /* write it in the global row multi-index */
130  for (idx k = 0; k < n_subsys_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, n_subsys, Cdimssubsys, Cmidxrowsubsys);
138  /* write it in the global row multi-index */
139  for (idx k = 0; k < n_subsys; ++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>
172 dyn_col_vect<typename Derived::Scalar>
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
204 template <typename Derived>
205 std::tuple<idx, std::vector<double>, std::vector<cmat>>
206 measure(const Eigen::MatrixBase<Derived>& A, const std::vector<cmat>& Ks) {
207  const dyn_mat<typename Derived::Scalar>& rA = A.derived();
208 
209  // EXCEPTION CHECKS
210 
211  // check zero-size
213  throw exception::ZeroSize("qpp::measure()");
214 
215  // check the Kraus operators
216  if (Ks.size() == 0)
217  throw exception::ZeroSize("qpp::measure()");
218  if (!internal::check_square_mat(Ks[0]))
219  throw exception::MatrixNotSquare("qpp::measure()");
220  if (Ks[0].rows() != rA.rows())
221  throw exception::DimsMismatchMatrix("qpp::measure()");
222  for (auto&& elem : Ks)
223  if (elem.rows() != Ks[0].rows() || elem.cols() != Ks[0].rows())
224  throw exception::DimsNotEqual("qpp::measure()");
225  // END EXCEPTION CHECKS
226 
227  // probabilities
228  std::vector<double> prob(Ks.size());
229  // resulting states
230  std::vector<cmat> outstates(Ks.size());
231 
232  //************ density matrix ************//
233  if (internal::check_square_mat(rA)) // square matrix
234  {
235  for (idx i = 0; i < Ks.size(); ++i) {
236  outstates[i] = cmat::Zero(rA.rows(), rA.rows());
237  cmat tmp = Ks[i] * rA * adjoint(Ks[i]); // un-normalized;
238  prob[i] = std::abs(trace(tmp)); // probability
239  if (prob[i] > 0)
240  outstates[i] = tmp / prob[i]; // normalized
241  }
242  }
243  //************ ket ************//
244  else if (internal::check_cvector(rA)) // column vector
245  {
246  for (idx i = 0; i < Ks.size(); ++i) {
247  outstates[i] = ket::Zero(rA.rows());
248  ket tmp = Ks[i] * rA; // un-normalized;
249  // probability
250  prob[i] = std::pow(norm(tmp), 2);
251  if (prob[i] > 0)
252  outstates[i] = tmp / std::sqrt(prob[i]); // normalized
253  }
254  } else
255  throw exception::MatrixNotSquareNorCvector("qpp::measure()");
256 
257  // sample from the probability distribution
258  std::discrete_distribution<idx> dd(std::begin(prob), std::end(prob));
259  auto& gen =
260 #ifdef NO_THREAD_LOCAL_
261  RandomDevices::get_instance().get_prng();
262 #else
263  RandomDevices::get_thread_local_instance().get_prng();
264 #endif
265  idx result = dd(gen);
266 
267  return std::make_tuple(result, prob, outstates);
268 }
269 
270 // std::initializer_list overload, avoids ambiguity for 2-element lists, see
271 // http://stackoverflow.com
272 // /questions/26750039/ambiguity-when-using-initializer-list-as-parameter
283 template <typename Derived>
284 std::tuple<idx, std::vector<double>, std::vector<cmat>>
285 measure(const Eigen::MatrixBase<Derived>& A,
286  const std::initializer_list<cmat>& Ks) {
287  return measure(A, std::vector<cmat>(Ks));
288 }
289 
300 template <typename Derived>
301 std::tuple<idx, std::vector<double>, std::vector<cmat>>
302 measure(const Eigen::MatrixBase<Derived>& A, const cmat& U) {
303  const dyn_mat<typename Derived::Scalar>& rA = A.derived();
304 
305  // EXCEPTION CHECKS
306 
307  // check zero-size
309  throw exception::ZeroSize("qpp::measure()");
310 
311  // check the unitary basis matrix U
313  throw exception::ZeroSize("qpp::measure()");
315  throw exception::MatrixNotSquare("qpp::measure()");
316  if (U.rows() != rA.rows())
317  throw exception::DimsMismatchMatrix("qpp::measure()");
318  // END EXCEPTION CHECKS
319 
320  std::vector<cmat> Ks(U.rows());
321  for (idx i = 0; i < static_cast<idx>(U.rows()); ++i)
322  Ks[i] = U.col(i) * adjoint(U.col(i));
323 
324  return measure(rA, Ks);
325 }
326 
327 // partial measurements
344 template <typename Derived>
345 std::tuple<idx, std::vector<double>, std::vector<cmat>>
346 measure(const Eigen::MatrixBase<Derived>& A, const std::vector<cmat>& Ks,
347  const std::vector<idx>& target, const std::vector<idx>& dims) {
348  const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA = A.derived();
349 
350  // EXCEPTION CHECKS
351 
352  // check zero-size
354  throw exception::ZeroSize("qpp::measure()");
355 
356  // check that dimension is valid
357  if (!internal::check_dims(dims))
358  throw exception::DimsInvalid("qpp::measure()");
359 
360  // check that target is valid w.r.t. dims
361  if (!internal::check_subsys_match_dims(target, dims))
362  throw exception::SubsysMismatchDims("qpp::measure()");
363 
364  std::vector<idx> subsys_dims(target.size());
365  for (idx i = 0; i < target.size(); ++i)
366  subsys_dims[i] = dims[target[i]];
367 
368  idx D = prod(std::begin(dims), std::end(dims));
369  idx Dsubsys = prod(std::begin(subsys_dims), std::end(subsys_dims));
370  idx Dsubsys_bar = D / Dsubsys;
371 
372  // check the Kraus operators
373  if (Ks.size() == 0)
374  throw exception::ZeroSize("qpp::measure()");
375  if (!internal::check_square_mat(Ks[0]))
376  throw exception::MatrixNotSquare("qpp::measure()");
377  if (Dsubsys != static_cast<idx>(Ks[0].rows()))
378  throw exception::DimsMismatchMatrix("qpp::measure()");
379  for (auto&& elem : Ks)
380  if (elem.rows() != Ks[0].rows() || elem.cols() != Ks[0].rows())
381  throw exception::DimsNotEqual("qpp::measure()");
382  // END EXCEPTION CHECKS
383 
384  // probabilities
385  std::vector<double> prob(Ks.size());
386  // resulting states
387  std::vector<cmat> outstates(Ks.size(),
388  cmat::Zero(Dsubsys_bar, Dsubsys_bar));
389 
390  //************ density matrix ************//
391  if (internal::check_square_mat(rA)) // square matrix
392  {
393  // check that dims match rho matrix
394  if (!internal::check_dims_match_mat(dims, rA))
395  throw exception::DimsMismatchMatrix("qpp::measure()");
396  for (idx i = 0; i < Ks.size(); ++i) {
397  cmat tmp = apply(rA, Ks[i], target, dims);
398  tmp = ptrace(tmp, target, dims);
399  prob[i] = std::abs(trace(tmp)); // probability
400  if (prob[i] > 0) {
401  // normalized output state
402  // corresponding to measurement result i
403  outstates[i] = tmp / prob[i];
404  }
405  }
406  }
407  //************ ket ************//
408  else if (internal::check_cvector(rA)) // column vector
409  {
410  // check that dims match psi column vector
411  if (!internal::check_dims_match_cvect(dims, rA))
412  throw exception::DimsMismatchCvector("qpp::measure()");
413  for (idx i = 0; i < Ks.size(); ++i) {
414  ket tmp = apply(rA, Ks[i], target, dims);
415  prob[i] = std::pow(norm(tmp), 2);
416  if (prob[i] > 0) {
417  // normalized output state
418  // corresponding to measurement result i
419  tmp /= std::sqrt(prob[i]);
420  outstates[i] = ptrace(tmp, target, dims);
421  }
422  }
423  } else
424  throw exception::MatrixNotSquareNorCvector("qpp::measure()");
425 
426  // sample from the probability distribution
427  std::discrete_distribution<idx> dd(std::begin(prob), std::end(prob));
428  auto& gen =
429 #ifdef NO_THREAD_LOCAL_
430  RandomDevices::get_instance().get_prng();
431 #else
432  RandomDevices::get_thread_local_instance().get_prng();
433 #endif
434  idx result = dd(gen);
435 
436  return std::make_tuple(result, prob, outstates);
437 }
438 
439 // std::initializer_list overload, avoids ambiguity for 2-element lists, see
440 // http://stackoverflow.com
441 // /questions/26750039/ambiguity-when-using-initializer-list-as-parameter
458 template <typename Derived>
459 std::tuple<idx, std::vector<double>, std::vector<cmat>>
460 measure(const Eigen::MatrixBase<Derived>& A,
461  const std::initializer_list<cmat>& Ks, const std::vector<idx>& target,
462  const std::vector<idx>& dims) {
463  return measure(A, std::vector<cmat>(Ks), target, dims);
464 }
465 
482 template <typename Derived>
483 std::tuple<idx, std::vector<double>, std::vector<cmat>>
484 measure(const Eigen::MatrixBase<Derived>& A, const std::vector<cmat>& Ks,
485  const std::vector<idx>& target, idx d = 2) {
486  const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA = A.derived();
487 
488  // EXCEPTION CHECKS
489 
490  // check zero size
492  throw exception::ZeroSize("qpp::measure()");
493 
494  // check valid dims
495  if (d < 2)
496  throw exception::DimsInvalid("qpp::measure()");
497  // END EXCEPTION CHECKS
498 
499  idx n = internal::get_num_subsys(static_cast<idx>(rA.rows()), d);
500  std::vector<idx> dims(n, d); // local dimensions vector
501 
502  return measure(rA, Ks, target, dims);
503 }
504 
505 // std::initializer_list overload, avoids ambiguity for 2-element lists, see
506 // http://stackoverflow.com
507 // /questions/26750039/ambiguity-when-using-initializer-list-as-parameter
524 template <typename Derived>
525 std::tuple<idx, std::vector<double>, std::vector<cmat>>
526 measure(const Eigen::MatrixBase<Derived>& A,
527  const std::initializer_list<cmat>& Ks, const std::vector<idx>& target,
528  idx d = 2) {
529  return measure(A, std::vector<cmat>(Ks), target, d);
530 }
531 
550 template <typename Derived>
551 std::tuple<idx, std::vector<double>, std::vector<cmat>>
552 measure(const Eigen::MatrixBase<Derived>& A, const cmat& V,
553  const std::vector<idx>& target, const std::vector<idx>& dims) {
554  const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA = A.derived();
555 
556  // EXCEPTION CHECKS
557 
558  // check zero-size
560  throw exception::ZeroSize("qpp::measure()");
561 
562  // check that dimension is valid
563  if (!internal::check_dims(dims))
564  throw exception::DimsInvalid("qpp::measure()");
565 
566  // check that target is valid w.r.t. dims
567  if (!internal::check_subsys_match_dims(target, dims))
568  throw exception::SubsysMismatchDims("qpp::measure()");
569 
570  std::vector<idx> subsys_dims(target.size());
571  for (idx i = 0; i < target.size(); ++i)
572  subsys_dims[i] = dims[target[i]];
573 
574  idx Dsubsys = prod(std::begin(subsys_dims), std::end(subsys_dims));
575 
576  // check the matrix V
578  throw exception::ZeroSize("qpp::measure()");
579  if (Dsubsys != static_cast<idx>(V.rows()))
580  throw exception::DimsMismatchMatrix("qpp::measure()");
581  // END EXCEPTION CHECKS
582 
583  // number of basis elements or number of rank-1 projectors
584  idx M = static_cast<idx>(V.cols());
585 
586  //************ ket ************//
587  if (internal::check_cvector(rA)) {
588  const ket& rpsi = A.derived();
589  // check that dims match state vector
590  if (!internal::check_dims_match_cvect(dims, rA))
591  throw exception::DimsMismatchCvector("qpp::measure()");
592 
593  std::vector<double> prob(M); // probabilities
594  std::vector<cmat> outstates(M); // resulting states
595 
596 #ifdef WITH_OPENMP_
597 #pragma omp parallel for
598 #endif // WITH_OPENMP_
599  for (idx i = 0; i < M; ++i)
600  outstates[i] =
601  ip(static_cast<const ket&>(V.col(i)), rpsi, target, dims);
602 
603  for (idx i = 0; i < M; ++i) {
604  double tmp = norm(outstates[i]);
605  prob[i] = tmp * tmp;
606  if (prob[i] > 0) {
607  // normalized output state
608  // corresponding to measurement result m
609  outstates[i] /= tmp;
610  }
611  }
612 
613  // sample from the probability distribution
614  std::discrete_distribution<idx> dd(std::begin(prob), std::end(prob));
615  auto& gen =
616 #ifdef NO_THREAD_LOCAL_
617  RandomDevices::get_instance().get_prng();
618 #else
619  RandomDevices::get_thread_local_instance().get_prng();
620 #endif
621  idx result = dd(gen);
622 
623  return std::make_tuple(result, prob, outstates);
624  }
625  //************ density matrix ************//
626  else if (internal::check_square_mat(rA)) {
627  // check that dims match rho matrix
628  if (!internal::check_dims_match_mat(dims, rA))
629  throw exception::DimsMismatchMatrix("qpp::measure()");
630 
631  std::vector<cmat> Ks(M);
632  for (idx i = 0; i < M; ++i)
633  Ks[i] = V.col(i) * adjoint(V.col(i));
634 
635  return measure(rA, Ks, target, dims);
636  }
637  //************ Exception: not ket nor density matrix ************//
638  throw exception::MatrixNotSquareNorCvector("qpp::measure()");
639 }
640 
659 template <typename Derived>
660 std::tuple<idx, std::vector<double>, std::vector<cmat>>
661 measure(const Eigen::MatrixBase<Derived>& A, const cmat& V,
662  const std::vector<idx>& target, idx d = 2) {
663  const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA = A.derived();
664 
665  // EXCEPTION CHECKS
666 
667  // check zero size
669  throw exception::ZeroSize("qpp::measure()");
670 
671  // check valid dims
672  if (d < 2)
673  throw exception::DimsInvalid("qpp::measure()");
674  // END EXCEPTION CHECKS
675 
676  idx n = internal::get_num_subsys(static_cast<idx>(rA.rows()), d);
677  std::vector<idx> dims(n, d); // local dimensions vector
678 
679  return measure(rA, V, target, dims);
680 }
681 
695 template <typename Derived>
696 std::tuple<std::vector<idx>, double, cmat>
697 measure_seq(const Eigen::MatrixBase<Derived>& A, std::vector<idx> target,
698  std::vector<idx> dims) {
699  // typename std::remove_const<
700  // typename Eigen::MatrixBase<Derived>::EvalReturnType
701  // >::type rA = A.derived();
702 
703  dyn_mat<typename Derived::Scalar> rA = A.derived();
704 
705  // EXCEPTION CHECKS
706 
707  // check zero-size
709  throw exception::ZeroSize("qpp::measure_seq()");
710  // check that dimension is valid
711  if (!internal::check_dims(dims))
712  throw exception::DimsInvalid("qpp::measure_seq()");
713 
714  // check square matrix or column vector
715  if (internal::check_square_mat(rA)) {
716  // check that dims match rho matrix
717  if (!internal::check_dims_match_mat(dims, rA))
718  throw exception::DimsMismatchMatrix("qpp::measure_seq()");
719  } else if (internal::check_cvector(rA)) {
720  // check that dims match psi column vector
721  if (!internal::check_dims_match_cvect(dims, rA))
722  throw exception::DimsMismatchCvector("qpp::measure_seq()");
723  } else
724  throw exception::MatrixNotSquareNorCvector("qpp::measure_seq()");
725 
726  // check that target is valid w.r.t. dims
727  if (!internal::check_subsys_match_dims(target, dims))
728  throw exception::SubsysMismatchDims("qpp::measure_seq()");
729  // END EXCEPTION CHECKS
730 
731  std::vector<idx> result;
732  double prob = 1;
733 
734  // sort target in decreasing order,
735  // the order of measurements does not matter
736  std::sort(std::begin(target), std::end(target), std::greater<idx>{});
737 
738  //************ density matrix or column vector ************//
739  while (target.size() > 0) {
740  auto tmp = measure(rA, Gates::get_instance().Id(dims[target[0]]),
741  {target[0]}, dims);
742  result.push_back(std::get<0>(tmp));
743  prob *= std::get<1>(tmp)[std::get<0>(tmp)];
744  rA = std::get<2>(tmp)[std::get<0>(tmp)];
745 
746  // remove the subsystem
747  dims.erase(std::next(std::begin(dims), target[0]));
748  target.erase(std::begin(target));
749  }
750  // order result in increasing order with respect to target
751  std::reverse(std::begin(result), std::end(result));
752 
753  return std::make_tuple(result, prob, rA);
754 }
755 
769 template <typename Derived>
770 std::tuple<std::vector<idx>, double, cmat>
771 measure_seq(const Eigen::MatrixBase<Derived>& A, std::vector<idx> target,
772  idx d = 2) {
773  const typename Eigen::MatrixBase<Derived>::EvalReturnType& rA = A.derived();
774 
775  // EXCEPTION CHECKS
776 
777  // check zero size
779  throw exception::ZeroSize("qpp::measure_seq()");
780 
781  // check valid dims
782  if (d < 2)
783  throw exception::DimsInvalid("qpp::measure_seq()");
784  // END EXCEPTION CHECKS
785 
786  idx n = internal::get_num_subsys(static_cast<idx>(rA.rows()), d);
787  std::vector<idx> dims(n, d); // local dimensions vector
788 
789  return measure_seq(rA, target, dims);
790 }
791 
792 } /* namespace qpp */
793 
794 #endif /* INSTRUMENTS_H_ */
bool check_nonzero_size(const T &x) noexcept
Definition: util.h:123
Dimensions not equal exception.
Definition: exception.h:284
Dimension(s) mismatch matrix size exception.
Definition: exception.h:300
constexpr idx maxn
Maximum number of allowed qubits/qudits (subsystems)
Definition: constants.h:67
bool check_subsys_match_dims(const std::vector< idx > &subsys, const std::vector< idx > &dims)
Definition: util.h:219
std::tuple< idx, std::vector< double >, std::vector< cmat > > measure(const Eigen::MatrixBase< Derived > &A, const cmat &V, const std::vector< idx > &target, idx d=2)
Measures the part target of the multi-partite state vector or density matrix A in the orthonormal bas...
Definition: instruments.h:661
bool check_cvector(const Eigen::MatrixBase< Derived > &A)
Definition: util.h:117
dyn_col_vect< typename Derived::Scalar > ip(const Eigen::MatrixBase< Derived > &phi, const Eigen::MatrixBase< Derived > &psi, const std::vector< idx > &subsys, idx d=2)
Generalized inner product.
Definition: instruments.h:173
Derived::Scalar prod(const Eigen::MatrixBase< Derived > &A)
Element-wise product of A.
Definition: functions.h:228
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:365
Eigen::VectorXcd ket
Complex (double precision) dynamic Eigen column vector.
Definition: types.h:54
Matrix is not a column vector exception.
Definition: exception.h:164
Quantum++ main namespace.
Definition: circuits.h:35
double norm(const Eigen::MatrixBase< Derived > &A)
Frobenius norm.
Definition: functions.h:248
Matrix is not square nor column vector exception.
Definition: exception.h:209
Invalid dimension(s) exception.
Definition: exception.h:269
idx get_num_subsys(idx D, idx d)
Definition: util.h:370
bool check_dims_match_cvect(const std::vector< idx > &dims, const Eigen::MatrixBase< Derived > &A)
Definition: util.h:165
dyn_mat< typename Derived::Scalar > ptrace(const Eigen::MatrixBase< Derived > &A, const std::vector< idx > &target, const std::vector< idx > &dims)
Partial trace.
Definition: operations.h:1187
dyn_mat< typename Derived1::Scalar > apply(const Eigen::MatrixBase< Derived1 > &state, const Eigen::MatrixBase< Derived2 > &A, const std::vector< idx > &target, const std::vector< idx > &dims)
Applies the gate A to the part target of the multi-partite state vector or density matrix state...
Definition: operations.h:444
dyn_mat< typename Derived::Scalar > adjoint(const Eigen::MatrixBase< Derived > &A)
Adjoint.
Definition: functions.h:89
Dimension(s) mismatch column vector size exception.
Definition: exception.h:316
std::tuple< std::vector< idx >, double, cmat > measure_seq(const Eigen::MatrixBase< Derived > &A, std::vector< idx > target, idx d=2)
Sequentially measures the part target of the multi-partite state vector or density matrix A in the co...
Definition: instruments.h:771
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
bool check_square_mat(const Eigen::MatrixBase< Derived > &A)
Definition: util.h:99
Derived::Scalar trace(const Eigen::MatrixBase< Derived > &A)
Trace.
Definition: functions.h:130
Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > dyn_col_vect
Dynamic Eigen column vector over the field specified by Scalar.
Definition: types.h:93
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, make sure you use an unsigned type.
Definition: types.h:39
Matrix is not square exception.
Definition: exception.h:149
std::vector< idx > complement(std::vector< idx > subsys, idx n)
Constructs the complement of a subsystem vector.
Definition: functions.h:1780
Object has zero size exception.
Definition: exception.h:134