Tomographer  v1.0a
Tomographer C++ Framework Documentation
random_unitary.h
Go to the documentation of this file.
1 /* This file is part of the Tomographer project, which is distributed under the
2  * terms of the MIT license.
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2015 ETH Zurich, Institute for Theoretical Physics, Philippe Faist
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 
27 #ifndef RANDOM_UNITARY_H
28 #define RANDOM_UNITARY_H
29 
37 #include <iostream>
38 #include <random>
39 
40 #include <Eigen/Core>
41 
42 #include <tomographer/qit/util.h>
44 
45 
46 namespace Tomographer
47 {
48 
49 
59 template<typename DerU, typename Rng, typename Log>
60 inline void random_unitary(Eigen::MatrixBase<DerU> & U, Rng & rng, Log & logger)
61 {
62  { using namespace Eigen; EIGEN_STATIC_ASSERT_LVALUE(DerU); }
63 
64  assert(U.rows() == U.cols());
65  const int n = U.rows();
66 
67  logger.longdebug("random_unitary()", "n = %d", n);
68 
69  typedef typename DerU::Scalar Scalar;
72 
73  // first, get a matrix of normally distributed random numbers
74  MatrixType A(n,n);
75 
76  std::normal_distribution<> normdist(0.0, 1.0);
77  A = Tomographer::dense_random<MatrixType>(rng, normdist, n, n);
78 
79  // logger.longdebug("random_unitary()", [&](std::ostream& str) {
80  // str << "got A = \n" << A;
81  // });
82 
83  // gram-schmidt orthogonalization
84 
85  for (int j = 0; j < n; ++j) {
86 
87  VectorType v = VectorType::Zero(n);
88  v = A.col(j);
89  //auto v = A.col(j);
90 
91  for (int k = 0; k < j; ++k) {
92  Scalar p = U.col(k).adjoint() * v;
93  v = v - p*U.col(k);
94  }
95 
96  U.col(j) = v / v.norm();
97 
98  // logger.longdebug("random_unitary()", [&](std::ostream & str) {
99  // str << "dealt with column " << j << " = " << v.transpose() << "\n"
100  // << "\t--> " << U.col(j).transpose() << "\n"
101  // << "\tnorm = " << U.col(j).squaredNorm() << " == " << U.col(j).adjoint() * U.col(j);
102  // });
103  }
104 
105  logger.longdebug("random_unitary()", [&](std::ostream& str) {
106  str << "random_unitary: got U = \n" << U << "\n"
107  << "Check: U*U.adjoint() ==\n" << U*U.adjoint() << "\n"
108  << "Check: U.adjoint()*U ==\n" << U.adjoint()*U;
109  });
110 }
111 
113 template<typename Der1, typename Rng>
114 inline void random_unitary(Eigen::MatrixBase<Der1> & U, Rng & rng)
115 {
116  random_unitary<Der1, Rng>(U, rng, Logger::vacuum_logger);
117 }
118 
119 
120 
121 } // namespace Tomographer
122 
123 #endif
Base namespace for the Tomographer project.
Definition: dmmhrw.h:51
ColXpr col(Index i)
void random_unitary(Eigen::MatrixBase< DerU > &U, Rng &rng, Log &logger)
Generate a Haar-distributed random unitary.
const AdjointReturnType adjoint() const
STL class.
Basic utilities for dealing with Eigen matrices and other types.
Utilities for logging messages.