Skip to content

Commit

Permalink
Support for circuit.draw(initial_state=False) (Qiskit#4068)
Browse files Browse the repository at this point in the history
* internal option

* external API

* testing

* lint

* clean

* seed in the transpiler

* simpler test

* latex support

* maxdiff

* docstring

* doc

* wire

* ket is special

* reno

* initial_state

* more refactor

* reno lint

* Update releasenotes/notes/initial_state_draw_parameter-f360ac4e998ee944.yaml

Co-Authored-By: Matthew Treinish <mtreinish@kortar.org>

* Update releasenotes/notes/initial_state_draw_parameter-f360ac4e998ee944.yaml

Co-Authored-By: Matthew Treinish <mtreinish@kortar.org>

* Update releasenotes/notes/initial_state_draw_parameter-f360ac4e998ee944.yaml

Co-Authored-By: Matthew Treinish <mtreinish@kortar.org>

* release note

* release note section

* examples with text drawer

* import

* maybe with an extra space

Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
3 people committed Apr 6, 2020
1 parent f45aae9 commit f5043c9
Show file tree
Hide file tree
Showing 7 changed files with 186 additions and 104 deletions.
8 changes: 6 additions & 2 deletions qiskit/circuit/quantumcircuit.py
Expand Up @@ -693,7 +693,7 @@ def qasm(self, formatted=False, filename=None):
def draw(self, output=None, scale=0.7, filename=None, style=None,
interactive=False, line_length=None, plot_barriers=True,
reverse_bits=False, justify=None, vertical_compression='medium', idle_wires=True,
with_layout=True, fold=None, ax=None):
with_layout=True, fold=None, ax=None, initial_state=False):
"""Draw the quantum circuit.
**text**: ASCII art TextDrawing that can be printed in the console.
Expand Down Expand Up @@ -763,6 +763,9 @@ def draw(self, output=None, scale=0.7, filename=None, style=None,
there will be no returned Figure since it is redundant. This is
only used when the ``output`` kwarg is set to use the ``mpl``
backend. It will be silently ignored with all other outputs.
initial_state (bool): Optional. Adds ``|0>`` in the beginning of the wire.
Only used by the ``text``, ``latex`` and ``latex_source`` outputs.
Default: ``False``.
Returns:
:class:`PIL.Image` or :class:`matplotlib.figure` or :class:`str` or
Expand Down Expand Up @@ -904,7 +907,8 @@ def draw(self, output=None, scale=0.7, filename=None, style=None,
idle_wires=idle_wires,
with_layout=with_layout,
fold=fold,
ax=ax)
ax=ax,
initial_state=initial_state)

def size(self):
"""Returns total number of gate operations in circuit.
Expand Down
36 changes: 25 additions & 11 deletions qiskit/visualization/circuit_visualization.py
Expand Up @@ -64,7 +64,8 @@ def circuit_drawer(circuit,
idle_wires=True,
with_layout=True,
fold=None,
ax=None):
ax=None,
initial_state=False):
"""Draw a quantum circuit to different formats (set by output parameter):
**text**: ASCII art TextDrawing that can be printed in the console.
Expand Down Expand Up @@ -133,7 +134,9 @@ def circuit_drawer(circuit,
will be no returned Figure since it is redundant. This is only used
when the ``output`` kwarg is set to use the ``mpl`` backend. It
will be silently ignored with all other outputs.
initial_state (bool): Optional. Adds ``|0>`` in the beginning of the wire.
Only used by the ``text``, ``latex`` and ``latex_source`` outputs.
Default: ``False``.
Returns:
:class:`PIL.Image` or :class:`matplotlib.figure` or :class:`str` or
:class:`TextDrawing`:
Expand Down Expand Up @@ -282,15 +285,17 @@ def circuit_drawer(circuit,
vertical_compression=vertical_compression,
idle_wires=idle_wires,
with_layout=with_layout,
fold=fold)
fold=fold,
initial_state=initial_state)
elif output == 'latex':
image = _latex_circuit_drawer(circuit, scale=scale,
filename=filename, style=style,
plot_barriers=plot_barriers,
reverse_bits=reverse_bits,
justify=justify,
idle_wires=idle_wires,
with_layout=with_layout)
with_layout=with_layout,
initial_state=initial_state)
elif output == 'latex_source':
return _generate_latex_source(circuit,
filename=filename, scale=scale,
Expand All @@ -299,7 +304,8 @@ def circuit_drawer(circuit,
reverse_bits=reverse_bits,
justify=justify,
idle_wires=idle_wires,
with_layout=with_layout)
with_layout=with_layout,
initial_state=initial_state)
elif output == 'mpl':
image = _matplotlib_circuit_drawer(circuit, scale=scale,
filename=filename, style=style,
Expand Down Expand Up @@ -400,7 +406,7 @@ def qx_color_scheme():

def _text_circuit_drawer(circuit, filename=None, line_length=None, reverse_bits=False,
plot_barriers=True, justify=None, vertical_compression='high',
idle_wires=True, with_layout=True, fold=None,):
idle_wires=True, with_layout=True, fold=None, initial_state=True):
"""Draws a circuit using ascii art.
Args:
Expand All @@ -421,6 +427,7 @@ def _text_circuit_drawer(circuit, filename=None, line_length=None, reverse_bits=
None (default), it will try to guess the console width using
`shutil.get_terminal_size()`. If you don't want pagination
at all, set `fold=-1`.
initial_state (bool): Optional. Adds |0> in the beginning of the line. Default: `True`.
Returns:
TextDrawing: An instances that, when printed, draws the circuit in ascii art.
"""
Expand All @@ -435,7 +442,7 @@ def _text_circuit_drawer(circuit, filename=None, line_length=None, reverse_bits=
if line_length:
warn('The parameter "line_length" is being replaced by "fold"', DeprecationWarning, 3)
fold = line_length
text_drawing = _text.TextDrawing(qregs, cregs, ops, layout=layout)
text_drawing = _text.TextDrawing(qregs, cregs, ops, layout=layout, initial_state=initial_state)
text_drawing.plotbarriers = plot_barriers
text_drawing.line_length = fold
text_drawing.vertical_compression = vertical_compression
Expand All @@ -458,7 +465,8 @@ def _latex_circuit_drawer(circuit,
reverse_bits=False,
justify=None,
idle_wires=True,
with_layout=True):
with_layout=True,
initial_state=False):
"""Draw a quantum circuit based on latex (Qcircuit package)
Requires version >=2.6.0 of the qcircuit LaTeX package.
Expand All @@ -477,6 +485,8 @@ def _latex_circuit_drawer(circuit,
idle_wires (bool): Include idle wires. Default is True.
with_layout (bool): Include layout information, with labels on the physical
layout. Default: True
initial_state (bool): Optional. Adds |0> in the beginning of the line. Default: `False`.
Returns:
PIL.Image: an in-memory representation of the circuit diagram
Expand All @@ -493,7 +503,8 @@ def _latex_circuit_drawer(circuit,
scale=scale, style=style,
plot_barriers=plot_barriers,
reverse_bits=reverse_bits, justify=justify,
idle_wires=idle_wires, with_layout=with_layout)
idle_wires=idle_wires, with_layout=with_layout,
initial_state=initial_state)
try:

subprocess.run(["pdflatex", "-halt-on-error",
Expand Down Expand Up @@ -539,7 +550,7 @@ def _latex_circuit_drawer(circuit,
def _generate_latex_source(circuit, filename=None,
scale=0.7, style=None, reverse_bits=False,
plot_barriers=True, justify=None, idle_wires=True,
with_layout=True):
with_layout=True, initial_state=False):
"""Convert QuantumCircuit to LaTeX string.
Args:
Expand All @@ -556,6 +567,8 @@ def _generate_latex_source(circuit, filename=None,
idle_wires (bool): Include idle wires. Default is True.
with_layout (bool): Include layout information, with labels on the physical
layout. Default: True
initial_state (bool): Optional. Adds |0> in the beginning of the line. Default: `False`.
Returns:
str: Latex string appropriate for writing to file.
"""
Expand All @@ -569,7 +582,8 @@ def _generate_latex_source(circuit, filename=None,

qcimg = _latex.QCircuitImage(qregs, cregs, ops, scale, style=style,
plot_barriers=plot_barriers,
reverse_bits=reverse_bits, layout=layout)
reverse_bits=reverse_bits, layout=layout,
initial_state=initial_state)
latex = qcimg.latex()
if filename:
with open(filename, 'w') as latex_file:
Expand Down
11 changes: 8 additions & 3 deletions qiskit/visualization/latex.py
Expand Up @@ -41,7 +41,7 @@ class QCircuitImage:
"""

def __init__(self, qubits, clbits, ops, scale, style=None,
plot_barriers=True, reverse_bits=False, layout=None):
plot_barriers=True, reverse_bits=False, layout=None, initial_state=False):
"""QCircuitImage initializer.
Args:
Expand All @@ -56,6 +56,7 @@ def __init__(self, qubits, clbits, ops, scale, style=None,
circuit. Defaults to True.
layout (Layout or None): If present, the layout information will be
included.
initial_state (bool): Optional. Adds |0> in the beginning of the line. Default: `False`.
Raises:
ImportError: If pylatexenc is not installed
"""
Expand Down Expand Up @@ -113,6 +114,7 @@ def __init__(self, qubits, clbits, ops, scale, style=None,
self.has_target = False
self.reverse_bits = reverse_bits
self.layout = layout
self.initial_state = initial_state
self.plot_barriers = plot_barriers

#################################
Expand Down Expand Up @@ -213,13 +215,16 @@ def _initialize_latex_array(self, aliases=None):
": 0}"
else:
if self.layout is None:
label = "\\lstick{{ {{{}}}_{{{}}} : \\ket{{0}} }}".format(
label = "\\lstick{{ {{{}}}_{{{}}} : ".format(
self.ordered_regs[i].register.name, self.ordered_regs[i].index)
else:
label = "\\lstick{{ {{{}}}_{{{}}}\\mapsto{{{}}} : \\ket{{0}} }}".format(
label = "\\lstick{{ {{{}}}_{{{}}}\\mapsto{{{}}} : ".format(
self.layout[self.ordered_regs[i].index].register.name,
self.layout[self.ordered_regs[i].index].index,
self.ordered_regs[i].index)
if self.initial_state:
label += "\\ket{{0}}"
label += " }"
self._latex[i][0] = label

def _get_image_depth(self):
Expand Down
13 changes: 7 additions & 6 deletions qiskit/visualization/text.py
Expand Up @@ -495,11 +495,12 @@ class TextDrawing():
""" The text drawing"""

def __init__(self, qregs, cregs, instructions, plotbarriers=True,
line_length=None, vertical_compression='high', layout=None):
line_length=None, vertical_compression='high', layout=None, initial_state=True):
self.qregs = qregs
self.cregs = cregs
self.instructions = instructions
self.layout = layout
self.initial_state = initial_state

self.plotbarriers = plotbarriers
self.line_length = line_length
Expand Down Expand Up @@ -591,7 +592,7 @@ def lines(self, line_length=None):
rest_of_the_line = line_length - layer_groups[-1][-1][0].length

layer_groups[-1].append(
InputWire.fillup_layer(self.wire_names(with_initial_value=False)))
InputWire.fillup_layer(self.wire_names(with_initial_state=False)))
rest_of_the_line -= layer_groups[-1][-1][0].length

layer_groups[-1].append(layer)
Expand All @@ -604,17 +605,17 @@ def lines(self, line_length=None):

return lines

def wire_names(self, with_initial_value=True):
def wire_names(self, with_initial_state=False):
"""Returns a list of names for each wire.
Args:
with_initial_value (bool): Optional (Default: True). If true, adds
with_initial_state (bool): Optional (Default: False). If true, adds
the initial value to the name.
Returns:
List: The list of wire names.
"""
if with_initial_value:
if with_initial_state:
initial_qubit_value = '|0>'
initial_clbit_value = '0 '
else:
Expand Down Expand Up @@ -997,7 +998,7 @@ def build_layers(self):
Raises:
VisualizationError: When the drawing is, for some reason, impossible to be drawn.
"""
wire_names = self.wire_names(with_initial_value=True)
wire_names = self.wire_names(with_initial_state=self.initial_state)
if not wire_names:
return []

Expand Down
@@ -0,0 +1,41 @@
---
upgrade:
- |
The :class:`~qiskit.circuit.QuantumCircuit` method :meth:`~qiskit.circuit.QuantumCircuit.draw`
and :func:`qiskit.visualization.circuit_drawer` function will no longer include the initial
state included in visualizations by default. If you would like to retain the initial state in
the output visualization you need to set the ``initial_state`` kwarg to ``True``. For example,
running:
.. jupyter-execute::
from qiskit import QuantumCircuit
circuit = QuantumCircuit(2)
circuit.measure_all()
circuit.draw(output='text')
This no longer includes the initial state. If you'd like to retain it you can run:
.. jupyter-execute::
from qiskit import QuantumCircuit
circuit = QuantumCircuit(2)
circuit.measure_all()
circuit.draw(output='text', initial_state=True)
features:
- |
A new kwarg, ``initial_state`` has been added to the :func:`qiskit.visualization.circuit_drawer`
function and the :class:`~qiskit.circuit.QuantumCircuit` method
:meth:`~qiskit.circuit.QuantumCircuit.draw`. When set to ``True`` the initial state will be included
in circuit visualizations for all backends. For example:
.. jupyter-execute::
from qiskit import QuantumCircuit
circuit = QuantumCircuit(2)
circuit.measure_all()
circuit.draw(output='text', initial_state=True)

0 comments on commit f5043c9

Please sign in to comment.