cuda-quantum icon indicating copy to clipboard operation
cuda-quantum copied to clipboard

Fix spin op bug

Open sacpis opened this issue 5 months ago • 13 comments

  • Fixing the phase calculation in spin_op multiplication operator
  • Removing terms with 0 coefficient
  • Adding unittests for all combinations of Pauli matrices multiplication

The output follows the Openfermion's implementation of Jordan Wigner transformation (mapping fermion operators to spin operators) implementation. (Above comment and following code examples by @amccaskey)

p = 0 
q = 2 
one_elec = openfermion.FermionOperator(((q,1),(p,0)))-openfermion.FermionOperator(((p,1),(q,0)))
print(openfermion.jordan_wigner(one_elec))

-0.5j [X0 Z1 Y2] +
0.5j [Y0 Z1 X2]

This is how @amccaskey is implementing Wigner transformation using CUDA-Q

#include "cudaq/spin_op.h"

using namespace cudaq; 

spin_op adag(std::size_t numQubits, std::size_t p) {
  spin_op zprod;
  for (std::size_t k = 0; k < p; k++)
    zprod *= spin::z(k);
  return 0.5 * zprod * (spin::x(p) - std::complex<double>{0, 1} * spin::y(p));
}

spin_op a(std::size_t numQubits, std::size_t q) {
  spin_op zprod;
  for (std::size_t k = 0; k < q; k++)
    zprod *= spin::z(k);
  return 0.5 * zprod * (spin::x(q) + std::complex<double>{0, 1} * spin::y(q));
}


int main() {
  std::size_t p = 0;
  std::size_t q = 2;

  auto op = adag(4, q) * a(4, p) - adag(4, p) * a(4, q);
  op.dump();
}

output

root@e57345e57788:/workspaces/cuda-quantum# nvq++ examples/cpp/other/test.cpp -o a.out && ./a.out
[0-0.5j] XZY
[0+0.5j] YZX

ctest result

100% tests passed, 0 tests failed out of 644

Label Time Summary:
gpu_required    =  88.55 sec*proc (367 tests)

Total Test time (real) = 1061.41 sec

Test result for tetsing done with code in Bettina's branch

# With block commented (in expressions)

pauliX(0) * (pauliZ(0) + pauliZ(1)): 

[[ 0.+0.j  0.+0.j  0.+0.j  0.+0.j]
 [ 2.+0.j  0.+0.j  0.+0.j  0.+0.j]
 [ 0.+0.j  0.+0.j  0.+0.j -2.+0.j]
 [ 0.+0.j  0.+0.j  0.+0.j  0.+0.j]]

(pauliZ(0) + pauliZ(1)) * pauliX(0): 

[[ 0.+0.j  2.+0.j  0.+0.j  0.+0.j]
 [ 0.+0.j  0.+0.j  0.+0.j  0.+0.j]
 [ 0.+0.j  0.+0.j  0.+0.j  0.+0.j]
 [ 0.+0.j  0.+0.j -2.+0.j  0.+0.j]]


# Without block commented (in expressions)

pauliX(0) * (pauliZ(0) + pauliZ(1)): 

[[ 0.+0.j  0.+0.j  0.+0.j  0.+0.j]
 [ 2.+0.j  0.+0.j  0.+0.j  0.+0.j]
 [ 0.+0.j  0.+0.j  0.+0.j -2.+0.j]
 [ 0.+0.j  0.+0.j  0.+0.j  0.+0.j]]

(pauliZ(0) + pauliZ(1)) * pauliX(0): 

[[ 0.+0.j  2.+0.j  0.+0.j  0.+0.j]
 [ 0.+0.j  0.+0.j  0.+0.j  0.+0.j]
 [ 0.+0.j  0.+0.j  0.+0.j  0.+0.j]
 [ 0.+0.j  0.+0.j -2.+0.j  0.+0.j]]

Tests from Marwa's script

Openfermion

a_p a^dagger_q
1.0 [3 7^]
(-0.25+0j) [X3 Z4 Z5 Z6 X7] +
0.25j [X3 Z4 Z5 Z6 Y7] +
-0.25j [Y3 Z4 Z5 Z6 X7] +
(-0.25+0j) [Y3 Z4 Z5 Z6 Y7]


a_q a^dagger_p
1.0 [7^ 3]
(0.25+0j) [X3 Z4 Z5 Z6 X7] +
-0.25j [X3 Z4 Z5 Z6 Y7] +
0.25j [Y3 Z4 Z5 Z6 X7] +
(0.25+0j) [Y3 Z4 Z5 Z6 Y7]

a_p a^dagger_q
1.0 [3^ 7]
(0.25+0j) [X3 Z4 Z5 Z6 X7] +
0.25j [X3 Z4 Z5 Z6 Y7] +
-0.25j [Y3 Z4 Z5 Z6 X7] +
(0.25+0j) [Y3 Z4 Z5 Z6 Y7]


a_q a^dagger_p
1.0 [7 3^]
(-0.25+0j) [X3 Z4 Z5 Z6 X7] +
-0.25j [X3 Z4 Z5 Z6 Y7] +
0.25j [Y3 Z4 Z5 Z6 X7] +
(-0.25+0j) [Y3 Z4 Z5 Z6 Y7]


From CUDA-Q

a_p a^dagger_q
3 7^
[-0.25+0j] IIIXZZZX
[0+0.25j] IIIXZZZY
[0-0.25j] IIIYZZZX
[-0.25+0j] IIIYZZZY

a_q a^dagger_p
7^ 3
[0.25+0j] IIIXZZZX
[0+0.25j] IIIYZZZX
[0-0.25j] IIIXZZZY
[0.25+0j] IIIYZZZY

a_q a^dagger_p
3^ 7
[0.25+0j] IIIXZZZX
[0+0.25j] IIIXZZZY
[0-0.25j] IIIYZZZX
[0.25+0j] IIIYZZZY

a_p a^dagger_q
7 3^
[-0.25+0j] IIIXZZZX
[0+0.25j] IIIYZZZX
[0-0.25j] IIIXZZZY
[-0.25+0j] IIIYZZZY

sacpis avatar Aug 29 '24 17:08 sacpis