123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- """
- qasm.py - Functions to parse a set of qasm commands into a SymPy Circuit.
- Examples taken from Chuang's page: http://www.media.mit.edu/quanta/qasm2circ/
- The code returns a circuit and an associated list of labels.
- >>> from sympy.physics.quantum.qasm import Qasm
- >>> q = Qasm('qubit q0', 'qubit q1', 'h q0', 'cnot q0,q1')
- >>> q.get_circuit()
- CNOT(1,0)*H(1)
- >>> q = Qasm('qubit q0', 'qubit q1', 'cnot q0,q1', 'cnot q1,q0', 'cnot q0,q1')
- >>> q.get_circuit()
- CNOT(1,0)*CNOT(0,1)*CNOT(1,0)
- """
- __all__ = [
- 'Qasm',
- ]
- from sympy.physics.quantum.gate import H, CNOT, X, Z, CGate, CGateS, SWAP, S, T,CPHASE
- from sympy.physics.quantum.circuitplot import Mz
- def read_qasm(lines):
- return Qasm(*lines.splitlines())
- def read_qasm_file(filename):
- return Qasm(*open(filename).readlines())
- def prod(c):
- p = 1
- for ci in c:
- p *= ci
- return p
- def flip_index(i, n):
- """Reorder qubit indices from largest to smallest.
- >>> from sympy.physics.quantum.qasm import flip_index
- >>> flip_index(0, 2)
- 1
- >>> flip_index(1, 2)
- 0
- """
- return n-i-1
- def trim(line):
- """Remove everything following comment # characters in line.
- >>> from sympy.physics.quantum.qasm import trim
- >>> trim('nothing happens here')
- 'nothing happens here'
- >>> trim('something #happens here')
- 'something '
- """
- if '#' not in line:
- return line
- return line.split('#')[0]
- def get_index(target, labels):
- """Get qubit labels from the rest of the line,and return indices
- >>> from sympy.physics.quantum.qasm import get_index
- >>> get_index('q0', ['q0', 'q1'])
- 1
- >>> get_index('q1', ['q0', 'q1'])
- 0
- """
- nq = len(labels)
- return flip_index(labels.index(target), nq)
- def get_indices(targets, labels):
- return [get_index(t, labels) for t in targets]
- def nonblank(args):
- for line in args:
- line = trim(line)
- if line.isspace():
- continue
- yield line
- return
- def fullsplit(line):
- words = line.split()
- rest = ' '.join(words[1:])
- return fixcommand(words[0]), [s.strip() for s in rest.split(',')]
- def fixcommand(c):
- """Fix Qasm command names.
- Remove all of forbidden characters from command c, and
- replace 'def' with 'qdef'.
- """
- forbidden_characters = ['-']
- c = c.lower()
- for char in forbidden_characters:
- c = c.replace(char, '')
- if c == 'def':
- return 'qdef'
- return c
- def stripquotes(s):
- """Replace explicit quotes in a string.
- >>> from sympy.physics.quantum.qasm import stripquotes
- >>> stripquotes("'S'") == 'S'
- True
- >>> stripquotes('"S"') == 'S'
- True
- >>> stripquotes('S') == 'S'
- True
- """
- s = s.replace('"', '') # Remove second set of quotes?
- s = s.replace("'", '')
- return s
- class Qasm:
- """Class to form objects from Qasm lines
- >>> from sympy.physics.quantum.qasm import Qasm
- >>> q = Qasm('qubit q0', 'qubit q1', 'h q0', 'cnot q0,q1')
- >>> q.get_circuit()
- CNOT(1,0)*H(1)
- >>> q = Qasm('qubit q0', 'qubit q1', 'cnot q0,q1', 'cnot q1,q0', 'cnot q0,q1')
- >>> q.get_circuit()
- CNOT(1,0)*CNOT(0,1)*CNOT(1,0)
- """
- def __init__(self, *args, **kwargs):
- self.defs = {}
- self.circuit = []
- self.labels = []
- self.inits = {}
- self.add(*args)
- self.kwargs = kwargs
- def add(self, *lines):
- for line in nonblank(lines):
- command, rest = fullsplit(line)
- if self.defs.get(command): #defs come first, since you can override built-in
- function = self.defs.get(command)
- indices = self.indices(rest)
- if len(indices) == 1:
- self.circuit.append(function(indices[0]))
- else:
- self.circuit.append(function(indices[:-1], indices[-1]))
- elif hasattr(self, command):
- function = getattr(self, command)
- function(*rest)
- else:
- print("Function %s not defined. Skipping" % command)
- def get_circuit(self):
- return prod(reversed(self.circuit))
- def get_labels(self):
- return list(reversed(self.labels))
- def plot(self):
- from sympy.physics.quantum.circuitplot import CircuitPlot
- circuit, labels = self.get_circuit(), self.get_labels()
- CircuitPlot(circuit, len(labels), labels=labels, inits=self.inits)
- def qubit(self, arg, init=None):
- self.labels.append(arg)
- if init: self.inits[arg] = init
- def indices(self, args):
- return get_indices(args, self.labels)
- def index(self, arg):
- return get_index(arg, self.labels)
- def nop(self, *args):
- pass
- def x(self, arg):
- self.circuit.append(X(self.index(arg)))
- def z(self, arg):
- self.circuit.append(Z(self.index(arg)))
- def h(self, arg):
- self.circuit.append(H(self.index(arg)))
- def s(self, arg):
- self.circuit.append(S(self.index(arg)))
- def t(self, arg):
- self.circuit.append(T(self.index(arg)))
- def measure(self, arg):
- self.circuit.append(Mz(self.index(arg)))
- def cnot(self, a1, a2):
- self.circuit.append(CNOT(*self.indices([a1, a2])))
- def swap(self, a1, a2):
- self.circuit.append(SWAP(*self.indices([a1, a2])))
- def cphase(self, a1, a2):
- self.circuit.append(CPHASE(*self.indices([a1, a2])))
- def toffoli(self, a1, a2, a3):
- i1, i2, i3 = self.indices([a1, a2, a3])
- self.circuit.append(CGateS((i1, i2), X(i3)))
- def cx(self, a1, a2):
- fi, fj = self.indices([a1, a2])
- self.circuit.append(CGate(fi, X(fj)))
- def cz(self, a1, a2):
- fi, fj = self.indices([a1, a2])
- self.circuit.append(CGate(fi, Z(fj)))
- def defbox(self, *args):
- print("defbox not supported yet. Skipping: ", args)
- def qdef(self, name, ncontrols, symbol):
- from sympy.physics.quantum.circuitplot import CreateOneQubitGate, CreateCGate
- ncontrols = int(ncontrols)
- command = fixcommand(name)
- symbol = stripquotes(symbol)
- if ncontrols > 0:
- self.defs[command] = CreateCGate(symbol)
- else:
- self.defs[command] = CreateOneQubitGate(symbol)
|