Tomographer  v2.0
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 
44 #include <tomographer2/tools/cxxutil.h> // tomographer_assert()
45 
46 
47 namespace Tomographer {
48 namespace MathTools {
49 
50 
60 template<typename DerU, typename Rng, typename Log>
61 inline void randomUnitary(Eigen::MatrixBase<DerU> & U, Rng & rng, Log & logger)
62 {
63  { using namespace Eigen; EIGEN_STATIC_ASSERT_LVALUE(DerU); }
64 
65  tomographer_assert(U.rows() == U.cols());
66  const int n = U.rows();
67 
68  logger.longdebug("randomUnitary()", "n = %d", n);
69 
70  typedef typename DerU::Scalar Scalar;
73 
74  // first, get a matrix of normally distributed random numbers
75  MatrixType A(n,n);
76 
77  std::normal_distribution<> normdist(0.0, 1.0);
78  A = Tomographer::Tools::denseRandom<MatrixType>(rng, normdist, n, n);
79 
80  // logger.longdebug("randomUnitary()", [&](std::ostream& str) {
81  // str << "got A = \n" << A;
82  // });
83 
84  // Gram-Schmidt orthogonalization
85 
86  for (int j = 0; j < n; ++j) {
87 
88  VectorType v = VectorType::Zero(n);
89  v = A.col(j);
90  //auto v = A.col(j);
91 
92  for (int k = 0; k < j; ++k) {
93  Scalar p = U.col(k).adjoint() * v;
94  v = v - p*U.col(k);
95  }
96 
97  U.col(j) = v / v.norm();
98 
99  // logger.longdebug("randomUnitary()", [&](std::ostream & str) {
100  // str << "dealt with column " << j << " = " << v.transpose() << "\n"
101  // << "\t--> " << U.col(j).transpose() << "\n"
102  // << "\tnorm = " << U.col(j).squaredNorm() << " == " << U.col(j).adjoint() * U.col(j);
103  // });
104  }
105 
106  logger.longdebug("randomUnitary()", [&](std::ostream& str) {
107  str << "randomUnitary: got U = \n" << U << "\n"
108  << "Check: U*U.adjoint() ==\n" << U*U.adjoint() << "\n"
109  << "Check: U.adjoint()*U ==\n" << U.adjoint()*U;
110  });
111 }
112 
114 template<typename Der1, typename Rng>
115 inline void randomUnitary(Eigen::MatrixBase<Der1> & U, Rng & rng)
116 {
117  randomUnitary<Der1, Rng>(U, rng, Logger::vacuum_logger);
118 }
119 
120 
121 } // namespace MathTools
122 } // namespace Tomographer
123 
124 
125 #endif
Base namespace for the Tomographer project.
Definition: densellh.h:44
ColXpr col(Index i)
void randomUnitary(Eigen::MatrixBase< DerU > &U, Rng &rng, Log &logger)
Generate a Haar-distributed random unitary.
Basic utilities for dealing with Eigen matrices and other types.
Some C++ utilities, with a tad of C++11 tricks.
const AdjointReturnType adjoint() const
STL class.
Utilities for logging messages.