@@ -90,7 +90,7 @@ Note that in the example above, the transposition (0 2) was automatically added.
9090
9191 (declare (inline check-transposition))
9292
93- (loop :for (a . b) :in transpositions :do
93+ (loop :for (a . b) :of-type alexandria :non-negative-fixnum : in transpositions :do
9494 (check-transposition a b)
9595 (unless (= a b)
9696 (pushnew (cons a b) transpositions*)
@@ -204,10 +204,11 @@ DQVM2> (write (apply-qubit-permutation (make-permutation '((2 . 0))) #b001) :bas
204204 (let ((tau (slot-value permutation ' tau)))
205205 (declare (type (unsigned-byte 6 ) tau))
206206
207- (rotatef (ldb (byte 1 0 ) address) (ldb (byte 1 tau) address))
208- address))
207+ ; ; Swap bits 0 and TAU in ADDRESS.
208+ (let ((x (logxor (logand address 1 ) (logand (ash address (- tau)) 1 ))))
209+ (logxor address (logior x (ash x tau))))))
209210
210- (defmethod apply-qubit-permutation ((permutation permutation) address)
211+ (defmethod apply-qubit-permutation ((permutation permutation-general ) address)
211212 ; ; Alternatively, in-place permutations could be implemented following:
212213 ; ;
213214 ; ; F. Fich, J. Munro, and P. Poblete, “Permuting in Place,” SIAM
@@ -239,6 +240,55 @@ DQVM2> (write (apply-qubit-permutation (make-permutation '((2 . 0))) #b001) :bas
239240 address)))
240241 :finally (return address))))
241242
243+ (defgeneric generate-qubit-permutation-code (permutation)
244+ (:documentation " Generate lambda function equivalent to APPLY-QUBIT-PERMUTATION suitable to be compiled." )
245+ (declare #. qvm::*optimize-dangerously-fast* ))
246+
247+ (defmethod generate-qubit-permutation-code ((permutation (eql nil )))
248+ (let ((address (gensym " ADDRESS-" )))
249+ ` (lambda (, address)
250+ (declare #. qvm::*optimize-dangerously-fast* )
251+ , address)))
252+
253+ (defmethod generate-qubit-permutation-code ((permutation permutation-transposition))
254+ (let* ((address (gensym " ADDRESS-" ))
255+ (tau (slot-value permutation ' tau))
256+ (minus-tau (- tau)))
257+ ` (lambda (, address)
258+ (declare #. qvm::*optimize-dangerously-fast*
259+ (type (unsigned-byte 64 ) , address) ; Imposed maximum number of qubits.
260+ (values qvm :amplitude-address))
261+
262+ ; ; Swap bits 0 and TAU in ADDRESS.
263+ (let ((x (logxor (logand , address 1 ) (logand (ash , address , minus-tau) 1 ))))
264+ (logxor , address (logior x (ash x , tau)))))))
265+
266+ (defmethod generate-qubit-permutation-code ((permutation permutation-general))
267+ (let ((address (gensym " ADDRESS-" ))
268+ (transpositions (slot-value permutation ' transpositions))
269+ (number-of-transpositions (slot-value permutation ' number-of-transpositions)))
270+ ` (lambda (, address)
271+ (declare #. qvm::*optimize-dangerously-fast*
272+ (type (or null permutation) permutation)
273+ (type (unsigned-byte 64 ) , address)
274+ (values qvm :amplitude-address))
275+
276+ (let ((bit-vector (make-array , number-of-transpositions :element-type ' bit)))
277+ (declare (dynamic-extent bit-vector ))
278+
279+ ,@ (loop :for index :from 0
280+ :for transposition :of-type transposition :in transpositions
281+ :collect ` (setf (bit bit-vector , index) (ldb (byte 1 , (first transposition))
282+ , address)))
283+
284+ ,@ (loop :for index :from 0
285+ :for transposition :of-type transposition :in transpositions
286+ :collect ` (setf , address (the qvm :amplitude-address
287+ (dpb (bit bit-vector , index)
288+ (byte 1 (the (unsigned-byte 6 ) , (rest transposition)))
289+ , address))))
290+ , address))))
291+
242292(defun-inlinable apply-inverse-qubit-permutation (permutation address)
243293 (apply-qubit-permutation (inverse-permutation permutation) address))
244294
0 commit comments