mirror of https://github.com/Qiskit/qiskit.git
Merge branch 'Dev' into isma/clean-quantum-program
This commit is contained in:
commit
d5a3dfceab
45
README.md
45
README.md
|
@ -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.
|
||||||
|
|
|
@ -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))
|
|
@ -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
|
|
||||||
|
|
|
@ -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())
|
|
|
@ -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()
|
|
|
@ -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 |
|
@ -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 |
|
@ -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']
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
from ._unitarysimulator import UnitarySimulator
|
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
|
|
@ -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)
|
|
|
@ -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)
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
|
@ -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];
|
15
test/test.py
15
test/test.py
|
@ -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()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)))
|
|
@ -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",
|
||||||
|
|
|
@ -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
|
@ -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
|
||||||
|
}
|
Loading…
Reference in New Issue