Compare commits

..

No commits in common. "less-efficient" and "main" have entirely different histories.

5 changed files with 73 additions and 105 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 (size operator gate target &optional control) (defun circuit-arbitrary-gate (state operator gate target &optional control)
(declare (ignorable operator)) (declare (ignorable operator))
(if control (if control
(make-controlled-operator size gate target control) (napply-controlled-gate state gate target control)
(make-operator size gate target))) (napply-gate state gate target)))
(defun circuit-matrix-operation (size operator target &optional control) (defun circuit-matrix-operation (state 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,13 +22,16 @@
(:cnot +pauli-x-gate+) (:cnot +pauli-x-gate+)
(:cz +pauli-z-gate+)))) (:cz +pauli-z-gate+))))
(if control (if control
(make-controlled-operator size matrix target control) (napply-controlled-gate state matrix target control)
(make-operator size matrix target)))) (napply-gate state matrix target))))
(defun circuit-n-controlled-gate (size operator target controls) (defun circuit-n-controlled-gate (state operator target controls)
(case operator (let ((func (case operator
(:ntoff (make-n-toffoli-operator size target controls)) (:ntoff 'make-n-toffoli-operator)
(:ncz (make-n-controlled-z-operator size target controls)))) (:ncz 'make-n-controlled-z-operator))))
(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
@ -44,72 +47,36 @@
(: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 (bits) (defun make-circuit ()
"Create a new blank circuit of BITS bits." "Create a new blank circuit."
`(:circuit ,bits)) '(:circuit))
(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 ((bits (second circuit)) (let ((entry (assoc operator *circuit-operators*)))
(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 has-output func) entry (destructuring-bind (name arg-count has-rest &rest r) entry
(declare (ignorable name)) (declare (ignorable name r))
(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)))
(let ((action (apply func bits operator args)) (nconc circuit (list (cons 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))
(defun build-circuit-add-action (bits actions args) (defmacro with-build-circuit (&body body)
"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)))
(bits-var (gensym))) `(let ((,circuit-var))
`(let ((,circuit-var)
(,bits-var ,bits))
(macrolet (macrolet
(,@(mapcar (lambda (oper) (,@(mapcar (lambda (oper)
(let ((arg (gensym)) (let ((arg (gensym))
@ -124,37 +91,44 @@ 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))))
`(setq ,',circuit-var `(push (list ,@,arg) ,',circuit-var))))
(build-circuit-add-action
,',bits-var ,',circuit-var (list ,@,arg))))))
*circuit-operators*)) *circuit-operators*))
,@body) ,@body)
(apply 'list :circuit ,bits-var (nreverse ,circuit-var))))) (cons :circuit (nreverse ,circuit-var)))))
(defun run-circuit (circuit &key (state :zero) (places 5)) (defun apply-circuit-operator-to-state (state operator args)
"Run the circuit CIRCUIT and return the final state. The initial STATE can be "Apply the circuit operator OPERATOR to STATE by calling its function with
specified in one of four ways: ARGS."
- :ZERO: a zero state is used -> #(1 0 0 0), etc. (destructuring-bind (&optional name arg-count has-rest has-output function)
- :UNIFORM: a uniform state -> #(1/sqrt(2) 1/sqrt(2)), etc (assoc operator *circuit-operators*)
- a vector: the initial coefficients" (declare (ignorable name arg-count has-rest))
(let ((real-state (cond (assert function ()
((eq state :zero) "Invalid circuit operator: ~s" operator)
(make-zero-state (second circuit))) (let ((output (apply function state operator args)))
((eq state :uniform) (when has-output
(make-uniform-normal-state (second circuit))) (cons (car (last args)) output)))))
(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
real-state state
(loop with *circuit-measure-places* = places (loop with *circuit-measure-places* = places
with outputs = () for element in (cdr circuit)
for action in (cddr circuit) do for name = (car element)
(cond for args = (cdr element)
((matrixp action) for result = (apply-circuit-operator-to-state state name args)
(replace-state real-state (*mv action real-state))) when result
((consp action) collect result))))
(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 (bits) (defun make-bell-phi+-circuit ()
"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 bits (with-build-circuit
(:h 0) (:h 0)
(:cnot 1 0))) (:cnot 1 0)))
(defun make-bell-phi--circuit (bits) (defun make-bell-phi--circuit ()
"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 bits (with-build-circuit
(:h 0) (:h 0)
(:cnot 1 0) (:cnot 1 0)
(:z 1))) (:z 1)))
(defun make-bell-psi+-circuit (bits) (defun make-bell-psi+-circuit ()
"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 bits (with-build-circuit
(:x 1) (:x 1)
(:h 0) (:h 0)
(:cnot 1 0))) (:cnot 1 0)))
(defun make-bell-psi--circuit (bits) (defun make-bell-psi--circuit ()
"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 bits (with-build-circuit
(: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 bits (with-build-circuit
;; Setup ;; Setup
(loop for i below bits do (:h i)) (loop for i below bits do (:h i))

View File

@ -42,11 +42,6 @@ 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,7 +4,6 @@ quantum operators.")
(:use :cl) (:use :cl)
(:export #:domatrix (:export #:domatrix
#:mapmatrix #:mapmatrix
#:matrixp
#:minor #:minor
#:cofactor #:cofactor
#:det #:det