Merge branch 'Dev' into isma/clean-quantum-program

This commit is contained in:
ismael faro 2017-05-15 09:48:43 -04:00
commit d5a3dfceab
40 changed files with 1314 additions and 606 deletions

View File

@ -12,51 +12,50 @@ Related external projects:
## Organization ## Organization
The *scripts* directory contains Jupyter notebooks showing how to use the The *tutorial* directory contains Jupyter notebooks showing how to use the
[Python API](https://github.com/IBM/qiskit-api-py) with [Python API](https://github.com/IBM/qiskit-api-py) with
[OPENQASM](https://github.com/IBM/qiskit-openqasm). [OPENQASM](https://github.com/IBM/qiskit-openqasm).
There are Jupyter notebooks demonstrating components of There are Jupyter notebooks demonstrating components of
the SDK in the *scripts* directory. There are also command line test scripts the SDK in the *tutorial* directory, and more python and qasm examples in the *examples* directory. There are also command line test scripts
in the *testscripts* directory. The root directory contains some miscellaneous in the *test* directory.
examples and an index Jupyter notebook.
We want to reorganize the SDK so that it has a comfortable and intuitive Users can construct a *QuantumProgram* to create, modify, compile, and execute a collection of quantum circuits.
interface for developers.
Users can create instances of *QuantumRegister* and *ClassicalRegister*, and Each *QuantumCircuit* has some set of registers, *QuantumRegister* and *ClassicalRegister*, and methods of these objects are used to apply instructions within the circuit. The *extensions* directory extends
use these to construct a *QuantumCircuit*. They can then call methods of these the quantum circuit as needed to support new gate sets and algorithms. For example, the "cswap" gate in the standard extension shows how to build gates that are sequences of
objects to apply gates within the circuit. The *extensions* directory extends
these objects as needed to support new gate sets and algorithms. The "cswap"
gate in the standard extension shows how to build gates that are sequences of
other unitary gates. The Python file "header.py" shows how we append OPENQASM other unitary gates. The Python file "header.py" shows how we append OPENQASM
gate definitions as we import extensions. The *QuantumCircuit* can generate gate definitions as we import extensions. The *QuantumCircuit* can generate
OPENQASM code that can flow through other components in the *qiskit* directory. OPENQASM code that can flow through other components in the *qiskit* directory.
The *qiskit* directory is the main Python module and contains the programming The *qiskit* directory is the main Python module and contains the programming
interface objects *QuantumRegister*, *ClassicalRegister*, and *QuantumCircuit*. interface objects *QuantumProgram*, *QuantumRegister*, *ClassicalRegister*, and *QuantumCircuit*.
The directory also contains a *qasm* module for parsing OPENQASM circuits, The directory also contains internal modules: a *qasm* module for parsing OPENQASM circuits,
an *unroll* module to flatten QASM for a target gate basis by expanding an *unroll* module to "flatten" QASM for a target gate basis by expanding
gate subroutines as needed, a *circuit* module for working with circuits as gate subroutines as needed, a *circuit* module for working with circuits as
graphs, and a *localize* module for mapping all-to-all circuits to run on graphs, and a *mapper* module for mapping all-to-all circuits to run on
devices with fixed couplings. devices with fixed couplings.
Quantum circuits flow through the components as follows. The programming Quantum circuits flow through the components as follows. The programming
interface is used to generate **OPENQASM** circuits. **OPENQASM** source, interface is used to generate **OPENQASM** circuits. **OPENQASM** source,
as a file or string, is passed into a *Qasm* object, whose *parse* method as a file or string, is passed into a *Qasm* object, whose *parse* method
produces an abstract syntax tree (**AST**) representation. The **AST** is produces an abstract syntax tree (**AST**). The **AST** is
passed to an *Unroller* that is attached to an *UnrollerBackend*. There is passed to an *Unroller* that is attached to an *UnrollerBackend*. There is
a *PrinterBackend* for outputting text and a *CircuitBackend* for constructing *Circuit* objects. The *Circuit* object represents an unrolled **OPENQASM** a *PrinterBackend* for outputting text and a *CircuitBackend* for constructing *Circuit* objects. The *Circuit* object represents an unrolled **OPENQASM**
circuit as a directed acyclic graph (**DAG**). The *Circuit* provides methods circuit as a directed acyclic graph (**DAG**). The *Circuit* provides methods
for representing, transforming, and computing properties of a circuit as a for representing, transforming, and computing properties of a circuit as a
**DAG** and outputting the results again as **OPENQASM**. The whole flow is **DAG** and outputting the results again as **OPENQASM**. The whole flow is
used by the *localize* module's *swap_mapper* method to insert SWAP gates used by the *mapper* module to rewrite a circuit to execute on a device
so a circuit can execute on a device with fixed couplings given by a with fixed couplings given by a *CouplingGraph*.
*CouplingGraph*.
The circuit representations and how they are currently transformed into each other are summarized in ![](images/circuit_representations.png?raw=true).
The unroller backends and their outputs are summarized in ![](images/unroller_backends.png?raw=true).
## Install ## Install
- Intall Anaconda: https://www.continuum.io/downloads - Install Anaconda: https://www.continuum.io/downloads
- Clone the repo: - Clone the repo:
```sh ```sh
@ -86,7 +85,7 @@ make run
## FAQ ## FAQ
If you upgrade the dependencies and next error happens try with this fix: If you upgrade the dependencies and next error happens try this fix:
```sh ```sh
pip install --upgrade IBMQuantumExperience pip install --upgrade IBMQuantumExperience
@ -98,7 +97,7 @@ curl https://bootstrap.pypa.io/ez_setup.py -o - | python
## Developer guide ## Developer guide
Please, use [GitHub pull requests](https://help.github.com/articles/using-pull-requests) to send the contributions. Please, use [GitHub pull requests](https://help.github.com/articles/using-pull-requests) to send contributions.
We use [Pylint](https://www.pylint.org) and [PEP 8](https://www.python.org/dev/peps/pep-0008) style guide. We use [Pylint](https://www.pylint.org) and [PEP 8](https://www.python.org/dev/peps/pep-0008) style guide.
@ -121,6 +120,6 @@ Note: You can get yout "putYourQExperienceTokenHere" from [IBM Quantum Experienc
### Commit messages rules ### Commit messages rules
- It should be formed by a one-line subject, followed by one line of white space. Followed by one or more descriptive paragraphs, each separated by one line of white space. All of them finished by a dot. - It should be formed by a one-line subject, followed by one line of white space. Followed by one or more descriptive paragraphs, each separated by one line of white space. All of them finished by a dot.
- If it fixes an issue, it should include a reference to the issue ID in the first line of the commit. - If it fixes an issue, it should include a reference to the issue ID in the first line of the commit.
- It should provide enough information for a reviewer to understand the changes and their relation to the rest of the code. - It should provide enough information for a reviewer to understand the changes and their relation to the rest of the code.

View File

@ -1,9 +1,9 @@
""" """
Test script for localization of quantum circuits. Test script for mapping quantum circuits.
This script takes a QASM file and produces output that shows the This script takes a QASM file and produces output that shows the
process of finding SWAP gates to map the circuit onto the coupling graph. process of mapping the circuit onto the coupling graph.
The final output is QASM source for a "localized" version of the input The final output is QASM source for a "mapped" version of the input
circuit. circuit.
The coupling graph and target basis are hard-coded into this script. The coupling graph and target basis are hard-coded into this script.
@ -106,14 +106,14 @@ def make_unrolled_circuit_from_data(dat, basis):
if len(sys.argv) < 2: if len(sys.argv) < 2:
print("localize.py <qasm>\n") print("mapper.py <qasm>\n")
print(" qasm = main circuit") print(" qasm = main circuit")
print("") print("")
print("Generates a new \"localized\" circuit matching the coupling.") print("Generates a new \"mapped\" circuit matching the coupling.")
sys.exit(1) sys.exit(1)
# This is the QE basis # This is the QE basis
basis = "u1,u2,u3,cx" basis = "u1,u2,u3,cx,id"
layout_type = "qe5" # "qe5" or "2x8" layout_type = "qe5" # "qe5" or "2x8"
@ -148,7 +148,7 @@ elif layout_type == "2x8":
# Three', expand swaps into cx gates # Three', expand swaps into cx gates
c_prime = make_unrolled_circuit_from_data(c_prime.qasm(qeflag=True), c_prime = make_unrolled_circuit_from_data(c_prime.qasm(qeflag=True),
"cx,u1,u2,u3") "cx,u1,u2,u3,id")
# Fourth, do direction mapping # Fourth, do direction mapping
c_dblp = mapper.direction_mapper(c_prime, coupling, verbose=True) c_dblp = mapper.direction_mapper(c_prime, coupling, verbose=True)
@ -156,5 +156,5 @@ print("c_dblp.qasm() = \n%s" % c_dblp.qasm(qeflag=True))
# Unroll again # Unroll again
c_final = make_unrolled_circuit_from_data(c_dblp.qasm(qeflag=True), c_final = make_unrolled_circuit_from_data(c_dblp.qasm(qeflag=True),
"cx,u1,u2,u3") "cx,u1,u2,u3,id")
print("c_final.qasm() = \n%s" % c_final.qasm(qeflag=True)) print("c_final.qasm() = \n%s" % c_final.qasm(qeflag=True))

View File

@ -239,7 +239,3 @@ print("factors = %d" % C_directions_unrolled.num_tensor_factors())
print("operations:") print("operations:")
for key, val in C_directions_unrolled.count_ops().items(): for key, val in C_directions_unrolled.count_ops().items():
print(" %s: %d" % (key, val)) print(" %s: %d" % (key, val))
# TODO: test on examples using simulator
# TODO: understand swap_mapper with all-all
# TODO: simple unit tests for qasm, mapper, unroller, circuit

View File

@ -1,23 +0,0 @@
import sys
import os
# We don't know from where the user is running the example,
# so we need a relative position from this file path.
# TODO: Relative imports for intra-package imports are highly discouraged.
# http://stackoverflow.com/a/7506006
sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
from qiskit.extensions.standard import h, cx
q2 = QuantumRegister("q", 2)
c2 = ClassicalRegister("c", 2)
bell = QuantumCircuit(q2, c2)
bell.h(q2[0])
bell.cx(q2[0], q2[1])
measureIZ = QuantumCircuit(q2, c2)
measureIZ.measure(q2[0], c2[0])
c = bell + measureIZ
print(c.qasm())

View File

@ -1,16 +0,0 @@
import sys
import os
# We don't know from where the user is running the example,
# so we need a relative position from this file path.
# TODO: Relative imports for intra-package imports are highly discouraged.
# http://stackoverflow.com/a/7506006
sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
from qiskit.qasm import Qasm
badqasm = """
OPENQASM 2.0;
qreg Q[5];
"""
ast = Qasm(data=badqasm).parse()

View File

@ -19,10 +19,8 @@ from qiskit.extensions.standard import barrier, ubase, cxbase
from qiskit.extensions.standard import h, cx, u1, u2, u3, iden, x, y, z, s from qiskit.extensions.standard import h, cx, u1, u2, u3, iden, x, y, z, s
from qiskit.extensions.standard import t, ccx, cswap from qiskit.extensions.standard import t, ccx, cswap
# Issues # Issues:
# .q_if is not implemented, store controls on each gate, two methods # .q_if is not implemented
# Ismael advice - keep it simple
n = 5 n = 5
q = QuantumRegister("q", n) q = QuantumRegister("q", n)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 73 KiB

View File

@ -9,9 +9,9 @@
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="373.08823mm" width="373.08826mm"
height="188.52194mm" height="188.52196mm"
viewBox="0 0 1321.9661 667.99114" viewBox="0 0 1321.9662 667.99119"
id="svg2" id="svg2"
version="1.1" version="1.1"
inkscape:version="0.91 r13725" inkscape:version="0.91 r13725"
@ -262,8 +262,8 @@
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="0.49497475" inkscape:zoom="0.49497475"
inkscape:cx="692.84134" inkscape:cx="692.84131"
inkscape:cy="446.68561" inkscape:cy="446.68564"
inkscape:document-units="px" inkscape:document-units="px"
inkscape:current-layer="layer1" inkscape:current-layer="layer1"
showgrid="false" showgrid="false"
@ -292,7 +292,7 @@
inkscape:label="Layer 1" inkscape:label="Layer 1"
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer1" id="layer1"
transform="translate(782.22436,66.629243)"> transform="translate(782.22433,66.629243)">
<rect <rect
style="fill:#bfd6e9;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter4198-1-0-3-3)" style="fill:#bfd6e9;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter4198-1-0-3-3)"
id="rect3336-7-6-5-6" id="rect3336-7-6-5-6"
@ -442,27 +442,37 @@
<text <text
xml:space="preserve" xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="-573.70044" x="-569.70044"
y="395.6506" y="395.6506"
id="text4210-6" id="text4210-6"
sodipodi:linespacing="125%"><tspan sodipodi:linespacing="125%"><tspan
sodipodi:role="line" sodipodi:role="line"
x="-573.70044" x="-569.70044"
y="395.6506" y="395.6506"
id="tspan4224-6" id="tspan4224-6"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold'">UnitarySimulator</tspan></text> style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold'">SimulatorBackend</tspan></text>
<text <text
xml:space="preserve" xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:15px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" style="font-style:normal;font-weight:normal;font-size:15px;line-height:125%;font-family:sans-serif;text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="-695.38416" x="-576.29749"
y="567.98627" y="567.98627"
id="text7822-2" id="text7822-2"
sodipodi:linespacing="125%"><tspan sodipodi:linespacing="125%"><tspan
sodipodi:role="line" sodipodi:role="line"
id="tspan7824-0" id="tspan7824-0"
x="-695.38416" x="-576.29749"
y="567.98627" y="567.98627"
style="font-size:25px">Simulator input data</tspan></text> style="font-size:25px;text-align:center;text-anchor:middle">Simulator input data</tspan><tspan
sodipodi:role="line"
x="-576.29749"
y="599.23627"
style="font-size:25px;text-align:center;text-anchor:middle"
id="tspan3534">unroller.backend.circuit</tspan><tspan
sodipodi:role="line"
x="-576.29749"
y="630.48627"
style="font-size:25px;text-align:center;text-anchor:middle"
id="tspan3532" /></text>
<path <path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.06642962;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Mend-1-6-4)" style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.06642962;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Mend-1-6-4)"
d="m -568.31169,433.32069 0,95.70907" d="m -568.31169,433.32069 0,95.70907"

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -23,6 +23,7 @@ Authors: Andrew Cross, Jay M. Gambetta, Ismael Faro
# pylint: disable=line-too-long # pylint: disable=line-too-long
import time import time
import random
from collections import Counter from collections import Counter
# use the external IBMQuantumExperience Library # use the external IBMQuantumExperience Library
from IBMQuantumExperience.IBMQuantumExperience import IBMQuantumExperience from IBMQuantumExperience.IBMQuantumExperience import IBMQuantumExperience
@ -38,6 +39,10 @@ from . import unroll
from . import qasm from . import qasm
from . import mapper from . import mapper
from .unroll import SimulatorBackend
from .simulators._unitarysimulator import UnitarySimulator
from .simulators._qasmsimulator import QasmSimulator
import sys import sys
sys.path.append("..") sys.path.append("..")
from qiskit.extensions.standard import x, h, cx, s, ry, barrier from qiskit.extensions.standard import x, h, cx, s, ry, barrier
@ -47,8 +52,8 @@ class QuantumProgram(object):
""" Quantum Program Class """ Quantum Program Class
Class internal properties """ Class internal properties """
__online_devices = ["qx5q", "qx5qv2","simulator", "online_simulator"] __online_devices = ["qx5qv2", "ibmqx2", "ibmqx3", "ibmqx_qasm_simulator", "simulator"]
__local_devices = ["unitary_simulator"] __local_devices = ["local_unitary_simulator", "local_qasm_simulator"]
__specs = {} __specs = {}
__quantum_registers = {} __quantum_registers = {}
@ -168,16 +173,6 @@ class QuantumProgram(object):
""" Set the API url """ """ Set the API url """
self.set_api(url=url) self.set_api(url=url)
def get_job_list_status(self, jobids):
"""Given a list of job ids, return a list of job status.
jobids is a list of id strings.
api is an IBMQuantumExperience object.
"""
status_list = []
for i in jobids:
status_list.append(self.__api.get_job(i)['status'])
return status_list
def load_qasm(self, qasm_file, basis_gates=None): def load_qasm(self, qasm_file, basis_gates=None):
""" Load qasm file """ Load qasm file
qasm_file qasm file name qasm_file qasm file name
@ -219,14 +214,14 @@ class QuantumProgram(object):
qasm_circuits.append({'qasm': circuit.qasm()}) qasm_circuits.append({'qasm': circuit.qasm()})
return qasm_circuits return qasm_circuits
def compile(self, circuits, device="simulator", shots=1024, max_credits=3, coupling_map=None): def compile(self, circuits, device="simulator", shots=1024, max_credits=3, basis_gates=None, coupling_map=None):
""" Compile unrole the code """ Compile unrole the code
circuits are circuits to unroll circuits are circuits to unroll
basis_gates are the base gates by default are: u1,u2,u3,cx,id basis_gates are the base gates by default are: u1,u2,u3,cx,id
""" """
qasm_circuits = [] qasm_circuits = []
for circuit in circuits: for circuit in circuits:
qasm_source, circuit_unrolled = self.unroller_code(circuit) qasm_source, circuit_unrolled = self.unroller_code(circuit, basis_gates)
if coupling_map: if coupling_map:
print("pre-mapping properties: %s" print("pre-mapping properties: %s"
% circuit_unrolled.property_summary()) % circuit_unrolled.property_summary())
@ -258,12 +253,8 @@ class QuantumProgram(object):
def run(self, wait=5, timeout=60): def run(self, wait=5, timeout=60):
"""Run a program (a pre compiled quantum program). """Run a program (a pre compiled quantum program).
program is a list of quantum_circuits wait time to check if the job is Completed.
api the api for the device timeout time after that the execution stop
device is a string for real or simulator
shots is the number of shots
max_credits is the credits of the experiments.
basis_gates are the base gates by default are: u1,u2,u3,cx,id
""" """
backend = self.__qasm_compile['backend']['name'] backend = self.__qasm_compile['backend']['name']
@ -283,7 +274,8 @@ class QuantumProgram(object):
if job_result['status'] == 'Error': if job_result['status'] == 'Error':
return job_result return job_result
else: else:
return {"status": "Error", "result": "Not local simulations"} self.run_local()
# return {"status": "Error", "result": "Not local simulations"}
self.__qasm_compile['compiled_circuits'] = job_result['qasms'] self.__qasm_compile['compiled_circuits'] = job_result['qasms']
self.__qasm_compile['used_credits'] = job_result['usedCredits'] self.__qasm_compile['used_credits'] = job_result['usedCredits']
@ -299,10 +291,35 @@ class QuantumProgram(object):
max_credits is the credits of the experiments. max_credits is the credits of the experiments.
basis_gates are the base gates by default are: u1,u2,u3,cx,id basis_gates are the base gates by default are: u1,u2,u3,cx,id
""" """
pass shots = self.__qasm_compile['shots']
qasms = self.__qasm_compile['compiled_circuits']
def execute(self, circuits, device, shots, coupling_map=None, # /print(qasms)
max_credits=3, basis_gates=None, wait=5, timeout=60):
outcomes = {'qasms':[]}
for qasm in qasms:
print('----------------')
print(qasm['qasm'])
print('----------------')
basis = []
unroller = unroll.Unroller(qasm['qasm'],SimulatorBackend(basis))
print('----%%-----')
unroller.backend.set_trace(False)
print('-----++-----')
unroller.execute()
print('------**-----')
for i in range(shots):
print('.................')
b = QasmSimulator(unroller.backend.circuit, random.random()).run()
print('.................')
print(b)
# outcomes['qasms'].append(bin(b['result']['classical_state'])[2:].zfill(b['number_of_cbits']))
print(outcomes)
return outcomes
def execute(self, circuits, device, shots=1024,
max_credits=3, wait=5, timeout=60, basis_gates=None, coupling_map=None):
"""Execute, compile and run a program (array of quantum circuits). """Execute, compile and run a program (array of quantum circuits).
program is a list of quantum_circuits program is a list of quantum_circuits
api the api for the device api the api for the device
@ -359,6 +376,16 @@ class QuantumProgram(object):
return {"status": "Error", "result": "Time Out"} return {"status": "Error", "result": "Time Out"}
return job return job
def get_job_list_status(self, jobids):
"""Given a list of job ids, return a list of job status.
jobids is a list of id strings.
api is an IBMQuantumExperience object.
"""
status_list = []
for i in jobids:
status_list.append(self.__api.get_job(i)['status'])
return status_list
def wait_for_jobs(self, jobids, wait=5, timeout=60): def wait_for_jobs(self, jobids, wait=5, timeout=60):
"""Wait until all status results are 'COMPLETED'. """Wait until all status results are 'COMPLETED'.
jobids is a list of id strings. jobids is a list of id strings.
@ -540,6 +567,9 @@ class QuantumProgram(object):
else: else:
basicplotter.plot_qsphere(data, circuit_number) basicplotter.plot_qsphere(data, circuit_number)
def get_qasm_image(self,):
pass
def get_data(self, results, i): def get_data(self, results, i):
"""Get the dict of labels and counts from the output of get_job.""" """Get the dict of labels and counts from the output of get_job."""
return results['qasms'][i]['result']['data']['counts'] return results['qasms'][i]['result']['data']['counts']

View File

@ -1,7 +1,6 @@
""" """Rotation around the x-axis.
Rotation around the x-axis.
Author: Jay using andrew code. Author: Jay Gambetta and Andrew Cross
""" """
from qiskit import QuantumRegister from qiskit import QuantumRegister
from qiskit import QuantumCircuit from qiskit import QuantumCircuit

View File

@ -1,7 +1,6 @@
""" """Rotation around the y-axis.
Rotation around the y-axis.
Author: Jay using andrew code. Author: Jay Gambetta and Andrew Cross
""" """
from qiskit import QuantumRegister from qiskit import QuantumRegister
from qiskit import QuantumCircuit from qiskit import QuantumCircuit

View File

@ -1,7 +1,6 @@
""" """Rotation around the z-axis.
Rotation around the z-axis.
Author: Jay using andrew code. Author: Jay Gambetta and Andrew Cross
""" """
from qiskit import QuantumRegister from qiskit import QuantumRegister
from qiskit import QuantumCircuit from qiskit import QuantumCircuit

View File

@ -4,16 +4,17 @@ OPENQASM Lexer.
This is a wrapper around the PLY lexer to support the "include" statement This is a wrapper around the PLY lexer to support the "include" statement
by creating a stack of lexers. by creating a stack of lexers.
Author: Jim Challenger Authors: Jim Challenger
Jesus Perez <jesusper@us.ibm.com>
""" """
import os import os
import ply.lex as lex import ply.lex as lex
from ._qasmexception import QasmException from ._qasmexception import QasmException
from . import _node as node from . import _node as node
CORE_LIBS_PATH = os.path.join(os.path.dirname(__file__), 'libs') CORE_LIBS_PATH = os.path.join(os.path.dirname(__file__), 'libs')
# TODO: Get dinamically from the folder "qasm/lib" CORE_LIBS = os.listdir(CORE_LIBS_PATH)
CORE_LIBS = ['qelib1.inc']
class QasmLexer(object): class QasmLexer(object):

View File

@ -1 +1 @@
from ._unitarysimulator import UnitarySimulator

View File

@ -0,0 +1,193 @@
"""
Contains a (slow) python simulator that makes the qasm of the circuit.
We advise using the c++ simulator or online for larger size systems
Author: Jay Gambetta
{'number_of_qubits': 2,
'number_of_cbits': 2,
'number_of_operations': 2
'qubit_order': {('q', 0): 0, ('v', 0): 1}
'cbit_order': {('c', 1): 1, ('c', 0): 0},
'qasm': [{
'type': 'gate',
'name': 'U(1.570796326794897,0.000000000000000,3.141592653589793)',
'qubit_indices': [0],
'gate_size': 1,
'matrix': array([[ 0.70710678 +0.00000000e+00j,
0.70710678 -8.65956056e-17j],
[ 0.70710678 +0.00000000e+00j,
-0.70710678 +8.65956056e-17j]])
},
{
'type': 'measure',
'cbit_indices': [0],
'qubit_indices': [0]
}],
'result': {
'quantum_state': array([ 1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j]),
'classical_state': 0
}
}
"""
import numpy as np
import random
class QasmSimulator(object):
"""
Python implementation of a unitary computer simulator.
"""
def __init__(self, circuit, random_seed):
self.circuit = circuit
self._number_of_qubits = self.circuit['number_of_qubits']
self._number_of_cbits = self.circuit['number_of_cbits']
self.circuit['result'] = {}
self._quantum_state = np.zeros(2**(self._number_of_qubits),
dtype=complex)
self._quantum_state[0] = 1
self._classical_state = 0
random.seed(random_seed)
self._number_of_operations = self.circuit['number_of_operations']
def _add_qasm_single(self, gate, qubit):
"""Apply the single qubit gate.
gate is the single qubit gate
qubit is the qubit to apply it on counts from 0 and order
is q_{n-1} ... otimes q_1 otimes q_0
number_of_qubits is the number of qubits in the system
returns a complex numpy array
"""
temp_1 = np.identity(2**(self._number_of_qubits-qubit-1),
dtype=complex)
temp_2 = np.identity(2**(qubit), dtype=complex)
unitaty_add = np.kron(temp_1, np.kron(gate, temp_2))
self._quantum_state = np.dot(unitaty_add, self._quantum_state)
def _add_qasm_two(self, gate, qubit_1, qubit_2):
"""Apply the two-qubit gate.
gate is the two-qubit gate
qubit_1 is the first qubit (control) counts from 0
qubit_2 is the second qubit (target)
number_of_qubits is the number of qubits in the system
returns a complex numpy array
"""
temp_1 = np.kron(np.identity(2**(self._number_of_qubits-2),
dtype=complex), gate)
unitaty_add = np.identity(2**(self._number_of_qubits), dtype=complex)
# print('here !!!!!!!!!!!!!!!')
for ii in range(2**self._number_of_qubits):
iistring = bin(ii)[2:]
bits = list(reversed(iistring.zfill(self._number_of_qubits)))
swap_1 = bits[0]
swap_2 = bits[1]
bits[0] = bits[qubit_1]
bits[1] = bits[qubit_2]
bits[qubit_1] = swap_1
bits[qubit_2] = swap_2
iistring = ''.join(reversed(bits))
iip = int(iistring, 2)
for jj in range(2**self._number_of_qubits):
jjstring = bin(jj)[2:]
bits = list(reversed(jjstring.zfill(self._number_of_qubits)))
swap_1 = bits[0]
swap_2 = bits[1]
bits[0] = bits[qubit_1]
bits[1] = bits[qubit_2]
bits[qubit_1] = swap_1
bits[qubit_2] = swap_2
jjstring = ''.join(reversed(bits))
jjp = int(jjstring, 2)
unitaty_add[iip, jjp] = temp_1[ii, jj]
self._quantum_state = np.dot(unitaty_add, self._quantum_state)
# print(self._quantum_state)
def _add_qasm_decision(self, qubit):
"""Apply the measurement/reset qubit gate."""
# print(qubit)
probability_zero = 0
random_number = random.random()
for ii in range(2**self._number_of_qubits):
iistring = bin(ii)[2:]
bits = list(reversed(iistring.zfill(self._number_of_qubits)))
if bits[qubit] == '0':
probability_zero += np.abs(self._quantum_state[ii])**2
# print(probability_zero)
if random_number <= probability_zero:
outcome = '0'
norm = np.sqrt(probability_zero)
else:
outcome = '1'
norm = np.sqrt(1-probability_zero)
return (outcome, norm)
def _add_qasm_measure(self, qubit, cbit):
"""Apply the measurement qubit gate."""
outcome, norm = self._add_qasm_decision(qubit)
# print(outcome)
# print(norm)
for ii in range(2**self._number_of_qubits):
# update quantum state
iistring = bin(ii)[2:]
bits = list(reversed(iistring.zfill(self._number_of_qubits)))
if bits[qubit] == outcome:
self._quantum_state[ii] = self._quantum_state[ii]/norm
else:
self._quantum_state[ii] = 0
# update classical state
temp = bin(self._classical_state)[2:]
cbits_string = list(reversed(temp.zfill(self._number_of_cbits)))
cbits_string[cbit] = outcome
self._classical_state = int(''.join(reversed(cbits_string)), 2)
def _add_qasm_reset(self, qubit):
"""Apply the reset to the qubit.
I to this by applying a measurment and ignoring the outcome"""
"""Apply the measurement qubit gate."""
outcome, norm = self._add_qasm_decision(qubit)
# print(outcome)
temp = self._quantum_state
for ii in range(2**self._number_of_qubits):
# update quantum state
iistring = bin(ii)[2:]
bits = list(reversed(iistring.zfill(self._number_of_qubits)))
if outcome == '0':
iip = ii
else:
bits[qubit] == '0'
iip = int(''.join(reversed(bits)), 2)
if bits[qubit] == '0':
self._quantum_state[iip] = temp[ii]/norm
else:
self._quantum_state[iip] = 0
# print(self._quantum_state)
def run(self):
"""Run."""
for j in range(self._number_of_operations):
if self.circuit['qasm'][j]['type'] == 'gate':
gate = self.circuit['qasm'][j]['matrix']
if self.circuit['qasm'][j]['gate_size'] == 1:
qubit = self.circuit['qasm'][j]['qubit_indices'][0]
self._add_qasm_single(gate, qubit)
elif self.circuit['qasm'][j]['gate_size'] == 2:
qubit0 = self.circuit['qasm'][j]['qubit_indices'][0]
qubit1 = self.circuit['qasm'][j]['qubit_indices'][1]
self._add_qasm_two(gate, qubit0, qubit1)
elif self.circuit['qasm'][j]['type'] == 'measure':
qubit = self.circuit['qasm'][j]['qubit_indices'][0]
cbit = self.circuit['qasm'][j]['cbit_indices'][0]
self._add_qasm_measure(qubit, cbit)
elif self.circuit['qasm'][j]['type'] == 'reset':
qubit = self.circuit['qasm'][j]['qubit_indices'][0]
self._add_qasm_reset(qubit)
self.circuit['result']['quantum_state'] = self._quantum_state
self.circuit['result']['classical_state'] = self._classical_state
return self.circuit

View File

@ -0,0 +1,119 @@
"""
Contains a (slow) python simulator that makes the unitary of the circuit.
These are simple methods for making common matrices used in quantum computing.
Author: Jay Gambetta
circuit =
{
'number_of_qubits': 2,
'number_of_operations': 2
'qubit_order': {('q', 0): 0, ('v', 0): 1}
'qasm': [{
'type': 'gate',
'name': 'U(1.570796326794897,0.000000000000000,3.141592653589793)',
'qubit_indices': [0],
'gate_size': 1,
'matrix': array([[ 0.70710678 +0.00000000e+00j,
0.70710678 -8.65956056e-17j],
[ 0.70710678 +0.00000000e+00j,
-0.70710678 +8.65956056e-17j]])
}]
'result': {
unitary: array([[ 0.70710678 +0.00000000e+00j,
0.70710678 -8.65956056e-17j],
[ 0.70710678 +0.00000000e+00j,
-0.70710678 +8.65956056e-17j]])
}
}
"""
import numpy as np
class UnitarySimulator(object):
"""UnitarySimulator class."""
def __init__(self, circuit):
self.circuit = circuit
self._number_of_qubits = self.circuit['number_of_qubits']
self.circuit['result'] = {}
self._unitary_state = np.identity(2**(self._number_of_qubits),
dtype=complex)
self._number_of_operations = self.circuit['number_of_operations']
# print(self._unitary_state)
def _add_unitary_single(self, gate, qubit):
"""Apply the single qubit gate.
gate is the single qubit gate
qubit is the qubit to apply it on counts from 0 and order
is q_{n-1} ... otimes q_1 otimes q_0
number_of_qubits is the number of qubits in the system
returns a complex numpy array
"""
temp_1 = np.identity(2**(self._number_of_qubits-qubit-1),
dtype=complex)
temp_2 = np.identity(2**(qubit), dtype=complex)
unitaty_add = np.kron(temp_1, np.kron(gate, temp_2))
self._unitary_state = np.dot(unitaty_add, self._unitary_state)
def _add_unitary_two(self, gate, qubit_1, qubit_2):
"""Apply the two-qubit gate.
gate is the two-qubit gate
qubit_1 is the first qubit (control) counts from 0
qubit_2 is the second qubit (target)
number_of_qubits is the number of qubits in the system
returns a complex numpy array
"""
temp_1 = np.kron(np.identity(2**(self._number_of_qubits-2),
dtype=complex), gate)
unitaty_add = np.identity(2**(self._number_of_qubits), dtype=complex)
for ii in range(2**self._number_of_qubits):
iistring = bin(ii)[2:]
bits = list(reversed(iistring.zfill(self._number_of_qubits)))
# this is reverse order for assignement as list jut put it out
# 0001 is 4 qubit int 1 and this becomes [0,0,0,1]
# print(bits)
swap_1 = bits[0]
swap_2 = bits[1]
bits[0] = bits[qubit_1]
bits[1] = bits[qubit_2]
bits[qubit_1] = swap_1
bits[qubit_2] = swap_2
iistring = ''.join(reversed(bits))
iip = int(iistring, 2)
# print(iip)
for jj in range(2**self._number_of_qubits):
jjstring = bin(jj)[2:]
bits = list(reversed(jjstring.zfill(self._number_of_qubits)))
swap_1 = bits[0]
swap_2 = bits[1]
bits[0] = bits[qubit_1]
bits[1] = bits[qubit_2]
bits[qubit_1] = swap_1
bits[qubit_2] = swap_2
jjstring = ''.join(reversed(bits))
jjp = int(jjstring, 2)
unitaty_add[iip, jjp] = temp_1[ii, jj]
self._unitary_state = np.dot(unitaty_add, self._unitary_state)
def run(self):
"""Apply the single qubit gate."""
for j in range(self._number_of_operations):
if self.circuit['qasm'][j]['type'] == 'gate':
gate = self.circuit['qasm'][j]['matrix']
if self.circuit['qasm'][j]['gate_size'] == 1:
qubit = self.circuit['qasm'][j]['qubit_indices'][0]
self._add_unitary_single(gate, qubit)
elif self.circuit['qasm'][j]['gate_size'] == 2:
qubit0 = self.circuit['qasm'][j]['qubit_indices'][0]
qubit1 = self.circuit['qasm'][j]['qubit_indices'][1]
self._add_unitary_two(gate, qubit0, qubit1)
elif self.circuit['qasm'][j]['type'] == 'measure':
print('Warning have droped measure from unitary simulator')
elif self.circuit['qasm'][j]['type'] == 'reset':
print('Warning have droped reset from unitary simulator')
self.circuit['result']['unitary'] = self._unitary_state
return self.circuit

View File

@ -1,12 +0,0 @@
OPENQASM 2.0;
include "qelib1.inc";
qreg q[1];
creg c[2];
h q;
qreg v[1];
h v;
cx q[0],v[0];
h v;
h q;

View File

@ -1,13 +0,0 @@
"""Quick test program for unitary simulator backend."""
import qiskit.unroll as unroll
from qiskit.qasm import Qasm
from qiskit.simulators import UnitarySimulator
from unitary import unitary_simulator
basis = [] # empty basis, defaults to U, CX
unroller = unroll.Unroller(Qasm(filename="example.qasm").parse(),
UnitarySimulator(basis))
unroller.backend.set_trace(False) # print calls as they happen
unroller.execute() # Here is where simulation happens
unitary_gates = unroller.backend.unitary_gates
unitary_simulator(unitary_gates)
# print(unitary_gates)

View File

@ -1,73 +0,0 @@
"""
Quantum tools and common operators.
These are simple methods for making common matrices used in quantum computing.
Author: Jay Gambetta
"""
import numpy as np
def unitary_qi(gate, qubit, number_of_qubits):
"""Apply the single qubit gate.
gate is the single qubit gate
qubit is the qubit to apply it on counts from 0 and order
is q_{n-1} ... otimes q_1 otimes q_0
number_of_qubits is the number of qubits in the system
returns a complex numpy array
"""
return np.kron(np.identity(2**(number_of_qubits-qubit-1), dtype=complex),
np.kron(gate, np.identity(2**(qubit), dtype=complex)))
def unitary_qij(gate, qubit_1, qubit_2, number_of_qubits):
"""Apply the two-qubit gate.
gate is the two-qubit gate
qubit_1 is the first qubit (control) counts from 0
qubit_2 is the second qubit (target)
number_of_qubits is the number of qubits in the system
returns a complex numpy array
"""
temp_1 = np.kron(np.identity(2**(number_of_qubits-2), dtype=complex), gate)
temp_2 = np.identity(2**(number_of_qubits), dtype=complex)
for ii in range(2**number_of_qubits):
iistring = bin(ii)[2:]
bits = list(iistring.zfill(number_of_qubits))
swap_1 = bits[0]
swap_2 = bits[1]
bits[0] = bits[qubit_1]
bits[1] = bits[qubit_2]
bits[qubit_1] = swap_1
bits[qubit_2] = swap_2
iistring = ''.join(bits)
iip = int(iistring, 2)
for jj in range(2**number_of_qubits):
jjstring = bin(jj)[2:]
bits = list(jjstring.zfill(number_of_qubits))
swap_1 = bits[0]
swap_2 = bits[1]
bits[0] = bits[qubit_1]
bits[1] = bits[qubit_2]
bits[qubit_1] = swap_1
bits[qubit_2] = swap_2
jjstring = ''.join(bits)
jjp = int(jjstring, 2)
temp_2[iip, jjp] = temp_1[ii, jj]
return temp_2
def unitary_simulator(unitary_gates):
number_of_qubits = unitary_gates['number_of_qubits']
number_of_gates = unitary_gates['number_of_gates']
unitary_state = np.identity(2**(number_of_qubits))
for key in sorted(unitary_gates['gates'].keys()):
gate = unitary_gates['gates'][key]['matrix']
if unitary_gates['gates'][key]['qubits'] == 1:
unitary_state = unitary_qi(gate, unitary_gates['gates'][key]
['elements'][0], number_of_qubits) * unitary_state
elif unitary_gates['gates'][key]['qubits'] == 2:
unitary_state = unitary_qij(gate, unitary_gates['gates'][key]['elements'][0],
unitary_gates['gates'][key]['elements'][1], number_of_qubits) * unitary_state
print(unitary_state)

View File

@ -4,3 +4,4 @@ from ._oneregisterbackend import OneRegisterBackend
from ._printerbackend import PrinterBackend from ._printerbackend import PrinterBackend
from ._unrollerbackend import UnrollerBackend from ._unrollerbackend import UnrollerBackend
from ._backendexception import BackendException from ._backendexception import BackendException
from ._simulatorbackend import SimulatorBackend

View File

@ -1,37 +1,49 @@
""" """Backend for the unroller that composes unitary matrices to simulate circuit.
Backend for the unroller that composes unitary matrices to simulate circuit.
Author: Andrew Cross and Jay Gambetta Author: Jay Gambetta and Andrew Cross
{'number_of_qubits': 2,
'number_of_cbits': 2,
'number_of_operations': 2
'qubit_order': {('q', 0): 0, ('v', 0): 1}
'cbit_order': {('c', 1): 1, ('c', 0): 0},
'qasm': [{
'type': 'gate',
'name': 'U(1.570796326794897,0.000000000000000,3.141592653589793)',
'qubit_indices': [0],
'gate_size': 1,
'matrix': array([[ 0.70710678 +0.00000000e+00j,
0.70710678 -8.65956056e-17j],
[ 0.70710678 +0.00000000e+00j,
-0.70710678 +8.65956056e-17j]])
},
{
'type': 'measure',
'cbit_indices': [0],
'qubit_indices': [0]
}],
}
""" """
import numpy as np import numpy as np
from qiskit.unroll import BackendException from qiskit.unroll import BackendException
from qiskit.unroll import UnrollerBackend from qiskit.unroll import UnrollerBackend
# Jay, attach the backend to the unroller and run it:
# Take a look at ~/test/testsim.py
# I could not test it because QuantumProgram is hosed.
# You probably want "getters" to give back the final unitary matrix class SimulatorBackend(UnrollerBackend):
# or print it in some nice way (not implemented): """Backend for the unroller that composes unitary matrices."""
#
# print(unroller.backend.get_unitary_matrix())
class UnitarySimulator(UnrollerBackend):
""" Backend for the unroller that composes unitary matrices.
"""
def __init__(self, basis=None): def __init__(self, basis=None):
"""Setup this backend. """Setup this backend.
basis is a list of operation name strings. basis is a list of operation name strings.
""" """
self.unitary_gates = {} self.circuit = {}
self.unitary_gates['gates'] = {} self.circuit['qasm'] = []
self.unitaries = {} self._number_of_qubits = 0
self.number_of_qubits = 0 self._number_of_cbits = 0
self.qubit_order = {} self._qubit_order = {}
self.gate_order = 0 self._cbit_order = {}
self._operation_order = 0
self.prec = 15 self.prec = 15
self.creg = None self.creg = None
self.cval = None self.cval = None
@ -49,10 +61,6 @@ class UnitarySimulator(UnrollerBackend):
"""Set trace to True to enable.""" """Set trace to True to enable."""
self.trace = trace self.trace = trace
def get_unitary_gates(self):
"""reteurns the dictionary of unitary gates."""
return self.unitary_gates
def set_basis(self, basis): def set_basis(self, basis):
"""Declare the set of user-defined gates to emit. """Declare the set of user-defined gates to emit.
@ -84,13 +92,14 @@ class UnitarySimulator(UnrollerBackend):
assert size >= 0, "invalid qreg size" assert size >= 0, "invalid qreg size"
for j in range(size): for j in range(size):
self.qubit_order[(name, j)] = self.number_of_qubits + j self._qubit_order[(name, j)] = self._number_of_qubits + j
self.number_of_qubits += size self._number_of_qubits += size
# print(self.qubit_order) # print(self.qubit_order)
self.unitary_gates['number_of_qubits'] = self.number_of_qubits self.circuit['number_of_qubits'] = self._number_of_qubits
self.circuit['qubit_order'] = self._qubit_order
if self.trace: if self.trace:
print("added %d qubits from qreg %s giving a total of %d qubits" % print("added %d qubits from qreg %s giving a total of %d qubits" %
(size, name, self.number_of_qubits)) (size, name, self._number_of_qubits))
def new_creg(self, name, size): def new_creg(self, name, size):
"""Create a new classical register. """Create a new classical register.
@ -98,7 +107,16 @@ class UnitarySimulator(UnrollerBackend):
name = name of the register name = name of the register
sz = size of the register sz = size of the register
""" """
pass assert size >= 0, "invalid creg size"
for j in range(size):
self._cbit_order[(name, j)] = self._number_of_cbits + j
self._number_of_cbits += size
self.circuit['number_of_cbits'] = self._number_of_cbits
self.circuit['cbit_order'] = self._cbit_order
if self.trace:
print("added %d cbits from creg %s giving a total of %d qubits" %
(size, name, self._number_of_cbits))
def define_gate(self, name, gatedata): def define_gate(self, name, gatedata):
"""Define a new quantum gate. """Define a new quantum gate.
@ -128,18 +146,23 @@ class UnitarySimulator(UnrollerBackend):
qubit[1])) qubit[1]))
if self.creg is not None: if self.creg is not None:
raise BackendException("UnitarySimulator does not support if") raise BackendException("UnitarySimulator does not support if")
element = self.qubit_order.get(qubit) qubit_indices = [self._qubit_order.get(qubit)]
self.gate_order +=1 self._operation_order += 1
gate = np.array([[np.cos(arg[0]/2.0), -np.exp(1j*arg[2])*np.sin(arg[0]/2.0)], [np.exp(1j*arg[1])*np.sin(arg[0]/2.0), np.exp(1j*arg[1])*np.exp(1j*arg[2])*np.cos(arg[0]/2.0)]]) # print(np.exp(1j*arg[2])*np.sin(arg[0]/2.0))
self.unitary_gates['number_of_gates'] = self.gate_order gate = np.array([[np.cos(arg[0]/2.0),
self.unitary_gates['gates'][self.gate_order] = { -np.exp(1j*arg[2])*np.sin(arg[0]/2.0)],
'qubits': 1, [np.exp(1j*arg[1])*np.sin(arg[0]/2.0),
np.exp(1j*arg[1]+1j*arg[2])*np.cos(arg[0]/2.0)]])
self.circuit['number_of_operations'] = self._operation_order
self.circuit['qasm'].append({
'type': 'gate',
'gate_size': 1,
'matrix': gate, 'matrix': gate,
'name': "U(%s,%s,%s)" % (self._fs(arg[0]), 'name': "U(%s,%s,%s)" % (self._fs(arg[0]),
self._fs(arg[1]), self._fs(arg[1]),
self._fs(arg[2])), self._fs(arg[2])),
'elements': [element] 'qubit_indices': qubit_indices
} })
# print(self.unitary_gates) # print(self.unitary_gates)
@ -149,7 +172,6 @@ class UnitarySimulator(UnrollerBackend):
qubit0 is (regname,idx) tuple for the control qubit. qubit0 is (regname,idx) tuple for the control qubit.
qubit1 is (regname,idx) tuple for the target qubit. qubit1 is (regname,idx) tuple for the target qubit.
""" """
if self.listen: if self.listen:
if "CX" not in self.basis: if "CX" not in self.basis:
self.basis.append("CX") self.basis.append("CX")
@ -160,26 +182,35 @@ class UnitarySimulator(UnrollerBackend):
qubit1[0], qubit1[1])) qubit1[0], qubit1[1]))
if self.creg is not None: if self.creg is not None:
raise BackendException("UnitarySimulator does not support if") raise BackendException("UnitarySimulator does not support if")
element = [self.qubit_order.get(qubit0), qubit_indices = [self._qubit_order.get(qubit0),
self.qubit_order.get(qubit1)] self._qubit_order.get(qubit1)]
self.gate_order +=1 self._operation_order += 1
cx = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], cx = np.array([[1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0],
[0, 0, 1, 0]]) [0, 1, 0, 0]])
self.unitary_gates['number_of_gates'] = self.gate_order self.circuit['number_of_operations'] = self._operation_order
self.unitary_gates['gates'][self.gate_order] = { self.circuit['qasm'].append({
'qubits': 2, 'type': 'gate',
'gate_size': 2,
'matrix': cx, 'matrix': cx,
'name': 'CX', 'name': 'CX',
'elements': element, 'qubit_indices': qubit_indices,
} })
def measure(self, qubit, bit): def measure(self, qubit, cbit):
"""Measurement operation. """Measurement operation.
qubit is (regname, idx) tuple for the input qubit. qubit is (regname, idx) tuple for the input qubit.
bit is (regname, idx) tuple for the output bit. bit is (regname, idx) tuple for the output bit.
""" """
raise BackendException("UnitarySimulator does not support measurement") self._operation_order += 1
self.circuit['number_of_operations'] = self._operation_order
qubit_indices = [self._qubit_order.get(qubit)]
cbit_indices = [self._cbit_order.get(cbit)]
self.circuit['qasm'].append({
'type': 'measure',
'qubit_indices': qubit_indices,
'cbit_indices': cbit_indices
})
def barrier(self, qubitlists): def barrier(self, qubitlists):
"""Barrier instruction. """Barrier instruction.
@ -193,7 +224,13 @@ class UnitarySimulator(UnrollerBackend):
qubit is a (regname, idx) tuple. qubit is a (regname, idx) tuple.
""" """
raise BackendException("UnitarySimulator does not support reset") self._operation_order += 1
self.circuit['number_of_operations'] = self._operation_order
qubit_indices = [self._qubit_order.get(qubit)]
self.circuit['qasm'].append({
'type': 'reset',
'qubit_indices': qubit_indices,
})
def set_condition(self, creg, cval): def set_condition(self, creg, cval):
"""Attach a current condition. """Attach a current condition.

