Adding terra documentation (Qiskit/qiskit-metapackage#35)

This commit is contained in:
Jay M. Gambetta 2019-01-13 07:52:32 -05:00 committed by Diego M. Rodríguez
parent 82e5e4f173
commit f19aa5b456
2 changed files with 1319 additions and 0 deletions

View File

@ -0,0 +1,671 @@
Getting Started with Qiskit
===========================
Here, we provide an overview of working with Qiskit. Qiskit provides the
basic building blocks necessary to program quantum computers. The
foundation of Qiskit is the Terra element. The basic concept of Qiskit
Terra is an array of quantum circuits. A workflow using Terra consists
of two stages: **Build** and **Execute**. **Build** allows you to make
different quantum circuits that represent the problem you are solving,
and **Execute** allows you to run them on different backends. After the
jobs have been run, the data is collected. There are methods for putting
this data together, depending on the program. This either gives you the
answer you wanted, or allows you to make a better program for the next
instance.
**Contents**
`Circuit basics <#circuit_basics>`__
`Simulating circuits with Qiskit Aer <#aer_simulation>`__
`Running circuits using the IBMQ provider <#ibmq_provider>`__
**Code imports**
.. code:: ipython3
import numpy as np
from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister
from qiskit import execute
Circuit Basics
---------------
Building the circuit
~~~~~~~~~~~~~~~~~~~~
The basic elements needed for your first program are the QuantumCircuit,
and QuantumRegister.
.. code:: ipython3
# Create a Quantum Register with 3 qubits.
q = QuantumRegister(3, 'q')
# Create a Quantum Circuit acting on the q register
circ = QuantumCircuit(q)
.. raw:: html
<div class="alert alert-block alert-info">
Note: Naming the QuantumRegister is optional and not required.
.. raw:: html
</div>
After you create the circuit with its registers, you can add gates
(“operations”) to manipulate the registers. As you proceed through the
documentation you will find more gates and circuits; the below is an
example of a quantum circuit that makes a three-qubit GHZ state
.. math:: |\psi\rangle = \left(|000\rangle+|111\rangle\right)/\sqrt{2}.
To create such a state, we start with a 3-qubit quantum register. By
default, each qubit in the register is initialized to :math:`|0\rangle`.
To make the GHZ state, we apply the following gates: \* A Hadamard gate
:math:`H` on qubit 0, which puts it into a superposition state. \* A
controlled-Not operation (:math:`C_{X}`) between qubit 0 and qubit 1. \*
A controlled-Not operation between qubit 0 and qubit 2.
On an ideal quantum computer, the state produced by running this circuit
would be the GHZ state above.
In Qiskit Terra, operations can be added to the circuit one-by-one, as
shown below.
.. code:: ipython3
# Add a H gate on qubit 0, putting this qubit in superposition.
circ.h(q[0])
# Add a CX (CNOT) gate on control qubit 0 and target qubit 1, putting
# the qubits in a Bell state.
circ.cx(q[0], q[1])
# Add a CX (CNOT) gate on control qubit 0 and target qubit 2, putting
# the qubits in a GHZ state.
circ.cx(q[0], q[2])
.. parsed-literal::
<qiskit.extensions.standard.cx.CnotGate at 0xa20709128>
Visualize Circuit
-----------------
You can visualize your circuit using Qiskit Terra
``QuantumCircuit.draw()``, which plots circuit in the form found in many
textbooks.
.. code:: ipython3
circ.draw()
.. raw:: html
<pre style="word-wrap: normal;white-space: pre;line-height: 15px;"> ┌───┐
q_0: |0>┤ H ├──■────■──
└───┘┌─┴─┐ │
q_1: |0>─────┤ X ├──┼──
└───┘┌─┴─┐
q_2: |0>──────────┤ X ├
└───┘</pre>
In this circuit, the qubits are put in order with qubit zero at the top
and qubit two at the bottom. The circuit is read left-to-right (meaning
that gates which are applied earlier in the circuit show up further to
the left).
Simulating circuits using Qiskit Aer
-------------------------------------
Qiskit Aer is our package for simulating quantum circuits. It provides
many different backends for doing a simulation. Here we use the basic
python version.
Statevector backend
~~~~~~~~~~~~~~~~~~~
The most common backend in Qiskit Aer is the ``statevector_simulator``.
This simulator returns the quantum state which is a complex vector of
dimensions :math:`2^n` where :math:`n` is the number of qubits (so be
careful using this as it will quickly get too large to run on your
machine).
.. raw:: html
<div class="alert alert-block alert-info">
When representing the state of a multi-qubit system, the tensor order
used in qiskit is different than that use in most physics textbooks.
Suppose there are :math:`n` qubits, and qubit :math:`j` is labeled as
:math:`Q_{j}`. In most textbooks (such as Nielsen and Chuangs “Quantum
Computation and Information”), the basis vectors for the :math:`n`-qubit
state space would be labeled as
:math:`Q_{0}\otimes Q_{1} \otimes \cdots \otimes Q_{n}`. **This is not
the ordering used by qiskit!** Instead, qiskit uses an ordering in which
the :math:`n^{\mathrm{th}}` qubit is on the *left* side of the tesnsor
product, so that the basis vectors are labeled as
:math:`Q_n\otimes \cdots \otimes Q_1\otimes Q_0`.
For example, if qubit zero is in state 0, qubit 1 is in state 0, and
qubit 2 is in state 1, qiskit would represent this state as
:math:`|100\rangle`, whereas most physics textbooks would represent it
as :math:`|001\rangle`.
This difference in labeling affects the way multi-qubit operations are
represented as matrices. For example, qiskit represents a controlled-X
(:math:`C_{X}`) operation with qubit 0 being the control and qubit 1
being the target as
.. math:: C_X = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\\end{pmatrix}.
.. raw:: html
</div>
To run the above circuit using the statevector simulator, first you need
to import Aer and then set the backend to ``statevector_simulator``.
.. code:: ipython3
# Import Aer
from qiskit import BasicAer
# Run the quantum circuit on a statevector simulator backend
backend = BasicAer.get_backend('statevector_simulator')
Now we have chosen the backend its time to compile and run the quantum
circuit. In Qiskit Terra we provide the ``execute`` function for this.
``execute`` returns a ``job`` object that encapsulates information about
the job submitted to the backend.
.. raw:: html
<div class="alert alert-block alert-info">
Tip: You can obtain the above parameters in Jupyter. Simply place the
text cursor on a function and press Shift+Tab.
.. raw:: html
</div>
.. code:: ipython3
# Create a Quantum Program for execution
job = execute(circ, backend)
When you run a program, a job object is made that has the following two
useful methods: ``job.status()`` and ``job.result()`` which return the
status of the job and a result object respectively.
.. raw:: html
<div class="alert alert-block alert-info">
Note: Jobs run asynchronously but when the result method is called it
switches to synchronous and waits for it to finish before moving on to
another task.
.. raw:: html
</div>
.. code:: ipython3
result = job.result()
The results object contains the data and Qiskit Terra provides the
method ``result.get_statevector(circ)`` to return the state vector for
the quantum circuit.
.. code:: ipython3
outputstate = result.get_statevector(circ, decimals=3)
print(outputstate)
.. parsed-literal::
[0.707+0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j
0.707+0.j]
Qiskit Terra also provides a visualization toolbox to allow you to view
these results.
Below, we use the visualization function to plot the real and imaginary
components of the state vector.
.. code:: ipython3
from qiskit.tools.visualization import plot_state_city
plot_state_city(outputstate)
.. image:: getting_started_with_qiskit_terra_files/getting_started_with_qiskit_terra_21_0.png
Unitary backend
~~~~~~~~~~~~~~~
Qiskit Aer also includes a ``unitary_simulator`` that works *provided
all the elements in the circuit are unitary operations*. This backend
calculates the :math:`2^n \times 2^n` matrix representing the gates in
the quantum circuit.
.. code:: ipython3
# Run the quantum circuit on a unitary simulator backend
backend = BasicAer.get_backend('unitary_simulator')
job = execute(circ, backend)
result = job.result()
# Show the results
print(result.get_unitary(circ, decimals=3))
.. parsed-literal::
[[ 0.707+0.j 0.707+0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j
0. +0.j 0. +0.j]
[ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j
0.707+0.j -0.707+0.j]
[ 0. +0.j 0. +0.j 0.707+0.j 0.707+0.j 0. +0.j 0. +0.j
0. +0.j 0. +0.j]
[ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0.707+0.j -0.707+0.j
0. +0.j 0. +0.j]
[ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0.707+0.j 0.707+0.j
0. +0.j 0. +0.j]
[ 0. +0.j 0. +0.j 0.707+0.j -0.707+0.j 0. +0.j 0. +0.j
0. +0.j 0. +0.j]
[ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j
0.707+0.j 0.707+0.j]
[ 0.707+0.j -0.707+0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j
0. +0.j 0. +0.j]]
OpenQASM backend
~~~~~~~~~~~~~~~~
The simulators above are useful because they provide information about
the state output by the ideal circuit and the matrix representation of
the circuit. However, a real experiment terminates by *measuring* each
qubit (usually in the computational :math:`|0\rangle, |1\rangle` basis).
Without measurement, we cannot gain information about the state.
Measurements cause the quantum system to collapse into classical bits.
For example, suppose we make independent measurements on each qubit of
the three-qubit GHZ state
.. math:: |\psi\rangle = |000\rangle +|111\rangle)/\sqrt{2},
and let :math:`xyz` denote the bitstring that results. Recall that,
under the qubit labeling used by Qiskit, :math:`x` would correspond to
the outcome on qubit 2, :math:`y` to the outcome on qubit 1, and
:math:`z` to the outcome on qubit 0. This representation of the
bitstring puts the most significant bit (MSB) on the left, and the least
significant bit (LSB) on the right. This is the standard ordering of
binary bitstrings. We order the qubits in the same way, which is why
Qiskit uses a non-standard tensor product order.
The probability of obtaining outcome :math:`xyz` is given by
.. math:: \mathrm{Pr}(xyz) = |\langle xyz | \psi \rangle |^{2}.
By explicit computation, we see there are only two bitstrings that will
occur: :math:`000` and :math:`111`. If the bitstring :math:`000` is
obtained, the state of the qubits is :math:`|000\rangle`, and if the
bitstring is :math:`111`, the qubits are left in the state
:math:`|111\rangle`. The probability of obtaining 000 or 111 is the
same; namely, 1/2:
.. math::
\begin{align}
\mathrm{Pr}(000) &= |\langle 000 | \psi \rangle |^{2} = \frac{1}{2}\\
\mathrm{Pr}(111) &= |\langle 111 | \psi \rangle |^{2} = \frac{1}{2}.
\end{align}
To simulate a circuit that includes measurement, we need to add
measurements to the original circuit above, and use a different Aer
backend.
.. code:: ipython3
# Create a Classical Register with 3 bits.
c = ClassicalRegister(3, 'c')
# Create a Quantum Circuit
meas = QuantumCircuit(q, c)
meas.barrier(q)
# map the quantum measurement to the classical bits
meas.measure(q,c)
# The Qiskit circuit object supports composition using
# the addition operator.
qc = circ+meas
#drawing the circuit
qc.draw()
.. raw:: html
<pre style="word-wrap: normal;white-space: pre;line-height: 15px;"> ┌───┐ ░ ┌─┐
q_0: |0>┤ H ├──■────■───░───────┤M├
└───┘┌─┴─┐ │ ░ ┌─┐└╥┘
q_1: |0>─────┤ X ├──┼───░────┤M├─╫─
└───┘┌─┴─┐ ░ ┌─┐└╥┘ ║
q_2: |0>──────────┤ X ├─░─┤M├─╫──╫─
└───┘ ░ └╥┘ ║ ║
c_0: 0 ═══════════════════╬══╬══╩═
║ ║
c_1: 0 ═══════════════════╬══╩════
c_2: 0 ═══════════════════╩═══════
</pre>
This circuit adds a classical register, and three measurements that are
used to map the outcome of qubits to the classical bits.
To simulate this circuit, we use the ``qasm_simulator`` in Qiskit Aer.
Each run of this circuit will yield either the bitstring 000 or 111. To
build up statistics about the distribution of the bitstrings (to, e.g.,
estimate :math:`\mathrm{Pr}(000)`), we need to repeat the circuit many
times. The number of times the circuit is repeated can be specified in
the ``execute`` function, via the ``shots`` keyword.
.. code:: ipython3
# Use Aer's qasm_simulator
backend_sim = BasicAer.get_backend('qasm_simulator')
# Execute the circuit on the qasm simulator.
# We've set the number of repeats of the circuit
# to be 1024, which is the default.
job_sim = execute(qc, backend_sim, shots=1024)
# Grab the results from the job.
result_sim = job_sim.result()
Once you have a result object, you can access the counts via the
function ``get_counts(circuit)``. This gives you the *aggregated* binary
outcomes of the circuit you submitted.
.. code:: ipython3
counts = result_sim.get_counts(qc)
print(counts)
.. parsed-literal::
{'000': 497, '111': 527}
Approximately 50 percent of the time the output bitstring is 000. Qiskit
Terra also provides a function ``plot_histogram`` which allows you to
view the outcomes.
.. code:: ipython3
from qiskit.tools.visualization import plot_histogram
plot_histogram(counts)
.. image:: getting_started_with_qiskit_terra_files/getting_started_with_qiskit_terra_33_0.png
The estimated outcome probabilities :math:`\mathrm{Pr}(000)` and
:math:`\mathrm{Pr}(111)` are computed by taking the aggregate counts and
dividing by the number of shots (times the circuit was repeated). Try
changing the ``shots`` keyword in the ``execute`` function and see how
the estimated probabilities change.
Running circuits using the IBMQ provider
-----------------------------------------
To faciliate access to real quantum computing hardware, we have provided
a simple API interface. To access IBMQ devices, youll need an API
token. For the public IBM Q devices, you can generate an API token
`here <https://quantumexperience.ng.bluemix.net/qx/account/advanced>`__
(create an account if you dont already have one). For Q Network
devices, login to the q-console, click your hub, group, and project, and
expand “Get Access” to generate your API token and access url.
Our IBMQ provider lets you run your circuit on real devices or on our
HPC simulator. Currently, this provider exists within Qiskit, and can be
imported as shown below. For details on the provider, see `The IBMQ
Provider <the_ibmq_provider.ipynb>`__.
.. code:: ipython3
from qiskit import IBMQ
After generating your API token, call,
``IBMQ.save_account('MY_TOKEN')``. For Q Network users, youll also need
to include your access url: ``IBMQ.save_account('MY_TOKEN', 'URL')``
This will store your IBMQ credentials in a local file. Unless your
registration information has changed, you only need to do this once. You
may now load your accounts by calling,
.. code:: ipython3
IBMQ.load_accounts()
Once your account has been loaded, you can view the list of backends
available to you.
.. code:: ipython3
print("Available backends:")
IBMQ.backends()
.. parsed-literal::
Available backends:
.. parsed-literal::
[<IBMQBackend('ibmqx4') from IBMQ()>,
<IBMQBackend('ibmq_16_melbourne') from IBMQ()>,
<IBMQBackend('ibmq_qasm_simulator') from IBMQ()>,
<IBMQBackend('ibmq_20_tokyo') from IBMQ(ibm-q-internal, research, yorktown)>,
<IBMQBackend('ibmq_qasm_simulator') from IBMQ(ibm-q-internal, research, yorktown)>]
Running circuits on real devices
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Todays quantum information processors are small and noisy, but are
advancing at a fast pace. They provide a great opportunity to explore
what `noisy, intermediate-scale quantum
(NISQ) <https://arxiv.org/abs/1801.00862>`__ computers can do.
The IBMQ provider uses a queue to allocate the devices to users. We now
choose a device with the least busy queue which can support our program
(has at least 3 qubits).
.. code:: ipython3
from qiskit.providers.ibmq import least_busy
large_enough_devices = IBMQ.backends(filters=lambda x: x.configuration().n_qubits > 4 and
not x.configuration().simulator)
backend = least_busy(large_enough_devices)
print("The best backend is " + backend.name())
.. parsed-literal::
The best backend is ibmqx4
To run the circuit on the backend, we need to specify the number of
shots and the number of credits we are willing to spend to run the
circuit. Then, we execute the circuit on the backend using the
``execute`` function.
.. code:: ipython3
from qiskit.tools.monitor import job_monitor
shots = 1024 # Number of shots to run the program (experiment); maximum is 8192 shots.
max_credits = 3 # Maximum number of credits to spend on executions.
job_exp = execute(qc, backend=backend, shots=shots, max_credits=max_credits)
job_monitor(job_exp)
.. parsed-literal::
HTML(value="<p style='font-size:16px;'>Job Status: job is being initialized </p>")
``job_exp`` has a ``.result()`` method that lets us get the results from
running our circuit.
.. raw:: html
<div class="alert alert-block alert-info">
Note: When the .result() method is called, the code block will wait
until the job has finished before releasing the cell.
.. raw:: html
</div>
.. code:: ipython3
result_exp = job_exp.result()
Like before, the counts from the execution can be obtained using
``get_counts(qc)``
.. code:: ipython3
counts_exp = result_exp.get_counts(qc)
plot_histogram([counts_exp,counts])
.. image:: getting_started_with_qiskit_terra_files/getting_started_with_qiskit_terra_49_0.png
Simulating circuits using a HPC simulator
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The IBMQ provider also comes with a remote optimized simulator called
``ibmq_qasm_simulator``. This remote simulator is capable of simulating
up to 32 qubits. It can be used the same way as the remote real
backends.
.. code:: ipython3
backend = IBMQ.get_backend('ibmq_qasm_simulator', hub=None)
.. code:: ipython3
shots = 1024 # Number of shots to run the program (experiment); maximum is 8192 shots.
max_credits = 3 # Maximum number of credits to spend on executions.
job_hpc = execute(qc, backend=backend, shots=shots, max_credits=max_credits)
.. code:: ipython3
result_hpc = job_hpc.result()
.. code:: ipython3
counts_hpc = result_hpc.get_counts(qc)
plot_histogram(counts_hpc)
.. image:: getting_started_with_qiskit_terra_files/getting_started_with_qiskit_terra_54_0.png
Retrieving a previously ran job
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If your experiment takes longer to run then you have time to wait
around, or if you simply want to retrieve old jobs back, the IBMQ
backends allow you to do that. First you would need to note your jobs
ID:
.. code:: ipython3
jobID = job_exp.job_id()
print('JOB ID: {}'.format(jobID))
.. parsed-literal::
JOB ID: 5c1a2b4f39c21300575b61b0
Given a job ID, that job object can be later reconstructed from the
backend using retrieve_job:
.. code:: ipython3
job_get=backend.retrieve_job(jobID)
and then the results can be obtained from the new job object.
.. code:: ipython3
job_get.result().get_counts(qc)
.. parsed-literal::
{'000': 393,
'110': 32,
'111': 340,
'010': 43,
'101': 124,
'001': 14,
'011': 48,
'100': 30}

