# Copyright (C) 2002-2006 Alexei Gilchrist and Paul Cochrane
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# $Id: quantumcircuits.py,v 1.12 2006/03/01 09:59:03 paultcochrane Exp $
'''
Quantum circuits objects library
'''
__revision__ = '$Revision: 1.12 $'
from pyscript import Color,Group,Area,Rectangle,P,Circle,\
Dot, Path, C, TeX
class Boxed(Group, Area):
'''
Draws a box around an object,
the box can be placed according to standard Area tags
'''
def __init__(self, obj, **options):
bbox = obj.bbox()
pad = .1
w = bbox.width + 2*pad
h = bbox.height + 2*pad
self.width = w
self.height = h
self.bg = options.get('bg', Color(1))
if options.has_key('bg'):
del options['bg']
apply(Group.__init__, (self,), options)
apply(Area.__init__, (self,), options)
obj.c = P(w/2., h/2.)
self.append(
Rectangle(width=w, height=h, bg=self.bg),
obj,
)
class Circled(Group, Area):
"""
Draws a circle around an object
"""
def __init__(self, obj, **options):
bbox = obj.bbox()
pad = .1
r = max( bbox.width+2*pad, bbox.height+2*pad )/2.0
self.width = 2.0*r
self.height = 2.0*r
self.bg = options.get('bg', Color(1))
if options.has_key('bg'):
del options['bg']
apply(Group.__init__, (self,), options)
apply(Area.__init__, (self,), options)
obj.c = P(r, r)
self.append(
Circle(r=r, bg=self.bg, c=P(r, r)),
obj,
)
def cbox(obj, x, yt, yc):
'''
@param obj: the object to put a box around
@type obj: object
@param x: x position of line and centre of box
@type x: float
@param yt: y position of target
@type yt: float
@param yc: y position of control
@type yc: float
@return: a controlled box
'''
g = Group(
Path(P(x, yt), P(x, yc)),
Boxed(obj, c=P(x, yt), bg=Color(1)),
Dot(P(x, yc)),
)
return g
def detector(**options):
'''
@return: a D shaped detector
'''
r = 0.3
c = 0.65*r
path = [
P(0, -r),
P(0, r),
C(P(c, r), P(r, c)),
P(r, 0),
C(P(r, -c), P(c, -r)),
P(0, -r)
]
options['bg'] = options.get('bg', Color(.8))
options['closed'] = 1
p = apply(Path, path, options)
a = Area(width=r, height=2*r, e=P(0, 0))
return Group(a, p)
def classicalpath(*paths):
'''
@param paths: 1 or more Path() objects
@return: classical path
'''
g = Group()
for path in paths:
g.append(path.copy(linewidth=2, fg=Color(0)))
# reuse these paths
for path in paths:
g.append(path(linewidth=1, fg=Color(1)))
return g
# Rail
def Rail(w=P(0, 0), length=1.0, labelIn=None, labelOut=None, buff=0.05):
"""
A Rail of a quantum circuit diagram
@param length: length of the rail
@type length: float
@param labelIn: input label
@type labelIn: string
@param labelOut: output label
@type labelOut: string
@param buff: buffer of space between the end of the rail and the label
@type buff: float
"""
if labelIn is not None and labelOut is not None:
return Group(
Path(w+P(0, 0), w+P(length, 0)),
TeX(labelIn, e=w-P(buff, 0)),
TeX(labelOut, w=w+P(buff+length, 0))
)
elif labelIn is not None and labelOut is None:
return Group(
Path(w+P(0, 0), w+P(length, 0)),
TeX(labelIn, e=w-P(buff, 0))
)
elif labelIn is None and labelOut is not None:
return Group(
Path(w+P(0, 0), w+P(length, 0)),
TeX(labelOut, w=w+P(buff+length, 0))
)
else:
return Group(
Path(w+P(0, 0), w+P(length, 0))
)
# CNOT (controlled not)
def Cnot(c=P(0, 0), targetDist=1.0, direction="up"):
"""
Controlled NOT gate
@param targetDist: distance to the target rail
@type targetDist: float
@param direction: in which direction is the target rail? up/down
@type direction: string
"""
if direction is "up":
return Group(
Circle(r=0.06, bg=Color("black"), c=c),
Circle(r=0.2, c=c+P(0, targetDist)),
Path(c, c+P(0, targetDist+0.2))
)
elif direction is "down":
return Group(
Circle(r=0.06, bg=Color("black"), c=c),
Circle(r=0.2, c=c+P(0, -targetDist)),
Path(c, c+P(0, -targetDist-0.2))
)
# Hadamard gate
def HGate(c=P(0, 0), side=0.5):
"""
Hadamard get
@param side: length of the box side
@type side: float
"""
return Group(
Rectangle(width=side, height=side, c=c, bg=Color("white")),
TeX(r'H', c=c)
)
# Phase gate
def PGate(c=P(0, 0), side=0.5):
"""
Phase gate
@param side: length of the box side
@type side: float
"""
return Group(
Rectangle(width=side, height=side, c=c, bg=Color("white")),
TeX(r'P', c=c)
)
# Controlled phase gate
def CPGate(c=P(0, 0), controlDist=1.0, direction="up", side=0.5):
"""
Controlled phase gate
@param controlDist: distance to the control
@type controlDist: float
@param direction: in which direction is the control? up/down
@type direction: string
@param side: length of the box side
@type side: float
"""
if direction is "up":
return Group(
Circle(c=c+P(0, controlDist), r=0.065, bg=Color("black")),
Path(c+P(0, side/2.), c+P(0, controlDist)),
Rectangle(width=side, height=side, c=c, bg=Color("white")),
TeX(r'P', c=c)
)
elif direction is "down":
return Group(
Circle(c=c-P(0,controlDist), r=0.65, bg=Color("black")),
Path(c-P(0, side/2.), c-P(0, controlDist)),
Rectangle(width=side, height=side, c=c, bg=Color("white")),
TeX(r'P', c=c)
)
def Detector(e=P(0, 0), height=1.0, label=None):
"""
Detector
@param height: height of detector
@type height: float
@param label: detector label
@type label: string
"""
if label is not None:
return Group(Path(e-P(0, height/2.0), e+P(0, height/2.0)),
Circle(c=e, r=height/2.0, start=0, end=180), label)
else:
return Group(Path(e-P(0, height/2.0), e+P(0, height/2.0)),
Circle(c=e, r=height/2.0, start=0, end=180))
# X gate
def XGate(c=P(0, 0), side=0.5):
"""
X gate
@param side: length of the box side
@type side: float
"""
return Group(
Rectangle(width=side, height=side, c=c, bg=Color("white")),
TeX(r'X', c=c)
)
# Y gate
def YGate(c=P(0, 0), side=0.5):
"""
Y gate
@param side: length of the box side
@type side: float
"""
return Group(
Rectangle(width=side, height=side, c=c, bg=Color("white")),
TeX(r'Y', c=c)
)
# Z gate
def ZGate(c=P(0, 0), side=0.5):
"""
Z gate
@param side: length of the box side
@type side: float
"""
return Group(
Rectangle(width=side, height=side, c=c, bg=Color("white")),
TeX(r'Z', c=c)
)
# Controlled X gate
def CXGate(c=P(0, 0), controlDist=1.0, direction="up", side=0.5):
"""
Controlled X gate
@param controlDist: distance to the control
@type controlDist: float
@param direction: in which direction is the control? up/down
@type direction: string
@param side: length of the box side
@type side: float
"""
if direction is "up":
return Group(
Circle(c=c+P(0, controlDist), r=0.065, bg=Color("black")),
Path(c+P(0, side/2.), c+P(0, controlDist)),
Rectangle(width=side, height=side, c=c, bg=Color("white")),
TeX(r'X', c=c)
)
elif direction is "down":
return Group(
Circle(c=c-P(0, controlDist), r=0.65, bg=Color("black")),
Path(c-P(0, side/2.), c-P(0, controlDist)),
Rectangle(width=side, height=side, c=c, bg=Color("white")),
TeX(r'X', c=c)
)
# Controlled Y gate
def CYGate(c=P(0, 0), controlDist=1.0, direction="up", side=0.5):
"""
Controlled Y gate
@param controlDist: distance to the control
@type controlDist: float
@param direction: in which direction is the control? up/down
@type direction: string
@param side: length of the box side
@type side: float
"""
if direction is "up":
return Group(
Circle(c=c+P(0, controlDist), r=0.065, bg=Color("black")),
Path(c+P(0, side/2.), c+P(0, controlDist)),
Rectangle(width=side, height=side, c=c, bg=Color("white")),
TeX(r'Y', c=c)
)
elif direction is "down":
return Group(
Circle(c=c-P(0, controlDist), r=0.65, bg=Color("black")),
Path(c-P(0, side/2.), c-P(0, controlDist)),
Rectangle(width=side, height=side, c=c, bg=Color("white")),
TeX(r'Y', c=c)
)
# Controlled Z gate
def CZGate(c=P(0, 0), controlDist=1.0, direction="up", side=0.5):
"""
Controlled Z gate
@param controlDist: distance to the control
@type controlDist: float
@param direction: in which direction is the control? up/down
@type direction: string
@param side: length of the box side
@type side: float
"""
if direction is "up":
return Group(
Circle(c=c+P(0, controlDist), r=0.065, bg=Color("black")),
Path(c+P(0, side/2.), c+P(0, controlDist)),
Rectangle(width=side, height=side, c=c, bg=Color("white")),
TeX(r'Z', c=c)
)
elif direction is "down":
return Group(
Circle(c=c-P(0, controlDist), r=0.65, bg=Color("black")),
Path(c-P(0, side/2.), c-P(0,controlDist)),
Rectangle(width=side, height=side, c=c, bg=Color("white")),
TeX(r'Z', c=c)
)
# vim: expandtab shiftwidth=4:
|