private int i1, i2; // Indices of non-trivial submatrix. public TwoLevelUnitary(Complex[,] mx, int i1, int i2) { Debug.Assert(MatrixUtils.IsMatrixUnitary(mx), "Matrix is not unitary"); this.mx = mx; this.i1 = i1; this.i2 = i2; }
// Decomposes unitary matrix into product of 2-level unitary matrices. // Every resulting 2-level matrix is represnted by 2x2 non-trivial submatrix and indices // of this submatrix. Indices are guaranteed to be sorted and to differ in exactly one // bit. private IQArray <(IQArray <IQArray <Quantum.Math.Complex> >, long, long)> Decompose( IQArray <IQArray <Quantum.Math.Complex> > unitary) { Complex[,] a = MatrixUtils.MatrixFromQs(unitary); return(new QArray <(IQArray <IQArray <Quantum.Math.Complex> >, long, long)>( TwoLevelDecomposeGray(a).Select(matrix => matrix.ToQsharp()) )); }
// Returns list of two-level unitary matrices, which multiply to A. // Every matrix has indices differing in exactly 1 bit. private static IEnumerable <TwoLevelUnitary> TwoLevelDecomposeGray(Complex[,] A) { int n = A.GetLength(0); Debug.Assert(A.GetLength(1) == n, "Matrix is not square."); Debug.Assert(MatrixUtils.IsMatrixUnitary(A), "Matrix is not unitary."); int[] perm = GrayCode(n); A = PermuteMatrix(A, perm); foreach (TwoLevelUnitary matrix in TwoLevelDecompose(A)) { matrix.ApplyPermutation(perm); matrix.OrderIndices(); yield return(matrix); } }