From ef06abe12d92b07cf4dace8214d017e2cf334ce6 Mon Sep 17 00:00:00 2001 From: Ali Javadi-Abhari Date: Thu, 26 Sep 2019 10:39:55 -0400 Subject: [PATCH] rebase ion-trap branch (#3153) * Remove changelog and document automated creation (#3109) * Remove changelog and document automated creation With the introduction of the qiskit-bot release automation for terra we no longer need to manually maintain or keep a changelog in repo. The github release pages (which we were manually copy and pasting the changelog into already) take the place of this file. For all future releases the creation of this page is completely automatic and handled by the bot. This works by using the git log and PR tags to figure out which commits belong in the changelog summary. The commit msg summary (the first line) is used for the changelog based on the tags. If a longer explanation is necessary that should be handled in the reno release notes. Fixes #3077 * Add README section on changelog * Make tweaks to readme for clarity * The option fig.tight_layout is triggering warnings in some situations so it is being removed (#3123) * no fig.tight_layout * removing the rest of fig.tight_layout() * check casteable types in Layout (#3100) * test * cast in insinstance * style * layouts are already layouts :) * Travis CI: The sudo: tag is deprecated on Travis (#3134) https://blog.travis-ci.com/2018-11-19-required-linux-infrastructure-migration * Fix a syntax error in QuantumCircuit.mirror. (#3138) * Fix for #3106 gatefacecolor key on circuit diagrams (#3137) * Issue #3106 gatefacecolor key has no effect on circuit diagrams If the style property "gatefacecolor" is set to a different value than the default, this color is applied. Fixes #3106 * Solved style problem space before : eliminated * Update plot_state_hinton() formatting (#3093) Add axes to the image part. It looks like the image axes already exist for non-empty graphs. The change that I made here is to remove if np.any(dataimag != 0): if the desired behavior is to see the axes on graphs that don't contain any elements. Replace rho with the latex rho Use standard format for real and imag parts of rho Fixes #2321 * Set barrier across multi-qubits correctly (#3042) * Previously it was assumed that specified barrier has a single contiguous span across qubits. Qubits for the barrier need not be adjacent in the diagram. This commit handles this case by adding barrier across correct qubits. * compute multiple short spans. Fixes #2918 * Test pulse clipping fix Osx #1. (#3144) * Remove superfluous reference to timeslots from assemble_schedules (#3139) * Extend custom multiqubit gates over classical bits for mpl (#3062) * Got it to extend over the clasical bits * Fixed a small bug * Removed a file accidentally modified * Fix linter * Deprecate allowing extra keys in circuit drawer style dict (#3105) * test * cast in insinstance * style * layouts are already layouts :) * style['plotbarrier'] is being deprecated * internal param for text drawer renamed to plot_barriers * error when style contains unknown options * better error message * remove #3100, since it was not my intention to be on it * style * remove plotbarrier * unused import * replace error with warning * release note * rochester_layout (#3125) * Use _append when args already converted and broadcast. (#2936) * Remove line in init which had been commented out (#3150) * Fix circuit drawing justification (#3061) Fixes #2802 qiskit/visualization/utils.py _get_layered_instructions() was erroneous and did not justify left nor right correctly. I have reworked that code which underlies many visual representations of circuits to the user. * refactored, needs more work on right justification * Looks like this works for qiskit-terra issue #2802 * May fix first test failure for this pull request, while causing another? * Draws conditionals on ClassicalRegister correctly now. * - Occurs check for gate in gates leads to good test results. - Added a few more self.maxDiff = None while debugging. Should they be pulled out? * tabs and trailing spaces ;) * removed the maxDiff's because they make the Style and lint test in Python 3.5 fail * added tests modified changelog * Test case extended to include original issue reported in #2802 * oops, left a maxDiff=None in from testing. Fixed * changes to utils.py requested by reviewer maddy-tod * test cases split as requested by reviewer maddy-tod * added circuit diagrams in comments to new tests * removed note from changelog and made it a release note per @mtreinish * made _LayerSpooler a private class * Revert "Remove changelog and document automated creation (#3109)" This reverts commit effad1228e0d9f24ea3343e0821054b74bd4e8ea. * Make _LayerSpooler a subclass of list The _LayerSpooler class was only ever used as list. While the class was an independent type it basically just wrapped an internal list. THen there were helper functions to access and manipulate that list. These methods just duplicated what python already provides and the list class itself already implements. This commit fixes this so the _LayerSpooler itself is a subclass of list so when it's initialized you can just treat it as the output list it was generating. * Clean up release note, fix only, not prelude * un reverted my revert of CONTRIBUTING.md * refactored, needs more work on right justification * Looks like this works for qiskit-terra issue #2802 * May fix first test failure for this pull request, while causing another? * Draws conditionals on ClassicalRegister correctly now. * - Occurs check for gate in gates leads to good test results. - Added a few more self.maxDiff = None while debugging. Should they be pulled out? * tabs and trailing spaces ;) * removed the maxDiff's because they make the Style and lint test in Python 3.5 fail * added tests modified changelog * Test case extended to include original issue reported in #2802 * oops, left a maxDiff=None in from testing. Fixed * changes to utils.py requested by reviewer maddy-tod * test cases split as requested by reviewer maddy-tod * added circuit diagrams in comments to new tests * removed note from changelog and made it a release note per @mtreinish * made _LayerSpooler a private class * Make _LayerSpooler a subclass of list The _LayerSpooler class was only ever used as list. While the class was an independent type it basically just wrapped an internal list. THen there were helper functions to access and manipulate that list. These methods just duplicated what python already provides and the list class itself already implements. This commit fixes this so the _LayerSpooler itself is a subclass of list so when it's initialized you can just treat it as the output list it was generating. * Clean up release note, fix only, not prelude * put back missing section * Add partial transpiler support for targeting ion trap backends. (#3122) * handle reset/barrier/measure (#3130) * Do not unroll an Rx,Ry,Rxx circuit to U3,CX because of measure. (#3140) --- .travis.yml | 1 - CHANGELOG.md | 1326 ----------------- CONTRIBUTING.md | 50 +- README.md | 21 + qiskit/assembler/assemble_schedules.py | 2 +- qiskit/circuit/quantumcircuit.py | 6 +- qiskit/compiler/transpile.py | 9 +- qiskit/converters/__init__.py | 22 + qiskit/pulse/__init__.py | 1 - qiskit/pulse/commands/sample_pulse.py | 8 +- qiskit/tools/jupyter/backend_monitor.py | 1 - qiskit/transpiler/layout.py | 11 +- qiskit/visualization/circuit_visualization.py | 9 +- qiskit/visualization/gate_map.py | 16 +- qiskit/visualization/latex.py | 21 +- qiskit/visualization/matplotlib.py | 24 +- qiskit/visualization/qcstyle.py | 100 +- qiskit/visualization/state_visualization.py | 18 +- qiskit/visualization/utils.py | 237 +-- ...-drawing-has-changed-f62ce5aaeb8ce221.yaml | 8 + ...ecate_unknown_styles-93f84aedd1887c44.yaml | 6 + .../python/circuit/test_circuit_operations.py | 20 + test/python/transpiler/test_layout.py | 14 + .../test_circuit_matplotlib_drawer.py | 2 +- .../visualization/test_circuit_text_drawer.py | 2 +- .../visualization/test_visualization.py | 173 +++ 26 files changed, 596 insertions(+), 1512 deletions(-) delete mode 100644 CHANGELOG.md create mode 100644 releasenotes/notes/Instruction-layering-for-circuit-drawing-has-changed-f62ce5aaeb8ce221.yaml create mode 100644 releasenotes/notes/deprecate_unknown_styles-93f84aedd1887c44.yaml diff --git a/.travis.yml b/.travis.yml index f92ee6082775..df55f8c07884 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,6 @@ notifications: email: false cache: pip -sudo: false ############################################################################### # Anchored and aliased definitions. diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index a028e7c863f6..000000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,1326 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog]. - -> **Types of changes:** -> -> - **Added**: for new features. -> - **Changed**: for changes in existing functionality. -> - **Deprecated**: for soon-to-be removed features. -> - **Removed**: for now removed features. -> - **Fixed**: for any bug fixes. -> - **Security**: in case of vulnerabilities. - -## [UNRELEASED] - -### Changed - -- Assignments and modifications to `QuantumCircuit.data` will now be broadcast - and validated following the same rules used throughout the - `QuantumCircuit` API. (\#2826) - -### Added -- The mock backends in `qiskit.test.mock` now have a snapshot of real - calibration data, returned via `backend.properties()`. - -### Fixed -- Fixed a bug in drawing conditional gates with matplotlib circuit drawer. - -### Changed -- Returned `matplotlib.figure.Figure` objects are only closed in jupyter - notebooks configured with an inline backend (\#3051) - -### Removed - -- Removed `DeviceSpecification` in favor of `PulseChannelSpec`. (\#3033) -- Removed deprecated `ops.py` from pulse. Use `Schedule` and `Instruction` - methods directly. (\#3034) - -### Deprecated - -- Comparing tuples to `Bit`s is being deprecated. Representing a qubit or - a classical bit as a tuple is being abandon in favor of `Qubit` and `Clbit` - objects. - -## [0.9.0] - 2019-08-22 - -### Deprecated - -- The full import path `qiskit.pulse.channels.pulse_channels` is deprecated; - code is moved to `qiskit.pulse.channels.channels` instead. Users should - keep importing from `qiskit.pulse.channels` (\#3094). -- The gates `U` and `CX` are being deprecated in favor of `u3` and - `cx`. (\#2380) -- The gate `u0` is being deprecated in favor of using multiple `id` gates - to insert delays (\#2664) -- The decorator `requires_qe_access` is being deprecated in favor of - `online_test`. -- The `as_dict` method of Qobj is deprecated in favor of `to_dict`. (\#2556) - -### Added - -- Added in tests for `ccx` and `crz` under `test_gate_definitions`. (\#2964) -- A new pulse instruction, `Delay`. A `Delay` occupies a pulse channel for a - duration of time, blocking other instructions from being inserted in this time. (\#2869) -- Ability to check for equality of pulse `Schedule` and `Instruction`. (\#2873) -- Added tests for `gate_map` and reference images for testing `plot_gate_map` -- New `CountOpsLongest` analysis pass to retrieve the number of operations - on the longest path of the DAGCircuit. (\#2734) -- Added `sech` and `sech_deriv` pulses in `qiskit.pulse.pulse_lib`. -- The option `vertical_compression` was added to the text drawer and - to the `QuantumCircuit.draw` method. The option allows to control - how much room the text circuit drawing takes. -- The option `idle_wires` was added to the drawers to control - if wires without any operation should be included in the drawing. (\#2692) -- Introduced a visualization for the Pass Manager. (\#2445) -- New pulse schedule method `Schedule.filter` to filter by instruction - channel, time, and type. (\#2597) -- Decomposition of arbitrary isometries (\#2600) -- Decomposition of diagonal gates (\#2600) -- Decomposition of multiplexed rotation gates (\#2600) -- Decomposition of multiplexed single-qubit unitaries (Option: decompose - up to a diagonal gate) (\#2600) -- ZYZ decomposition for single-qubit unitaries (\#2600) -- Gray-Synth and Patel–Markov–Hayes algorithms for synthesis of - CNOT-Phase and CNOT-only (linear) circuits (\#2457) -- Added n-qubit unitaries to BasicAer simulator basis gates (\#2342) -- Added a ``random_circuit`` function under ``qiskit.circuit.random`` - (\#2553) -- Added `equiv` method to `Operator` and `Statevector` classes for - testing if two objects are equivalent up to global phase (\#2910) -- Added ``output_name`` as a transpiler parameter to set the name of - output circuits (\#2745) -- Simple expressions of Parameters can now be created via the four basic math - operations (+,-,\*,/). (\#2537) -- A `ParmeterVector` class has been added to ease the construction of circuits - requiring a large number of parameters. (\#2379) -- dag.draw() method to visualize DAGCircuit objects (\#3016) - - -### Changed - -- Intervals are now defined by start and stop, rather than begin and end. (\#2870) -- TimeslotCollections now are sorted by default and have more efficient merges. (\#2870) -- Pulse samples are now clipped if their norm is between 1 and 1+epsilon. - Otherwise an error is raised. -- `Schedule.instructions` now returns with time-ordering. -- More informative errors are now raised if `qubit_lo_freq` and - `meas_lo_freq` are not supplied to `assemble_schedules`. (\#2833) -- `pulse.samplers` module has now been moved to `pulse.pulse_lib.samplers`. (\#2881) -- The number of memory slots required will now be inferred from the supplied - schedules if `memory_slots` is not supplied. -- All circuit drawers now express most commonly used fractions - of PI (\#2808). -- Set default repetition time to be the first available. -- Pulse commands may now start with capitalized letters. -- The `pylatexenc` and `pillow` requirements are now optional. These - are only used by the `latex` and `latex_source` circuit - visualization backends. To continue using them ensure these are - installed. (\#2451) -- When adding a register to a circuit, an error will now be raised if - a register of the same name is already present. Previously, an error - would only be raised if the same register was added twice. -- Qubits and classical bits are not represented as a tuples anymore, - but as instances of `Qubit` and `Clbit` respectively. (\#2414) -- The ApplyLayout pass is incorporated in all preset pass managers to - delineate a virtual circuit from a physical circuit (\#2672) -- Mapping passes (`CXDirection`, Swap passes, `CheckMap`, `CheckCnotDirection`) - now operate on a register-less circuit corresponding to - an already embedded physical circuit. (\#2672) -- Replaces `LegacySwap` by faster, more stable `StochasticSwap` pass (\#2672) -- Uses level 1 by default as transpiler optimization level (\#2672) -- Change `Snapshot` signature to match `simulator.snapshot` (\#2592) -- `DAGCircuit.width()` formerly returned number of qubits, now returns total - number of qubits + classical bits (\#2564) -- Functions assuming the former semantics of `DAGCircuit.width()` now call - `DAGCircuit.num_qubits()` (\#2564) -- `DAGCircuit.num_cbits()` renamed to `DAGCircuit.num_clbits()` (\#2564) -- Changed definition of `Cu3Gate` to to equivalent to the canonical - definition of a controlled `U3Gate` (\#2755) -- `coupling_map` now required to validate a `backend.configuration()` (\#2836) -- The method `QuantumCircuit.count_ops` now returns an `OrderedDict` instead of a dict. -- If layout information is available in - the circuit, it will be included to the circuit drawing. This can be removed - using the option ``with_layout=False`` in the method - ``QuantumCircuit.draw``. (\#2739) -- Q-sphere visualization is enhanced and corrected (\#2932) -- Shorter CH gate definition involving only 1 CX (\#2837) -- Now PassManager.draw() (without any argument) will return an in-memory PIL image. - -### Removed -- The ability to set the `Timeslot`s for a pulse `Instruction` at initialization. -- The previously deprecated functions - `qiskit.visualization.plot_state` and - `qiskit.visualization.iplot_state` have been removed. Instead use - the specific functions for each plot type (\#2325). -- International documentation of outdated readme etc (\#2302) -- Removed deprecated options in `execute`, `transpile`, and `assemble`. - Removed deprecated `compiler`. -- Removed deprecated `qcvv `in tools. Removed deprecated converters - `qobj_to_circuits` and `circuits_to_qobj` (\#2301) -- The previously deprecated `qiskit._util` module has been removed. - Use `qiskit.util` instead. (\#2329) -- The logging tools in `qiskit.tools.logging` are removed. (\#2387) -- The `qiskit.qiskiterror` module has been removed. Please use - `qiskit.exceptions` instead. (\#2399) -- Removed previously deprecated `DAGCircuit` methods (\#2542) -- Removed `CompositeGate` class, in favor of adding Instruction - objects directly (\#2543) -- Removed `ignore_requires` and `ignore_preserves` options from - `PassManager` (\#2565). - -### Fixed - -- Fixes a bug where the `CmdDef` was getting built without buffers on channels. -- Fixed bug in `Pulse` for multiple parameters being added (\#2742) -- Fixed bug in `Pulse` for `CmdDef` arguments (\#2741) -- Fixed bug in `Operator` and `SuperOp` for initializing from circuit - containing gates without an explicit matrix definition (\#2723) -- Possible to decompose SU(4) gate into non-CNOT basis with - `TwoQubitDecomposer` -- Fixes a bug that removed `id` gates from circuit. id gates are - like a `wait` command and will never be removed (\#2663) -- Fixed bug in `CommutationAnalysis` pass affecting conditional gates (\#2669) -- Fixed bug in measure sampling for `BasicAer` Qasm simulator if a qubit - was measured into more than one classical bit (\#2735) -- Correctly serialize complex numbers with a nonzero real part -- Fixed bug in measure sampling for `BasicAer` Qasm simulator if only a - subset of qubits are measured (\#2790) -- Parameter objects can be serialized and communicated between - sub-processes (\#2429) -- Parameterized circuits no longer need to be transpiled individually (\#2864) - - -## [0.8.2] - 2019-06-14 - -### Fixed - -- Fixed an issue with latex circuit drawer backend that could lead to an - empty image output (\#2531) -- Fixes for issues with the backend monitors for recent changes to IBMQ - backends (\#2637) -- Fixed an issue where a `TimeSlotCollection` object would be mutated by - the `is_mergable_with()` method (\#2639) - - -## [0.8.1] - 2019-05-29 - -### Fixed - -- Corrected the deprecation warning message for - `qiskit.converters.qobj_to_circuits` (\#2350) -- Fixed `execute()` and `transpile()` functions to enable setting - optimization level 0. (\#2370) -- Set the swapper with the seed transpiler for optimization level 2 and 3 - (\#2361) -- Fix default basis gate set for other transpiler passes (\#2357) -- Fix the docstring for transpile to include optimization_level 3 (\#2367) -- Fix spacing in the text circuit drawer (\#2382) -- Fix for too strict math sanitization pulse instructions (\#2397) -- Arguments to `assemble_schedule` were not actually optional, ensure - they're required (\#2398) -- Fix for framechange instructions being converted to a string instead of a - float (\#2437) -- Fix for rep_times as a float, now it's an integer (\#2438) -- Fix type error for integer framechange instructions (\#2458) -- Fix for missing cython source files in sdist (\#2436) -- Fix for different pulse schedules created with the same name (\#2431) -- Only create a single AquireInstruction for all qubits (\#2485) -- Stop modifying layout in stochastic swap pass (\#2507) -- Only call CXDirection pass on optimization_level=3 if coupling map is - provided (\#2526) -- Fix `optimization_level=0` without a coupling map (\#2509) - - -## [0.8.0] - 2019-05-02 - -### Added - -- Added exact and approximate decomposition of SU(4) to arbitrary - supercontrolled basis -- Introduced schedule lo configuration. (\#2115) -- Introduced pulse schedule assembler. (\#2115) -- Builtin library of continuous pulses and builtin library of discrete - pulses which are obtained by sampling continuous pulses with default - sampling strategy. -- Sampler decorator and standard sampler library for conversion of - continuous pulses to discrete `SamplePulse` (\#2042). -- Core StochasticSwap routine implimented in Cython (\#1789). -- Added QuantumChannel classes SuperOp, Choi, Kraus, Stinespring, PTM, - Chi to quantum\_info for manipulating quantum channels and CPTP - maps. -- Added Operator object to quantum\_info for representing matrix - operators. -- Introduced the backend defaults model and endpoint for pulse - backends (\#2101). -- `meas_level` to result schema (\#2085). -- Core StochasticSwap routine implemented in Cython (\#1789). -- New EnlargeWithAncilla pass for adding ancilla qubits after a Layout - selection pass (\#1603). -- New Unroll2Q pass for unrolling gates down to just 1q or 2q gates - (\#1614). -- Added support for register slicing when applying operations to a - register (\#1643). -- Added in new parameter `justify` to the text, mpl and latex circuit - drawers to say how the circuit should be aligned. (\#1725, \#1797, - \#1977) -- Added function for purity of a mixed state in - `qiskit.quantum_information` (\#1733) -- Added parameter to the TextProgressBar to allow the output to be - sent to a different output stream -- Added a `__qiskit_version__` parameter to the qiskit namespace. This - will contain a dictionary of versions for all installed qiskit - elements. (\#1885). -- Added a `RunConfig` object for configurations related to running an - experiment (e.g. shots, memory) (\#1856) -- Added a `TranspileConfig` object for configurations related to - transforming circuits (e.g. basis\_gates, coupling\_map, - initial\_layout) (\#1856) -- Added a `qiskit.compiler` namespace for all functions that - transpile, schedule and assemble circuits and pulses (\#1856) -- Added support for passing a list of `basis_gates`, `coupling_map` - etc. to the `qiskit.compiler.transpile()` function, each - corresponding to one of the circuits (\#2163) -- Added a `qiskit.compiler.assemble_circuits()` function to generate - qobj from some circuits and a RunConfig (\#1856) -- `execute()` and `assemble()` allow setting a qobj\_header, of type - QobjHeader or dict, to add extra information to the qobj (and thus - result). -- Register indexing supports negative indices (\#1875) -- Added new resource estimation passes: `Depth`, `Width`, `Size`, - `CountOps`, and `NumTensorFactors`, all grouped in the - `ResourceEstimation` analysis pass. -- Added `nodes_on_wire()` to DAGCircuit which returns an iterator over - all the operations on the given wire -- Added new properties to an Instruction: `num_qubits`, `num_clbits` - (\#1816). -- Added a `QuantumCircuit.append` public method for appending - arbitrary instructions to some qubits and clbits in the circuit - (\#1816). -- Added an `Instruction.definition` property that defines a composite - instruction in terms of other, simpler instructions (\#1816). -- Added an `Instruction.mirror()` method that mirrors a composite - instruction (reverses its sub-instructions) (\#1816). -- Added an `PassManager.passes()` method that returns a list of the - passes that have been added to the pass manager, including options - and flow controllers. -- Added a `PassManager.run()` that transforms a `QuantumCircuit` - according to its pass schedule and returns a `QuantumCircuit`. -- Added a `qiskit.quantum_info.random` for generating random states, - unitaries, etc (\#2119). -- Added a `qiskit.quantum_info.synthesis` for algorithms that - synthesize circuits (\#2119). -- Added a `NoiseAdaptiveLayout` pass to compute a backend - calibration-data aware initial qubit layout. (\#2089) -- Gates and instructions in a circuit accept integers as parameters to - refer to wires instead of named bits. -- Added a `OptimizeSwapBeforeMeasure` pass that removes the swap gates - when they are followed by a measurement instruction, moving the - latter to the proper wire. (\#1890) -- Added a `RemoveDiagonalGatesBeforeMeasure` pass that removes the - diagonal gates when they are followed by a measurement instruction. - (\#2208) -- Added a `CommutativeCancellation` pass that cancels self-inverse - gates and combines rotations about the Z axis, leveraging - previously-found gate commutation relations. (\#2012) -- Add an option for using a user config file to enable changing - default settings for various functions in qiskit. Right now it only - supports setting the default circuit drawing backend. (\#2122) -- Added a `Collect2qBlocks` pass that analyzes the circuit for - uninterrupted sequences of gates (blocks) acting on 2 qubits. - (\#2134) -- Added a `ConsolidateBlocks` that turns previously-collected blocks - of any size into equivalent Unitary operators in the circuit. - (\#2134) -- Added support for parameterized circuits. (\#2103) -- Added preset PassManagers that offer predetermined pipelines of - transpiler passes. (\#2163) - -### Changed - -- require scipy\>=1.0, use - `scipy.stats.unitary_group.rvs` for - `random_unitary()`. -- two\_qubit\_kak decomposition works with Operator or raw matrix - input objects. -- process\_fidelity works with QuantumChannel and Operator object - inputs. -- Backend defaults values are no longer required (\#2101). -- QuantumCircuit properties more self-consistent and no longer need - DAG (\#1993). -- The most connected subset in DenseLayout is now reduced bandwidth - (\#2021). -- plot\_histogram now allows sorting by Hamming distance from - target\_string (\#2064). -- FunctionalPulse is no longer a class and instead is a decorator, - `functional_pulse` that returns a - `SamplePulse` when called. (\#2043) -- Changed `average_data` to accept observable input in matrix form - (\#1858) -- Change random\_state to take in dim over number of qubits (\#1857) -- The `Exception` subclasses have been moved to an `.exceptions` - module within each package (for example, - `qiskit.exceptions.QiskitError`) (\#1600). -- The `QiskitTestCase` and testing utilities are now included as part - of `qiskit.test` and thus available for third-party implementations, - with convenience test cases for providers and backends. (\#1616, - \#1844) -- The snapshot instruction now takes `label` and `snap_type` instead - of `slot` (\#1615). -- The test folders have been reorganized to match the python modules - (\#1625) -- The circuits\_to\_qobj no longers uses the unrollers (\#1629) -- The previously deprecated default output of `circuit_drawer()` - (using latex and falling back to mpl) is no longer present. Instead - the default output is the ascii art `text` output backend. -- Changed param to params in Instruction (\#1665). -- `dag_drawer` and `plot_gate_map` are available via importing - `qiskit.tools.visualization`. They will raise at the point of use, - if dependencies are not installed (\#1669). -- The `qiskit.validation` schemas are now strict and raise a more - specific `ModelValidationError` (\#1695). -- The default transpile pipeline will now add a barrier before the set - of final measurements when compiling for both simulators and devices - (\#1591). -- Purity function in `qiskit.tools.qi.qi` calls new version in - `qiskit.quantum_information` and issues deprecation warning (\#1733) -- Updated `dag.node_counter` to return the current number - of nodes (\#1763) -- The argument `basis_gates` used in `compile`, `execute`, and - `transpile` is not longer a comma-separated string but a list of - strings. For example, this basis `['u1','u2','u3','cx']` should be - used instead of `'u1,u2,u3,cx'` (\#1333) -- Methods on the `DAGCircuit` which previously returned node\_ids - and/or dicts now return `DAGNodes` -- The `Qobj` classes have been reimplemented using models and schemas, - as the rest of spec-defined entities. (\#1909). -- The rzz gate is now represented as a line when printed in text - (\#1957). -- Text drawer has support for multi-q gates (\#1939). -- Separate `Qobj` into `PulseQobj` and `QasmQobj` (\#1969). -- It is possible to define a layout as a list of integers. This maps - the ordered list of virtual circuit qubits to physical qubits as - defined by the list of integers (\#1946). -- Instructions no longer have context about where they are in a - circuit. Instead, the circuit keeps this context. So Instructions - are now light-weight and only have a name, num\_qubits, num\_clbits - and params (\#1816). -- The old syntax for attaching a gate to the circuit then modifying it - is no longer supported (e.g. `circuit.s(qr).inverse()` or - `circuit.s(qr).c_if(cr, 4)`). Instead, you must first modify the - gate then attach it (\#1816). -- `QuantumCircuit.data` now contains a list of tuples, where each - tuple is a (instruction, qarg, carg) (\#1816). -- The visualization subpackage has moved from - `qiskit.tools.visualization` to `qiskit.visualization`. The public - API (which was declared stable in the 0.7 release) is still - accessible off of `qiskit.tools.visualization`. (\#1878) -- Layout object can now only be constructed from a dictionary, and - must be bijective (\#2157). -- `transpile()` accepts `initial_layout` in the form of dict, list or - Layout (\#2157). -- Not specifying a basis in `execute()` or `transpile()` no longer - defaults to unrolling to the \[\'u1\', \'u2\', \'u3\', \'cx\'\] - basis. Instead the default behavior is to not unroll, unless - specifically requested (\#2166). -- Instruction.copy() is now a shallow copy instead of deep (\#2214) -- Layout and CouplingMap classes are now accessible from - qiskit.transpiler (\#2222). - -### Deprecated - -- The methods prefixed by `\_get` in the DAGCircuit object - are being renamed without that prefix (see \#1346) -- Changed elements in `couplinglist` of `CouplingMap` from tuples to - lists (\#1666). -- Unroller bases must now be explicit, and violation raises an - informative `QiskitError` (\#1802). -- The `qiskit.tools.qcvv` package is deprecated in favor of Qiskit - Ignis (\#1884). -- The `qiskit.compile()` function is now deprecated in favor of - explicitly using the `qiskit.compiler.transpile()` function to - transform a circuit followed by `qiskit.compiler.assemble()` to make - a qobj out of it. -- `qiskit.converters.qobj_to_circuits()` has been deprecated and will - be removed in a future release. Instead - `qiskit.compiler.disassemble_circuits()` should be used to extract - `QuantumCircuit` objects from a compiled qobj. (\#2137) -- The `qiskit.transpiler.transpile()` function is deprecated in favor - of `qiskit.compiler.transpile()` (\#2166). -- The `seed_mapper` argument in `transpile()` and `execute()` is - deprecated in favor of `seed_transpile()`, which sets the seed for - all stochastic stages of the transpiler (\#2166). -- The `seed` argument is `execute()` is deprecated in favor of - `seed_simulator` (\#2166). -- The `pass_manager` argument in `transpile()` is deprecated. Instead, - the `pass_manager.run()` methdod can be used directly to transform - the circuit (\#2166). -- The `qiskit._util` module is deprecated and replaced by - `qiskit.util`. `qiskit._util` will be removed in the 0.9 release. - (\#2154) - -### Fixed - -- Fixed \#1892, whereby inheriting from QuantumRegister or - ClassicalRegister would cause a QiskitError in instruction.py - (\#1908). -- Fixed \#829 by removing dependence on scipy unitary\_group (\#1857). -- Fixed a bug with measurement sampling optimization in BasicAer - qasm\_simulator (\#1624). -- Fixed a bug where barriers didn\'t plot over all qubits when using - matplotlib (\#1718). -- Fixed a minor conda env bug in Makefile (\#1691). -- Fixed a bug in BasicMapper pass operating over multiple registers - (\#1611). -- Fixed a bug in BarrierBeforeFinalMeasurements which incorrectly - moved measurements used in conditional operations (\#1705). -- Fixed a bug that with transpile ignoring initial layout when - coupling map is provided (\#1711). -- Fixed a bug in the definition of the rzz gate (\#1940). -- Fixed a bug in DAGCircuit.collect\_runs() that did not exclude - conditional gates (\#1943). -- Fixed a mapping issue with layouts on non-adjacent qubits, by adding - ancillas (\#2023). -- Fixed a bug in which an `initial_layout` could be - changed even if it made the circuit compatible with the device - `coupling_map` (\#2036). -- Fixed `qobj_to_circuits` for circuits that contain initialize - instructions (\#2138) - -### Removed - -- The previously deprecated functions `plot_circuit()`, - `latex_circuit_drawer()`, `generate_latex_source()`, and - `matplotlib_circuit_drawer()` from `qiskit.tools.visualization` have - been removed. The `circuit_drawer()` function from the same module - should be used instead. -- The previously deprecated keys `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. -- Removed the wrapper folder as part of the post 0.7 cleanup (\#1613). -- Removed the python wrappers of the legacy simualtors now that Qiskit - Aer is out (\#1615). -- Removed simulator instructions `save`, `load`, `wait`, `noise` as - unsupported in Aer (\#1615). -- Removed circuit.add as deprecated (\#1627) -- Removed the unroller (\#1629) -- Removed deprecated `result` methods (\#1659) -- Removed deprecated `couplingdict` kwarg from `CouplingMap` (\#1666) -- Removed deprecated `transpile_dag()` `format` kwarg (\#1664) -- Removed deprecated `Pauli` `v`, `w`, and `pauli_group` case arg as - int (\#1680) -- Removed deprecated `state_fidelity()` function from `tools.qi` - (\#1681) -- Removed `QISKitError` in favor of `QiskitError`. (\#1684) -- The IBMQ provider (`qiskit.providers.ibmq`) has been moved to its - own package (`pip install qiskit-ibmq-provider`). (\#1700) -- `compiled_circuit_qasm` has been removed from the Qobj header, since - it was part of the pre-qobj specification (\#1715). -- Removed the wigner plotting functions `plot_wigner_function`, - `plot_wigner_curve`, `plot_wigner_plaquette`, and `plot_wigner_data` - (\#1860). -- Removed `Instruction.reapply()` method (\#1816). - -## [0.7.2] - 2019-05-01 - -### Fixed - -- A potential issue where the backend configuration schema validation - would improperly reject valid responses from the API (\#2258) - -## [0.7.1] - 2019-03-04 - -### Fixed - -- Fixed a bug with measurement sampling optimization in BasicAer - qasm\_simulator (\#1624). - -## [0.7.0] - 2018-12-19 - -### Added - -- Added DAG visualizer which requires - [Graphivz](https://www.graphviz.org/) (\#1059) -- Added an ASCII art circuit visualizer (\#909) -- The QuantumCircuit class now returns an ASCII art visualization when - treated as a string (\#911) -- The QuantumCircuit class now has a `draw()` method which - behaves the same as the - `qiskit.tools.visualization.circuit_drawer()` function - for visualizing the quantum circuit (\#911) -- A new method `hinton` can be used on - `qiskit.tools.visualization.plot_state()` to draw a - hinton diagram (\#1246) -- Two new constructor methods, `from_qasm_str()` and - `from_qasm_file()`, to create a QuantumCircuit object - from OpenQASM were added to the QuantumCircuit class. (\#1172) -- New methods in QuantumCircuit for common circuit metrics: - `size()`, `depth()`, `width()`, - `count_ops()`, `num_tensor_factors()` - (\#1285) -- Added `backend_monitor` and - `backend_overview` Jupyter magics, as well as - `plot_coupling_map` (\#1231) -- Added a `Layout` object (\#1313) -- New `plot_bloch_multivector()` to plot Bloch vectors - from a tensored state vector or density matrix. (\#1359) -- Per-shot measurement results are available in simulators and select - devices. Request them by setting `memory=True` in - `compile()`/`execute()`, and retrieve them from - `result.get_memory()` (\#1385). -- Added a `qiskit.converters` module for translation between commonly - used representations of a circuit: `dag_to_circuits`, - `circuits_to_dag`, `qobj_to_circuits`, `circuits_to_qobj`, - `ast_to_dag`. -- PassManager can schedule passes at \_\_init\_\_ time (\#1510). -- Added a `.qobj()` method for IBMQ and local simulator Jobs (\#1532). -- New Decompose pass for decomposing a gate according to a rule - (\#1487). -- New Unroller pass in the transpiler for unrolling up to some basis - (\#1455). -- New BarrierBeforeFinalMeasurements pass for preventing final measure - reorder (\#1538). -- New CommutationAnalysis and CommutationTransformation transpiler - passes for modifying a DAG based on gate commutativity relations - (\#1500). -- New transpiler mapper pass: BasicSwap (\#1270). -- New transpiler mapper pass: LookaheadSwap (\#1140). -- New transpiler mapper pass: StochasticSwap (\#1520). -- New CXDirection pass for fixing the direction of cx gates (\#1410). -- New CheckMap pass for checking if circuit meets mapping requirements - (\#1433). -- New Optimize1QGate pass for combining chains of 1q rotations - (\#1442). - -### Changed - -- Schedules and underlying classes are now immutable. (\#2186) -- Evolved pass-based transpiler to support advanced functionality - (\#1060) -- `.retrieve_job()` and `.jobs()` no longer - returns results by default, instead the result must be accessed by - the `result()` method on the job objects (\#1082). -- Make `backend.status()` dictionary conform with schema. -- The different output backends for the circuit\_drawer() - visualizations have been moved into separate private modules in - `qiskit.tools.visualizations`. (\#1105, \#1111) -- DAG nodes contain pointers to Register and Instruction objects, - rather than their string names (\#1189). -- Upgraded some external dependencies to: - - networkx\>=2.2 (\#1267). - -- The `qiskit.tools.visualization.circuit_drawer()` - method now returns a matplotlib.Figure object when the - `mpl` output is used and a `TextDrawer` - object when `text` output is used. (\#1224, \#1181) -- Speed up the Pauli class and extended its operators (\#1271 \#1166). -- `IBMQ.save_account()` now takes an - `overwrite` option to replace an existing account on - disk. Default is False (\#1295). -- Backend and Provider methods defined in the specification use model - objects rather than dicts, along with validation against schemas - (\#1249, \#1277, \#1350). The updated methods include: - - `backend.status()` (\#1301). - - `backend.configuration()` (and `__init__`) (\#1323). - - `backend.properties()`, returning `None` for sims (\#1331, - \#1401). - - `qiskit.Result` (\#1360). -- `backend.provider()` is now a method instead of a property (\#1312). -- Remove local backend (Aer) fallback (\#1303) -- The signatures for the plotting functions in - `qiskit.tools.visualization._counts_visualization.py`, - `qiskit.tools.visualization._state_visualization.py`, - and `qiskit.tools.visualization.interactive` have been - modified to make them in-line with standard Matplotlib calling - conventions (\#1359). -- Remove local backend (Aer) fallback (\#1303). -- DAGCircuits store Instruction and Register objects, instead of name - references. The DAGCircuit class methods are updated accordingly - (\#1210). -- `transpile()` now takes QuantumCircuit(s) to QuantumCircuit(s), and - DAG processing is only done internally (\#1397). -- The different unrollers are deprecated. The only unrolling happens - from DAG to DAG (\#1210). -- Moved all the circuit modules into a circuit module but for most - users it is still imported in the top level for QuantumCircuit, - QuantumRegister, ClassicalRegister -- `qiskit.backends` has been renamed to `qiskit.providers` (\#1531). -- `qiskit.backends.aer` has been removed in favor of - `qiskit.providers.builtinsimulators` (Python simulators) and - `qiskit.providers.legacysimulators` (C++ simulators) (\#1484) -- `Aer` in `qiskit` root module depends on having the qiskit-aer - package installed, by default it is not present. Instead there are 2 - new provider instances in the root module `BasicAer` which provides - the Python simulators and `LegacySimulators` which provides the old - C++ simulators in qiskit-terra. (\#1484) - -### Deprecated - -- `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. - (\#1055) -- The current default output of `circuit_drawer()` (using latex and falling - back on python) is deprecated and will be changed in the future. - (\#1055) -- 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()` contstructor - methods should be used instead (\#1172) -- 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. (\#1180) -- The `transpile_dag()` function `format` kwarg for emitting different - output formats is deprecated (\#1319). -- Several methods of `qiskit.Result` have been deprecated (\#1360). -- The functions `plot_state()` and - `iplot_state()` have been depreciated. Instead the - functions `plot_state_\*()` and - `iplot_state_\*()` should be called. (\#1359) -- The `skip_transpiler` arg has been deprecated from `compile()` and - `execute()` in favor of using the PassManager directly. - -### Fixed - -- Fixed a variety of typos throughout sources (\#1139) -- Fixed horizontal spacing when drawing barriers before CCNOT gates in - latex circuit plots (\#1051) -- Use case insensitive matching when comparing premium account URLs. - (\#1102) -- Fixed AerJob status when the submitted Job is in a PENDING state. - (\#1215) -- Add fallback for when CPU count can\'t be determined (\#1214) -- Fix `random_state` from returning nan (\#1258) -- The Clifford simulator `run()` method now works - correctly with the updated AerJob usage (\#1125) -- Fixed an edge case when connection checks would raise an unhandled - exception (\#1226) -- Fixed a bug where the transpiler moved middle-of-circuit - measurements to the end (\#1334) -- The `number_to_keep` kwarg in `plot_histgram()` now - functions correctly (\#1359). -- parallel\_map no longer creates a progress bar for a single circuit - (\#1394). -- The `timeout` parameter is now passed into the inner - `_wait_for_submission` function in `IBMQJob` from `_wait_for_result` - (\#1542). - -### Removed - -- Remove register, available\_backends (\#1131). -- Remove tools/apps (\#1184). -- Removed the dependency on `IBMQuantumExperience`, as it is now - included in `qiskit.backends.IBMQ` (\#1198). -- `matplotlib` is no longer in the package requirements and is now an - optional dependency. In order to use any matplotlib based - visualizations (which includes the - `qiskit.tools.visualization.circuit_drawer()` `mpl` output, - `qiskit.tools.visualization.plot_state`, - `qiskit.tools.visualization.plot_histogram`, and - `qiskit.tools.visualization.plot_bloch_vector` you will now need to - ensure you manually install and configure matplotlib independently. -- The `basis` kwarg for the `circuit_drawer()` function to provide an - alternative list of basis gates has been removed. Instead users - should adjust the basis gates prior to visualizing the circuit. - (\#1151) -- `backend.parameters()` and `backend.calibration()` have been fully - deprecated, in favour of `backend.properties()` (\#1305). -- The `qiskit.tools.file_io` module has been removed. Conversion - between `qiskit.Result` and json can be achieved using `.to_dict()` - and `.from_dict()` directly (\#1360). -- The `qiskit.Result` class method for `len()` and indexing have been - removed, along with the functions that perform post-processing - (\#1351). -- The `get_snapshot()` and `get_snapshots()` method from the `Result` - class has been removed. Instead you can access the snapshots in a - Result using `Result.data()['snapshots']`. -- Completed the deprecation of `job.backend_name()`, `job.id()`, and - the `backend_name` parameter in its constructor. -- The `qiskit.Result` class now does post-processing of results - returned from backends if they are called via the `Result.get_xxx()` - methods (i.e. `get_counts()`, `get_memory()`, `get_statevector()`, - `get_unitary()`). The raw data is accessible through `Result.data()` - (\#1404). -- The `transpile()` function kwarg `format` has been removed and will - always return a circuit object. Instead you\'ll need to manually - convert the output with the functions provided in - `qiskit.converters`. - -## [0.6.0] - 2018-10-04 - -### Added - -- Added `SchemaValidationError` to be thrown when schema - validation fails (\#881) -- Generalized Qobj schema validation functions for all qiskit schemas - (\#882). -- Added decorator to check for C++ simulator availability (\#662) -- It is possible to cancel jobs in non comercial backends (\#687) -- Introduced new `qiskit.IBMQ` provider, with centralized - handling of IBMQ credentials (qiskitrc file, environment variables). - (\#547, \#948, \#1000) -- Add OpenMP parallelization for Apple builds of the cpp simulator - (\#698). -- Add parallelization utilities (\#701) -- Parallelize transpilation (\#701) -- New interactive visualizations (\#765). -- Added option to reverse the qubit order when plotting a circuit. - (\#762, \#786) -- Jupyter notebook magic function qiskit\_job\_status, - qiskit\_progress\_bar (\#701, \#734) -- Add a new function `qobj_to_circuits` to convert a Qobj object to a - list of QuantumCircuit objects (\#877) -- Allow selective loading of accounts from disk via hub/group/project - filters to `IBMQ.load_accounts()`. -- Add new `job_monitor` function to automaically check - the status of a job (\#975). - -### Changed - -- Schema tests in `tests/schemas/test_schemas.py` - replaced with proper unit test (\#834). -- Renamed `QISKit` to `Qiskit` in the documentation. (\#634) -- Use `Qobj` as the formally defined schema for sending information to - the devices: - - introduce the `qiskit.qobj` module. (\#589, \#655) - - update the `Qobj` JSON schema. (\#668, \#677, \#703, \#709) - - update the local simulators for accepting `Qobj` as input. - (\#667) - - update the `Result` class. (\#773) -- Use `get_status_job()` for checking IBMQJob status. (\#641) -- Q network hub/group/project credentials replaced by new url format. - (\#740) -- Breaking change: `Jobs` API simplification. (\#686) -- Breaking change: altered tomography APIs to not use QuantumProgram. - (\#818) -- Breaking change: `BaseBackend` API changed, properties are now - methods (\#858) -- When `plot_histogram()` or `plot_state()` are called from a jupyter - notebook if there is network connectivity the interactive plots will - be used by default (\#862, \#866) -- Breaking change: `BaseJob` API changed, any job constructor must be - passed the backend used to run them and a unique job id (\#936). -- Add support for drawing circuit barriers to the latex circuit - drawer. This requires having the LaTeX qcircuit package - version \>=2.6.0 installed (\#764) - -### Deprecated - -- The `number_to_keep` kwarg on the `plot_histogram()` function is now - deprecated. A field of the same name should be used in the `option` - dictionary kwarg instead. (\#866) -- Breaking change: `backend.properties()` instead of - `backend.calibration()` and `backend.parameters()` (\#870) - -### Removed - -- Removed the QuantumProgram class. (\#724) - -### Fixed - -- Fixed `get_ran_qasm` methods on `Result` instances (\#688). -- Fixed `probabilities_ket` computation in C++ simulator (\#580). -- Fixed bug in the definition of `cswap` gate and its test (\#685). -- Fixed the examples to be compatible with version 0.5+ (\#672). -- Fixed swap mapper using qubits after measurement (\#691). -- Fixed error in cpp simulator for 3+ qubit operations (\#698). -- Fixed issue with combining or extending circuits that contain - CompositeGate (\#710). -- Fixed the random unitary generation from the Haar measure (\#760). -- Fixed the issue with control lines spanning through several - classical registers (\#762). -- Fixed visualizations crashing when using simulator extensions - (\#885). -- Fixed check for network connection when loading interactive - visualizations (\#892). -- Fixed bug in checking that a circuit already matches a coupling map - (\#1024). - -## [0.5.7] - 2018-07-19 - -### Changed - -- Add new backend names support, with aliasing for the old ones. - -## [0.5.6] - 2018-07-06 - -### Changed - -- Rename repository to `qiskit-terra` (\#606). -- Update Bloch sphere to QuTiP version (\#618). -- Adjust margin of matplotlib\_circuit\_drawer (\#632) - -### Removed - -- Remove OpenQuantumCompiler (\#610). - -### Fixed - -- Fixed broken process error and simulator slowdown on Windows - (\#613). -- Fixed yzy\_to\_zyz bugs (\#520, \#607) by moving to quaternions - (\#626). - -## [0.5.5] - 2018-07-02 - -### Added - -- Retrieve IBM Q jobs from server (\#563, \#585). -- Add German introductory documentation (`doc/de`) (\#592). -- Add `unregister()` for removing previously registered providers - (\#584). -- Add matplotlib-based circuit drawer (\#579). -- Adding backend filtering by least busy (\#575). -- Allow running with new display names for IBMQ devices, and return - those from `available_backends()` (\#566) -- Introduce Qiskit Transpiler and refactor compilation flow (\#578) -- Add CXCancellation pass (\#578) - -### Changed - -- Remove backend filtering in individual providers, keep only in - wrapper (\#575). -- Single source of version information (\#581) -- Bumped IBMQuantumExperience dependency to 1.9.6 (\#600). -- For backend status, `status\[\'available\'\]` is now - `status\[\'operational\'\]` (\#609). -- Added support for registering third-party providers in - `register()` (\#602). -- Order strings in the output of `available_backends()` (\#566) - -### Removed - -- Remove Clifford simulator from default available\_backends, until - its stable release (\#555). -- Remove ProjectQ simulators for moving to new repository (\#553). -- Remove QuantumJob class (\#616) - -### Fixed - -- Fix issue with unintended inversion of initializer gates (\#573). -- Fix issue with skip\_transpiler causing some gates to be ignored - silently (\#562). - -## [0.5.4] - 2018-06-11 - -### Added - -- Performance improvements: - - remove deepcopies from dagcircuit, and extra check on qasm() - (\#523). - -### Changed - -- Rename repository to `qiskit-core` (\#530). -- Repository improvements: new changelog format (\#535), updated issue - templates (\#531). -- Renamed the specification schemas (\#464). -- Convert `LocalJob` tests into unit-tests. (\#526) -- Move wrapper `load_qasm_*` methods to a submodule (\#533). - -### Removed - -- Remove Sympy simulators for moving to new repository (\#514) - -### Fixed - -- Fix erroneous density matrix and probabilities in C++ simulator - (\#518) -- Fix hardcoded backend mapping tests (\#521) -- Removed `_modifiers call` from `reapply` (\#534) -- Fix circuit drawer issue with filename location on windows (\#543) -- Change initial qubit layout only if the backend coupling map is not - satisfied (\#527) -- Fix incorrect unrolling of t to tdg in CircuitBackend (\#557) -- Fix issue with simulator extension commands not reapplying correctly - (\#556) - -## [0.5.3] - 2018-05-29 - -### Added - -- load\_qasm\_file / load\_qasm\_string methods - -### Changed - -- Dependencies version bumped - -### Fixed - -- Crash in the cpp simulator for some linux platforms -- Fixed some minor bugs - -## [0.5.2] - 2018-05-21 - -### Changed - -- Adding Result.get\_unitary() - -### Deprecated - -- Deprecating `ibmqx_hpc_qasm_simulator` and `ibmqx_qasm_simulator` in - favor of `ibmq_qasm_simulator`. - -### Fixed - -- Fixing a Mapper issue. -- Fixing Windows 7 builds. - -## [0.5.1] - 2018-05-15 - -- There are no code changes. - - MacOS simulator has been rebuilt with external user libraries - compiled statically, so there's no need for users to have a - preinstalled gcc environment. - - Pypi forces us to bump up the version number if we want to upload a - new package, so this is basically what have changed. - -## [0.5.0] - 2018-05-11 - -### Improvements - -- Introduce providers and rework backends (\#376). - - Split backends into `local` and `ibmq`. - - Each provider derives from the following classes for its - specific requirements (`BaseProvider`, `BaseBackend`, - `BaseJob`). - - Allow querying result by both circuit name and - QuantumCircuit instance. -- Introduce the Qiskit `wrapper` (\#376). - - Introduce convenience wrapper functions around commonly used - Qiskit components (e.g. `compile` and `execute` functions). - - Introduce the DefaultQISKitProvider, which acts as a context - manager for the current session (e.g. providing easy access - to all `available_backends`). - - Avoid relying on QuantumProgram (eventual deprecation). - - The functions are also available as top-level functions (for - example, `qiskit.get_backend()`). -- Introduce `BaseJob` class and asynchronous jobs (\#403). - - Return `BaseJob` after `run()`. - - Mechanisms for querying `status` and `results`, or to - `cancel` a job. -- Introduce a `skip_transpiler` flag for `compile()` (\#411). -- Introduce schemas for validating interfaces between qiskit and - backends (\#434) - - qobj\_schema - - result\_schema - - job\_status\_schema - - default\_pulse\_config\_schema - - backend\_config\_schema - - backend\_props\_schema - - backend\_status\_schema -- Improve C++ simulator (\#386) - - Add `tensor_index.hpp` for multi-partite qubit vector - indexing. - - Add `qubit_vector.hpp` for multi-partite qubit vector - algebra. - - Rework C++ simulator backends to use QubitVector class - instead of `std::vector`. -- Improve interface to simulator backends (\#435) - - Introduce `local_statevector_simulator_py` and - `local_statevector_simulator_cpp`. - - Introduce aliased and deprecated backend names and - mechanisms for resolving them. - - Introduce optional `compact` flag to query backend names - only by unique function. - - Introduce result convenience functions `get_statevector`, - `get_unitary` - - Add `snapshot` command for caching a copy of the current - simulator state. -- Introduce circuit drawing via `circuit_drawer()` and - `plot_circuit()` (\#295, \#414) -- Introduce benchmark suite for performance testing - (`test/performance`) (\#277) -- Introduce more robust probability testing via assertDictAlmostEqual - (\#390) -- Allow combining circuits across both depth and width (\#389) -- Enforce string token names (\#395) - -### Fixed - -- Fix coherent error bug in `local_qasm_simulator_cpp` (\#318) -- Fix the order and format of result bits obtained from device - backends (\#430) -- Fix support for noises in the idle gate of - `local_clifford_simulator_cpp` (\#440) -- Fix JobProcessor modifying input qobj (\#392) (and removed - JobProcessor during \#403) -- Fix ability to apply all gates on register (\#369) - -### Deprecated - -- Some methods of `QuantumProgram` are soon to be deprecated. Please - use the top-level functions instead. -- The `Register` instantiation now expects `size, name`. Using - `name, size` is still supported but will be deprecated in the - future. -- Simulators no longer return wavefunction by setting shots=1. - Instead, use the `local_statevector_simulator`, or explicitly ask - for `snapshot`. -- Return `job` instance after `run()`, rather than `result`. -- Rename simulators according to - `PROVIDERNAME_SIMPLEALIAS_simulator_LANGUAGEORPROJECT` -- Move simulator extensions to `qiskit/extensions/simulator` -- Move Rzz and CSwap to standard extension library - -## [0.4.15] - 2018-05-07 - -### Fixed - -- Fixed an issue with legacy code that was affecting Developers - Challenge. - -## [0.4.14] - 2018-04-18 - -### Fixed - -- Fixed an issue about handling Basis Gates parameters on backend - configurations. - -## [0.4.13] - 2018-04-16 - -### Changed - -- OpenQuantumCompiler.dag2json() restored for backward compatibility. - -### Fixed - -- Fixes an issue regarding barrier gate misuse in some circumstances. - -## [0.4.12] - 2018-03-11 - -### Changed - -- Improved circuit visualization. -- Improvements in infrastructure code, mostly tests and build system. -- Better documentation regarding contributors. - -### Fixed - -- A bunch of minor bugs have been fixed. - -## [0.4.11] - 2018-03-13 - -### Added - -- More testing :) - -### Changed - -- Stabilizing code related to external dependencies. - -### Fixed - -- Fixed bug in circuit drawing where some gates in the standard - library were not plotting correctly. - -## [0.4.10] - 2018-03-06 - -### Added - -- Chinese translation of README. - -### Changed - -- Changes related with infrastructure (linter, tests, automation) - enhancement. - -### Fixed - -- Fix installation issue when simulator cannot be built. -- Fix bug with auto-generated CNOT coherent error matrix in C++ - simulator. -- Fix a bug in the async code. - -## [0.4.9] - 2018-02-12 - -### Changed - -- CMake integration. -- QASM improvements. -- Mapper optimizer improvements. - -### Fixed - -- Some minor C++ Simulator bug-fixes. - -## [0.4.8] - 2018-01-29 - -### Fixed - -- Fix parsing U\_error matrix in C++ Simulator python helper class. -- Fix display of code-blocks on `.rst` pages. - -## [0.4.7] - 2018-01-26 - -### Changed - -- Changes some naming conventions for `amp_error` noise parameters to - `calibration_error`. - -### Fixed - -- Fixes several bugs with noise implementations in the simulator. -- Fixes many spelling mistakes in simulator README. - -## [0.4.6] - 2018-01-22 - -### Changed - -- We have upgraded some of out external dependencies to: - - matplotlib \>=2.1,\<2.2 - - networkx\>=1.11,\<2.1 - - numpy\>=1.13,\<1.15 - - ply==3.10 - - scipy\>=0.19,\<1.1 - - Sphinx\>=1.6,\<1.7 - - sympy\>=1.0 - -## [0.4.4] - 2018-01-09 - -### Changed - -- Update dependencies to more recent versions. - -### Fixed - -- Fix bug with process tomography reversing qubit preparation order. - -## [0.4.3] - 2018-01-08 - -### Removed - -- Static compilation has been removed because it seems to be failing - while installing Qiskit via pip on Mac. - -## [0.4.2] - 2018-01-08 - -### Fixed - -- Minor bug fixing related to pip installation process. - -## [0.4.0] - 2018-01-08 - -### Added - -- Job handling improvements. - - Allow asynchronous job submission. - - New JobProcessor class: utilizes concurrent.futures. - - New QuantumJob class: job description. -- Modularize circuit \"compilation\". - - Takes quantum circuit and information about backend to transform - circuit into one which can run on the backend. -- Standardize job description. - - All backends take QuantumJob objects which wraps `qobj` program - description. -- Simplify addition of backends, where circuits are run/simulated. - - `qiskit.backends` package added. - - Real devices and simulators are considered \"backends\" - which inherent from `BaseBackend`. -- Reorganize and improve Sphinx documentation. -- Improve unittest framework. -- Add tools for generating random circuits. -- New utilities for fermionic Hamiltonians - (`qiskit/tools/apps/fermion`). -- New utilities for classical optimization and chemistry - (`qiskit/tools/apps/optimization`). -- Randomized benchmarking data handling. -- Quantum tomography (`qiskit/tools/qcvv`). - - Added functions for generating, running and fitting process - tomography experiments. -- Quantum information functions (`qiskit/tools/qi`). - - Partial trace over subsystems of multi-partite vector. - - Partial trace over subsystems of multi-partite matrix. - - Flatten an operator to a vector in a specified basis. - - Generate random unitary matrix. - - Generate random density matrix. - - Generate normally distributed complex matrix. - - Generate random density matrix from Hilbert-Schmidt metric. - - Generate random density matrix from the Bures metric. - - Compute Shannon entropy of probability vector. - - Compute von Neumann entropy of quantum state. - - Compute mutual information of a bipartite state. - - Compute the entanglement of formation of quantum state. -- Visualization improvements (`qiskit/tools`). - - Wigner function representation. - - Latex figure of circuit. -- Use python logging facility for info, warnings, etc. -- Auto-deployment of sphinx docs to github pages. -- Check IBMQuantumExperience version at runtime. -- Add QuantumProgram method to reconfigure already generated qobj. -- Add Japanese introductory documentation (`doc/ja`). -- Add Korean translation of readme (`doc/ko`). -- Add appveyor for continuous integration on Windows. -- Enable new IBM Q parameters for hub/group/project. -- Add QuantumProgram methods for destroying registers and circuits. -- Use Sympy for evaluating expressions. -- Add support for ibmqx\_hpc\_qasm\_simulator backend. -- Add backend interface to Project Q C++ simulator. - - Requires installation of Project Q. -- Introduce `Initialize` class. - - Generates circuit which initializes qubits in arbitrary state. -- Introduce `local_qiskit_simulator` a C++ simulator with realistic noise. - - Requires C++ build environment for `make`-based build. -- Introduce `local_clifford_simulator` a C++ Clifford simulator. - - Requires C++ build environment for `make`-based build. - -### Changed - -- The standard extension for creating U base gates has been modified - to be consistent with the rest of the gate APIs (see \#203). - -### Removed - -- The `silent` parameter has been removed from a number of - `QuantumProgram` methods. The same behaviour can be achieved now by - using the `enable_logs()` and `disable_logs()` methods, which use - the standard Python logging. - -### Fixed - -- Fix basis gates (\#76). -- Enable QASM parser to work in multiuser environments. -- Correct operator precedence when parsing expressions (\#190). -- Fix \"math domain error\" in mapping (\#111, \#151). - -[UNRELEASED]: https://github.com/Qiskit/qiskit-terra/compare/0.9.0...HEAD -[0.9.0]: https://github.com/Qiskit/qiskit-terra/compare/0.8.2...0.9.0 -[0.8.2]: https://github.com/Qiskit/qiskit-terra/compare/0.8.1...0.8.2 -[0.8.1]: https://github.com/Qiskit/qiskit-terra/compare/0.8.0...0.8.1 -[0.8.0]: https://github.com/Qiskit/qiskit-terra/compare/0.7.2...0.8.0 -[0.7.2]: https://github.com/Qiskit/qiskit-terra/compare/0.7.1...0.7.2 -[0.7.1]: https://github.com/Qiskit/qiskit-terra/compare/0.7.0...0.7.1 -[0.7.0]: https://github.com/Qiskit/qiskit-terra/compare/0.6.0...0.7.0 -[0.6.0]: https://github.com/Qiskit/qiskit-terra/compare/0.5.7...0.6.0 -[0.5.7]: https://github.com/Qiskit/qiskit-terra/compare/0.5.6...0.5.7 -[0.5.6]: https://github.com/Qiskit/qiskit-terra/compare/0.5.5...0.5.6 -[0.5.5]: https://github.com/Qiskit/qiskit-terra/compare/0.5.4...0.5.5 -[0.5.4]: https://github.com/Qiskit/qiskit-terra/compare/0.5.3...0.5.4 -[0.5.3]: https://github.com/Qiskit/qiskit-terra/compare/0.5.2...0.5.3 -[0.5.2]: https://github.com/Qiskit/qiskit-terra/compare/0.5.1...0.5.2 -[0.5.1]: https://github.com/Qiskit/qiskit-terra/compare/0.5.0...0.5.1 -[0.5.0]: https://github.com/Qiskit/qiskit-terra/compare/0.4.15...0.5.0 -[0.4.15]: https://github.com/Qiskit/qiskit-terra/compare/0.4.14...0.4.15 -[0.4.14]: https://github.com/Qiskit/qiskit-terra/compare/0.4.13...0.4.14 -[0.4.13]: https://github.com/Qiskit/qiskit-terra/compare/0.4.12...0.4.13 -[0.4.12]: https://github.com/Qiskit/qiskit-terra/compare/0.4.11...0.4.12 -[0.4.11]: https://github.com/Qiskit/qiskit-terra/compare/0.4.10...0.4.11 -[0.4.10]: https://github.com/Qiskit/qiskit-terra/compare/0.4.9...0.4.10 -[0.4.9]: https://github.com/Qiskit/qiskit-terra/compare/0.4.8...0.4.9 -[0.4.8]: https://github.com/Qiskit/qiskit-terra/compare/0.4.7...0.4.8 -[0.4.7]: https://github.com/Qiskit/qiskit-terra/compare/0.4.6...0.4.7 -[0.4.6]: https://github.com/Qiskit/qiskit-terra/compare/0.4.5...0.4.6 -[0.4.4]: https://github.com/Qiskit/qiskit-terra/compare/0.4.3...0.4.4 -[0.4.3]: https://github.com/Qiskit/qiskit-terra/compare/0.4.2...0.4.3 -[0.4.2]: https://github.com/Qiskit/qiskit-terra/compare/0.4.1...0.4.2 -[0.4.0]: https://github.com/Qiskit/qiskit-terra/compare/0.3.16...0.4.0 - -[Keep a Changelog]: http://keepachangelog.com/en/1.0.0/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 09afd818d241..fcc7fcd09839 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -100,8 +100,31 @@ please ensure that: 3. If it makes sense for your change that you have added new tests that cover the changes. 4. Ensure that if your change has an end user facing impact (new feature, - deprecation, removal etc) that you have updated the CHANGELOG.md and - added a reno release note for that change. + deprecation, removal etc) that you have added a reno release note for that + change and that the PR is tagged for the changelog. + +### Changelog generation + +The changelog is automatically generated as part of the release process +automation. This works through a combination of the git log and the pull +request. When a release is tagged and pushed to github the release automation +bot looks at all commit messages from the git log for the release. It takes the +PR numbers from the git log (assuming a squash merge) and checks if that PR had +a `Changelog:` label on it. If there is a label it will add the git commit +message summary line from the git log for the release to the changelog. + +If there are multiple `Changelog:` tags on a PR the git commit message summary +line from the git log will be used for each changelog category tagged. + +The current categories for each label are as follows: + +| PR Label | Changelog Category | +| -----------------------|--------------------| +| Changelog: Deprecation | Deprecated | +| Changelog: New Feature | Added | +| Changelog: API Change | Changed | +| Changelog: Removal | Removed | +| Changelog: Bugfix | Fixed | ### Commit messages @@ -157,6 +180,10 @@ git annotate messages, gitk viewer annotations, merge commit messages, and many more places where space is at a premium. As well as summarizing the change itself, it should take care to detail what part of the code is affected. +In addition the first line of the commit message gets used as entries in the +generated changelog if the PR is tagged as being included in the changelog. +It's critically important that you write a clear and succinct summary lines. + * Describe any limitations of the current code. If the code being changed still has future scope for improvements, or any known @@ -450,7 +477,7 @@ the project boards in Github for project management. We use milestones in Github to track work for specific releases. The features or other changes that we want to include in a release will be tagged and discussed in Github. As we're preparing a new release we'll document what has changed since the -previous version in the release notes and Changelog. +previous version in the release notes. ### Branches @@ -471,11 +498,18 @@ merged to it are bugfixes. When it is time to release a new minor version of qiskit-terra we will: -1. Create a stable branch for the new minor version from the current - HEAD on the `master` branch -2. Create a new tag with the version number on the HEAD of the new stable - branch. -3. Change the `master` version to the next release version. +1. Create a new tag with the version number and push it to github +2. Change the `master` version to the next release version. + +The release automation processes will be triggered by the new tag and perform +the following steps: + +1. Create a stable branch for the new minor version from the release tag + on the `master` branch +2. Build and upload binary wheels to pypi +3. Create a github release page with a generated changelog +4. Generate a PR on the meta-repository to bump the terra version and + meta-package version. The `stable/*` branches should only receive changes in the form of bug fixes. diff --git a/README.md b/README.md index c26fc7b133c5..157908b73065 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,27 @@ Now you're set up and ready to check out some of the other examples from our Qiskit Terra is the work of [many people](https://github.com/Qiskit/qiskit-terra/graphs/contributors) who contribute to the project at different levels. If you use Qiskit, please cite as per the included [BibTeX file](https://github.com/Qiskit/qiskit/blob/master/Qiskit.bib). +## Changelog and Release Notes + +The changelog for a particular release is dynamically generated and gets +written to the release page on Github for each release. For example, you can +find the page for the `0.9.0` release here: + +https://github.com/Qiskit/qiskit-terra/releases/tag/0.9.0 + +The changelog for the current release can be found in the releases tab: +![](https://img.shields.io/github/release/Qiskit/qiskit-terra.svg?style=popout-square) +The changelog provides a quick overview of noteable changes for a given +release. + +Additionally, as part of each release detailed release notes are written to +document in detail what has changed as part of a release. This includes any +documentation on potential breaking changes on upgrade and new features. +For example, You can find the release notes for the `0.9.0` release in the +Qiskit documentation here: + +https://qiskit.org/documentation/release_notes.html#terra-0-9 + ## License [Apache License 2.0](LICENSE.txt) diff --git a/qiskit/assembler/assemble_schedules.py b/qiskit/assembler/assemble_schedules.py index 24ca27bf30e7..dd3739e607f9 100644 --- a/qiskit/assembler/assemble_schedules.py +++ b/qiskit/assembler/assemble_schedules.py @@ -83,7 +83,7 @@ def assemble_schedules(schedules, qobj_id, qobj_header, run_config): instruction = PulseInstruction( command=SamplePulse(name=name, samples=instruction.command.samples), name=instruction.name, - channel=instruction.timeslots.channels[0]) + channel=instruction.channels[0]) # add samples to pulse library user_pulselib[name] = instruction.command diff --git a/qiskit/circuit/quantumcircuit.py b/qiskit/circuit/quantumcircuit.py index cb3a0f991d72..809afceccdfa 100644 --- a/qiskit/circuit/quantumcircuit.py +++ b/qiskit/circuit/quantumcircuit.py @@ -188,7 +188,7 @@ def mirror(self): reverse_circ = self.copy(name=self.name + '_mirror') reverse_circ._data = [] for inst, qargs, cargs in reversed(self.data): - reverse_circ.append((inst.mirror(), qargs, cargs)) + reverse_circ.append(inst.mirror(), qargs, cargs) return reverse_circ def inverse(self): @@ -234,7 +234,7 @@ def combine(self, rhs): combined_cregs.append(element) circuit = QuantumCircuit(*combined_qregs, *combined_cregs) for instruction_context in itertools.chain(self.data, rhs.data): - circuit.append(*instruction_context) + circuit._append(*instruction_context) return circuit def extend(self, rhs): @@ -261,7 +261,7 @@ def extend(self, rhs): # Add new gates for instruction_context in rhs.data: - self.append(*instruction_context) + self._append(*instruction_context) return self @property diff --git a/qiskit/compiler/transpile.py b/qiskit/compiler/transpile.py index aa14d3ffeaa0..2fcacc993d54 100644 --- a/qiskit/compiler/transpile.py +++ b/qiskit/compiler/transpile.py @@ -24,6 +24,7 @@ from qiskit.circuit.quantumregister import Qubit from qiskit import user_config from qiskit.transpiler.exceptions import TranspilerError +from qiskit.converters import isinstanceint, isinstancelist def transpile(circuits, @@ -330,13 +331,17 @@ def _parse_initial_layout(initial_layout, circuits): # initial_layout could be None, or a list of ints, e.g. [0, 5, 14] # or a list of tuples/None e.g. [qr[0], None, qr[1]] or a dict e.g. {qr[0]: 0} def _layout_from_raw(initial_layout, circuit): - if isinstance(initial_layout, list): - if all(isinstance(elem, int) for elem in initial_layout): + if initial_layout is None or isinstance(initial_layout, Layout): + return initial_layout + elif isinstancelist(initial_layout): + if all(isinstanceint(elem) for elem in initial_layout): initial_layout = Layout.from_intlist(initial_layout, *circuit.qregs) elif all(elem is None or isinstance(elem, Qubit) for elem in initial_layout): initial_layout = Layout.from_qubit_list(initial_layout) elif isinstance(initial_layout, dict): initial_layout = Layout(initial_layout) + else: + raise TranspilerError("The initial_layout parameter could not be parsed") return initial_layout # multiple layouts? diff --git a/qiskit/converters/__init__.py b/qiskit/converters/__init__.py index 2c3fa89968f5..ca668d3a2d0a 100644 --- a/qiskit/converters/__init__.py +++ b/qiskit/converters/__init__.py @@ -21,3 +21,25 @@ from .dag_to_circuit import dag_to_circuit from .ast_to_dag import ast_to_dag from .circuit_to_instruction import circuit_to_instruction + + +def isinstanceint(obj): + """ Like isinstance(obj,int), but with casting. Except for strings.""" + if isinstance(obj, str): + return False + try: + int(obj) + return True + except TypeError: + return False + + +def isinstancelist(obj): + """ Like isinstance(obj, list), but with casting. Except for strings and dicts.""" + if isinstance(obj, (str, dict)): + return False + try: + list(obj) + return True + except TypeError: + return False diff --git a/qiskit/pulse/__init__.py b/qiskit/pulse/__init__.py index 5ff47d933519..87ed22e580f9 100644 --- a/qiskit/pulse/__init__.py +++ b/qiskit/pulse/__init__.py @@ -24,5 +24,4 @@ from .configuration import LoConfig, LoRange from .exceptions import PulseError from .interfaces import ScheduleComponent -# from .parser import parse_string_expr from .schedule import Schedule diff --git a/qiskit/pulse/commands/sample_pulse.py b/qiskit/pulse/commands/sample_pulse.py index ca3240bb7bf0..cbecdc361039 100644 --- a/qiskit/pulse/commands/sample_pulse.py +++ b/qiskit/pulse/commands/sample_pulse.py @@ -55,7 +55,7 @@ def samples(self): """Return sample values.""" return self._samples - def _clip(self, samples: np.ndarray, epsilon: float = 1e-6): + def _clip(self, samples: np.ndarray, epsilon: float = 1e-5): """If samples are within epsilon of unit norm, clip sample by reducing norm by (1-epsilon). If difference is greater than epsilon error is raised. @@ -86,8 +86,10 @@ def _clip(self, samples: np.ndarray, epsilon: float = 1e-6): return samples - def draw(self, dt: float = 1, style: Optional['PulseStyle'] = None, - filename: Optional[str] = None, interp_method: Optional[Callable] = None, + def draw(self, dt: float = 1, + style: Optional['PulseStyle'] = None, + filename: Optional[str] = None, + interp_method: Optional[Callable] = None, scaling: float = 1, interactive: bool = False): """Plot the interpolated envelope of pulse. diff --git a/qiskit/tools/jupyter/backend_monitor.py b/qiskit/tools/jupyter/backend_monitor.py index a1da81bba11f..7d08cf63b9f2 100644 --- a/qiskit/tools/jupyter/backend_monitor.py +++ b/qiskit/tools/jupyter/backend_monitor.py @@ -562,5 +562,4 @@ def get_date(job): ax.add_artist(Circle((0, 0), 0.7, color='white', zorder=1)) ax.text(0, 0, total_jobs, horizontalalignment='center', verticalalignment='center', fontsize=26) - fig.tight_layout() return fig diff --git a/qiskit/transpiler/layout.py b/qiskit/transpiler/layout.py index 4b10e72774a8..8a1143a1a5ff 100644 --- a/qiskit/transpiler/layout.py +++ b/qiskit/transpiler/layout.py @@ -23,6 +23,7 @@ from qiskit.circuit.quantumregister import Qubit from qiskit.transpiler.exceptions import LayoutError +from qiskit.converters import isinstanceint class Layout(): @@ -87,11 +88,11 @@ def from_dict(self, input_dict): @staticmethod def order_based_on_type(value1, value2): """decides which one is physical/virtual based on the type. Returns (virtual, physical)""" - if isinstance(value1, int) and isinstance(value2, (Qubit, type(None))): - physical = value1 + if isinstanceint(value1) and isinstance(value2, (Qubit, type(None))): + physical = int(value1) virtual = value2 - elif isinstance(value2, int) and isinstance(value1, (Qubit, type(None))): - physical = value2 + elif isinstanceint(value2) and isinstance(value1, (Qubit, type(None))): + physical = int(value2) virtual = value1 else: raise LayoutError('The map (%s -> %s) has to be a (Bit -> integer)' @@ -272,7 +273,7 @@ def from_intlist(int_list, *qregs): Raises: LayoutError: Invalid input layout. """ - if not all(isinstance(i, int) for i in int_list): + if not all(isinstanceint(i) for i in int_list): raise LayoutError('Expected a list of ints') if len(int_list) != len(set(int_list)): raise LayoutError('Duplicate values not permitted; Layout is bijective.') diff --git a/qiskit/visualization/circuit_visualization.py b/qiskit/visualization/circuit_visualization.py index 8b304d9fc9b6..d0e320622446 100644 --- a/qiskit/visualization/circuit_visualization.py +++ b/qiskit/visualization/circuit_visualization.py @@ -225,7 +225,7 @@ def circuit_drawer(circuit, return _text_circuit_drawer(circuit, filename=filename, line_length=line_length, reverse_bits=reverse_bits, - plotbarriers=plot_barriers, + plot_barriers=plot_barriers, justify=justify, vertical_compression=vertical_compression, idle_wires=idle_wires, @@ -327,7 +327,6 @@ def qx_color_scheme(): "latexdrawerstyle": True, "usepiformat": False, "cregbundle": False, - "plotbarrier": False, "showindex": False, "compress": True, "margin": [2.0, 0.0, 0.0, 0.3], @@ -342,7 +341,7 @@ def qx_color_scheme(): def _text_circuit_drawer(circuit, filename=None, line_length=None, reverse_bits=False, - plotbarriers=True, justify=None, vertical_compression='high', + plot_barriers=True, justify=None, vertical_compression='high', idle_wires=True, with_layout=True): """ Draws a circuit using ascii art. @@ -355,7 +354,7 @@ def _text_circuit_drawer(circuit, filename=None, line_length=None, reverse_bits= shutil.get_terminal_size(). If you don't want pagination at all, set line_length=-1. reverse_bits (bool): Rearrange the bits in reverse order. - plotbarriers (bool): Draws the barriers when they are there. + plot_barriers (bool): Draws the barriers when they are there. justify (str) : `left`, `right` or `none`. Defaults to `left`. Says how the circuit should be justified. vertical_compression (string): `high`, `medium`, or `low`. It merges the @@ -375,7 +374,7 @@ def _text_circuit_drawer(circuit, filename=None, line_length=None, reverse_bits= else: layout = None text_drawing = _text.TextDrawing(qregs, cregs, ops, layout=layout) - text_drawing.plotbarriers = plotbarriers + text_drawing.plotbarriers = plot_barriers text_drawing.line_length = line_length text_drawing.vertical_compression = vertical_compression diff --git a/qiskit/visualization/gate_map.py b/qiskit/visualization/gate_map.py index c5bc859866a6..cbb826ec2d22 100644 --- a/qiskit/visualization/gate_map.py +++ b/qiskit/visualization/gate_map.py @@ -128,6 +128,21 @@ def plot_gate_map(backend, figsize=None, mpl_data[5] = [[1, 0], [0, 1], [1, 1], [1, 2], [2, 1]] + mpl_data[53] = [[0, 2], [0, 3], [0, 4], [0, 5], [0, 6], + [1, 2], [1, 6], + [2, 0], [2, 1], [2, 2], [2, 3], [2, 4], + [2, 5], [2, 6], [2, 7], [2, 8], + [3, 0], [3, 4], [3, 8], + [4, 0], [4, 1], [4, 2], [4, 3], [4, 4], + [4, 5], [4, 6], [4, 7], [4, 8], + [5, 2], [5, 6], + [6, 0], [6, 1], [6, 2], [6, 3], [6, 4], + [6, 5], [6, 6], [6, 7], [6, 8], + [7, 0], [7, 4], [7, 8], + [8, 0], [8, 1], [8, 2], [8, 3], [8, 4], + [8, 5], [8, 6], [8, 7], [8, 8], + [9, 2], [9, 6]] + config = backend.configuration() n_qubits = config.n_qubits cmap = config.coupling_map @@ -161,7 +176,6 @@ def plot_gate_map(backend, figsize=None, if ax is None: fig, ax = plt.subplots(figsize=figsize) # pylint: disable=invalid-name ax.axis('off') - fig.set_tight_layout(True) # set coloring if qubit_color is None: diff --git a/qiskit/visualization/latex.py b/qiskit/visualization/latex.py index c4abde54f2fa..3b34bcfb8522 100644 --- a/qiskit/visualization/latex.py +++ b/qiskit/visualization/latex.py @@ -721,15 +721,24 @@ def _build_latex_array(self, aliases=None): if self.plot_barriers: qarglist = op.qargs indexes = [self._get_qubit_index(x) for x in qarglist] - start_bit = self.qubit_list[min(indexes)] + indexes.sort() if aliases is not None: qarglist = map(lambda x: aliases[x], qarglist) - start = self.img_regs[start_bit] - span = len(op.qargs) - 1 - self._latex[start][column - 1] += " \\barrier[0em]{" + str( - span) + "}" - self._latex[start][column] = "\\qw" + first = last = indexes[0] + for index in indexes[1:]: + if index - 1 == last: + last = index + else: + pos = self.img_regs[self.qubit_list[first]] + self._latex[pos][column - 1] += " \\barrier[0em]{" + str( + last - first) + "}" + self._latex[pos][column] = "\\qw" + first = last = index + pos = self.img_regs[self.qubit_list[first]] + self._latex[pos][column - 1] += " \\barrier[0em]{" + str( + last - first) + "}" + self._latex[pos][column] = "\\qw" else: raise exceptions.VisualizationError("bad node data") diff --git a/qiskit/visualization/matplotlib.py b/qiskit/visualization/matplotlib.py index 6c43743aeed3..9a59a8213a5e 100644 --- a/qiskit/visualization/matplotlib.py +++ b/qiskit/visualization/matplotlib.py @@ -168,11 +168,14 @@ def _registers(self, creg, qreg): def ast(self): return self._ast - def _custom_multiqubit_gate(self, xy, fc=None, wide=True, text=None, + def _custom_multiqubit_gate(self, xy, cxy=None, fc=None, wide=True, text=None, subtext=None): xpos = min([x[0] for x in xy]) ypos = min([y[1] for y in xy]) ypos_max = max([y[1] for y in xy]) + + if cxy: + ypos = min([y[1] for y in cxy]) if wide: if subtext: boxes_length = round(max([len(text), len(subtext)]) / 8) or 1 @@ -186,7 +189,10 @@ def _custom_multiqubit_gate(self, xy, fc=None, wide=True, text=None, _fc = fc else: if self._style.name != 'bw': - _fc = self._style.dispcol['multi'] + if self._style.gc != DefaultStyle().gc: + _fc = self._style.gc + else: + _fc = self._style.dispcol['multi'] _ec = self._style.dispcol['multi'] else: _fc = self._style.gc @@ -239,6 +245,8 @@ def _gate(self, xy, fc=None, wide=False, text=None, subtext=None): wid = WID if fc: _fc = fc + elif self._style.gc != DefaultStyle().gc: + _fc = self._style.gc elif text and text in self._style.dispcol: _fc = self._style.dispcol[text] else: @@ -383,6 +391,9 @@ def _conds(self, xy, istrue=False): self.ax.add_patch(box) def _ctrl_qubit(self, xy, fc=None, ec=None): + if self._style.gc != DefaultStyle().gc: + fc = self._style.gc + ec = self._style.gc if fc is None: fc = self._style.lc if ec is None: @@ -395,6 +406,9 @@ def _ctrl_qubit(self, xy, fc=None, ec=None): def _tgt_qubit(self, xy, fc=None, ec=None, ac=None, add_width=None): + if self._style.gc != DefaultStyle().gc: + fc = self._style.gc + ec = self._style.gc if fc is None: fc = self._style.dispcol['target'] if ec is None: @@ -873,7 +887,7 @@ def _draw_ops(self, verbose=False): self._line(qreg_b, qreg_t, lc=self._style.dispcol['swap']) # Custom gate else: - self._custom_multiqubit_gate(q_xy, wide=_iswide, + self._custom_multiqubit_gate(q_xy, c_xy, wide=_iswide, text=op.name) # # draw multi-qubit gates (n=3) @@ -906,12 +920,12 @@ def _draw_ops(self, verbose=False): self._line(qreg_b, qreg_t, lc=self._style.dispcol['multi']) # custom gate else: - self._custom_multiqubit_gate(q_xy, wide=_iswide, + self._custom_multiqubit_gate(q_xy, c_xy, wide=_iswide, text=op.name) # draw custom multi-qubit gate elif len(q_xy) > 3: - self._custom_multiqubit_gate(q_xy, wide=_iswide, + self._custom_multiqubit_gate(q_xy, c_xy, wide=_iswide, text=op.name) else: logger.critical('Invalid gate %s', op) diff --git a/qiskit/visualization/qcstyle.py b/qiskit/visualization/qcstyle.py index 64c6239342c8..f5beafdde21b 100644 --- a/qiskit/visualization/qcstyle.py +++ b/qiskit/visualization/qcstyle.py @@ -14,10 +14,14 @@ # pylint: disable=invalid-name,missing-docstring +from copy import copy +from warnings import warn + class DefaultStyle: """IBM Design Style colors """ + def __init__(self): # Set colors basis_color = '#FA74A6' @@ -88,37 +92,39 @@ def __init__(self): self.latexmode = False self.fold = 25 self.bundle = True - self.barrier = True self.index = False self.figwidth = -1 self.dpi = 150 self.margin = [2.0, 0.1, 0.1, 0.3] self.cline = 'doublet' - def set_style(self, dic): - self.tc = dic.get('textcolor', self.tc) - self.sc = dic.get('subtextcolor', self.sc) - self.lc = dic.get('linecolor', self.lc) - self.cc = dic.get('creglinecolor', self.cc) - self.gt = dic.get('gatetextcolor', self.tc) - self.gc = dic.get('gatefacecolor', self.gc) - self.bc = dic.get('barrierfacecolor', self.bc) - self.bg = dic.get('backgroundcolor', self.bg) - self.fs = dic.get('fontsize', self.fs) - self.sfs = dic.get('subfontsize', self.sfs) - self.disptex = dic.get('displaytext', self.disptex) - self.dispcol = dic.get('displaycolor', self.dispcol) - self.latexmode = dic.get('latexdrawerstyle', self.latexmode) - self.fold = dic.get('fold', self.fold) + def set_style(self, style_dic): + dic = copy(style_dic) + self.tc = dic.pop('textcolor', self.tc) + self.sc = dic.pop('subtextcolor', self.sc) + self.lc = dic.pop('linecolor', self.lc) + self.cc = dic.pop('creglinecolor', self.cc) + self.gt = dic.pop('gatetextcolor', self.tc) + self.gc = dic.pop('gatefacecolor', self.gc) + self.bc = dic.pop('barrierfacecolor', self.bc) + self.bg = dic.pop('backgroundcolor', self.bg) + self.fs = dic.pop('fontsize', self.fs) + self.sfs = dic.pop('subfontsize', self.sfs) + self.disptex = dic.pop('displaytext', self.disptex) + self.dispcol = dic.pop('displaycolor', self.dispcol) + self.latexmode = dic.pop('latexdrawerstyle', self.latexmode) + self.fold = dic.pop('fold', self.fold) if self.fold < 2: self.fold = -1 - self.bundle = dic.get('cregbundle', self.bundle) - self.barrier = dic.get('plotbarrier', self.barrier) - self.index = dic.get('showindex', self.index) - self.figwidth = dic.get('figwidth', self.figwidth) - self.dpi = dic.get('dpi', self.dpi) - self.margin = dic.get('margin', self.margin) - self.cline = dic.get('creglinestyle', self.cline) + self.bundle = dic.pop('cregbundle', self.bundle) + self.index = dic.pop('showindex', self.index) + self.figwidth = dic.pop('figwidth', self.figwidth) + self.dpi = dic.pop('dpi', self.dpi) + self.margin = dic.pop('margin', self.margin) + self.cline = dic.pop('creglinestyle', self.cline) + if dic: + warn('style option/s ({}) is/are not ' + 'supported'.format(', '.join(dic.keys())), DeprecationWarning, 2) class BWStyle: @@ -184,36 +190,38 @@ def __init__(self): self.latexmode = False self.fold = 25 self.bundle = True - self.barrier = True self.index = False self.figwidth = -1 self.dpi = 150 self.margin = [2.0, 0.0, 0.0, 0.3] self.cline = 'doublet' - def set_style(self, dic): - self.tc = dic.get('textcolor', self.tc) - self.sc = dic.get('subtextcolor', self.sc) - self.lc = dic.get('linecolor', self.lc) - self.cc = dic.get('creglinecolor', self.cc) - self.gt = dic.get('gatetextcolor', self.tc) - self.gc = dic.get('gatefacecolor', self.gc) - self.bc = dic.get('barrierfacecolor', self.bc) - self.bg = dic.get('backgroundcolor', self.bg) - self.fs = dic.get('fontsize', self.fs) - self.sfs = dic.get('subfontsize', self.sfs) - self.disptex = dic.get('displaytext', self.disptex) + def set_style(self, style_dic): + dic = copy(style_dic) + self.tc = dic.pop('textcolor', self.tc) + self.sc = dic.pop('subtextcolor', self.sc) + self.lc = dic.pop('linecolor', self.lc) + self.cc = dic.pop('creglinecolor', self.cc) + self.gt = dic.pop('gatetextcolor', self.tc) + self.gc = dic.pop('gatefacecolor', self.gc) + self.bc = dic.pop('barrierfacecolor', self.bc) + self.bg = dic.pop('backgroundcolor', self.bg) + self.fs = dic.pop('fontsize', self.fs) + self.sfs = dic.pop('subfontsize', self.sfs) + self.disptex = dic.pop('displaytext', self.disptex) for key in self.dispcol.keys(): self.dispcol[key] = self.gc - self.dispcol = dic.get('displaycolor', self.dispcol) - self.latexmode = dic.get('latexdrawerstyle', self.latexmode) - self.fold = dic.get('fold', self.fold) + self.dispcol = dic.pop('displaycolor', self.dispcol) + self.latexmode = dic.pop('latexdrawerstyle', self.latexmode) + self.fold = dic.pop('fold', self.fold) if self.fold < 2: self.fold = -1 - self.bundle = dic.get('cregbundle', self.bundle) - self.barrier = dic.get('plotbarrier', self.barrier) - self.index = dic.get('showindex', self.index) - self.figwidth = dic.get('figwidth', self.figwidth) - self.dpi = dic.get('dpi', self.dpi) - self.margin = dic.get('margin', self.margin) - self.cline = dic.get('creglinestyle', self.cline) + self.bundle = dic.pop('cregbundle', self.bundle) + self.index = dic.pop('showindex', self.index) + self.figwidth = dic.pop('figwidth', self.figwidth) + self.dpi = dic.pop('dpi', self.dpi) + self.margin = dic.pop('margin', self.margin) + self.cline = dic.pop('creglinestyle', self.cline) + if dic: + warn('style option/s ({}) is/are not ' + 'supported'.format(', '.join(dic.keys())), DeprecationWarning, 2) diff --git a/qiskit/visualization/state_visualization.py b/qiskit/visualization/state_visualization.py index e8c39be00c9e..0b613aeaaa81 100644 --- a/qiskit/visualization/state_visualization.py +++ b/qiskit/visualization/state_visualization.py @@ -104,7 +104,7 @@ def plot_state_hinton(rho, title='', figsize=None): ax1.set_xticklabels(column_names, fontsize=14, rotation=90) ax1.autoscale_view() ax1.invert_yaxis() - ax1.set_title('Real[rho]', fontsize=14) + ax1.set_title('Re[$\\rho$]', fontsize=14) # Imaginary ax2.patch.set_facecolor('gray') ax2.set_aspect('equal', 'box') @@ -117,17 +117,17 @@ def plot_state_hinton(rho, title='', figsize=None): rect = plt.Rectangle([x - size / 2, y - size / 2], size, size, facecolor=color, edgecolor=color) ax2.add_patch(rect) - if np.any(dataimag != 0): - ax2.set_xticks(np.arange(0, lx+0.5, 1)) - ax2.set_yticks(np.arange(0, ly+0.5, 1)) - ax2.set_yticklabels(row_names, fontsize=14) - ax2.set_xticklabels(column_names, fontsize=14, rotation=90) + + ax2.set_xticks(np.arange(0, lx+0.5, 1)) + ax2.set_yticks(np.arange(0, ly+0.5, 1)) + ax2.set_yticklabels(row_names, fontsize=14) + ax2.set_xticklabels(column_names, fontsize=14, rotation=90) + ax2.autoscale_view() ax2.invert_yaxis() - ax2.set_title('Imag[rho]', fontsize=14) + ax2.set_title('Im[$\\rho$]', fontsize=14) if title: fig.suptitle(title, fontsize=16) - plt.tight_layout() if get_backend() in ['module://ipykernel.pylab.backend_inline', 'nbAgg']: plt.close(fig) @@ -353,7 +353,6 @@ def plot_state_city(rho, title="", figsize=None, color=None, for tick in ax2.zaxis.get_major_ticks(): tick.label.set_fontsize(14) plt.suptitle(title, fontsize=16) - plt.tight_layout() if get_backend() in ['module://ipykernel.pylab.backend_inline', 'nbAgg']: plt.close(fig) @@ -636,7 +635,6 @@ def plot_state_qsphere(rho, figsize=None): ax2.text(0, -offset, r'$3\pi/2$', horizontalalignment='center', verticalalignment='center', fontsize=14) - fig.tight_layout() if get_backend() in ['module://ipykernel.pylab.backend_inline', 'nbAgg']: plt.close(fig) diff --git a/qiskit/visualization/utils.py b/qiskit/visualization/utils.py index 728903b71df7..2b5ee02861b2 100644 --- a/qiskit/visualization/utils.py +++ b/qiskit/visualization/utils.py @@ -64,7 +64,8 @@ def _trim(image): return image -def _get_layered_instructions(circuit, reverse_bits=False, justify=None, idle_wires=True): +def _get_layered_instructions(circuit, reverse_bits=False, + justify=None, idle_wires=True): """ Given a circuit, return a tuple (qregs, cregs, ops) where qregs and cregs are the quantum and classical registers @@ -95,89 +96,8 @@ def _get_layered_instructions(circuit, reverse_bits=False, justify=None, idle_wi for node in dag.topological_op_nodes(): ops.append([node]) - if justify == 'left': - for dag_layer in dag.layers(): - layers = [] - current_layer = [] - - dag_nodes = dag_layer['graph'].op_nodes() - dag_nodes.sort(key=lambda nd: nd._node_id) - - for node in dag_nodes: - multibit_gate = len(node.qargs) + len(node.cargs) > 1 - - if multibit_gate: - # need to see if it crosses over any other nodes - gate_span = _get_gate_span(qregs, node) - - all_indices = [] - for check_node in dag_nodes: - if check_node != node: - all_indices += _get_gate_span(qregs, check_node) - - if any(i in gate_span for i in all_indices): - # needs to be a new layer - layers.append([node]) - else: - # can be added - current_layer.append(node) - else: - current_layer.append(node) - - if current_layer: - layers.append(current_layer) - ops += layers - - if justify == 'right': - dag_layers = [] - - for dag_layer in dag.layers(): - dag_layers.append(dag_layer) - - # Have to work from the end of the circuit - dag_layers.reverse() - - # Dict per layer, keys are qubits and values are the gate - layer_dicts = [{}] - - for dag_layer in dag_layers: - - dag_instructions = dag_layer['graph'].op_nodes() - - # sort into the order they were input - dag_instructions.sort(key=lambda nd: nd._node_id) - for instruction_node in dag_instructions: - - gate_span = _get_gate_span(qregs, instruction_node) - - added = False - for i in range(len(layer_dicts)): - # iterate from the end - curr_dict = layer_dicts[-1 - i] - - if any(index in curr_dict for index in gate_span): - added = True - - if i == 0: - new_dict = {} - - for index in gate_span: - new_dict[index] = instruction_node - layer_dicts.append(new_dict) - else: - curr_dict = layer_dicts[-i] - for index in gate_span: - curr_dict[index] = instruction_node - - break - - if not added: - for index in gate_span: - layer_dicts[0][index] = instruction_node - - # need to convert from dict format to layers - layer_dicts.reverse() - ops = [list(layer.values()) for layer in layer_dicts] + else: + ops = _LayerSpooler(dag, justify) if reverse_bits: qregs.reverse() @@ -193,9 +113,20 @@ def _get_layered_instructions(circuit, reverse_bits=False, justify=None, idle_wi return qregs, cregs, ops -def _get_gate_span(qregs, instruction): - """Get the list of qubits drawing this gate would cover""" +def _sorted_nodes(dag_layer): + """Convert DAG layer into list of nodes sorted by node_id + qiskit-terra #2802 + """ + dag_instructions = dag_layer['graph'].op_nodes() + # sort into the order they were input + dag_instructions.sort(key=lambda nd: nd._node_id) + return dag_instructions + +def _get_gate_span(qregs, instruction): + """Get the list of qubits drawing this gate would cover + qiskit-terra #2802 + """ min_index = len(qregs) max_index = 0 for qreg in instruction.qargs: @@ -208,5 +139,139 @@ def _get_gate_span(qregs, instruction): if instruction.cargs: return qregs[min_index:] + if instruction.condition: + return qregs[min_index:] return qregs[min_index:max_index + 1] + + +def _any_crossover(qregs, node, nodes): + """Return True .IFF. 'node' crosses over any in 'nodes',""" + gate_span = _get_gate_span(qregs, node) + all_indices = [] + for check_node in nodes: + if check_node != node: + all_indices += _get_gate_span(qregs, check_node) + return any(i in gate_span for i in all_indices) + + +class _LayerSpooler(list): + """Manipulate list of layer dicts for _get_layered_instructions.""" + + def __init__(self, dag, justification): + """Create spool""" + super(_LayerSpooler, self).__init__() + self.dag = dag + self.qregs = dag.qubits() + self.justification = justification + + if self.justification == 'left': + + for dag_layer in dag.layers(): + current_index = len(self) - 1 + dag_nodes = _sorted_nodes(dag_layer) + for node in dag_nodes: + self.add(node, current_index) + + else: + dag_layers = [] + + for dag_layer in dag.layers(): + dag_layers.append(dag_layer) + + # going right to left! + dag_layers.reverse() + + for dag_layer in dag_layers: + current_index = 0 + dag_nodes = _sorted_nodes(dag_layer) + for node in dag_nodes: + self.add(node, current_index) + + def is_found_in(self, node, nodes): + """Is any qreq in node found in any of nodes?""" + all_qargs = [] + for a_node in nodes: + for qarg in a_node.qargs: + all_qargs.append(qarg) + return any(i in node.qargs for i in all_qargs) + + def insertable(self, node, nodes): + """True .IFF. we can add 'node' to layer 'nodes'""" + return not _any_crossover(self.qregs, node, nodes) + + def slide_from_left(self, node, index): + """Insert node into first layer where there is no conflict going l > r""" + if not self: + self.append([node]) + inserted = True + + else: + inserted = False + curr_index = index + last_insertable_index = None + + while curr_index > -1: + if self.is_found_in(node, self[curr_index]): + break + if self.insertable(node, self[curr_index]): + last_insertable_index = curr_index + curr_index = curr_index - 1 + + if last_insertable_index: + self[last_insertable_index].append(node) + inserted = True + + else: + inserted = False + curr_index = index + while curr_index < len(self): + if self.insertable(node, self[curr_index]): + self[curr_index].append(node) + inserted = True + break + curr_index = curr_index + 1 + + if not inserted: + self.append([node]) + + def slide_from_right(self, node, index): + """Insert node into rightmost layer as long there is no conflict.""" + if not self: + self.insert(0, [node]) + inserted = True + + else: + inserted = False + curr_index = index + last_insertable_index = None + + while curr_index < len(self): + if self.is_found_in(node, self[curr_index]): + break + if self.insertable(node, self[curr_index]): + last_insertable_index = curr_index + curr_index = curr_index + 1 + + if last_insertable_index: + self[last_insertable_index].append(node) + inserted = True + + else: + curr_index = index + while curr_index > -1: + if self.insertable(node, self[curr_index]): + self[curr_index].append(node) + inserted = True + break + curr_index = curr_index - 1 + + if not inserted: + self.insert(0, [node]) + + def add(self, node, index): + """Add 'node' where it belongs, starting the try at 'index'.""" + if self.justification == "left": + self.slide_from_left(node, index) + else: + self.slide_from_right(node, index) diff --git a/releasenotes/notes/Instruction-layering-for-circuit-drawing-has-changed-f62ce5aaeb8ce221.yaml b/releasenotes/notes/Instruction-layering-for-circuit-drawing-has-changed-f62ce5aaeb8ce221.yaml new file mode 100644 index 000000000000..4a16dcf8313f --- /dev/null +++ b/releasenotes/notes/Instruction-layering-for-circuit-drawing-has-changed-f62ce5aaeb8ce221.yaml @@ -0,0 +1,8 @@ +--- +fixes: + - | + Instructions layering which underlies all types of circuit drawing has + changed to address right/left justification. This sometimes results in + output which is topologically equivalent to the rendering in prior versions + but visually different than previously rendered. The change in layering + fixes qiskit-terra issue \#2802 diff --git a/releasenotes/notes/deprecate_unknown_styles-93f84aedd1887c44.yaml b/releasenotes/notes/deprecate_unknown_styles-93f84aedd1887c44.yaml new file mode 100644 index 000000000000..7ada0d9f524c --- /dev/null +++ b/releasenotes/notes/deprecate_unknown_styles-93f84aedd1887c44.yaml @@ -0,0 +1,6 @@ +--- +deprecations: + - | + The matplotlib drawer raises a warning when the `style` argument dictonary includes + a key that is not supported by the drawer. In the future, unsupported keys will raise + an exception. diff --git a/test/python/circuit/test_circuit_operations.py b/test/python/circuit/test_circuit_operations.py index 24e5001953d8..a54fc4f23313 100644 --- a/test/python/circuit/test_circuit_operations.py +++ b/test/python/circuit/test_circuit_operations.py @@ -158,6 +158,26 @@ def test_copy_circuit(self): self.assertEqual(qc, qc.copy()) + def test_mirror(self): + """Test mirror method reverses but does not invert.""" + qc = QuantumCircuit(2, 2) + qc.h(0) + qc.s(1) + qc.cx(0, 1) + qc.measure([0, 1], [0, 1]) + qc.x(0) + qc.y(1) + + expected = QuantumCircuit(2, 2) + expected.y(1) + expected.x(0) + expected.measure([0, 1], [0, 1]) + expected.cx(0, 1) + expected.s(1) + expected.h(0) + + self.assertEqual(qc.mirror(), expected) + class TestCircuitBuilding(QiskitTestCase): """QuantumCircuit tests.""" diff --git a/test/python/transpiler/test_layout.py b/test/python/transpiler/test_layout.py index 95d90f98acd3..cd8b99bc88d5 100644 --- a/test/python/transpiler/test_layout.py +++ b/test/python/transpiler/test_layout.py @@ -17,6 +17,7 @@ import copy import unittest import warnings +import numpy from qiskit.circuit import QuantumRegister, Qubit from qiskit.transpiler.layout import Layout @@ -325,6 +326,19 @@ def test_layout_from_intlist(self): self.assertDictEqual(layout._p2v, expected._p2v) self.assertDictEqual(layout._v2p, expected._v2p) + def test_layout_from_intlist_numpy(self): + """Create a layout from a list of numpy integers. See #3097 + """ + qr1 = QuantumRegister(1, 'qr1') + qr2 = QuantumRegister(2, 'qr2') + qr3 = QuantumRegister(3, 'qr3') + intlist_layout = numpy.array([0, 1, 2, 3, 4, 5]) + layout = Layout.from_intlist(intlist_layout, qr1, qr2, qr3) + + expected = Layout.generate_trivial_layout(qr1, qr2, qr3) + self.assertDictEqual(layout._p2v, expected._p2v) + self.assertDictEqual(layout._v2p, expected._v2p) + def test_layout_from_intlist_short(self): """If the intlist is longer that your quantum register, map them to None. virtual physical diff --git a/test/python/visualization/test_circuit_matplotlib_drawer.py b/test/python/visualization/test_circuit_matplotlib_drawer.py index f38b92a6eb82..279b45564c04 100644 --- a/test/python/visualization/test_circuit_matplotlib_drawer.py +++ b/test/python/visualization/test_circuit_matplotlib_drawer.py @@ -132,7 +132,7 @@ def test_long_name(self): filename = self._get_resource_path('current_%s_long_name_matplotlib.png' % os.name) visualization.circuit_drawer(circuit, output='mpl', filename=filename) - # self.addCleanup(os.remove, filename) + self.addCleanup(os.remove, filename) ref_filename = self._get_resource_path( 'visualization/references/%s_long_name_matplotlib.png' % os.name) diff --git a/test/python/visualization/test_circuit_text_drawer.py b/test/python/visualization/test_circuit_text_drawer.py index fc1ef42c09fb..cb7c0726a2eb 100644 --- a/test/python/visualization/test_circuit_text_drawer.py +++ b/test/python/visualization/test_circuit_text_drawer.py @@ -536,7 +536,7 @@ def test_text_no_barriers(self): circuit.barrier(qr1) circuit.barrier(qr2[1]) circuit.h(qr2) - self.assertEqual(str(_text_circuit_drawer(circuit, plotbarriers=False)), expected) + self.assertEqual(str(_text_circuit_drawer(circuit, plot_barriers=False)), expected) def test_text_measure_html(self): """ The measure operator. HTML representation. """ diff --git a/test/python/visualization/test_visualization.py b/test/python/visualization/test_visualization.py index 640797e5e7b5..f798f929cb2e 100644 --- a/test/python/visualization/test_visualization.py +++ b/test/python/visualization/test_visualization.py @@ -19,6 +19,7 @@ import unittest from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit +from qiskit.circuit import Qubit, Clbit from qiskit.circuit.random import random_circuit from qiskit.visualization import utils from qiskit.visualization import circuit_drawer @@ -209,6 +210,178 @@ def test_get_layered_instructions_remove_idle_wires(self): self.assertEqual(exp, [[(op.name, op.qargs, op.cargs) for op in ops] for ops in layered_ops]) + def test_get_layered_instructions_left_justification_simple(self): + """ Test _get_layered_instructions left justification simple since #2802 +q_0: |0>───────■── + ┌───┐ │ +q_1: |0>┤ H ├──┼── + ├───┤ │ +q_2: |0>┤ H ├──┼── + └───┘┌─┴─┐ +q_3: |0>─────┤ X ├ + └───┘ +""" + qc = QuantumCircuit(4) + qc.h(1) + qc.h(2) + qc.cx(0, 3) + + (_, _, layered_ops) = utils._get_layered_instructions(qc, justify='left') + + l_exp = [[('h', [Qubit(QuantumRegister(4, 'q'), 1)], []), + ('h', [Qubit(QuantumRegister(4, 'q'), 2)], [])], + [('cx', [Qubit(QuantumRegister(4, 'q'), 0), + Qubit(QuantumRegister(4, 'q'), 3)], []) + ] + ] + + self.assertEqual(l_exp, + [[(op.name, op.qargs, op.cargs) for op in ops] for ops in layered_ops]) + + def test_get_layered_instructions_right_justification_simple(self): + """ Test _get_layered_instructions right justification simple since #2802 +q_0: |0>──■─────── + │ ┌───┐ +q_1: |0>──┼──┤ H ├ + │ ├───┤ +q_2: |0>──┼──┤ H ├ + ┌─┴─┐└───┘ +q_3: |0>┤ X ├───── + └───┘ +""" + qc = QuantumCircuit(4) + qc.h(1) + qc.h(2) + qc.cx(0, 3) + + (_, _, layered_ops) = utils._get_layered_instructions(qc, justify='right') + + r_exp = [[('cx', [Qubit(QuantumRegister(4, 'q'), 0), + Qubit(QuantumRegister(4, 'q'), 3)], [])], + [('h', [Qubit(QuantumRegister(4, 'q'), 1)], []), + ('h', [Qubit(QuantumRegister(4, 'q'), 2)], []) + ] + ] + + self.assertEqual(r_exp, + [[(op.name, op.qargs, op.cargs) for op in ops] for ops in layered_ops]) + + def test_get_layered_instructions_left_justification_less_simple(self): + """ Test _get_layered_instructions left justification + less simple example since #2802 + ┌────────────┐┌───┐┌────────────┐ ┌─┐┌────────────┐┌───┐┌────────────┐ +q_0: |0>┤ U2(0,pi/1) ├┤ X ├┤ U2(0,pi/1) ├──────────────┤M├┤ U2(0,pi/1) ├┤ X ├┤ U2(0,pi/1) ├ + ├────────────┤└─┬─┘├────────────┤┌────────────┐└╥┘└────────────┘└─┬─┘├────────────┤ +q_1: |0>┤ U2(0,pi/1) ├──■──┤ U2(0,pi/1) ├┤ U2(0,pi/1) ├─╫─────────────────■──┤ U2(0,pi/1) ├ + └────────────┘ └────────────┘└────────────┘ ║ └────────────┘ +q_2: |0>────────────────────────────────────────────────╫────────────────────────────────── + ║ +q_3: |0>────────────────────────────────────────────────╫────────────────────────────────── + ║ +q_4: |0>────────────────────────────────────────────────╫────────────────────────────────── + ║ +c1_0: 0 ════════════════════════════════════════════════╩══════════════════════════════════ + """ + qasm = """ + OPENQASM 2.0; + include "qelib1.inc"; + qreg q[5]; + creg c1[1]; + u2(0,3.14159265358979) q[0]; + u2(0,3.14159265358979) q[1]; + cx q[1],q[0]; + u2(0,3.14159265358979) q[0]; + u2(0,3.14159265358979) q[1]; + u2(0,3.14159265358979) q[1]; + measure q[0] -> c1[0]; + u2(0,3.14159265358979) q[0]; + cx q[1],q[0]; + u2(0,3.14159265358979) q[0]; + u2(0,3.14159265358979) q[1]; + """ + qc = QuantumCircuit.from_qasm_str(qasm) + + (_, _, layered_ops) = utils._get_layered_instructions(qc, justify='left') + + l_exp = [[('u2', [Qubit(QuantumRegister(5, 'q'), 0)], []), + ('u2', [Qubit(QuantumRegister(5, 'q'), 1)], [])], + [('cx', + [Qubit(QuantumRegister(5, 'q'), 1), Qubit(QuantumRegister(5, 'q'), 0)], + [])], + [('u2', [Qubit(QuantumRegister(5, 'q'), 0)], []), + ('u2', [Qubit(QuantumRegister(5, 'q'), 1)], [])], + [('u2', [Qubit(QuantumRegister(5, 'q'), 1)], [])], + [('measure', + [Qubit(QuantumRegister(5, 'q'), 0)], + [Clbit(ClassicalRegister(1, 'c1'), 0)])], + [('u2', [Qubit(QuantumRegister(5, 'q'), 0)], [])], + [('cx', + [Qubit(QuantumRegister(5, 'q'), 1), Qubit(QuantumRegister(5, 'q'), 0)], + [])], + [('u2', [Qubit(QuantumRegister(5, 'q'), 0)], []), + ('u2', [Qubit(QuantumRegister(5, 'q'), 1)], [])]] + + self.assertEqual(l_exp, + [[(op.name, op.qargs, op.cargs) for op in ops] for ops in layered_ops]) + + def test_get_layered_instructions_right_justification_less_simple(self): + """ Test _get_layered_instructions right justification + less simple example since #2802 + ┌────────────┐┌───┐┌────────────┐┌─┐┌────────────┐┌───┐┌────────────┐ +q_0: |0>┤ U2(0,pi/1) ├┤ X ├┤ U2(0,pi/1) ├┤M├┤ U2(0,pi/1) ├┤ X ├┤ U2(0,pi/1) ├ + ├────────────┤└─┬─┘├────────────┤└╥┘├────────────┤└─┬─┘├────────────┤ +q_1: |0>┤ U2(0,pi/1) ├──■──┤ U2(0,pi/1) ├─╫─┤ U2(0,pi/1) ├──■──┤ U2(0,pi/1) ├ + └────────────┘ └────────────┘ ║ └────────────┘ └────────────┘ +q_2: |0>──────────────────────────────────╫────────────────────────────────── + ║ +q_3: |0>──────────────────────────────────╫────────────────────────────────── + ║ +q_4: |0>──────────────────────────────────╫────────────────────────────────── + ║ +c1_0: 0 ══════════════════════════════════╩══════════════════════════════════ + """ + qasm = """ + OPENQASM 2.0; + include "qelib1.inc"; + qreg q[5]; + creg c1[1]; + u2(0,3.14159265358979) q[0]; + u2(0,3.14159265358979) q[1]; + cx q[1],q[0]; + u2(0,3.14159265358979) q[0]; + u2(0,3.14159265358979) q[1]; + u2(0,3.14159265358979) q[1]; + measure q[0] -> c1[0]; + u2(0,3.14159265358979) q[0]; + cx q[1],q[0]; + u2(0,3.14159265358979) q[0]; + u2(0,3.14159265358979) q[1]; + """ + qc = QuantumCircuit.from_qasm_str(qasm) + + (_, _, layered_ops) = utils._get_layered_instructions(qc, justify='right') + + r_exp = [[('u2', [Qubit(QuantumRegister(5, 'q'), 0)], []), + ('u2', [Qubit(QuantumRegister(5, 'q'), 1)], [])], + [('cx', + [Qubit(QuantumRegister(5, 'q'), 1), Qubit(QuantumRegister(5, 'q'), 0)], + [])], + [('u2', [Qubit(QuantumRegister(5, 'q'), 0)], []), + ('u2', [Qubit(QuantumRegister(5, 'q'), 1)], [])], + [('measure', + [Qubit(QuantumRegister(5, 'q'), 0)], + [Clbit(ClassicalRegister(1, 'c1'), 0)])], + [('u2', [Qubit(QuantumRegister(5, 'q'), 0)], []), + ('u2', [Qubit(QuantumRegister(5, 'q'), 1)], [])], + [('cx', + [Qubit(QuantumRegister(5, 'q'), 1), Qubit(QuantumRegister(5, 'q'), 0)], + [])], + [('u2', [Qubit(QuantumRegister(5, 'q'), 0)], []), + ('u2', [Qubit(QuantumRegister(5, 'q'), 1)], [])]] + + self.assertEqual(r_exp, + [[(op.name, op.qargs, op.cargs) for op in ops] for ops in layered_ops]) + if __name__ == '__main__': unittest.main(verbosity=2)