Given a unitary matrix U and a list of matrices Mlist how can I apply the unitary transformation to the list?

  • 2
    $\begingroup$ By mapping an appropriate function? Look up ‘Map’ as a start. You should also provide an example of these matrices and list. I notice that you asked a question along the same lines before, regarding applying ‘Complement’ to a list of matrices. Perhaps some of the techniques shown in the answers there provide a starting point as well. $\endgroup$
    – MarcoB
    Commented May 5, 2018 at 4:27

3 Answers 3


This is a sample example that uses Map. I have defined a function to generate any $2\times2$ $SU(2)$ transformation upto an overall phase and used one such transformation to change the list of matrices.

matrices = RandomComplex[{-1 - I, 1 + I}, {10, 2, 2}];

unitary[θ_, ϕ1_, ϕ2_] := {
 {E^(I ϕ1) Cos[θ], E^(I ϕ2) Sin[θ]}, 
 {-E^(I ϕ2) Sin[θ], E^(- I ϕ1) Cos[θ]}

      unitary[π/4, π/5, π/6]].#.unitary[π/4, π/ 5, π/6]) & /@ matrices;

Matrix operations automatically use parallelization when possible, so using matrix operations and avoiding Map will provide a speed gain. Using @Henrik's example:

a = Map[ConjugateTranspose[U].#.U&, matrices]; //RepeatedTiming
b = cf[matrices,ConjugateTranspose[U],U]; //RepeatedTiming
c = Transpose[ConjugateTranspose[U] . Transpose[matrices] . U]; //RepeatedTiming

Block[{Internal`$EqualTolerance=5}, a==b==c]

{0.0086, Null}

{0.0024, Null}

{0.0016, Null}


So, using Dot and Transpose is faster than @Henrik's compiled version.

Note that I used 10^4 matrices instead of 10^5. As the number of matrices increases, the compiled version eventually becomes faster.

  • 1
    $\begingroup$ Very interesting. Must be very machine dependend. On my old Haswell, method c takes 1.5 to 2 times as long as the compiled version. Might have to do with slower RAM (@1600 MHz)? This is why I got the habit to leave MTensors in their natural ordering. $\endgroup$ Commented May 5, 2018 at 17:11
  • 2
    $\begingroup$ @HenrikSchumacher I also get similar slower results for c on a 2013 MacBook Pro $\endgroup$
    – Michael E2
    Commented May 5, 2018 at 17:36

If you have to do that really often and with numerical matrices, it may be worth the effort to write a CompiledFunction with RuntimeAttributes -> {Listable}. This is usually faster than using Map, since it can also utilize parallelization.

cf = Compile[{{A, _Complex, 2}, {U, _Complex, 2}, {V, _Complex, 2}},
   RuntimeAttributes -> {Listable},
   Parallelization -> True

n = 4;
matrices = RandomComplex[{-1 - I, 1 + I}, {100000, n, n}];
U = RandomVariate[CircularUnitaryMatrixDistribution[n]];

a = Map[ConjugateTranspose[U].#.U &, matrices]; // RepeatedTiming // First
b = cf[matrices, ConjugateTranspose[U], U]; // RepeatedTiming // First
Max[Abs[a - b]]




  • $\begingroup$ I was totally unaware of the CircularUnitaryDistribution function. $\endgroup$
    – Subho
    Commented May 5, 2018 at 9:32
  • 1
    $\begingroup$ Yeah, it's great, isn't it? I experienced all the matrix distributions for myself only recently. $\endgroup$ Commented May 5, 2018 at 9:34
  • 1
    $\begingroup$ Sure it is! Great to stumble upon such functions every once in a while. $\endgroup$
    – Subho
    Commented May 5, 2018 at 9:35
  • 2
    $\begingroup$ @Subho95 The reason Map is so slow here is that the function defined in terms of f is uncompilable. The consequent unpacking of matrices also contributes to the slowness. Map[ConjugateTranspose[U].#.U &, matrices] is about 4-5 times faster and does not unpack matrices. The compiled cf and the difference with the compiled is another 4 times faster, which speedup is explained by parallelization (on my quad-core i7). $\endgroup$
    – Michael E2
    Commented May 5, 2018 at 12:29
  • $\begingroup$ @Michael E2, Thank you. $\endgroup$ Commented May 5, 2018 at 14:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.