Skip to content

Commit

Permalink
Merge pull request #380 from CQCL/release/1.2.2
Browse files Browse the repository at this point in the history
Release/1.2.2
  • Loading branch information
cqc-alec authored May 23, 2022
2 parents 83c80f4 + 25c94ba commit 28764ea
Show file tree
Hide file tree
Showing 63 changed files with 2,756 additions and 556 deletions.
7 changes: 5 additions & 2 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,20 @@ jobs:
${CONAN_CMD} install recipes/tket-tests --install-folder=build/tket-tests --profile=tket -o tket-tests:with_coverage=True
${CONAN_CMD} build recipes/tket-tests --configure --build-folder=build/tket-tests --source-folder=tket/tests
${CONAN_CMD} build recipes/tket-tests --build --build-folder=build/tket-tests
${CONAN_CMD} package recipes/tket-tests/ --build-folder=build/tket-tests --package-folder build/tket-tests/package --source-folder=tket/tests
- name: Install runtime test requirements
run: |
sudo apt-get install texlive texlive-latex-extra latexmk
mkdir -p ~/texmf/tex/latex
wget http://mirrors.ctan.org/graphics/pgf/contrib/quantikz/tikzlibraryquantikz.code.tex -P ~/texmf/tex/latex
- name: Run tket tests
if: github.event_name == 'pull_request' || github.event_name == 'push'
run: ./build/tket-tests/bin/test_tket
working-directory: ./build/tket-tests/package/bin
run: ./test_tket
- name: Run full tket tests
if: github.event_name == 'schedule'
run: ./build/tket-tests/bin/test_tket "[long],~[long]"
working-directory: ./build/tket-tests/package/bin
run: ./test_tket "[long],~[long]"
- name: Install gcovr
# gcovr 5.0 is incompatible with jinja2 3.1.0
run: pip install jinja2==3.0.3 gcovr==5.0
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,8 @@ jobs:
user: __token__
password: ${{ secrets.PYPI_PYTKET_API_TOKEN }}
verbose: true
# TODO Remove this line when long_description added:
verify_metadata: false