19
test/example.qasm Normal file
View File

@ -0,0 +1,19 @@
OPENQASM 2.0;
include "qelib1.inc";
qreg q[1];
creg c[3];
h q[0];
qreg v[2];
h v[1];
cx q[0],v[0];
//cx q[0],v[1];
// h v;
//h q;
reset v[1];
measure q[0] -> c[0];
measure v[0] -> c[1];
measure v[1] -> c[2];

View File

@ -339,6 +339,21 @@ class TestQISKit(unittest.TestCase):
def test_last(self): def test_last(self):
QP_program = QuantumProgram(specs=QPS_SPECS) QP_program = QuantumProgram(specs=QPS_SPECS)
qc, qr, cr = QP_program.quantum_elements()
qc2 = QP_program.create_circuit("qc2", ["qname"], ["cname"])
qc3 = QP_program.create_circuit("qc3", ["qname"], ["cname"])
qc2.h(qr[0])
qc3.h(qr[0])
circuits = [qc2, qc3]
device = 'local_qasm_simulator' # the device to run on
shots = 1024 # the number of shots in the experiment.
credits = 3
coupling_map = None
result = QP_program.execute(circuits, device, shots)
self.assertEqual(result['status'], 'COMPLETED')
# QP_program.plotter() # QP_program.plotter()

