XACC
noise.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 - 2020 Vlad Gheorghiu.
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 CLASSES_NOISE_H_
33 #define CLASSES_NOISE_H_
34 
35 namespace qpp {
40 struct NoiseType {
45  struct StateDependent;
46 
51  struct StateIndependent;
52 };
57 template <class T>
58 class NoiseBase {
59  public:
60  using noise_type = T;
61  static_assert(
62  std::is_same<NoiseType::StateDependent, noise_type>::value ||
63  std::is_same<NoiseType::StateIndependent, noise_type>::value,
64  "");
65 
66  protected:
67  const std::vector<cmat> Ks_;
68  mutable std::vector<double> probs_;
69  mutable idx d_{};
70 
71  mutable idx i_{};
72  mutable bool generated_{false};
73 
83  void compute_probs_(const cmat& state,
84  const std::vector<idx>& target) const {
85  if (!std::is_same<NoiseType::StateDependent, noise_type>::value)
86  return; // no-op
87 
88  // minimal EXCEPTION CHECKS
89 
90  if (!internal::check_nonzero_size(state))
91  throw exception::ZeroSize("qpp::NoiseBase::compute_probs_()");
92  // END EXCEPTION CHECKS
93 
94  cmat rho_i;
95  idx n = internal::get_num_subsys(state.rows(), d_);
96 
97  for (idx i = 0; i < Ks_.size(); ++i) {
98  rho_i = ptrace(state, complement(target, n), d_);
99  probs_[i] = trace(Ks_[i] * rho_i * adjoint(Ks_[i])).real();
100  }
101  } /* compute_probs_() */
102 
110  cmat compute_state_(const cmat& state,
111  const std::vector<idx>& target) const {
112  cmat result;
113  idx D = static_cast<idx>(state.rows());
114 
115  //************ ket ************//
116  if (internal::check_cvector(state)) {
117  result.resize(D, 1);
118  }
119  //************ density matrix ************//
120  else if (internal::check_square_mat(state)) {
121  result.resize(D, D);
122  }
123  //************ Exception: not ket nor density matrix ************//
124  else
125  throw exception::MatrixNotSquareNorCvector(
126  "qpp::NoiseBase::compute_state_()");
127 
128  // now do the actual noise generation
129  std::discrete_distribution<idx> dd{std::begin(probs_),
130  std::end(probs_)};
131  auto& gen =
132 #ifdef NO_THREAD_LOCAL_
133  RandomDevices::get_instance().get_prng();
134 #else
135  RandomDevices::get_thread_local_instance().get_prng();
136 #endif
137  i_ = dd(gen);
138  result = apply(state, Ks_[i_], target, d_);
139  generated_ = true;
140 
141  return normalize(result);
142  } /* compute_state_() */
143 
144  public:
152  template <typename U = noise_type>
153  explicit NoiseBase(
154  const std::vector<cmat>& Ks,
155  typename std::enable_if<
156  std::is_same<NoiseType::StateDependent, U>::value>::type* = nullptr)
157  : Ks_{Ks}, probs_(Ks.size()) {
158  // EXCEPTION CHECKS
159 
160  if (Ks.empty())
161  throw exception::ZeroSize("qpp::NoiseBase::NoiseBase()");
162  if (!internal::check_nonzero_size(Ks[0]))
163  throw exception::ZeroSize("qpp::NoiseBase::NoiseBase()");
164  if (!internal::check_square_mat(Ks[0]))
165  throw exception::MatrixNotSquare("qpp::NoiseBase::NoiseBase()");
166  for (auto&& elem : Ks)
167  if (elem.rows() != Ks[0].rows() || elem.cols() != Ks[0].rows())
168  throw exception::DimsNotEqual("qpp::NoiseBase::NoiseBase()");
169  // END EXCEPTION CHECKS
170 
171  d_ = Ks[0].rows(); // set the local dimension
172  }
173 
182  template <typename U = noise_type>
183  explicit NoiseBase(
184  const std::vector<cmat>& Ks, const std::vector<double>& probs,
185  typename std::enable_if<std::is_same<NoiseType::StateIndependent,
186  U>::value>::type* = nullptr)
187  : Ks_{Ks}, probs_(probs) {
188  // EXCEPTION CHECKS
189 
190  if (Ks.empty())
191  throw exception::ZeroSize("qpp::NoiseBase::NoiseBase()");
192  if (Ks.size() != probs.size())
193  throw exception::SizeMismatch("qpp::NoiseBase::NoiseBase");
194  if (!internal::check_nonzero_size(Ks[0]))
195  throw exception::ZeroSize("qpp::NoiseBase::NoiseBase()");
196  if (!internal::check_square_mat(Ks[0]))
197  throw exception::MatrixNotSquare("qpp::NoiseBase::NoiseBase()");
198  for (auto&& elem : Ks)
199  if (elem.rows() != Ks[0].rows() || elem.cols() != Ks[0].rows())
200  throw exception::DimsNotEqual("qpp::NoiseBase::NoiseBase()");
201  for (auto&& elem : probs)
202  if (elem < 0 || elem > 1)
203  throw exception::OutOfRange("qpp::NoiseBase::NoiseBase");
204  // END EXCEPTION CHECKS
205 
206  d_ = Ks[0].rows(); // set the local dimension
207  probs_ = probs;
208  }
209 
213  virtual ~NoiseBase() = default;
214 
215  // getters
221  idx get_d() const noexcept { return d_; };
222 
228  std::vector<cmat> get_Ks() const { return Ks_; }
229 
235  std::vector<double> get_probs() const {
236  if (generated_ ||
237  std::is_same<NoiseType::StateIndependent, noise_type>::value) {
238  return probs_;
239  } else
240  throw exception::CustomException(
241  "qpp::NoiseBase::get_probs()",
242  "NoiseBase::operator() was not yet invoked");
243  }
244 
250  idx get_last_idx() const {
251  if (generated_) {
252  return i_;
253  } else
254  throw exception::CustomException(
255  "qpp::NoiseBase::get_last_idx()",
256  "NoiseBase::operator() was not yet invoked");
257  }
258 
264  double get_last_p() const {
265  if (generated_) {
266  return probs_[i_];
267  } else
268  throw exception::CustomException(
269  "qpp::NoiseBase::get_last_p()",
270  "NoiseBase::operator() was not yet invoked");
271  }
272 
278  cmat get_last_K() const {
279  if (generated_) {
280  return Ks_[i_];
281  } else
282  throw exception::CustomException(
283  "qpp::NoiseBase::get_last_K()",
284  "NoiseBase::operator() was not yet invoked");
285  }
286  // end getters
287 
295  virtual cmat operator()(const cmat& state) const {
296  cmat result;
297  try {
298 
299  compute_probs_(state, std::vector<idx>{0});
300  result = compute_state_(state, std::vector<idx>{0});
301  } catch (exception::Exception&) {
302  std::cerr << "In qpp::NoiseBase::operator()\n";
303  throw;
304  }
305 
306  return result;
307  }
308 
318  virtual cmat operator()(const cmat& state, idx target) const {
319  cmat result;
320  try {
321  compute_probs_(state, std::vector<idx>{target});
322  result = compute_state_(state, std::vector<idx>{target});
323  } catch (exception::Exception&) {
324  std::cerr << "In qpp::NoiseBase::operator()\n";
325  throw;
326  }
327 
328  return result;
329  }
330 
340  virtual cmat operator()(const cmat& state,
341  const std::vector<idx>& target) const {
342  cmat result;
343  try {
344  compute_probs_(state, target);
345  result = compute_state_(state, target);
346  } catch (exception::Exception&) {
347  std::cerr << "In qpp::NoiseBase::operator()\n";
348  throw;
349  }
350 
351  return result;
352  }
353 }; /* class NoiseBase */
354 
355 // qubit noise models
356 
361 class QubitDepolarizingNoise : public NoiseBase<NoiseType::StateIndependent> {
362  public:
368  explicit QubitDepolarizingNoise(double p)
369  : NoiseBase({Gates::get_instance().Id2, Gates::get_instance().X,
370  Gates::get_instance().Y, Gates::get_instance().Z},
371  {1 - p, p / 3, p / 3, p / 3}) {
372  // EXCEPTION CHECKS
373 
374  if (p < 0 || p > 1)
375  throw exception::OutOfRange(
376  "qpp::QubitDepolarizingNoise::QubitDepolarizingNoise()");
377  // END EXCEPTION CHECKS
378  }
379 }; /* class QubitDepolarizingNoise */
380 
385 class QubitPhaseFlipNoise : public NoiseBase<NoiseType::StateIndependent> {
386  public:
392  explicit QubitPhaseFlipNoise(double p)
393  : NoiseBase({Gates::get_instance().Id2, Gates::get_instance().Z},
394  {1 - p, p}) {
395  // EXCEPTION CHECKS
396 
397  if (p < 0 || p > 1)
398  throw exception::OutOfRange(
399  "qpp::QubitPhaseFlipNoise::QubitPhaseFlipNoise()");
400  // END EXCEPTION CHECKS
401  }
402 }; /* class QubitPhaseFlipNoise */
403 
408 class QubitBitFlipNoise : public NoiseBase<NoiseType::StateIndependent> {
409  public:
415  explicit QubitBitFlipNoise(double p)
416  : NoiseBase({Gates::get_instance().Id2, Gates::get_instance().X},
417  {1 - p, p}) {
418  // EXCEPTION CHECKS
419 
420  if (p < 0 || p > 1)
421  throw exception::OutOfRange(
422  "qpp::QubitBitFlipNoise::QubitBitFlipNoise()");
423  // END EXCEPTION CHECKS
424  }
425 }; /* class QubitBitFlipNoise */
426 
431 class QubitBitPhaseFlipNoise : public NoiseBase<NoiseType::StateIndependent> {
432  public:
438  explicit QubitBitPhaseFlipNoise(double p)
439  : NoiseBase({Gates::get_instance().Id2, Gates::get_instance().Y},
440  {1 - p, p}) {
441  // EXCEPTION CHECKS
442 
443  if (p < 0 || p > 1)
444  throw exception::OutOfRange(
445  "qpp::QubitBitPhaseFlipNoise::QubitBitPhaseFlipNoise()");
446  // END EXCEPTION CHECKS
447  }
448 }; /* class QubitBitPhaseFlipNoise */
449 
454 class QubitAmplitudeDampingNoise : public NoiseBase<NoiseType::StateDependent> {
455  public:
461  explicit QubitAmplitudeDampingNoise(double gamma)
462  : NoiseBase(std::vector<cmat>{
463  ((cmat(2, 2)) << 1, 0, 0, std::sqrt(gamma)).finished(),
464  ((cmat(2, 2)) << 0, std::sqrt(1 - gamma), 0, 0).finished()}) {
465  // EXCEPTION CHECKS
466 
467  if (gamma < 0 || gamma > 1)
468  throw exception::OutOfRange("qpp::QubitAmplitudeDampingNoise::"
469  "QubitAmplitudeDampingNoise()");
470  // END EXCEPTION CHECKS
471  }
472 }; /* class QubitAmplitudeDampingNoise */
473 
478 class QubitPhaseDampingNoise : public NoiseBase<NoiseType::StateDependent> {
479  public:
485  explicit QubitPhaseDampingNoise(double lambda)
486  : NoiseBase(std::vector<cmat>{
487  ((cmat(2, 2)) << 1, 0, 0, std::sqrt(1 - lambda)).finished(),
488  ((cmat(2, 2)) << 0, 0, 0, std::sqrt(lambda)).finished()}) {
489  // EXCEPTION CHECKS
490 
491  if (lambda < 0 || lambda > 1)
492  throw exception::OutOfRange("qpp::QubitPhaseDampingNoise::"
493  "QubitPhaseDampingNoise()");
494  // END EXCEPTION CHECKS
495  }
496 }; /* class QubitPhaseDampingNoise */
497 
498 // qudit noise models
499 
504 class QuditDepolarizingNoise : public NoiseBase<NoiseType::StateIndependent> {
511  std::vector<cmat> fill_Ks_(idx d) const {
512  std::vector<cmat> Ks(d * d);
513  idx cnt = 0;
514  for (idx i = 0; i < d; ++i)
515  for (idx j = 0; j < d; ++j)
516  Ks[cnt++] = powm(Gates::get_instance().Xd(d), i) *
517  powm(Gates::get_instance().Zd(d), j);
518 
519  return Ks;
520  }
521 
529  std::vector<double> fill_probs_(double p, idx d) const {
530  std::vector<double> probs(d * d);
531  probs[0] = 1 - p;
532  for (idx i = 1; i < d * d; ++i)
533  probs[i] = p / (d - 1) * (d - 1);
534 
535  return probs;
536  }
537 
538  public:
545  explicit QuditDepolarizingNoise(double p, idx d)
546  : NoiseBase(fill_Ks_(d), fill_probs_(p, d)) {
547  // EXCEPTION CHECKS
548 
549  if (d < 2 || p < 0 || p > 1)
550  throw exception::OutOfRange(
551  "qpp::QuditDepolarizingNoise::QuditDepolarizingNoise()");
552  // END EXCEPTION CHECKS
553  }
554 }; /* class QuditDepolarizingNoise */
555 
556 } /* namespace qpp */
557 
558 #endif /* CLASSES_NOISE_H_ */
Quantum++ main namespace.
Definition: circuits.h:35