brute-force.cl 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. #include <pyopencl-complex.h>
  2. /*
  3. * Returns the nth number where a given digit
  4. * is cleared in the binary representation of the number
  5. */
  6. static uint nth_cleared(uint n, uint target)
  7. {
  8. uint mask = (1 << target) - 1;
  9. uint not_mask = ~mask;
  10. return (n & mask) | ((n & not_mask) << 1);
  11. }
  12. ///////////////////////////////////////////////
  13. // KERNELS
  14. ///////////////////////////////////////////////
  15. /*
  16. * Applies a single qubit gate to the register.
  17. * The gate matrix must be given in the form:
  18. *
  19. * A B
  20. * C D
  21. */
  22. __kernel void apply_gate(
  23. __global cfloat_t *amplitudes,
  24. uint target,
  25. cfloat_t A,
  26. cfloat_t B,
  27. cfloat_t C,
  28. cfloat_t D)
  29. {
  30. uint const global_id = get_global_id(0);
  31. uint const zero_state = nth_cleared(global_id, target);
  32. // uint const zero_state = state & (~(1 << target)); // Could just be state
  33. uint const one_state = zero_state | (1 << target);
  34. cfloat_t const zero_amp = amplitudes[zero_state];
  35. cfloat_t const one_amp = amplitudes[one_state];
  36. amplitudes[zero_state] = cfloat_add(cfloat_mul(A, zero_amp), cfloat_mul(B, one_amp));
  37. amplitudes[one_state] = cfloat_add(cfloat_mul(D, one_amp), cfloat_mul(C, zero_amp));
  38. }
  39. /*
  40. * Applies a controlled single qubit gate to the register.
  41. */
  42. __kernel void apply_controlled_gate(
  43. __global cfloat_t *amplitudes,
  44. uint control,
  45. uint target,
  46. cfloat_t A,
  47. cfloat_t B,
  48. cfloat_t C,
  49. cfloat_t D)
  50. {
  51. uint const global_id = get_global_id(0);
  52. uint const zero_state = nth_cleared(global_id, target);
  53. uint const one_state = zero_state | (1 << target); // Set the target bit
  54. uint const control_val_zero = (((1 << control) & zero_state) > 0) ? 1 : 0;
  55. uint const control_val_one = (((1 << control) & one_state) > 0) ? 1 : 0;
  56. cfloat_t const zero_amp = amplitudes[zero_state];
  57. cfloat_t const one_amp = amplitudes[one_state];
  58. if (control_val_zero == 1)
  59. {
  60. amplitudes[zero_state] = cfloat_add(cfloat_mul(A, zero_amp), cfloat_mul(B, one_amp));
  61. }
  62. if (control_val_one == 1)
  63. {
  64. amplitudes[one_state] = cfloat_add(cfloat_mul(D, one_amp), cfloat_mul(C, zero_amp));
  65. }
  66. }
  67. /*
  68. * Applies a controlled-controlled single qubit gate to the register.
  69. * NOT MIGRATED
  70. */
  71. __kernel void apply_controlled_controlled_gate(
  72. __global cfloat_t *const amplitudes,
  73. __global cfloat_t *amps,
  74. uint control1,
  75. uint control2,
  76. uint target,
  77. cfloat_t A,
  78. cfloat_t B,
  79. cfloat_t C,
  80. cfloat_t D)
  81. {
  82. uint const state = get_global_id(0);
  83. cfloat_t const amp = amplitudes[state];
  84. uint const zero_state = state & (~(1 << target));
  85. uint const one_state = state | (1 << target);
  86. uint const bit_val = (((1 << target) & state) > 0) ? 1 : 0;
  87. uint const control1_val = (((1 << control1) & state) > 0) ? 1 : 0;
  88. uint const control2_val = (((1 << control2) & state) > 0) ? 1 : 0;
  89. if (control1_val == 0 || control2_val == 0)
  90. {
  91. // Control is 0, don't apply gate
  92. amps[state] = amp;
  93. }
  94. else
  95. {
  96. // control is 1, apply gate.
  97. if (bit_val == 0)
  98. {
  99. // Bitval = 0
  100. amps[state] = cfloat_add(cfloat_mul(A, amp), cfloat_mul(B, amplitudes[one_state]));
  101. }
  102. else
  103. {
  104. amps[state] = cfloat_add(cfloat_mul(D, amp), cfloat_mul(C, amplitudes[zero_state]));
  105. }
  106. }
  107. }
  108. /*
  109. * Swaps the states of two qubits in the register
  110. * NOT MIGRATED
  111. */
  112. // __kernel void swap(
  113. // __global cfloat_t *const amplitudes,
  114. // __global cfloat_t *amps,
  115. // uint first_qubit,
  116. // uint second_qubit)
  117. // {
  118. // uint const state = get_global_id(0);
  119. // uint const first_bit_mask = 1 << first_qubit;
  120. // uint const second_bit_mask = 1 << second_qubit;
  121. // uint const new_second_bit = ((state & first_bit_mask) >> first_qubit) << second_qubit;
  122. // uint const new_first_bit = ((state & second_bit_mask) >> second_qubit) << first_qubit;
  123. // uint const new_state = (state & !first_bit_mask & !second_bit_mask) | new_first_bit | new_second_bit;
  124. // amps[new_state] = amplitudes[state];
  125. // }
  126. /**
  127. * Calculates The Probabilities Of A State Vector
  128. */
  129. __kernel void calculate_probabilities(
  130. __global cfloat_t *const amplitudes,
  131. __global float *probabilities)
  132. {
  133. uint const state = get_global_id(0);
  134. cfloat_t amp = amplitudes[state];
  135. probabilities[state] = cfloat_abs(cfloat_mul(amp, amp));
  136. }
  137. /**
  138. * Initializes a register to the value 1|0..100...0>
  139. * ^ target
  140. */
  141. __kernel void initialize_register(
  142. __global cfloat_t *amplitudes,
  143. uint const target)
  144. {
  145. uint const state = get_global_id(0);
  146. if (state == target)
  147. {
  148. amplitudes[state] = cfloat_new(1, 0);
  149. }
  150. else
  151. {
  152. amplitudes[state] = cfloat_new(0, 0);
  153. }
  154. }