36
test/testsim.py Normal file
View File

@ -0,0 +1,36 @@
"""Quick test program for unitary simulator backend.
Author: Jay Gambetta
"""
import qiskit.unroll as unroll
from qiskit.qasm import Qasm
from qiskit.unroll import SimulatorBackend
from qiskit.simulators._unitarysimulator import UnitarySimulator
from qiskit.simulators._qasmsimulator import QasmSimulator
import random
from collections import Counter
basis = [] # empty basis, defaults to U, CX
unroller = unroll.Unroller(Qasm(filename="example.qasm").parse(),
SimulatorBackend(basis))
unroller.backend.set_trace(False) # print calls as they happen
unroller.execute() # Here is where simulation happens
print('using the unirary simulator')
a = UnitarySimulator(unroller.backend.circuit).run()
print('\n\n Unitary = ')
print(a['result']['unitary'])
print('\n\nusing the qasm simulator')
shots = 1024
outcomes = []
for i in range(shots):
# running the quantum_circuit
b = QasmSimulator(unroller.backend.circuit, random.random()).run()
#print(b['result']['quantum_state'])
#print(b['result']['classical_state'])
outcomes.append(bin(b['result']['classical_state'])[2:].zfill(b['number_of_cbits']))
print('\n\n outcomes = ')
print(dict(Counter(outcomes)))