build_docs:
name: Build docs
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/valgrind.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,7 @@ jobs:
conan install recipes/tket-tests --install-folder=build/tket-tests --profile=tket
conan build recipes/tket-tests --configure --build-folder=build/tket-tests --source-folder=tket/tests
conan build recipes/tket-tests --build --build-folder=build/tket-tests
conan package recipes/tket-tests/ --build-folder=build/tket-tests --package-folder build/tket-tests/package --source-folder=tket/tests
- name: run tests under valgrind
run: valgrind --error-exitcode=1 ./build/tket-tests/bin/test_tket
working-directory: ./build/tket-tests/package/bin
run: valgrind --error-exitcode=1 ./test_tket
8 changes: 5 additions & 3 deletions pytket/binders/circuit/Circuit/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,12 @@ void init_circuit(py::module &m) {
py::class_<Circuit, std::shared_ptr<Circuit>> circuit_cls(
m, "Circuit", py::dynamic_attr(),
"Encapsulates a quantum circuit using a DAG representation.\n\n>>> "
"from pytket import Circuit\n>>> c = Circuit(4) # Create a circuit "
"with 4 qubits\n>>> c.H(0) # Apply a gate to qubit 0\n>>> "
"from pytket import Circuit\n>>> c = Circuit(4,2) # Create a circuit "
"with 4 qubits and 2 classical bits"
"\n>>> c.H(0) # Apply a gate to qubit 0\n>>> "
"c.Rx(0.5,1) # Angles of rotation are expressed in half-turns "
"(i.e. 0.5 means PI/2)\n>>> c.Measure(1)");
"(i.e. 0.5 means PI/2)\n>>> c.Measure(1,0) # Measure qubit 1, saving "
"result in bit 0");
init_circuit_add_op(circuit_cls);
init_circuit_add_classical_op(circuit_cls);
circuit_cls
Expand Down
21 changes: 18 additions & 3 deletions pytket/binders/passes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,9 +355,24 @@ PYBIND11_MODULE(passes, m) {
"Converts all multi-qubit gates into CX and single-qubit gates.");
m.def(
"GlobalisePhasedX", &GlobalisePhasedX,
"Replaces every occurence of PhasedX or NPhasedX gates with NPhasedX "
"gates acting on all qubits, and correcting rotation gates, so that the "
"GlobalPhasedXPredicate is satisfied.");
"Turns all PhasedX and NPhasedX gates into global gates\n\n"
"Replaces any PhasedX gates with global NPhasedX gates. "
"By default, this transform will squash all single-qubit gates "
"to PhasedX and Rz gates before proceeding further. "
"Existing non-global NPhasedX will not be preserved. "
"This is the recommended setting for best "
"performance. If squashing is disabled, each non-global PhasedX gate "
"will be replaced with two global NPhasedX, but any other gates will "
"be left untouched."
"\n\n:param squash: Whether to squash the circuit in pre-processing "
"(default: true)."
"\n\nIf squash=true (default), the `GlobalisePhasedX().apply` method "
"will always return true. "
"For squash=false, `apply()` will return true if the circuit was "
"changed and false otherwise.\n\n"
"It is not recommended to use this pass with symbolic expressions, as"
" in certain cases a blow-up in symbolic expression sizes may occur.",
py::arg("squash") = true);
m.def(
"DecomposeSingleQubitsTK1", &DecomposeSingleQubitsTK1,
"Converts all single-qubit gates into TK1 gates.");
Expand Down
35 changes: 26 additions & 9 deletions pytket/binders/transform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,9 @@ PYBIND11_MODULE(transform, m) {
"Rebase single qubit gates into Rz, Rx.")
.def_static(
"RebaseToCliffordSingles", &Transforms::decompose_cliffords_std,
"Identify Clifford-angle rotations (from U1, U2, U3, Rx, "
"Ry, Rz, TK1, PhasedX), replacing them with Z, X, S, V "
"gates. Any non-Clifford rotations will stay as they are.")
"Replace all single-qubit unitary gates outside the set {Z, X, S, V} "
"that are recognized as Clifford operations with an equivalent "
"sequence of gates from that set.")
.def_static(
"RebaseToCirq", &Transforms::rebase_cirq,
"Rebase from any gate set into PhasedX, Rz, CZ.")
Expand Down Expand Up @@ -294,12 +294,29 @@ PYBIND11_MODULE(transform, m) {
"of OpType to single-qubit gate error maps",
py::arg("op_node_errors"))
.def_static(
"GlobalisePhasedX", &Transforms::globalise_phasedx,
"Replaces every occurence of PhasedX or NPhasedX gates with NPhasedX "
"gates acting on all qubits, and correcting rotation gates."
"\n\nThis is achieved using the identity"
"\nPhX(α, β) = PhX(-1/2, β + 1/2) Rz(α) PhX(1/2, β + 1/2)"
"\n(circuit order).")
"DecomposeNPhasedX", &Transforms::decompose_NPhasedX,
"Decompose NPhasedX gates into single-qubit PhasedX gates.")
.def_static(
"GlobalisePhasedX", &Transforms::globalise_PhasedX,
"Turns all PhasedX and NPhasedX gates into global gates\n\n"
"Replaces any PhasedX gates with global NPhasedX gates. "
"By default, this transform will squash all single-qubit gates "
"to PhasedX and Rz gates before proceeding further. "
"Existing non-global NPhasedX will not be preserved. "
"This is the recommended setting for best "
"performance. If squashing is disabled, each non-global PhasedX gate "
"will be replaced with two global NPhasedX, but any other gates will "
"be left untouched."
"\n\n:param squash: Whether to squash the circuit in pre-processing "
"(default: true)."
"\n\nIf squash=true (default), the `GlobalisePhasedX().apply` method "
"will always returns true. "
"For squash=false, `apply()` will return true if the circuit was "
"changed and false otherwise.\n\n"
"It is not recommended to use this transformation with symbolic "
"expressions, as in certain cases a blow-up in symbolic expression "
"sizes may occur.",
py::arg("squash") = true)
.def_static(
"SynthesisePauliGraph", &Transforms::synthesise_pauli_graph,
"Synthesises Pauli Graphs.",
Expand Down
14 changes: 14 additions & 0 deletions pytket/docs/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
Changelog
=========

1.2.2 (May 2022)
----------------

Minor new features:

* The ``GlobalisePhasedX`` transform and homonymous pass take a new optional
``squash`` parameter. ``squash=true`` (default) implements a new algorithm
that significantly reduces the number of ``NPhasedX`` gates synthesised.
* New ``DecomposeNPhasedX`` transform and pass replaces all ``NPhasedX`` gates
with single-qubit ``PhasedX`` gates.
* Extend range of Clifford operations recognized by
``CliffordCircuitPredicate``.

1.2.1 (May 2022)
----------------

Expand All @@ -12,6 +25,7 @@ Minor new features:
* New pass ``SynthesiseTK`` and transform ``OptimiseStandard`` to synthesize
TK2 gates.
* Add ``Optype.WASM``, adding a classical wasm function call to the circuit
* Add optype for existing PhasePolyBox ``OpType.PhasePolyBox``

1.1.0 (April 2022)
------------------
Expand Down
3 changes: 2 additions & 1 deletion pytket/docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@
author = "Cambridge Quantum Computing Ltd"

# The short X.Y version
version = "1.2"
# The full version, including alpha/beta/rc tags
release = "1.2.1"
release = "1.2.2"


# -- General configuration ---------------------------------------------------
Expand Down
49 changes: 49 additions & 0 deletions pytket/package.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Project Description

Pytket is a python module for interfacing with TKET, an optimising compiler for quantum circuits developed by Cambridge Quantum. In addition to pytket there are several extension modules for accessing a range of quantum hardware and classical simulators. The extension modules also provide integration with several widely used quantum software tools.

The source code for the TKET compiler can be found in [this github repository](https://github.com/CQCL/tket).

## Installation

Installation is supported for Linux, MacOS and Windows. Installation requires python 3.8, 3.9 or 3.10.

To install run the pip command:

`` pip install pytket``

See [Installation troubleshooting](https://cqcl.github.io/tket/pytket/api/install.html) for help with installation.

To install the pytket extension modules add a hyphen and the extension name to the command:

`` pip install pytket-quantinuum ``

For a list of pytket extensions see this page: https://cqcl.github.io/pytket-extensions/api/index.html.

## Documentaion and Examples

API reference: https://cqcl.github.io/tket/pytket/api/

To get started using pytket see the [user manual](https://cqcl.github.io/pytket/manual/index.html).

For worked examples using TKET see our [examples repository](https://github.com/CQCL/pytket/tree/main/examples).

## Support and Discussion

For bugs and feature requests we recommend creating an issue on the [github repository](https://github.com/CQCL/tket).

User support: [email protected]

For discussion, join the public slack channel [here](https://join.slack.com/t/tketusers/shared_invite/zt-18qmsamj9-UqQFVdkRzxnXCcKtcarLRA).

Mailing list: join [here](https://list.cambridgequantum.com/cgi-bin/mailman/listinfo/tket-users).

## Citation

If you wish to cite TKET in any academic publications, we generally recommend citing our [software overview](https://arxiv.org/abs/2003.10611) paper for most cases.

If your work is on the topic of specific compilation tasks, it may be more appropriate to cite one of our other papers:

- "On the qubit routing problem" for qubit placement (a.k.a. allocation) and routing (a.k.a. swap network insertion, connectivity solving). https://arxiv.org/abs/1902.08091 .
- "Phase Gadget Synthesis for Shallow Circuits" for representing exponentiated Pauli operators in the ZX calculus and their circuit decompositions. https://arxiv.org/abs/1906.01734 .
- "A Generic Compilation Strategy for the Unitary Coupled Cluster Ansatz" for sequencing of terms in Trotterisation and Pauli diagonalisation. https://arxiv.org/abs/2007.10515 .
6 changes: 4 additions & 2 deletions pytket/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,12 +230,14 @@ def finalize_options(self):

setup(
name="pytket",
author="Seyon Sivarajah",
author_email="seyon.sivarajah@cambridgequantum.com",
author="TKET development team",
author_email="tket-support@cambridgequantum.com",
python_requires=">=3.8",
url="https://cqcl.github.io/tket/pytket/api/",
description="Python module for interfacing with the CQC tket library of quantum "
"software",
long_description=open("package.md", "r").read(),
long_description_content_type="text/markdown",
license="Apache 2",
packages=setuptools.find_packages(),
install_requires=[
Expand Down
2 changes: 1 addition & 1 deletion pytket/tests/transform_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def test_global_phasedx() -> None:
c = Circuit(3).add_gate(OpType.NPhasedX, [0.4, 2.3], [0, 1])
Transform.GlobalisePhasedX().apply(c)
assert c.n_gates_of_type(OpType.NPhasedX) == 2
assert c.n_gates_of_type(OpType.Rz) == 2
assert c.n_gates_of_type(OpType.Rz) == 6


def test_KAK() -> None:
Expand Down
6 changes: 5 additions & 1 deletion recipes/tket-tests/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,8 @@ def package(self):
if platform.system() == "Windows":
executable_filename = executable_filename + ".exe"
self.copy(executable_filename)
self.copy("random_angles.txt", dst="bin", keep_path=False)
self.copy(
os.path.join("test_circuits", "lexiroute_circuit.json"),
dst="bin",
keep_path=False,
)
5 changes: 2 additions & 3 deletions tket/src/Architecture/DistancesFromArchitecture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,8 @@ size_t DistancesFromArchitecture::operator()(size_t vertex1, size_t vertex2) {
distance_entry > 0 ||
AssertMessage() << "DistancesFromArchitecture: architecture has "
<< arch.n_nodes() << " vertices, "
<< arch.n_connections() << " edges; returned diameter "
<< arch.get_diameter() << " and d(" << vertex1 << ","
<< vertex2
<< arch.n_connections() << " edges; "
<< " and d(" << vertex1 << "," << vertex2
<< ")=0. "
"Is the graph connected?");
// GCOVR_EXCL_STOP
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ class SquareGrid : public Architecture {
unsigned layers;
};

typedef std::shared_ptr<const Architecture> ArchitecturePtr;
typedef std::shared_ptr<Architecture> ArchitecturePtr;

int tri_lexicographical_comparison(
const dist_vec &dist1, const dist_vec &dist2);
Expand Down
30 changes: 30 additions & 0 deletions tket/src/Circuit/Boxes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,14 @@

#include "CircUtils.hpp"
#include "Circuit/AssertionSynthesis.hpp"
#include "Command.hpp"
#include "Gate/Rotation.hpp"
#include "Ops/OpJsonFactory.hpp"
#include "Ops/OpPtr.hpp"
#include "ThreeQubitConversion.hpp"
#include "Utils/Assert.hpp"
#include "Utils/EigenConfig.hpp"
#include "Utils/Expression.hpp"
#include "Utils/Json.hpp"
#include "Utils/PauliStrings.hpp"

Expand Down Expand Up @@ -63,6 +67,7 @@ Op_ptr Box::deserialize(const nlohmann::json &j) {
}

CircBox::CircBox(const Circuit &circ) : Box(OpType::CircBox) {
if (!circ.is_simple()) throw SimpleOnly();
signature_ = op_signature_t(circ.n_qubits(), EdgeType::Quantum);
op_signature_t bits(circ.n_bits(), EdgeType::Classical);
signature_.insert(signature_.end(), bits.begin(), bits.end());
Expand All @@ -75,6 +80,13 @@ CircBox::CircBox() : Box(OpType::CircBox) {
circ_ = std::make_shared<Circuit>();
}

bool CircBox::is_clifford() const {
BGL_FORALL_VERTICES(v, circ_->dag, DAG) {
if (!circ_->get_Op_ptr_from_Vertex(v)->is_clifford()) return false;
}
return true;
}

Op_ptr CircBox::symbol_substitution(
const SymEngine::map_basic_basic &sub_map) const {
Circuit new_circ(*to_circuit());
Expand Down Expand Up @@ -112,6 +124,12 @@ Op_ptr Unitary1qBox::transpose() const {
return std::make_shared<Unitary1qBox>(m_.transpose());
}

bool Unitary1qBox::is_clifford() const {
std::vector<Command> cmds = to_circuit()->get_commands();
TKET_ASSERT(cmds.size() == 1);
return cmds[0].get_op_ptr()->is_clifford();
}

void Unitary1qBox::generate_circuit() const {
std::vector<double> tk1_params = tk1_angles_from_unitary(m_);
Circuit temp_circ(1);
Expand Down Expand Up @@ -201,6 +219,10 @@ PauliExpBox::PauliExpBox(const PauliExpBox &other)

PauliExpBox::PauliExpBox() : PauliExpBox({}, 0.) {}

bool PauliExpBox::is_clifford() const {
return equiv_0(4 * t_) || paulis_.empty();
}

SymSet PauliExpBox::free_symbols() const { return expr_free_symbols(t_); }

Op_ptr PauliExpBox::dagger() const {
Expand Down Expand Up @@ -302,6 +324,14 @@ std::string CustomGate::get_name(bool) const {
return s.str();
}

bool CustomGate::is_clifford() const {
std::shared_ptr<Circuit> circ = to_circuit();
BGL_FORALL_VERTICES(v, circ->dag, DAG) {
if (!circ->get_Op_ptr_from_Vertex(v)->is_clifford()) return false;
}
return true;
}

QControlBox::QControlBox(const Op_ptr &op, unsigned n_controls)
: Box(OpType::QControlBox), op_(op), n_controls_(n_controls) {
op_signature_t inner_sig = op_->get_signature();
Expand Down
Loading

0 comments on commit 28764ea

Please sign in to comment.