Experiment

This commit is contained in:
Alexander Rosenberg 2024-12-19 12:25:23 -08:00
parent f702251949
commit 806fc10d8a
Signed by: Zander671
GPG Key ID: 5FD0394ADBD72730
5 changed files with 105 additions and 73 deletions

View File

@ -4,13 +4,13 @@
(defparameter *circuit-measure-places* 5 (defparameter *circuit-measure-places* 5
"The number of places to use with the :measure instruction in circuits.") "The number of places to use with the :measure instruction in circuits.")
(defun circuit-arbitrary-gate (state operator gate target &optional control) (defun circuit-arbitrary-gate (size operator gate target &optional control)
(declare (ignorable operator)) (declare (ignorable operator))
(if control (if control
(napply-controlled-gate state gate target control) (make-controlled-operator size gate target control)
(napply-gate state gate target))) (make-operator size gate target)))
(defun circuit-matrix-operation (state operator target &optional control) (defun circuit-matrix-operation (size operator target &optional control)
(let ((matrix (case operator (let ((matrix (case operator
(:* +identity-2x2+) (:* +identity-2x2+)
(:x +pauli-x-gate+) (:x +pauli-x-gate+)
@ -22,16 +22,13 @@
(:cnot +pauli-x-gate+) (:cnot +pauli-x-gate+)
(:cz +pauli-z-gate+)))) (:cz +pauli-z-gate+))))
(if control (if control
(napply-controlled-gate state matrix target control) (make-controlled-operator size matrix target control)
(napply-gate state matrix target)))) (make-operator size matrix target))))
(defun circuit-n-controlled-gate (state operator target controls) (defun circuit-n-controlled-gate (size operator target controls)
(let ((func (case operator (case operator
(:ntoff 'make-n-toffoli-operator) (:ntoff (make-n-toffoli-operator size target controls))
(:ncz 'make-n-controlled-z-operator)))) (:ncz (make-n-controlled-z-operator size target controls))))
(replace-state state (*mv (funcall func (state-bits state)
target controls)
state))))
(defparameter *circuit-operators* (defparameter *circuit-operators*
;; Operator, # args, more args?, has output?, function ;; Operator, # args, more args?, has output?, function
@ -47,36 +44,72 @@
(:t 1 nil nil circuit-matrix-operation) (:t 1 nil nil circuit-matrix-operation)
(:cnot 2 nil nil circuit-matrix-operation) (:cnot 2 nil nil circuit-matrix-operation)
(:cz 2 nil nil circuit-matrix-operation) (:cz 2 nil nil circuit-matrix-operation)
(:measure 2 nil t ,(lambda (state operator &rest args)
(declare (ignorable operator))
(nmeasure state (car args)
:places *circuit-measure-places*)))
(:ntoff 2 nil nil circuit-n-controlled-gate) (:ntoff 2 nil nil circuit-n-controlled-gate)
(:ncz 2 nil nil circuit-n-controlled-gate))) (:ncz 2 nil nil circuit-n-controlled-gate)
(:measure 2 nil t ,(lambda (size operator bit target)
(declare (ignorable size operator target))
(lambda (state)
(nmeasure state bit
:places *circuit-measure-places*))))))
(defun make-circuit () (defun make-circuit (bits)
"Create a new blank circuit." "Create a new blank circuit of BITS bits."
'(:circuit)) `(:circuit ,bits))
(defun circuitp (obj)
"Return non-nil if OBJ is a quantum circuit."
(and (eq (first obj) :circuit)
(integerp (second obj))))
(defun add-to-circuit (circuit operator &rest args) (defun add-to-circuit (circuit operator &rest args)
"Add OPERATOR to CIRCUIT." "Add OPERATOR to CIRCUIT."
(let ((entry (assoc operator *circuit-operators*))) (let ((bits (second circuit))
(entry (assoc operator *circuit-operators*)))
(unless entry (unless entry
(error "Unknown circuit operator: ~s" operator)) (error "Unknown circuit operator: ~s" operator))
(destructuring-bind (name arg-count has-rest &rest r) entry (destructuring-bind (name arg-count has-rest has-output func) entry
(declare (ignorable name r)) (declare (ignorable name))
(unless (or (and has-rest (>= (length args) arg-count)) (unless (or (and has-rest (>= (length args) arg-count))
(= (length args) arg-count)) (= (length args) arg-count))
(error "Operator ~s expects ~@[~*exactly ~]~s arg~:p, got ~s" operator (error "Operator ~s expects ~@[~*exactly ~]~s arg~:p, got ~s" operator
(not has-rest) arg-count (length args))) (not has-rest) arg-count (length args)))
(nconc circuit (list (cons operator args)))) (let ((action (apply func bits operator args))
(prev-action (car (last circuit))))
(cond
((and (matrixp action) (matrixp prev-action))
(setf (car (last circuit)) (*mm action prev-action)))
((functionp action)
(setf (cdr (last circuit)) (list (cons action
(and has-output
(car (last args)))))))
(t (setf (cdr (last circuit)) (list action))))))
circuit)) circuit))
(defmacro with-build-circuit (&body body) (defun build-circuit-add-action (bits actions args)
"Add the action denoted by ARGS to the front of ACTIONS. The action is assumed
to operate on a state of BITS bits."
(let ((entry (assoc (car args) *circuit-operators*)))
(destructuring-bind (name arg-count has-rest has-output func) entry
(declare (ignorable arg-count has-rest))
(declare (ignorable name))
(let ((action (apply func bits (car args) (cdr args)))
(prev-action (car actions)))
(cond
((and (matrixp action) (matrixp prev-action))
(setf (car actions) (*mm action prev-action)))
((functionp action)
(push (cons action (and has-output (car (last args))))
actions))
(t (push action actions)))
actions))))
(defmacro with-build-circuit (bits &body body)
"Create a circuit using a simple DSL. BODY can be any valid Lisp forms, in "Create a circuit using a simple DSL. BODY can be any valid Lisp forms, in
addition to function calls to functions named in `*circuit-operators*'." addition to function calls to functions named in `*circuit-operators*'."
(let ((circuit-var (gensym))) (let ((circuit-var (gensym))
`(let ((,circuit-var)) (bits-var (gensym)))
`(let ((,circuit-var)
(,bits-var ,bits))
(macrolet (macrolet
(,@(mapcar (lambda (oper) (,@(mapcar (lambda (oper)
(let ((arg (gensym)) (let ((arg (gensym))
@ -91,44 +124,37 @@ addition to function calls to functions named in `*circuit-operators*'."
(declare (ignorable ,@arg-list (declare (ignorable ,@arg-list
,@(when (third oper) ,@(when (third oper)
(list whole-arg)))) (list whole-arg))))
`(push (list ,@,arg) ,',circuit-var)))) `(setq ,',circuit-var
(build-circuit-add-action
,',bits-var ,',circuit-var (list ,@,arg))))))
*circuit-operators*)) *circuit-operators*))
,@body) ,@body)
(cons :circuit (nreverse ,circuit-var))))) (apply 'list :circuit ,bits-var (nreverse ,circuit-var)))))
(defun apply-circuit-operator-to-state (state operator args) (defun run-circuit (circuit &key (state :zero) (places 5))
"Apply the circuit operator OPERATOR to STATE by calling its function with "Run the circuit CIRCUIT and return the final state. The initial STATE can be
ARGS." specified in one of four ways:
(destructuring-bind (&optional name arg-count has-rest has-output function) - :ZERO: a zero state is used -> #(1 0 0 0), etc.
(assoc operator *circuit-operators*) - :UNIFORM: a uniform state -> #(1/sqrt(2) 1/sqrt(2)), etc
(declare (ignorable name arg-count has-rest)) - a vector: the initial coefficients"
(assert function () (let ((real-state (cond
"Invalid circuit operator: ~s" operator) ((eq state :zero)
(let ((output (apply function state operator args))) (make-zero-state (second circuit)))
(when has-output ((eq state :uniform)
(cons (car (last args)) output))))) (make-uniform-normal-state (second circuit)))
(t (coerce state 'vector)))))
(defun run-circuit (circuit &key bits uniform coefficients probabilities (places 5))
"Run the circuit CIRCUIT and return the final state. The initial state can be
specified in one of three ways:
- BITS: the number of qbits
- COEFFICIENTS: the initial coefficients
- PROBABILITES: the initial probabilities"
(assert (= 1 (count-if 'identity (list bits coefficients probabilities uniform)))
()
"Exactly one of BITS, UNIFORM, COEFFICIENTS, and PROBABILITIES can ~
be present")
(let ((state (cond
(bits (make-zero-state bits))
(uniform (make-uniform-normal-state uniform))
(coefficients (coerce coefficients 'vector))
(probabilities (make-normal-state probabilities)))))
(values (values
state real-state
(loop with *circuit-measure-places* = places (loop with *circuit-measure-places* = places
for element in (cdr circuit) with outputs = ()
for name = (car element) for action in (cddr circuit) do
for args = (cdr element) (cond
for result = (apply-circuit-operator-to-state state name args) ((matrixp action)
when result (replace-state real-state (*mv action real-state)))
collect result)))) ((consp action)
(destructuring-bind (func output) action
(let ((res (funcall func real-state)))
(when output
(push res outputs)
(push output outputs)))))
(t (error "Unknown circuit element type: ~s" action)))))))

View File

@ -1,29 +1,29 @@
;;;; Example Bell state creation circuits ;;;; Example Bell state creation circuits
(in-package :cl-quantum/examples) (in-package :cl-quantum/examples)
(defun make-bell-phi+-circuit () (defun make-bell-phi+-circuit (bits)
"Return a circuit that makes a Bell phi+ state. That is |00>+|11>." "Return a circuit that makes a Bell phi+ state. That is |00>+|11>."
(with-build-circuit (with-build-circuit bits
(:h 0) (:h 0)
(:cnot 1 0))) (:cnot 1 0)))
(defun make-bell-phi--circuit () (defun make-bell-phi--circuit (bits)
"Return a circuit that makes a Bell phi- state. That is |00>-|11>." "Return a circuit that makes a Bell phi- state. That is |00>-|11>."
(with-build-circuit (with-build-circuit bits
(:h 0) (:h 0)
(:cnot 1 0) (:cnot 1 0)
(:z 1))) (:z 1)))
(defun make-bell-psi+-circuit () (defun make-bell-psi+-circuit (bits)
"Return a circuit that makes a Bell psi+ state. That is |01>+|10>." "Return a circuit that makes a Bell psi+ state. That is |01>+|10>."
(with-build-circuit (with-build-circuit bits
(:x 1) (:x 1)
(:h 0) (:h 0)
(:cnot 1 0))) (:cnot 1 0)))
(defun make-bell-psi--circuit () (defun make-bell-psi--circuit (bits)
"Return a circuit that makes a Bell psi- state. That is |01>-|10>." "Return a circuit that makes a Bell psi- state. That is |01>-|10>."
(with-build-circuit (with-build-circuit bits
(:x 1) (:x 1)
(:h 0) (:h 0)
(:cnot 1 0) (:cnot 1 0)

View File

@ -12,7 +12,7 @@ bits and finds when the state is equal to TARGET."
(assert (> (ash 1 bits) target) (assert (> (ash 1 bits) target)
(bits target) (bits target)
"Target bit of ~s out of range for state with ~s bits." target bits) "Target bit of ~s out of range for state with ~s bits." target bits)
(with-build-circuit (with-build-circuit bits
;; Setup ;; Setup
(loop for i below bits do (:h i)) (loop for i below bits do (:h i))

View File

@ -42,6 +42,11 @@ VALUE, the ROW, and the COLUMN."
(domatrix ((elem row col) matrix new-mat) (domatrix ((elem row col) matrix new-mat)
(setf (aref new-mat row col) (funcall function elem row col))))) (setf (aref new-mat row col) (funcall function elem row col)))))
(defun matrixp (obj)
"Return non-nil if OBJ is a matrix."
(and (arrayp obj)
(= (array-rank obj) 2)))
;; Matrix subroutines ;; Matrix subroutines
(defun minor (mat i j) (defun minor (mat i j)
"Find the minor of MAT for I and J." "Find the minor of MAT for I and J."

View File

@ -4,6 +4,7 @@ quantum operators.")
(:use :cl) (:use :cl)
(:export #:domatrix (:export #:domatrix
#:mapmatrix #:mapmatrix
#:matrixp
#:minor #:minor
#:cofactor #:cofactor
#:det #:det