View File

@ -19,7 +19,7 @@
"\n", "\n",
"***\n", "***\n",
"### Contributors\n", "### Contributors\n",
"Jay M. Gambetta, Andrew Cross, Antonio Córcoles, Andreas Fuhrer" "Jay M. Gambetta, Antonio Córcoles, Andrew Cross, Ismael Faro, Andreas Fuhrer "
] ]
}, },
{ {
@ -44,7 +44,11 @@
"## Introducing the tools\n", "## Introducing the tools\n",
"\n", "\n",
"These notebooks give an introduction to using the QISKit tools\n", "These notebooks give an introduction to using the QISKit tools\n",
"* [Getting Started with the Quantum Experience Web API](sections/getting_started_with_the_qx_api.ipynb) shows how to use the API to run your own quantum program on the QX. " "* [Getting Started with QISKit SDK, Tutorial for Developers](sections/tutorial4developer.ipynb) shows how to use the the QISKit SDK tools. \n",
"* Running the Local simulator \n",
"* Running on a real chip\n",
"* load/save a quantum program\n",
"* Visualizing a quanutm state"
] ]
}, },
{ {
@ -57,8 +61,6 @@
"\n", "\n",
"* [Superposition and entanglement](sections/superposition_and_entanglement.ipynb) - illustrates how to make simple quantum states on one and two qubits and shows concepts such as a quantum superpositions and entanglement. \n", "* [Superposition and entanglement](sections/superposition_and_entanglement.ipynb) - illustrates how to make simple quantum states on one and two qubits and shows concepts such as a quantum superpositions and entanglement. \n",
"* [Single qubit states: amplitude and phase](scripts/single_qubit_states_amplitude_and_phase.ipynb) illustrates more complicated single qubit states. \n", "* [Single qubit states: amplitude and phase](scripts/single_qubit_states_amplitude_and_phase.ipynb) illustrates more complicated single qubit states. \n",
"* [Superposition and entanglement](sections/superposition_and_entanglement.ipynb) - illustrates how to make simple quantum states on one and two qubits and shows concepts such as a quantum superpositions and entanglement. \n",
"* [Single qubit states: amplitude and phase](scripts/single_qubit_states_amplitude_and_phase.ipynb) TODO WITH JAY\n",
"* [Entanglement revisited](scripts/entanglement_revisited.ipynb) - illustrates the CHSH inequality and extensions for three qubits (Mermin). \n", "* [Entanglement revisited](scripts/entanglement_revisited.ipynb) - illustrates the CHSH inequality and extensions for three qubits (Mermin). \n",
"* Quantum sphere TODO WITH JAY\n", "* Quantum sphere TODO WITH JAY\n",
"* Quantum teleportation TODO WITH JAY\n", "* Quantum teleportation TODO WITH JAY\n",

View File

@ -1,95 +0,0 @@
// Quantum Experience (QE) Standard Header
// file: qelib1.inc
// --- QE Hardware primitives ---
// 3-parameter 2-pulse single qubit gate
gate u3(theta,phi,lambda) q { U(theta,phi,lambda) q; }
// 2-parameter 1-pulse single qubit gate
gate u2(phi,lambda) q { U(pi/2,phi,lambda) q; }
// 1-parameter 0-pulse single qubit gate
gate u1(lambda) q { U(0,0,lambda) q; }
// controlled-NOT
gate cx c,t { CX c,t; }
// idle gate (identity)
gate id a { U(0,0,0) a; }
// --- QE Standard Gates ---
// Pauli gate: bit-flip
gate x a { u3(pi,0,pi) a; }
// Pauli gate: bit and phase flip
gate y a { u3(pi,pi/2,pi/2) a; }
// Pauli gate: phase flip
gate z a { u1(pi) a; }
// Clifford gate: Hadamard
gate h a { u2(0,pi) a; }
// Clifford gate: sqrt(Z) phase gate
gate s a { u1(pi/2) a; }
// Clifford gate: conjugate of sqrt(Z)
gate sdg a { u1(-pi/2) a; }
// C3 gate: sqrt(S) phase gate
gate t a { u1(pi/4) a; }
// C3 gate: conjugate of sqrt(S)
gate tdg a { u1(-pi/4) a; }
// --- Standard rotations ---
// Rotation around X-axis
gate rx(theta) a { u3(theta, -pi/2,pi/2) a; }
// rotation around Y-axis
gate ry(theta) a { u3(theta,0,0) a; }
// rotation around Z axis
gate rz(phi) a { u1(phi) a; }
// --- QE Standard User-Defined Gates ---
// controlled-Phase
gate cz a,b { h b; cx a,b; h b; }
// controlled-Y
gate cy a,b { sdg b; cx a,b; s b; }
// controlled-H
gate ch a,b {
h b; sdg b;
cx a,b;
h b; t b;
cx a,b;
t b; h b; s b; x b; s a;
}
// C3 gate: Toffoli
gate ccx a,b,c
{
h c;
cx b,c; tdg c;
cx a,c; t c;
cx b,c; tdg c;
cx a,c; t b; t c; h c;
cx a,b; t a; tdg b;
cx a,b;
}
// controlled rz rotation
gate crz(lambda) a,b
{
u1(lambda/2) b;
cx a,b;
u1(-lambda/2) b;
cx a,b;
}
// controlled phase rotation
gate cu1(lambda) a,b
{
u1(lambda/2) a;
cx a,b;
u1(-lambda/2) b;
cx a,b;
u1(lambda/2) b;
}
// controlled-U
gate cu3(theta,phi,lambda) c, t
{
// implements controlled-U(theta,phi,lambda) with target t and control c
u1((lambda-phi)/2) t;
cx c,t;
u3(-theta/2,0,-(phi+lambda)/2) t;
cx c,t;
u3(theta/2,phi,0) t;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,516 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<img src=\"../images/QISKit-c.gif\" alt=\"Note: In order for images to show up in this jupyter notebook you need to select File => Trusted Notebook\" width=\"250 px\" align=\"left\">"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## _*Tutorial for Developers*_ \n",
"\n",
"For more information about how to use the Quantum Experience consult the [Quantum Experience tutorials](https://quantumexperience.ng.bluemix.net/qstage/#/tutorial?sectionId=c59b3710b928891a1420190148a72cce&pageIndex=0) or check-out the [community](https://quantumexperience.ng.bluemix.net/qstage/#/community).\n",
"\n",
"***\n",
"### Contributors\n",
"Ismael Faro, Jay M. Gambetta"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Quantum QISKit SDK tutorial\n",
"\n",
"This tutorial focus is to explain how use the QISKit SDK, from a developer point of view. We review how install, and start to use the SDK tools.\n",
"\n",
"QISKIt is a Python software development kit (SDK), that you can use to create your Quantum programs, based in circuits over [OpenQASM 2.0](https://github.com/IBM/qiskit-openqasm) Specs, compile and execute it in several Backends (Real Chips, Simulators online and Simulators in local). For the online Backend QISKit use our [python API connector](https://github.com/IBM/qiskit-api-py) to the [IBM Quantum Experience API project (http://quantumexperience.ng.bluemix.net/).\n",
"\n",
"We have other tutorials that introduce you to more complex concepts directly related with the Quantum.\n",
"\n",
"more examples:\n",
"[superposition and entanglement](superposition_and_entanglement.ipynb) we introduced you to the concept of entanglement.\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Install QISKit\n",
"\n",
"the most easy way to install QISKit is using Anaconda python distribution.\n",
"\n",
"- Install Anaconda: https://www.continuum.io/downloads\n",
"\n",
"After that you need to install your QISKit from the git repository\n",
"\n",
"- Clone the repo:\n",
"\n",
"```sh\n",
"git clone https://github.ibm.com/IBMQuantum/qiskit-sdk-py-dev\n",
"cd qiskit-sdk-py-dev\n",
"```\n",
"\n",
"- Create the environment with the dependencies:\n",
"\n",
"```sh\n",
"make env\n",
"```\n",
"\n",
"## Use\n",
"\n",
"You can use the examples in an easy way with Jupyter or Python\n",
"\n",
"Add your API token to the file \"Qconfig.py\" (get it from [IBM Quantum Experience](https://quantumexperience.ng.bluemix.net) > Account):\n",
"\n",
"```sh\n",
"cp tutorial/Qconfig.py.default Qconfig.py\n",
"```\n",
"Run Jupyter notebook.\n",
"- Run it:\n",
"\n",
"```sh\n",
"make run\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Basic Concept\n",
"\n",
"### Create a Program\n",
"\n",
"Firts you need to import the QuantumProgram from QISKit"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import sys\n",
"sys.path.append(\"../../\") # solve the relative dependencies if you clone QISKit from the Git repo and use like a global.\n",
"\n",
"from qiskit import QuantumProgram\n",
"import Qconfig"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The basic elements that you need to create your first program are, the QuantumProgram, one Circuit, one Quantum Register and One Classical Register."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# Creating Programs\n",
"# create your first QuantumProgram object instance.\n",
"Q_program = QuantumProgram()\n",
"\n",
"# Creating Registers\n",
"# create your first Quantum Register called \"qr\" with 2 Qbit \n",
"qr = Q_program.create_quantum_registers(\"qr\", 2)\n",
"# create your first Classical Register called \"cr\" with 2 bit\n",
"cr = Q_program.create_classical_registers(\"cr\", 2)\n",
"\n",
"# Creating Circuits\n",
"# create your first Quantum Circuit called \"qc\" related with your Quantum Register \"qr\"\n",
"# and your Classical Register \"cr\"\n",
"qc = Q_program.create_circuit(\"qc\", [\"qr\"], [\"cr\"])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As another option to create your QuantumProgram instance you can define a Dictionary with all the component of your program."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"Q_SPECS = {\n",
" \"name\": \"Program-tutorial\",\n",
" \"circuits\": [{\n",
" \"name\": \"Circuit\",\n",
" \"quantum_registers\": [{\n",
" \"name\":\"qr\",\n",
" \"size\": 4\n",
" }],\n",
" \"classical_registers\": [{\n",
" \"name\":\"cr\",\n",
" \"size\": 4\n",
" }]}],\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"One Program must to have a name, and one circuits array, any circuit must have a name and it can have several Quantum registers and several Classical Registers. Every register needs to have a name and the number of the elements (qubits or bits).\n",
"\n",
"After that, you can use this dictionary definition like the specs of one QuantumProgram object to initialize it."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"new_Q_program = QuantumProgram(specs=Q_SPECS)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can get every component from your new_Q_program to use."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"#get the components.\n",
"\n",
"#get the circuit by Name\n",
"circuit = new_Q_program.circuit(\"Circuit\")\n",
"\n",
"#get the Quantum Register by Name\n",
"quantum_r = new_Q_program.quantum_registers(\"qr\")\n",
"\n",
"#get the Quantum Register by Name\n",
"classical_r = new_Q_program.classical_registers('cr')"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"### add gates to your circuit\n",
"After you create the circuit with its registers you can add gates to manipulate the registers. The next is the example of the all the gates that you can use.\n",
"\n",
"You can find extensive information about these gates and how use it into our [Quantum Experience User Guide](https://quantumexperience.ng.bluemix.net/qstage/#/tutorial?sectionId=71972f437b08e12d1f465a8857f4514c&pageIndex=2) "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# H (Hadamard) gate to the Qbit 0 in the Quantum Register \"qr\" \n",
"circuit.h(quantum_r[0])\n",
"\n",
"# Pauli X gate to the Qbit 1 in the Quantum Register \"qr\" \n",
"circuit.x(quantum_r[1])\n",
"\n",
"# Pauli Y gate to the Qbit 2 in the Quantum Register \"qr\" \n",
"circuit.y(quantum_r[2])\n",
"\n",
"# Pauli Z gate to the Qbit 3 in the Quantum Register \"qr\" \n",
"circuit.z(quantum_r[3])\n",
"\n",
"# Cnot (Controlled-NOT)gate from Qbit 0 to the Qbit 2\n",
"circuit.cx(quantum_r[0], quantum_r[2])\n",
"\n",
"# add a barrier to your circuit\n",
"circuit.barrier()\n",
"\n",
"# first physical gate: u1(lambda) to Qbit 0\n",
"circuit.u1(0.3, quantum_r[0])\n",
"\n",
"# second physical gate: u2(phi,lambda) to Qbit 1\n",
"circuit.u2(0.3, 0.2, quantum_r[1])\n",
"\n",
"# second physical gate: u3(theta,phi,lambda) to Qbit 2\n",
"circuit.u3(0.3, 0.2, 0.1, quantum_r[2])\n",
"\n",
"# S Phase gate to Qbit 0\n",
"circuit.s(quantum_r[0])\n",
"\n",
"# T Phase gate to Qbit 1\n",
"circuit.t(quantum_r[1])\n",
"\n",
"# identity gate to Qbit 1\n",
"circuit.iden(quantum_r[1])\n",
"\n",
"# Classical if, from Qbit2 gate Z to classical bit 1\n",
"# circuit.z(quantum_r[2]).c_if(classical_r, 1)\n",
"\n",
"# measure gate from the Qbit 0 to Classical bit 0\n",
"circuit.measure(quantum_r[0], classical_r[0])\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### extract QASM\n",
"\n",
"You can obtain a QASM representation of your code."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# QASM from a circuit\n",
"\n",
"QASM_source = circuit.qasm()\n",
"\n",
"print (QASM_source)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# Qasm from a program\n",
"\n",
"QASM_source = new_Q_program.program_to_text()\n",
"\n",
"print(QASM_source)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"Note: you can appreciate that the both codes don't have the same notation, the second one return a conversion from every H, X, Y, Z gate the u1, u2 and u3 representation."
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"### Compile & run or Execute"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"device = 'simulator' #Backend where execute your program, in this case it is the online simulator\n",
"circuits = [circuit] #Group of circuits to exec\n",
"\n",
"Q_program.set_api(Qconfig.APItoken, Qconfig.config[\"url\"]) #set the APIToken and API url"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"Q_program.compile(circuits, device) #Compile your program\n",
"\n",
"result = Q_program.run(wait=2, timeout=240) #Run your program in the device and check the execution result every 2 seconds \n",
"\n",
"print(result)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"When you run a program the result can be:\n",
"\n",
"```JSON\n",
"JOB_STATUS = {\n",
" inProgress: 'RUNNING',\n",
" errorOnCreate: 'ERROR_CREATING_JOB',\n",
" errorExecuting: 'ERROR_RUNNING_JOB',\n",
" completed: 'COMPLETED'\n",
" };\n",
"```\n",
"\n",
"The *run()* command waiting until timeout or when receive the \"COMPLETED\" or some error message.\n",
"\n",
"You can use the *execute()* to make the compile and run in a unique step."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"result = Q_program.execute(circuits, device, wait=2, timeout=240)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Compile parameters\n",
"Q_program.compile(circuits, device=\"simulator\", shots=1024, max_credits=3, basis_gates=None, coupling_map=None)\n",
" - circuits: Array of circuit to compile\n",
" - device: Backend \n",
" [\"ibmqx_qasm_simulator\", # Online simulator\n",
" \"ibmqx2\", # Online RealChip, 5Qbits\n",
" \"ibmqx3\", # Online RealChip, 16Qbits\n",
" \"local_unitary_simulator\", # Local unitary Simulator \n",
" \"local_qasm_simulator\"] # Local Simulator \n",
" - shots: Number of shots, only for real chips and qasm simulators\n",
" - max_credits: Maximum number of the credits to spend in the executions. If the executions are more expensives, the job is aborted, only the real chips\n",
" - basis_gates: are the base gates, by default are: u1,u2,u3,cx,id\n",
" - coupling_map: Object that represent the physical/topological Layout of a chip.\n",
"#### Run parameters\n",
"Q_program.run(wait=5, timeout=60)\n",
" - wait: Time to wait to check if the execution is COMPLETED.\n",
" - timeout: Timeout of the execution.\n",
"#### Execute parameters \n",
"*the Execute has the combined parameters of Compile and Run*\n",
"\n",
"Q_program.execute(circuits, device, shots=1024,\n",
" max_credits=3, basis_gates=None, wait=5, timeout=60, basis_gates=None, coupling_map=None,)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Execute in a real device"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"device = 'qx5qv2' #Backed where execute your program, in this case in the Real Quantum Chip online \n",
"circuits = [circuit] #Group of circuits to exec\n",
"shots = 1024 #Number of Shots to run the program (experiment), Maximum 8192 shots.\n",
"max_credits=3 #Maximum number of the credits to spend in the executions. \n",
"\n",
"result = Q_program.execute(circuits, device, shots, max_credits=3, wait=10, timeout=240)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Result\n",
"You can access to the result in the element: qasms[n].result.data.counts "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"result['qasms'][0]['result']['data']['counts']"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"or you can use the function tool get_data(n) to obtain it directly"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"Q_program.get_data(result,0) "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.0"
}
},
"nbformat": 4,
"nbformat_minor": 0
}