Skip to content

Commit

Permalink
Merge pull request #1515 from CQCL/main
Browse files Browse the repository at this point in the history
update docs
  • Loading branch information
cqc-melf authored Aug 2, 2024
2 parents 883219f + 733f87d commit 6ebb95e
Show file tree
Hide file tree
Showing 19 changed files with 190 additions and 2,479 deletions.
9 changes: 0 additions & 9 deletions .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -304,15 +304,6 @@ jobs:
cd pytket/tests
pip install -r requirements.txt
pytest --ignore=simulator/
- name: Test building docs
if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
timeout-minutes: 20
run: |
pip install poetry==1.6.1
cd pytket/docs
poetry install
cd ../../
poetry run -C pytket/docs ./.github/workflows/build-docs
- name: Upload artifact
if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pytket_benchmarking.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ jobs:
uses: slackapi/[email protected]
with:
channel-id: 'G01CP0YFFA7'
slack-message: '${{ env.RETURN_TEST }}'
slack-message: '${{ env.RETURN_TEST }} Release tag: ${{ github.event.release.tag_name }}.'
env:
SLACK_BOT_TOKEN: ${{ secrets.PYTKET_BENCHMARKING_SLACK_BOT_TOKEN }}
RETURN_TEST: ${{ env.RETURN_TEST }}
1 change: 0 additions & 1 deletion nix-support/pytket.nix
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ in {
propagatedBuildInputs = with super.python3.pkgs; [
self.binders
super.lark
super.types-pkg_resources
super.qwasm
graphviz
networkx
Expand Down
11 changes: 0 additions & 11 deletions nix-support/third-party-python-packages.nix
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,6 @@ self: super: {
nativeBuildInputs = with super.python3Packages; [ setuptools ];
doCheck = false;
};
types-pkg_resources = let
pname = "types-pkg_resources";
version = "0.1.3";
in super.python3.pkgs.buildPythonPackage {
inherit pname version;
src = super.fetchPypi {
inherit pname version;
sha256 = "sha256:g0qbjT2+o0NWL9mdXTNZpyb2v503M7zNK08wlvurna4=";
};
doCheck = false;
};
sympy' = super.python3.pkgs.buildPythonPackage rec{
# version bump - nixpkgs' version is 1.12 at the time of writing
pname = "sympy";
Expand Down
2 changes: 1 addition & 1 deletion pytket/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def package(self):
cmake.install()

def requirements(self):
self.requires("tket/1.3.16@tket/stable")
self.requires("tket/1.3.17@tket/stable")
self.requires("tklog/0.3.3@tket/stable")
self.requires("tkrng/0.3.3@tket/stable")
self.requires("tkassert/0.3.4@tket/stable")
Expand Down
10 changes: 10 additions & 0 deletions pytket/docs/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
Changelog
=========

1.31.0 (August 2024)
--------------------

* Remove unnecessary types-pkg_resources dependency due to package being yanked from pypi
* add scratch_reg_resize_pass for decomposing temp bit register
* Update to pytket-circuit-renderer 0.9.

Fixes:
* Fix MultiplexedTensoredU2Box passing MultiplexedRotationBox an empty argument

1.30.0 (July 2024)
------------------

Expand Down
4 changes: 2 additions & 2 deletions pytket/docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@
author = "Quantinuum"

# The short X.Y version
version = "1.30"
version = "1.31"
# The full version, including alpha/beta/rc tags
release = "1.30.0"
release = "1.31.0"


# -- General configuration ---------------------------------------------------
Expand Down
10 changes: 10 additions & 0 deletions pytket/docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ Windows. To install, run
pip install pytket


.. admonition:: Known issue installing pytket (Added 2nd August 2024)
:class: attention

Due to the removal of the `types-pkg_resources` package from pypi there will likely be issues when installing old versions of pytket. It is recommend to use pytket `>=1.31` where possible.

If you require using a version of pytket older than 1.31 then you can try the following.


`pip install types-pkg-resources==0.1.3 pytket==<set version>`


If you have issues installing ``pytket`` please visit the `installation troubleshooting <https://tket.quantinuum.com/api-docs/install.html>`_ page.

Expand Down
2,423 changes: 0 additions & 2,423 deletions pytket/docs/poetry.lock

This file was deleted.

3 changes: 1 addition & 2 deletions pytket/docs/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ sphinx-copybutton = "^0.5.2"
jupyter-sphinx = "^0.5.3"
ipykernel = "^6.29.4"
enum-tools = {extras = ["sphinx"], version = "^0.12.0"}
pytket = "^1.29.2"
furo = "^2024.5.6"

pytket = "^1.31.0"

[build-system]
requires = ["poetry-core"]
Expand Down
2 changes: 1 addition & 1 deletion pytket/pytket/circuit/display/static/head_imports.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!-- Download Vue 3-->
<script type="application/javascript" src="https://cdn.jsdelivr.net/npm/vue@3"></script>
<!-- Download Circuit Renderer with styles -->
<script type="application/javascript" src="https://unpkg.com/pytket-circuit-renderer@0.8/dist/pytket-circuit-renderer.umd.js"></script>
<script type="application/javascript" src="https://unpkg.com/pytket-circuit-renderer@0.9/dist/pytket-circuit-renderer.umd.js"></script>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/pytket-circuit-renderer.css">
1 change: 1 addition & 0 deletions pytket/pytket/passes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@
from .script import compilation_pass_from_script, compilation_pass_grammar
from .auto_rebase import auto_rebase_pass, auto_squash_pass
from .passselector import PassSelector
from .resizeregpass import scratch_reg_resize_pass
43 changes: 43 additions & 0 deletions pytket/pytket/passes/resizeregpass.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Copyright 2019-2024 Cambridge Quantum Computing
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from pytket.unit_id import _TEMP_BIT_NAME
from pytket.circuit import Circuit, Bit
from .._tket.passes import BasePass, CustomPass

MAX_C_REG_WIDTH = 32


def _is_scratch(bit: Bit) -> bool:
reg_name = bit.reg_name
return bool(reg_name == _TEMP_BIT_NAME) or reg_name.startswith(f"{_TEMP_BIT_NAME}_")


def scratch_reg_resize_pass(max_size: int = MAX_C_REG_WIDTH) -> BasePass:
"""Given a max scratch register width, return a compiler pass that
breaks up the internal scratch bit registers into smaller registers
"""

def trans(circ: Circuit, max_size: int = max_size) -> Circuit:
# Find all scratch bits
scratch_bits = list(filter(_is_scratch, circ.bits))
# If the total number of scratch bits exceeds the max width, rename them
if len(scratch_bits) > max_size:
bits_map = {}
for i, bit in enumerate(scratch_bits):
bits_map[bit] = Bit(f"{_TEMP_BIT_NAME}_{i//max_size}", i % max_size)
circ.rename_units(bits_map) # type: ignore
return circ

return CustomPass(trans, label="resize scratch bits")
4 changes: 2 additions & 2 deletions pytket/pytket/utils/results.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Dict, List, Tuple, Union
from typing import Any, Dict, List, Tuple, Union

import numpy as np
from pytket.circuit import BasisOrder

StateTuple = Tuple[int, ...]
CountsDict = Dict[StateTuple, Union[int, float]]
KwargTypes = Union[int, float, str, None]
KwargTypes = Any


class BitPermuter:
Expand Down
1 change: 0 additions & 1 deletion pytket/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@ def finalize_options(self):
"networkx >= 2.8.8",
"graphviz >= 0.20.3",
"jinja2 >= 3.1.4",
"types-pkg_resources >= 0.1.3",
"typing-extensions >= 4.12.2",
"qwasm >= 1.0.1",
],
Expand Down
78 changes: 76 additions & 2 deletions pytket/tests/compilation_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from pytket.circuit import Circuit, OpType
from pytket.passes import FullPeepholeOptimise, PassSelector, CXMappingPass
from pytket.circuit import Circuit, OpType, reg_eq
from pytket.passes import (
FullPeepholeOptimise,
PassSelector,
CXMappingPass,
scratch_reg_resize_pass,
)
from pytket.architecture import Architecture
from pytket.placement import Placement
from pytket.unit_id import _TEMP_BIT_NAME, _TEMP_BIT_REG_BASE
import pytest


Expand Down Expand Up @@ -239,3 +245,71 @@ def count_gates(circ: Circuit) -> int:
assert sp.get_scores() == [0, 0]

assert count_gates(result) == min(x for x in sp.get_scores() if x is not None)


def test_resize_scratch_registers() -> None:
max_c_reg_width_list = [30, 40]
for max_c_reg_width in max_c_reg_width_list:
circ = Circuit(1)
reg_a = circ.add_c_register("a", 1)
reg_b = circ.add_c_register("b", 1)
n_scratch_bits = max_c_reg_width * 2 + 2
for _ in range(n_scratch_bits):
circ.add_gate(OpType.PhasedX, [1, 0], [0], condition=reg_a[0] ^ reg_b[0])
original_scratch_reg = circ.get_c_register(_TEMP_BIT_NAME)
# check the scratch reg size is max_c_reg_width
assert original_scratch_reg.size == n_scratch_bits

# apply the resize pass
c_compiled = circ.copy()
scratch_reg_resize_pass(max_c_reg_width).apply(c_compiled)

# check the old register is replaced
with pytest.raises(RuntimeError) as e:
c_compiled.get_c_register(_TEMP_BIT_NAME)
err_msg = "Cannot find classical register"
assert err_msg in str(e.value)

# check the new registers have the correct sizes
scratch_reg1 = c_compiled.get_c_register(f"{_TEMP_BIT_NAME}_0")
scratch_reg2 = c_compiled.get_c_register(f"{_TEMP_BIT_NAME}_1")
scratch_reg3 = c_compiled.get_c_register(f"{_TEMP_BIT_NAME}_2")
assert scratch_reg1.size == max_c_reg_width
assert scratch_reg2.size == max_c_reg_width
assert scratch_reg3.size == 2
args_map = dict()
original_cmds = circ.get_commands()
for cmd in original_cmds:
for arg in cmd.args:
args_map[arg] = arg

for i in range(n_scratch_bits):
args_map[original_scratch_reg[i]] = c_compiled.get_c_register(
f"{_TEMP_BIT_NAME}_{i//max_c_reg_width}"
)[i % max_c_reg_width]

# Check the compiled circuit is equivalent to the original one up to renaming
compiled_cmds = c_compiled.get_commands()
for i, cmd in enumerate(original_cmds):
for j, arg in enumerate(cmd.args):
assert compiled_cmds[i].args[j] == args_map[arg]

# If the max width is not exceeded, do nothing
circ = Circuit(1)
reg_a = circ.add_c_register("a", 1)
reg_b = circ.add_c_register("b", 1)
for _ in range(30):
circ.add_gate(OpType.PhasedX, [1, 0], [0], condition=reg_a[0] ^ reg_b[0])
c_compiled = circ.copy()
scratch_reg_resize_pass(40).apply(c_compiled)
assert circ == c_compiled

# Test _TEMP_BIT_REG_BASE is ignored
circ = Circuit(1, name="test_classical")
reg_a = circ.add_c_register("a", 1)
reg_b = circ.add_c_register("b", 1)
circ.X(0, condition=reg_eq(reg_a ^ reg_b, 1))
assert circ.get_c_register(f"{_TEMP_BIT_REG_BASE}_0").size == 64
c_compiled = circ.copy()
scratch_reg_resize_pass(10).apply(c_compiled)
assert circ == c_compiled
2 changes: 1 addition & 1 deletion tket/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

class TketConan(ConanFile):
name = "tket"
version = "1.3.16"
version = "1.3.17"
package_type = "library"
license = "Apache 2"
homepage = "https://github.com/CQCL/tket"
Expand Down
57 changes: 35 additions & 22 deletions tket/src/Circuit/Multiplexor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -998,37 +998,50 @@ void add_multi_rz(
// First get all GateSpec by constructing and decomposing
// MultiplexedRotationBox
for (unsigned target = 0; target < n_targets_; target++) {
all_decomps.push_back(
MultiplexedRotationBox(all_multiplexed_rz[target]).decompose());
ctrl_op_map_t map = all_multiplexed_rz[target];
if (!map.empty()) {
all_decomps.push_back(
MultiplexedRotationBox(all_multiplexed_rz[target]).decompose());
} else {
all_decomps.push_back({});
}
}
TKET_ASSERT(!all_decomps.empty());
unsigned reference_size = all_decomps[0].size();
for (unsigned i = 1; i < all_decomps.size(); i++) {
unsigned reference_size = 0;
for (unsigned i = 0; i < all_decomps.size(); i++) {
if (!all_decomps[i].empty() && !reference_size) {
reference_size = all_decomps[i].size();
}
TKET_ASSERT(reference_size == all_decomps[i].size());
}

// => no MultiplexedRz so we can carry on
if (!reference_size) return;

// Then iterate through all the commands, adding them to the circuit
// in an interleaved manner
for (unsigned i = 0; i < reference_size; i++) {
for (unsigned target = 0; target < all_decomps.size(); target++) {
GateSpec gate = all_decomps[target][i];
unsigned rotated_index;
switch (gate.type) {
case OpType::CX:
// we also need to map gate.qubit to the correct qubit
// we know that the bitstrings for the "target"th target have been
// left rotated by "target", so:
rotated_index = (*gate.qubit + (target % n_targets_)) % n_controls_;
circ.add_op<unsigned>(
OpType::CX, {rotated_index, n_controls_ + target});
break;
case OpType::Rz:
circ.add_op<unsigned>(
OpType::Rz, *gate.angle, {n_controls_ + target});
break;
default:
// this should never be hit
TKET_ASSERT(false);
if (!all_decomps[target].empty()) {
GateSpec gate = all_decomps[target][i];
unsigned rotated_index;
switch (gate.type) {
case OpType::CX:
// we also need to map gate.qubit to the correct qubit
// we know that the bitstrings for the "target"th target have been
// left rotated by "target", so:
rotated_index = (*gate.qubit + (target % n_targets_)) % n_controls_;
circ.add_op<unsigned>(
OpType::CX, {rotated_index, n_controls_ + target});
break;
case OpType::Rz:
circ.add_op<unsigned>(
OpType::Rz, *gate.angle, {n_controls_ + target});
break;
default:
// this should never be hit
TKET_ASSERT(false);
}
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions tket/test/src/Circuit/test_Multiplexor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -812,5 +812,11 @@ SCENARIO("Test MultiplexedTensoredU2Box exceptions", "[boxes]") {
"single-qubit unitary gate types or Unitary1qBox"));
}
}
SCENARIO("Test MultiplexedTensoredU2Box value error") {
ctrl_tensored_op_map_t op_map = {
{{0}, {get_op_ptr(OpType::X)}}, {{1}, {get_op_ptr(OpType::Y)}}};
MultiplexedTensoredU2Box box(op_map);
REQUIRE(box.to_circuit());
}
} // namespace test_Multiplexor
} // namespace tket

0 comments on commit 6ebb95e

Please sign in to comment.