View File

@ -0,0 +1,648 @@
###############
Release history
###############
*************
Release notes
*************
Qiskit Terra 0.7.0
==================
This release includes several new features and many bug fixes. With this
release the interfaces for circuit diagram, histogram, bloch vectors,
and state visualizations are declared stable. Additionally, this release includes a
defined and standardized bit order/endianness throughout all aspects of Qiskit.
These are all declared as stable interfaces in this release which won't have
breaking changes made moving forward, unless there is appropriate and lengthy
deprecation periods warning of any coming changes.
There is also the introduction of the following new features:
* A new ASCII art circuit drawing output mode
* A new ciruit drawing interface off of QuantumCircuit objects. Now you can
call ``circuit.draw()`` or ``print(circuit)`` and render a drawing of
the circuit.
* A visualizer for drawing the DAG representation of a circuit
* A new quantum state plot type for hinton diagrams in the local matplotlib
based state plots.
* 2 new constructor methods off the ``QuantumCircuit`` class
``from_qasm_str()`` and ``from_qasm_file()`` which let you easily create a
circuit object from OpenQASM.
* A new function ``plot_bloch_multivector()`` to plot Bloch vectors from a
tensored state vector or density matrix
* Per-shot measurement results are available in simulators and select devices.
These can be accessed by setting the ``memory`` kwarg to ``True`` when
calling ``compile()`` or ``execute()`` and then accessed using the
``get_memory()`` method on the ``Result`` object.
* A ``qiskit.quantum_info`` module with revamped Pauli objects and methods for
working with quantum states.
* New transpile passes for circuit analysis and transformation:
CommutationAnalysis, CommutationTransformation, CXCancellation, Decompose,
Unroll, Optimize1QGates, CheckMap, CXDirection, BarrierBeforeFinalMeasurements
* New alternative swap mapper passes in the transpiler:
BasicSwap, LookaheadSwap, StochasticSwap
* More advanced transpiler infrastructure with support for analysis passes,
transformation passes, a global property_set for the pass manager, and
repeat-until control of passes.
Upgrading to 0.7.0
------------------
Please note that some backwards-incompatible changes have been made during this
release. The following notes contain information on how to adapt to these
changes.
Changes to Result objects
^^^^^^^^^^^^^^^^^^^^^^^^^
As part of the rewrite of the Results object to be more consistent and a
stable interface moving forward a few changes have been made to how you access
the data stored in the result object. First the ``get_data()`` method has been
renamed to just ``data()``. Accompanying that change is a change in the data
format returned by the function. It is now returning the raw data from the
backends instead of doing any post-processing. For example, in previous
versions you could call::
result = execute(circuit, backend).result()
unitary = result.get_data()['unitary']
print(unitary)
and that would return the unitary matrix like::
[[1+0j, 0+0.5j], [0-0.5j][-1+0j]]
But now if you call (with the renamed method)::
result.data()['unitary']
it will return something like::
[[[1, 0], [0, -0.5]], [[0, -0.5], [-1, 0]]]
To get the post processed results in the same format as before the 0.7 release
you must use the ``get_counts()``, ``get_statevector()``, and ``get_unitary()``
methods on the result object instead of ``get_data()['counts']``,
``get_data()['statevector']``, and ``get_data()['unitary']`` respectively.
Additionally, support for ``len()`` and indexing on a ``Result`` object has
been removed. Instead you should deal with the output from the post processed
methods on the Result objects.
Also, the ``get_snapshot()`` and ``get_snapshots()`` methods from the
``Result`` class have been removed. Instead you can access the snapshots
using ``Result.data()['snapshots']``.
Changes to visualization
^^^^^^^^^^^^^^^^^^^^^^^^
The biggest change made to visualization in the 0.7 release is the removal of
Matplotlib and other visualization dependencies from the project requirements.
This was done to simplify the requirements and configuration required for
installing Qiskit. If you plan to use any visualizations (including all the
jupyter magics) except for the ``text``, ``latex``, and ``latex_source``
output for the circuit drawer you'll you must manually ensure that
the visualization dependencies are installed. You can leverage the optional
requirements to the Qiskit-Terra package to do this::
pip install qiskit-terra[visualization]
Aside from this there have been changes made to several of the interfaces
as part of the stabilization which may have an impact on existing code.
The first is the the ``basis`` kwarg in the ``circuit_drawer()`` function
is no longer accepted. If you were relying on the ``circuit_drawer()`` to
adjust the basis gates used in drawing a circuit diagram you will have to
do this priort to calling ``circuit_drawer()``. For example::
from qiskit.tools import visualization
visualization.circuit_drawer(circuit, basis_gates='x,U,CX')
will have to be adjust to be::
from qiskit import BasicAer
from qiskit import transpiler
from qiskit.tools import visualization
backend = BasicAer.backend('qasm_simulator')
draw_circ = transpiler.transpile(circuit, backend, basis_gates='x,U,CX')
visualization.circuit_drawer(draw_circ)
Moving forward the ``circuit_drawer()`` function will be the sole interface
for circuit drawing in the visualization module. Prior to the 0.7 release there
were several other functions which either used different output backends or
changed the output for drawing circuits. However, all those other functions
have been deprecated and that functionality has been integrated as options
on ``circuit_drawer()``.
For the other visualization functions, ``plot_histogram()`` and
``plot_state()`` there are also a few changes to check when upgrading. First
is the output from these functions has changed, in prior releases these would
interactively show the output visualization. However that has changed to
instead return a ``matplotlib.Figure`` object. This provides much more
flexibility and options to interact with the visualization prior to saving or
showing it. This will require adjustment to how these functions are consumed.
For example, prior to this release when calling::
plot_histogram(counts)
plot_state(rho)
would open up new windows (depending on matplotlib backend) to display the
visualization. However starting in the 0.7 you'll have to call ``show()`` on
the output to mirror this behavior. For example::
plot_histogram(counts).show()
plot_state(rho).show()
or::
hist_fig = plot_histogram(counts)
state_fig = plot_state(rho)
hist_fig.show()
state_fig.show()
Note that this is only for when running outside of Jupyter. No adjustment is
required inside a Jupyter environment because Jupyter notebooks natively
understand how to render ``matplotlib.Figure`` objects.
However, returning the Figure object provides additional flexibility for
dealing with the output. For example instead of just showing the figure you
can now directly save it to a file by leveraging the ``savefig()`` method.
For example::
hist_fig = plot_histogram(counts)
state_fig = plot_state(rho)
hist_fig.savefig('histogram.png')
state_fig.savefig('state_plot.png')
The other key aspect which has changed with these functions is when running
under jupyter. In the 0.6 release ``plot_state()`` and ``plot_histogram()``
when running under jupyter the default behavior was to use the interactive
Javascript plots if the externally hosted Javascript library for rendering
the visualization was reachable over the network. If not it would just use
the matplotlib version. However in the 0.7 release this no longer the case,
and separate functions for the interactive plots, ``iplot_state()`` and
``iplot_histogram()`` are to be used instead. ``plot_state()`` and
``plot_histogram()`` always use the matplotlib versions.
Additionally, starting in this release the ``plot_state()`` function is
deprecated in favor of calling individual methods for each method of plotting
a quantum state. While the ``plot_state()`` function will continue to work
until the 0.9 release, it will emit a warning each time it is used. The
================================== ========================
Qiskit Terra 0.6 Qiskit Terra 0.7+
================================== ========================
plot_state(rho) plot_state_city(rho)
plot_state(rho, method='city') plot_state_city(rho)
plot_state(rho, method='paulivec') plot_state_paulivec(rho)
plot_state(rho, method='qsphere') plot_state_qsphere(rho)
plot_state(rho, method='bloch') plot_bloch_multivector(rho)
plot_state(rho, method='hinton') plot_state_hinton(rho)
================================== ========================
The same is true for the interactive JS equivalent, ``iplot_state()``. The
function names are all the same, just with a prepended `i` for each function.
For example, ``iplot_state(rho, method='paulivec')`` is
``iplot_state_paulivec(rho)``.
Changes to Backends
^^^^^^^^^^^^^^^^^^^
With the improvements made in the 0.7 release there are a few things related
to backends to keep in mind when upgrading. The biggest change is the
restructuring of the provider instances in the root ``qiskit``` namespace.
The ``Aer`` provider is not installed by default and requires the installation
of the ``qiskit-aer`` package. This package contains the new high performance
fully featured simulator. If you installed via ``pip install qiskit`` you'll
already have this installed. The python simulators are now available under
``qiskit.BasicAer`` and the old C++ simulators are available with
``qiskit.LegacySimulators``. This also means that the implicit fallback to
python based simulators when the C++ simulators are not found doesn't exist
anymore. If you ask for a local C++ based simulator backend, and it can't be
found an exception will be raised instead of just using the python simulator
instead.
Additionally the previously deprecation top level functions ``register()`` and
``available_backends()`` have been removed. Also, the deprecated
``backend.parameters()`` and ``backend.calibration()`` methods have been
removed in favor of ``backend.properties()``. You can refer to the 0.6 release
notes section :ref:`backends` for more details on these changes.
The ``backend.jobs()`` and ``backend.retrieve_jobs()`` calls no longer return
results from those jobs. Instead you must call the ``result()`` method on the
returned jobs objects.
Changes to the compiler, transpiler, and unrollers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
As part of an effort to stabilize the compiler interfaces there have been
several changes to be aware of when leveraging the compiler functions.
First it is important to note that the ``qiskit.transpiler.transpile()``
function now takes a QuantumCircuit object (or a list of them) and returns
a QuantumCircuit object (or a list of them). The DAG processing is done
internally now.
You can also easily switch between circuits, DAGs, and Qobj now using the
functions in ``qiskit.converters``.
Deprecations
------------
As part of the part of the 0.7 release the following things have been
deprecated and will either be removed or changed in a backwards incompatible
manner in a future release. While not strictly necessary these are things to
adjust for before the next release to avoid a breaking change.
* ``plot_circuit()``, ``latex_circuit_drawer()``, ``generate_latex_source()``,
and ``matplotlib_circuit_drawer()`` from qiskit.tools.visualization are
deprecated. Instead the ``circuit_drawer()`` function from the same module
should be used, there are kwarg options to mirror the functionality of all
the deprecated functions.
* The current default output of ``circuit_drawer()`` (using latex and falling
back on python) is deprecated and will be changed to just use the ``text``
output by default in future releases.
* The `qiskit.wrapper.load_qasm_string()` and `qiskit.wrapper.load_qasm_file()`
functions are deprecated and the `QuantumCircuit.from_qasm_str()` and
`QuantumCircuit.from_qasm_file()` constructor methods should be used instead.
* The ``plot_barriers`` and ``reverse_bits`` keys in the ``style`` kwarg dict
are deprecated, instead the `qiskit.tools.visualization.circuit_drawer()`
kwargs ``plot_barriers`` and ``reverse_bits`` should be used instead.
* The functions `plot_state()` and `iplot_state()` have been depreciated.
Instead the functions `plot_state_*()` and `iplot_state_*()` should be
called for the visualization method required.
* The ``skip_transpiler`` arg has been deprecated from ``compile()`` and
``execute()``. Instead you can use the PassManager directly, just set
the ``pass_manager`` to a blank PassManager object with ``PassManager()``
* The ``transpile_dag()`` function ``format`` kwarg for emitting different
output formats is deprecated, instead you should convert the default output
``DAGCircuit`` object to the desired format.
* The unrollers have been deprecated, moving forward only DAG to DAG unrolling
will be supported.
Qiskit Terra 0.6.0
==================
This release includes a redesign of internal components centered around a new,
formal communication format (`qobj`), along with long awaited features to
improve the user experience as a whole. The highlights, compared to the 0.5
release, are:
* Improvements for inter-operability (based on the `qobj` specification) and
extensibility (facilities for extending Qiskit with new backends in a
seamless way).
* New options for handling credentials and authentication for the IBM Q
backends, aimed at simplifying the process and supporting automatic loading
of user credentials.
* A revamp of the visualization utilities: stylish interactive visualizations
are now available for Jupyter users, along with refinements for the circuit
drawer (including a matplotlib-based version).
* Performance improvements centered around circuit transpilation: the basis for
a more flexible and modular architecture have been set, including
paralellization of the circuit compilation and numerous optimizations.
Upgrading to 0.6.0
------------------
Please note that some backwards-incompatible changes have been introduced
during this release - the following notes contain information on how to adapt
to the new changes.
Removal of ``QuantumProgram``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
As hinted during the 0.5 release, the deprecation of the ``QuantumProgram``
class has now been completed and is no longer available, in favor of working
with the individual components (:class:`~qiskit.backends.basejob.BaseJob`,
:class:`~qiskit._quantumcircuit.QuantumCircuit`,
:class:`~qiskit._classicalregister.ClassicalRegister`,
:class:`~qiskit._quantumregister.QuantumRegister`,
:mod:`~qiskit`) directly.
Please check the :ref:`0.5 release notes <quantum-program-0-5>` and the
examples for details about the transition::
from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister
from qiskit import Aer, execute
q = QuantumRegister(2)
c = ClassicalRegister(2)
qc = QuantumCircuit(q, c)
qc.h(q[0])
qc.cx(q[0], q[1])
qc.measure(q, c)
backend = get_backend('qasm_simulator')
job_sim = execute(qc, backend)
sim_result = job_sim.result()
print("simulation: ", sim_result)
print(sim_result.get_counts(qc))
IBM Q Authentication and ``Qconfig.py``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The managing of credentials for authenticating when using the IBMQ backends has
been expanded, and there are new options that can be used for convenience:
1. save your credentials in disk once, and automatically load them in future
sessions. This provides a one-off mechanism::
from qiskit import IBMQ
IBQM.save_account('MY_API_TOKEN', 'MY_API_URL')
afterwards, your credentials can be automatically loaded from disk by invoking
:meth:`~qiskit.backends.ibmq.ibmqprovider.IBMQ.load_accounts`::
from qiskit import IBMQ
IBMQ.load_accounts()
or you can load only specific accounts if you only want to use those in a session::
IBMQ.load_accounts(project='MY_PROJECT')
2. use environment variables. If ``QE_TOKEN`` and ``QE_URL`` is set, the
``IBMQ.load_accounts()`` call will automatically load the credentials from
them.
Additionally, the previous method of having a ``Qconfig.py`` file in the
program folder and passing the credentials explicitly is still supported.
.. _backends:
Working with backends
^^^^^^^^^^^^^^^^^^^^^
A new mechanism has been introduced in Terra 0.6 as the recommended way for
obtaining a backend, allowing for more powerful and unified filtering and
integrated with the new credentials system. The previous top-level methods
:meth:`~qiskit.wrapper._wrapper.register`,
:meth:`~qiskit.wrapper._wrapper.available_backends` and
:meth:`~qiskit.wrapper._wrapper.get_backend` are still supported, but will
deprecated in upcoming versions in favor of using the `qiskit.IBMQ` and
`qiskit.Aer` objects directly, which allow for more complex filtering.
For example, to list and use a local backend::
from qiskit import Aer
all_local_backends = Aer.backends(local=True) # returns a list of instances
qasm_simulator = Aer.backends('qasm_simulator')
And for listing and using remote backends::
from qiskit import IBMQ
IBMQ.enable_account('MY_API_TOKEN')
5_qubit_devices = IBMQ.backends(simulator=True, n_qubits=5)
ibmqx4 = IBMQ.get_backend('ibmqx4')
Please note as well that the names of the local simulators have been
simplified. The previous names can still be used, but it is encouraged to use
the new, shorter names:
============================= ========================
Qiskit Terra 0.5 Qiskit Terra 0.6
============================= ========================
'local_qasm_simulator' 'qasm_simulator'
'local_statevector_simulator' 'statevector_simulator'
'local_unitary_simulator_py' 'unitary_simulator'
============================= ========================
Backend and Job API changes
^^^^^^^^^^^^^^^^^^^^^^^^^^^
* Jobs submitted to IBM Q backends have improved capabilities. It is possible
to cancel them and replenish credits (``job.cancel()``), and to retrieve
previous jobs executed on a specific backend either by job id
(``backend.retrieve_job(job_id)``) or in batch of latest jobs
(``backend.jobs(limit)``)
* Properties for checking each individual job status (``queued``, ``running``,
``validating``, ``done`` and ``cancelled``) no longer exist. If you
want to check the job status, use the identity comparison against
``job.status``::
from qiskit.backends import JobStatus
job = execute(circuit, backend)
if job.status() is JobStatus.RUNNING:
handle_job(job)
Please consult the new documentation of the
:class:`~qiskit.backends.ibmq.ibmqjob.IBMQJob` class to get further insight
in how to use the simplified API.
* A number of members of :class:`~qiskit.backends.basebackend.BaseBackend`
and :class:`~qiskit.backends.basejob.BaseJob` are no longer properties,
but methods, and as a result they need to be invoked as functions.
===================== ========================
Qiskit Terra 0.5 Qiskit Terra 0.6
===================== ========================
backend.name backend.name()
backend.status backend.status()
backend.configuration backend.configuration()
backend.calibration backend.properties()
backend.parameters backend.jobs()
backend.retrieve_job(job_id)
job.status job.status()
job.cancelled job.queue_position()
job.running job.cancel()
job.queued
job.done
===================== ========================
Better Jupyter tools
^^^^^^^^^^^^^^^^^^^^
The new release contains improvements to the user experience while using
Jupyter notebooks.
First, new interactive visualizations of counts histograms and quantum states
are provided:
:meth:`~qiskit.tools.visualization.plot_histogram` and
:meth:`~qiskit.tools.visualization.plot_state`.
These methods will default to the new interactive kind when the environment
is Jupyter and internet connection exists.
Secondly, the new release provides Jupyter cell magics for keeping track of
the progress of your code. Use ``%%qiskit_job_status`` to keep track of the
status of submitted jobs to IBMQ backends. Use ``%%qiskit_progress_bar`` to
keep track of the progress of compilation/execution.
Qiskit Terra 0.5.0
==================
This release brings a number of improvements to Qiskit, both for the user
experience and under the hood. Please refer to the full changelog for a
detailed description of the changes - the highlights are:
* new ``statevector`` :mod:`simulators <qiskit.backends.local>` and feature and
performance improvements to the existing ones (in particular to the C++
simulator), along with a reorganization of how to work with backends focused
on extensibility and flexibility (using aliases and backend providers).
* reorganization of the asynchronous features, providing a friendlier interface
for running jobs asynchronously via :class:`Job` instances.
* numerous improvements and fixes throughout the Terra as a whole, both for
convenience of the users (such as allowing anonymous registers) and for
enhanced functionality (such as improved plotting of circuits).
Upgrading to 0.5.0
------------------
Please note that several backwards-incompatible changes have been introduced
during this release as a result of the ongoing development. While some of these
features will continue to be supported during a period of time before being
fully deprecated, it is recommended to update your programs in order to prepare
for the new versions and take advantage of the new functionality.
.. _quantum-program-0-5:
``QuantumProgram`` changes
^^^^^^^^^^^^^^^^^^^^^^^^^^
Several methods of the :class:`~qiskit.QuantumProgram` class are on their way
to being deprecated:
* methods for interacting **with the backends and the API**:
The recommended way for opening a connection to the IBMQ API and for using
the backends is through the
:ref:`top-level functions <qiskit_top_level_functions>` directly instead of
the ``QuantumProgram`` methods. In particular, the
:func:`qiskit.register` method provides the equivalent of the previous
:func:`qiskit.QuantumProgram.set_api` call. In a similar vein, there is a new
:func:`qiskit.available_backends`, :func:`qiskit.get_backend` and related
functions for querying the available backends directly. For example, the
following snippet for version 0.4::
from qiskit import QuantumProgram
quantum_program = QuantumProgram()
quantum_program.set_api(token, url)
backends = quantum_program.available_backends()
print(quantum_program.get_backend_status('ibmqx4')
would be equivalent to the following snippet for version 0.5::
from qiskit import register, available_backends, get_backend
register(token, url)
backends = available_backends()
backend = get_backend('ibmqx4')
print(backend.status)
* methods for **compiling and executing programs**:
The :ref:`top-level functions <qiskit_top_level_functions>` now also provide
equivalents for the :func:`qiskit.QuantumProgram.compile` and
:func:`qiskit.QuantumProgram.execute` methods. For example, the following
snippet from version 0.4::
quantum_program.execute(circuit, args, ...)
would be equivalent to the following snippet for version 0.5::
from qiskit import execute
execute(circuit, args, ...)
In general, from version 0.5 onwards we encourage to try to make use of the
individual objects and classes directly instead of relying on
``QuantumProgram``. For example, a :class:`~qiskit.QuantumCircuit` can be
instantiated and constructed by appending :class:`~qiskit.QuantumRegister`,
:class:`~qiskit.ClassicalRegister`, and gates directly. Please check the
update example in the Quickstart section, or the
``using_qiskit_core_level_0.py`` and ``using_qiskit_core_level_1.py``
examples on the main repository.
Backend name changes
^^^^^^^^^^^^^^^^^^^^
In order to provide a more extensible framework for backends, there have been
some design changes accordingly:
* **local simulator names**
The names of the local simulators have been homogenized in order to follow
the same pattern: ``PROVIDERNAME_TYPE_simulator_LANGUAGEORPROJECT`` -
for example, the C++ simulator previously named ``local_qiskit_simulator``
is now ``local_qasm_simulator_cpp``. An overview of the current
simulators:
* ``QASM`` simulator is supposed to be like an experiment. You apply a
circuit on some qubits, and observe measurement results - and you repeat
for many shots to get a histogram of counts via ``result.get_counts()``.
* ``Statevector`` simulator is to get the full statevector (:math:`2^n`
amplitudes) after evolving the zero state through the circuit, and can be
obtained via ``result.get_statevector()``.
* ``Unitary`` simulator is to get the unitary matrix equivalent of the
circuit, returned via ``result.get_unitary()``.
* In addition, you can get intermediate states from a simulator by applying
a ``snapshot(slot)`` instruction at various spots in the circuit. This will
save the current state of the simulator in a given slot, which can later
be retrieved via ``result.get_snapshot(slot)``.
* **backend aliases**:
The SDK now provides an "alias" system that allows for automatically using
the most performant simulator of a specific type, if it is available in your
system. For example, with the following snippet::
from qiskit import get_backend
backend = get_backend('local_statevector_simulator')
the backend will be the C++ statevector simulator if available, falling
back to the Python statevector simulator if not present.
More flexible names and parameters
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Several functions of the SDK have been made more flexible and user-friendly:
* **automatic circuit and register names**
:class:`qiskit.ClassicalRegister`, :class:`qiskit.QuantumRegister` and
:class:`qiskit.QuantumCircuit` can now be instantiated without explicitly
giving them a name - a new autonaming feature will automatically assign them
an identifier::
q = QuantumRegister(2)
Please note as well that the order of the parameters have been swapped
``QuantumRegister(size, name)``.
* **methods accepting names or instances**
In combination with the autonaming changes, several methods such as
:func:`qiskit.Result.get_data` now accept both names and instances for
convenience. For example, when retrieving the results for a job that has a
single circuit such as::
qc = QuantumCircuit(..., name='my_circuit')
job = execute(qc, ...)
result = job.result()
The following calls are equivalent::
data = result.get_data('my_circuit')
data = result.get_data(qc)
data = result.get_data()
.. include:: CHANGELOG.rst